Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ui / events / ozone / evdev / libgestures_glue / gesture_interpreter_libevdev_cros.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.h"
6
7 #include <gestures/gestures.h>
8 #include <libevdev/libevdev.h>
9
10 #include "base/strings/stringprintf.h"
11 #include "base/timer/timer.h"
12 #include "ui/events/event.h"
13 #include "ui/events/ozone/evdev/cursor_delegate_evdev.h"
14 #include "ui/events/ozone/evdev/event_device_util.h"
15 #include "ui/events/ozone/evdev/event_modifiers_evdev.h"
16 #include "ui/events/ozone/evdev/keyboard_evdev.h"
17 #include "ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.h"
18 #include "ui/events/ozone/evdev/libgestures_glue/gesture_timer_provider.h"
19 #include "ui/gfx/geometry/point_f.h"
20
21 namespace ui {
22
23 namespace {
24
25 // Convert libevdev device class to libgestures device class.
26 GestureInterpreterDeviceClass GestureDeviceClass(Evdev* evdev) {
27   switch (evdev->info.evdev_class) {
28     case EvdevClassMouse:
29       return GESTURES_DEVCLASS_MOUSE;
30     case EvdevClassMultitouchMouse:
31       return GESTURES_DEVCLASS_MULTITOUCH_MOUSE;
32     case EvdevClassTouchpad:
33       return GESTURES_DEVCLASS_TOUCHPAD;
34     case EvdevClassTouchscreen:
35       return GESTURES_DEVCLASS_TOUCHSCREEN;
36     default:
37       return GESTURES_DEVCLASS_UNKNOWN;
38   }
39 }
40
41 // Convert libevdev state to libgestures hardware properties.
42 HardwareProperties GestureHardwareProperties(
43     Evdev* evdev,
44     const GestureDeviceProperties* props) {
45   HardwareProperties hwprops;
46   hwprops.left = props->area_left;
47   hwprops.top = props->area_top;
48   hwprops.right = props->area_right;
49   hwprops.bottom = props->area_bottom;
50   hwprops.res_x = props->res_x;
51   hwprops.res_y = props->res_y;
52   hwprops.screen_x_dpi = 133;
53   hwprops.screen_y_dpi = 133;
54   hwprops.orientation_minimum = props->orientation_minimum;
55   hwprops.orientation_maximum = props->orientation_maximum;
56   hwprops.max_finger_cnt = Event_Get_Slot_Count(evdev);
57   hwprops.max_touch_cnt = Event_Get_Touch_Count_Max(evdev);
58   hwprops.supports_t5r2 = Event_Get_T5R2(evdev);
59   hwprops.support_semi_mt = Event_Get_Semi_MT(evdev);
60   /* buttonpad means a physical button under the touch surface */
61   hwprops.is_button_pad = Event_Get_Button_Pad(evdev);
62   return hwprops;
63 }
64
65 // Callback from libgestures when a gesture is ready.
66 void OnGestureReadyHelper(void* client_data, const Gesture* gesture) {
67   GestureInterpreterLibevdevCros* interpreter =
68       static_cast<GestureInterpreterLibevdevCros*>(client_data);
69   interpreter->OnGestureReady(gesture);
70 }
71
72 // Convert gestures timestamp (stime_t) to ui::Event timestamp.
73 base::TimeDelta StimeToTimedelta(stime_t timestamp) {
74   return base::TimeDelta::FromMicroseconds(timestamp *
75                                            base::Time::kMicrosecondsPerSecond);
76 }
77
78 // Number of fingers for scroll gestures.
79 const int kGestureScrollFingerCount = 2;
80
81 // Number of fingers for swipe gestures.
82 const int kGestureSwipeFingerCount = 3;
83
84 }  // namespace
85
86 GestureInterpreterLibevdevCros::GestureInterpreterLibevdevCros(
87     int id,
88     EventModifiersEvdev* modifiers,
89     CursorDelegateEvdev* cursor,
90     KeyboardEvdev* keyboard,
91     GesturePropertyProvider* property_provider,
92     const EventDispatchCallback& callback)
93     : id_(id),
94       modifiers_(modifiers),
95       cursor_(cursor),
96       keyboard_(keyboard),
97       property_provider_(property_provider),
98       dispatch_callback_(callback),
99       interpreter_(NULL),
100       evdev_(NULL),
101       device_properties_(new GestureDeviceProperties) {
102   memset(&prev_key_state_, 0, sizeof(prev_key_state_));
103 }
104
105 GestureInterpreterLibevdevCros::~GestureInterpreterLibevdevCros() {
106   // Note that this destructor got called after the evdev device node has been
107   // closed. Therefore, all clean-up codes here shouldn't depend on the device
108   // information (except for the pointer address itself).
109
110   // Clean-up if the gesture interpreter has been successfully created.
111   if (interpreter_) {
112     // Unset callbacks.
113     GestureInterpreterSetCallback(interpreter_, NULL, NULL);
114     GestureInterpreterSetPropProvider(interpreter_, NULL, NULL);
115     GestureInterpreterSetTimerProvider(interpreter_, NULL, NULL);
116     DeleteGestureInterpreter(interpreter_);
117     interpreter_ = NULL;
118   }
119
120   // Unregister device from the gesture property provider.
121   GesturesPropFunctionsWrapper::UnregisterDevice(this);
122 }
123
124 void GestureInterpreterLibevdevCros::OnLibEvdevCrosOpen(
125     Evdev* evdev,
126     EventStateRec* evstate) {
127   DCHECK(evdev->info.is_monotonic) << "libevdev must use monotonic timestamps";
128   VLOG(9) << "HACK DO NOT REMOVE OR LINK WILL FAIL" << (void*)gestures_log;
129
130   // Set device pointer and initialize properties.
131   evdev_ = evdev;
132   GesturesPropFunctionsWrapper::InitializeDeviceProperties(
133       this, device_properties_.get());
134   HardwareProperties hwprops =
135       GestureHardwareProperties(evdev, device_properties_.get());
136   GestureInterpreterDeviceClass devclass = GestureDeviceClass(evdev);
137
138   // Create & initialize GestureInterpreter.
139   DCHECK(!interpreter_);
140   interpreter_ = NewGestureInterpreter();
141   GestureInterpreterSetPropProvider(
142       interpreter_,
143       const_cast<GesturesPropProvider*>(&kGesturePropProvider),
144       this);
145   GestureInterpreterInitialize(interpreter_, devclass);
146   GestureInterpreterSetHardwareProperties(interpreter_, &hwprops);
147   GestureInterpreterSetTimerProvider(
148       interpreter_,
149       const_cast<GesturesTimerProvider*>(&kGestureTimerProvider),
150       this);
151   GestureInterpreterSetCallback(interpreter_, OnGestureReadyHelper, this);
152 }
153
154 void GestureInterpreterLibevdevCros::OnLibEvdevCrosEvent(Evdev* evdev,
155                                                          EventStateRec* evstate,
156                                                          const timeval& time) {
157   // If the device has keys no it, dispatch any presses/release.
158   DispatchChangedKeys(evdev, time);
159
160   HardwareState hwstate;
161   memset(&hwstate, 0, sizeof(hwstate));
162   hwstate.timestamp = StimeFromTimeval(&time);
163
164   // Mouse.
165   hwstate.rel_x = evstate->rel_x;
166   hwstate.rel_y = evstate->rel_y;
167   hwstate.rel_wheel = evstate->rel_wheel;
168   hwstate.rel_hwheel = evstate->rel_hwheel;
169
170   // Touch.
171   FingerState fingers[Event_Get_Slot_Count(evdev)];
172   memset(&fingers, 0, sizeof(fingers));
173   int current_finger = 0;
174   for (int i = 0; i < evstate->slot_count; i++) {
175     MtSlotPtr slot = &evstate->slots[i];
176     if (slot->tracking_id == -1)
177       continue;
178     fingers[current_finger].touch_major = slot->touch_major;
179     fingers[current_finger].touch_minor = slot->touch_minor;
180     fingers[current_finger].width_major = slot->width_major;
181     fingers[current_finger].width_minor = slot->width_minor;
182     fingers[current_finger].pressure = slot->pressure;
183     fingers[current_finger].orientation = slot->orientation;
184     fingers[current_finger].position_x = slot->position_x;
185     fingers[current_finger].position_y = slot->position_y;
186     fingers[current_finger].tracking_id = slot->tracking_id;
187     current_finger++;
188   }
189   hwstate.touch_cnt = Event_Get_Touch_Count(evdev);
190   hwstate.finger_cnt = current_finger;
191   hwstate.fingers = fingers;
192
193   // Buttons.
194   if (Event_Get_Button_Left(evdev))
195     hwstate.buttons_down |= GESTURES_BUTTON_LEFT;
196   if (Event_Get_Button_Middle(evdev))
197     hwstate.buttons_down |= GESTURES_BUTTON_MIDDLE;
198   if (Event_Get_Button_Right(evdev))
199     hwstate.buttons_down |= GESTURES_BUTTON_RIGHT;
200
201   GestureInterpreterPushHardwareState(interpreter_, &hwstate);
202 }
203
204 void GestureInterpreterLibevdevCros::OnGestureReady(const Gesture* gesture) {
205   switch (gesture->type) {
206     case kGestureTypeMove:
207       OnGestureMove(gesture, &gesture->details.move);
208       break;
209     case kGestureTypeScroll:
210       OnGestureScroll(gesture, &gesture->details.scroll);
211       break;
212     case kGestureTypeButtonsChange:
213       OnGestureButtonsChange(gesture, &gesture->details.buttons);
214       break;
215     case kGestureTypeContactInitiated:
216       OnGestureContactInitiated(gesture);
217       break;
218     case kGestureTypeFling:
219       OnGestureFling(gesture, &gesture->details.fling);
220       break;
221     case kGestureTypeSwipe:
222       OnGestureSwipe(gesture, &gesture->details.swipe);
223       break;
224     case kGestureTypeSwipeLift:
225       OnGestureSwipeLift(gesture, &gesture->details.swipe_lift);
226       break;
227     case kGestureTypePinch:
228       OnGesturePinch(gesture, &gesture->details.pinch);
229       break;
230     case kGestureTypeMetrics:
231       OnGestureMetrics(gesture, &gesture->details.metrics);
232       break;
233     default:
234       LOG(WARNING) << base::StringPrintf("Unrecognized gesture type (%u)",
235                                          gesture->type);
236       break;
237   }
238 }
239
240 void GestureInterpreterLibevdevCros::OnGestureMove(const Gesture* gesture,
241                                                    const GestureMove* move) {
242   DVLOG(3) << base::StringPrintf("Gesture Move: (%f, %f) [%f, %f]",
243                                  move->dx,
244                                  move->dy,
245                                  move->ordinal_dx,
246                                  move->ordinal_dy);
247   if (!cursor_)
248     return;  // No cursor!
249
250   cursor_->MoveCursor(gfx::Vector2dF(move->dx, move->dy));
251   // TODO(spang): Use move->ordinal_dx, move->ordinal_dy
252   // TODO(spang): Use move->start_time, move->end_time
253   Dispatch(make_scoped_ptr(new MouseEvent(ET_MOUSE_MOVED,
254                                           cursor_->location(),
255                                           cursor_->location(),
256                                           modifiers_->GetModifierFlags(),
257                                           /* changed_button_flags */ 0)));
258 }
259
260 void GestureInterpreterLibevdevCros::OnGestureScroll(
261     const Gesture* gesture,
262     const GestureScroll* scroll) {
263   DVLOG(3) << base::StringPrintf("Gesture Scroll: (%f, %f) [%f, %f]",
264                                  scroll->dx,
265                                  scroll->dy,
266                                  scroll->ordinal_dx,
267                                  scroll->ordinal_dy);
268   if (!cursor_)
269     return;  // No cursor!
270
271   // TODO(spang): Support SetNaturalScroll
272   // TODO(spang): Use scroll->start_time
273   Dispatch(make_scoped_ptr(new ScrollEvent(ET_SCROLL,
274                                            cursor_->location(),
275                                            StimeToTimedelta(gesture->end_time),
276                                            modifiers_->GetModifierFlags(),
277                                            scroll->dx,
278                                            scroll->dy,
279                                            scroll->ordinal_dx,
280                                            scroll->ordinal_dy,
281                                            kGestureScrollFingerCount)));
282 }
283
284 void GestureInterpreterLibevdevCros::OnGestureButtonsChange(
285     const Gesture* gesture,
286     const GestureButtonsChange* buttons) {
287   DVLOG(3) << base::StringPrintf("Gesture Button Change: down=0x%02x up=0x%02x",
288                                  buttons->down,
289                                  buttons->up);
290
291   if (!cursor_)
292     return;  // No cursor!
293
294   // HACK for disabling TTC (actually, all clicks) on hidden cursor.
295   // This is normally plumbed via properties and can be removed soon.
296   // TODO(spang): Remove this.
297   if (buttons->down == GESTURES_BUTTON_LEFT &&
298       buttons->up == GESTURES_BUTTON_LEFT &&
299       !cursor_->IsCursorVisible())
300     return;
301
302   // TODO(spang): Use buttons->start_time, buttons->end_time
303   if (buttons->down & GESTURES_BUTTON_LEFT)
304     DispatchMouseButton(EVDEV_MODIFIER_LEFT_MOUSE_BUTTON, true);
305   if (buttons->down & GESTURES_BUTTON_MIDDLE)
306     DispatchMouseButton(EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON, true);
307   if (buttons->down & GESTURES_BUTTON_RIGHT)
308     DispatchMouseButton(EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON, true);
309   if (buttons->up & GESTURES_BUTTON_LEFT)
310     DispatchMouseButton(EVDEV_MODIFIER_LEFT_MOUSE_BUTTON, false);
311   if (buttons->up & GESTURES_BUTTON_MIDDLE)
312     DispatchMouseButton(EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON, false);
313   if (buttons->up & GESTURES_BUTTON_RIGHT)
314     DispatchMouseButton(EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON, false);
315 }
316
317 void GestureInterpreterLibevdevCros::OnGestureContactInitiated(
318     const Gesture* gesture) {
319   // TODO(spang): handle contact initiated.
320 }
321
322 void GestureInterpreterLibevdevCros::OnGestureFling(const Gesture* gesture,
323                                                     const GestureFling* fling) {
324   DVLOG(3) << base::StringPrintf(
325                   "Gesture Fling: (%f, %f) [%f, %f] fling_state=%d",
326                   fling->vx,
327                   fling->vy,
328                   fling->ordinal_vx,
329                   fling->ordinal_vy,
330                   fling->fling_state);
331
332   if (!cursor_)
333     return;  // No cursor!
334
335   EventType type =
336       (fling->fling_state == GESTURES_FLING_START ? ET_SCROLL_FLING_START
337                                                   : ET_SCROLL_FLING_CANCEL);
338
339   // Fling is like 2-finger scrolling but with velocity instead of displacement.
340   Dispatch(make_scoped_ptr(new ScrollEvent(type,
341                                            cursor_->location(),
342                                            StimeToTimedelta(gesture->end_time),
343                                            modifiers_->GetModifierFlags(),
344                                            fling->vx,
345                                            fling->vy,
346                                            fling->ordinal_vx,
347                                            fling->ordinal_vy,
348                                            kGestureScrollFingerCount)));
349 }
350
351 void GestureInterpreterLibevdevCros::OnGestureSwipe(const Gesture* gesture,
352                                                     const GestureSwipe* swipe) {
353   DVLOG(3) << base::StringPrintf("Gesture Swipe: (%f, %f) [%f, %f]",
354                                  swipe->dx,
355                                  swipe->dy,
356                                  swipe->ordinal_dx,
357                                  swipe->ordinal_dy);
358
359   if (!cursor_)
360     return;  // No cursor!
361
362   // Swipe is 3-finger scrolling.
363   Dispatch(make_scoped_ptr(new ScrollEvent(ET_SCROLL,
364                                            cursor_->location(),
365                                            StimeToTimedelta(gesture->end_time),
366                                            modifiers_->GetModifierFlags(),
367                                            swipe->dx,
368                                            swipe->dy,
369                                            swipe->ordinal_dx,
370                                            swipe->ordinal_dy,
371                                            kGestureSwipeFingerCount)));
372 }
373
374 void GestureInterpreterLibevdevCros::OnGestureSwipeLift(
375     const Gesture* gesture,
376     const GestureSwipeLift* swipelift) {
377   DVLOG(3) << base::StringPrintf("Gesture Swipe Lift");
378
379   if (!cursor_)
380     return;  // No cursor!
381
382   // Turn a swipe lift into a fling start.
383   // TODO(spang): Figure out why and put it in this comment.
384
385   Dispatch(make_scoped_ptr(new ScrollEvent(ET_SCROLL_FLING_START,
386                                            cursor_->location(),
387                                            StimeToTimedelta(gesture->end_time),
388                                            modifiers_->GetModifierFlags(),
389                                            /* x_offset */ 0,
390                                            /* y_offset */ 0,
391                                            /* x_offset_ordinal */ 0,
392                                            /* y_offset_ordinal */ 0,
393                                            kGestureScrollFingerCount)));
394 }
395
396 void GestureInterpreterLibevdevCros::OnGesturePinch(const Gesture* gesture,
397                                                     const GesturePinch* pinch) {
398   DVLOG(3) << base::StringPrintf(
399                   "Gesture Pinch: dz=%f [%f]", pinch->dz, pinch->ordinal_dz);
400
401   if (!cursor_)
402     return;  // No cursor!
403
404   NOTIMPLEMENTED();
405 }
406
407 void GestureInterpreterLibevdevCros::OnGestureMetrics(
408     const Gesture* gesture,
409     const GestureMetrics* metrics) {
410   DVLOG(3) << base::StringPrintf("Gesture Metrics: [%f, %f] type=%d",
411                                  metrics->data[0],
412                                  metrics->data[1],
413                                  metrics->type);
414   NOTIMPLEMENTED();
415 }
416
417 void GestureInterpreterLibevdevCros::Dispatch(scoped_ptr<Event> event) {
418   dispatch_callback_.Run(event.Pass());
419 }
420
421 void GestureInterpreterLibevdevCros::DispatchMouseButton(unsigned int modifier,
422                                                          bool down) {
423   const gfx::PointF& loc = cursor_->location();
424   int flag = modifiers_->GetEventFlagFromModifier(modifier);
425   EventType type = (down ? ET_MOUSE_PRESSED : ET_MOUSE_RELEASED);
426   modifiers_->UpdateModifier(modifier, down);
427   Dispatch(make_scoped_ptr(new MouseEvent(
428       type, loc, loc, modifiers_->GetModifierFlags() | flag, flag)));
429 }
430
431 void GestureInterpreterLibevdevCros::DispatchChangedKeys(Evdev* evdev,
432                                                          const timeval& time) {
433   unsigned long key_state_diff[EVDEV_BITS_TO_LONGS(KEY_CNT)];
434
435   // Find changed keys.
436   for (unsigned long i = 0; i < arraysize(key_state_diff); ++i)
437     key_state_diff[i] = evdev->key_state_bitmask[i] ^ prev_key_state_[i];
438
439   // Dispatch events for changed keys.
440   for (unsigned long key = 0; key < KEY_CNT; ++key) {
441     if (EvdevBitIsSet(key_state_diff, key)) {
442       bool value = EvdevBitIsSet(evdev->key_state_bitmask, key);
443
444       // Mouse buttons are handled by DispatchMouseButton.
445       if (key >= BTN_MOUSE && key < BTN_JOYSTICK)
446         continue;
447
448       // Ignore digi buttons (e.g. BTN_TOOL_FINGER).
449       if (key >= BTN_DIGI && key < BTN_WHEEL)
450         continue;
451
452       // Dispatch key press or release to keyboard.
453       keyboard_->OnKeyChange(key, value);
454     }
455   }
456
457   // Update internal key state.
458   for (unsigned long i = 0; i < EVDEV_BITS_TO_LONGS(KEY_CNT); ++i)
459     prev_key_state_[i] = evdev->key_state_bitmask[i];
460 }
461
462 }  // namespace ui