Upstream version 7.36.149.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_modifiers_evdev.h"
15 #include "ui/events/ozone/evdev/libgestures_glue/gesture_timer_provider.h"
16 #include "ui/gfx/geometry/point_f.h"
17
18 namespace ui {
19
20 namespace {
21
22 // Convert libevdev device class to libgestures device class.
23 GestureInterpreterDeviceClass GestureDeviceClass(Evdev* evdev) {
24   switch (evdev->info.evdev_class) {
25     case EvdevClassMouse:
26       return GESTURES_DEVCLASS_MOUSE;
27     case EvdevClassMultitouchMouse:
28       return GESTURES_DEVCLASS_MULTITOUCH_MOUSE;
29     case EvdevClassTouchpad:
30       return GESTURES_DEVCLASS_TOUCHPAD;
31     case EvdevClassTouchscreen:
32       return GESTURES_DEVCLASS_TOUCHSCREEN;
33     default:
34       return GESTURES_DEVCLASS_UNKNOWN;
35   }
36 }
37
38 // Convert libevdev state to libgestures hardware properties.
39 HardwareProperties GestureHardwareProperties(Evdev* evdev) {
40   HardwareProperties hwprops;
41   hwprops.left = Event_Get_Left(evdev);
42   hwprops.top = Event_Get_Top(evdev);
43   hwprops.right = Event_Get_Right(evdev);
44   hwprops.bottom = Event_Get_Bottom(evdev);
45   hwprops.res_x = Event_Get_Res_X(evdev);
46   hwprops.res_y = Event_Get_Res_Y(evdev);
47   hwprops.screen_x_dpi = 133;
48   hwprops.screen_y_dpi = 133;
49   hwprops.orientation_minimum = Event_Get_Orientation_Minimum(evdev);
50   hwprops.orientation_maximum = Event_Get_Orientation_Maximum(evdev);
51   hwprops.max_finger_cnt = Event_Get_Slot_Count(evdev);
52   hwprops.max_touch_cnt = Event_Get_Touch_Count_Max(evdev);
53   hwprops.supports_t5r2 = Event_Get_T5R2(evdev);
54   hwprops.support_semi_mt = Event_Get_Semi_MT(evdev);
55   /* buttonpad means a physical button under the touch surface */
56   hwprops.is_button_pad = Event_Get_Button_Pad(evdev);
57   return hwprops;
58 }
59
60 // Callback from libgestures when a gesture is ready.
61 void OnGestureReadyHelper(void* client_data, const Gesture* gesture) {
62   GestureInterpreterLibevdevCros* interpreter =
63       static_cast<GestureInterpreterLibevdevCros*>(client_data);
64   interpreter->OnGestureReady(gesture);
65 }
66
67 // Convert gestures timestamp (stime_t) to ui::Event timestamp.
68 base::TimeDelta StimeToTimedelta(stime_t timestamp) {
69   return base::TimeDelta::FromMicroseconds(timestamp *
70                                            base::Time::kMicrosecondsPerSecond);
71 }
72
73 // Number of fingers for scroll gestures.
74 const int kGestureScrollFingerCount = 2;
75
76 }  // namespace
77
78 GestureInterpreterLibevdevCros::GestureInterpreterLibevdevCros(
79     EventModifiersEvdev* modifiers,
80     CursorDelegateEvdev* cursor,
81     const EventDispatchCallback& callback)
82     : modifiers_(modifiers),
83       cursor_(cursor),
84       dispatch_callback_(callback),
85       interpreter_(NULL) {}
86
87 GestureInterpreterLibevdevCros::~GestureInterpreterLibevdevCros() {
88   if (interpreter_) {
89     DeleteGestureInterpreter(interpreter_);
90     interpreter_ = NULL;
91   }
92 }
93
94 void GestureInterpreterLibevdevCros::OnLibEvdevCrosOpen(
95     Evdev* evdev,
96     EventStateRec* evstate) {
97   CHECK(evdev->info.is_monotonic) << "libevdev must use monotonic timestamps";
98   VLOG(9) << "HACK DO NOT REMOVE OR LINK WILL FAIL" << (void*)gestures_log;
99
100   HardwareProperties hwprops = GestureHardwareProperties(evdev);
101   GestureInterpreterDeviceClass devclass = GestureDeviceClass(evdev);
102
103   // Create & initialize GestureInterpreter.
104   CHECK(!interpreter_);
105   interpreter_ = NewGestureInterpreter();
106   GestureInterpreterInitialize(interpreter_, devclass);
107   GestureInterpreterSetHardwareProperties(interpreter_, &hwprops);
108   GestureInterpreterSetTimerProvider(
109       interpreter_,
110       const_cast<GesturesTimerProvider*>(&kGestureTimerProvider),
111       this);
112   GestureInterpreterSetCallback(interpreter_, OnGestureReadyHelper, this);
113 }
114
115 void GestureInterpreterLibevdevCros::OnLibEvdevCrosEvent(Evdev* evdev,
116                                                          EventStateRec* evstate,
117                                                          const timeval& time) {
118   HardwareState hwstate;
119   memset(&hwstate, 0, sizeof(hwstate));
120   hwstate.timestamp = StimeFromTimeval(&time);
121
122   // Mouse.
123   hwstate.rel_x = evstate->rel_x;
124   hwstate.rel_y = evstate->rel_y;
125   hwstate.rel_wheel = evstate->rel_wheel;
126   hwstate.rel_hwheel = evstate->rel_hwheel;
127
128   // Touch.
129   FingerState fingers[Event_Get_Slot_Count(evdev)];
130   memset(&fingers, 0, sizeof(fingers));
131   int current_finger = 0;
132   for (int i = 0; i < evstate->slot_count; i++) {
133     MtSlotPtr slot = &evstate->slots[i];
134     if (slot->tracking_id == -1)
135       continue;
136     fingers[current_finger].touch_major = slot->touch_major;
137     fingers[current_finger].touch_minor = slot->touch_minor;
138     fingers[current_finger].width_major = slot->width_major;
139     fingers[current_finger].width_minor = slot->width_minor;
140     fingers[current_finger].pressure = slot->pressure;
141     fingers[current_finger].orientation = slot->orientation;
142     fingers[current_finger].position_x = slot->position_x;
143     fingers[current_finger].position_y = slot->position_y;
144     fingers[current_finger].tracking_id = slot->tracking_id;
145     current_finger++;
146   }
147   hwstate.touch_cnt = Event_Get_Touch_Count(evdev);
148   hwstate.finger_cnt = current_finger;
149   hwstate.fingers = fingers;
150
151   // Buttons.
152   if (Event_Get_Button_Left(evdev))
153     hwstate.buttons_down |= GESTURES_BUTTON_LEFT;
154   if (Event_Get_Button_Middle(evdev))
155     hwstate.buttons_down |= GESTURES_BUTTON_MIDDLE;
156   if (Event_Get_Button_Right(evdev))
157     hwstate.buttons_down |= GESTURES_BUTTON_RIGHT;
158
159   GestureInterpreterPushHardwareState(interpreter_, &hwstate);
160 }
161
162 void GestureInterpreterLibevdevCros::OnGestureReady(const Gesture* gesture) {
163   switch (gesture->type) {
164     case kGestureTypeMove:
165       OnGestureMove(gesture, &gesture->details.move);
166       break;
167     case kGestureTypeScroll:
168       OnGestureScroll(gesture, &gesture->details.scroll);
169       break;
170     case kGestureTypeButtonsChange:
171       OnGestureButtonsChange(gesture, &gesture->details.buttons);
172       break;
173     case kGestureTypeContactInitiated:
174     case kGestureTypeFling:
175     case kGestureTypeSwipe:
176     case kGestureTypeSwipeLift:
177     case kGestureTypePinch:
178     case kGestureTypeMetrics:
179       // TODO(spang): Support remaining gestures.
180       NOTIMPLEMENTED();
181       break;
182     default:
183       LOG(WARNING) << base::StringPrintf("Unrecognized gesture type (%u)",
184                                          gesture->type);
185       break;
186   }
187 }
188
189 void GestureInterpreterLibevdevCros::OnGestureMove(const Gesture* gesture,
190                                                    const GestureMove* move) {
191   DVLOG(3) << base::StringPrintf("Gesture Move: (%f, %f) [%f, %f]",
192                                  move->dx,
193                                  move->dy,
194                                  move->ordinal_dx,
195                                  move->ordinal_dy);
196   if (!cursor_)
197     return;  // No cursor!
198   cursor_->MoveCursor(gfx::Vector2dF(move->dx, move->dy));
199   // TODO(spang): Use move->ordinal_dx, move->ordinal_dy
200   // TODO(spang): Use move->start_time, move->end_time
201   MouseEvent event(ET_MOUSE_MOVED,
202                    cursor_->location(),
203                    cursor_->location(),
204                    modifiers_->GetModifierFlags(),
205                    /* changed_button_flags */ 0);
206   Dispatch(&event);
207 }
208
209 void GestureInterpreterLibevdevCros::OnGestureScroll(
210     const Gesture* gesture,
211     const GestureScroll* scroll) {
212   DVLOG(3) << base::StringPrintf("Gesture Scroll: (%f, %f) [%f, %f]",
213                                  scroll->dx,
214                                  scroll->dy,
215                                  scroll->ordinal_dx,
216                                  scroll->ordinal_dy);
217   // TODO(spang): Support SetNaturalScroll
218   // TODO(spang): Use scroll->start_time
219   ScrollEvent event(ET_SCROLL,
220                     cursor_->location(),
221                     StimeToTimedelta(gesture->end_time),
222                     modifiers_->GetModifierFlags(),
223                     scroll->dx,
224                     scroll->dy,
225                     scroll->ordinal_dx,
226                     scroll->ordinal_dy,
227                     kGestureScrollFingerCount);
228   Dispatch(&event);
229 }
230
231 void GestureInterpreterLibevdevCros::OnGestureButtonsChange(
232     const Gesture* gesture,
233     const GestureButtonsChange* buttons) {
234   DVLOG(3) << base::StringPrintf("Gesture Button Change: down=0x%02x up=0x%02x",
235                                  buttons->down,
236                                  buttons->up);
237   // TODO(spang): Use buttons->start_time, buttons->end_time
238   if (buttons->down & GESTURES_BUTTON_LEFT)
239     DispatchMouseButton(EVDEV_MODIFIER_LEFT_MOUSE_BUTTON, true);
240   if (buttons->down & GESTURES_BUTTON_MIDDLE)
241     DispatchMouseButton(EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON, true);
242   if (buttons->down & GESTURES_BUTTON_RIGHT)
243     DispatchMouseButton(EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON, true);
244   if (buttons->up & GESTURES_BUTTON_LEFT)
245     DispatchMouseButton(EVDEV_MODIFIER_LEFT_MOUSE_BUTTON, false);
246   if (buttons->up & GESTURES_BUTTON_MIDDLE)
247     DispatchMouseButton(EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON, false);
248   if (buttons->up & GESTURES_BUTTON_RIGHT)
249     DispatchMouseButton(EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON, false);
250 }
251
252 void GestureInterpreterLibevdevCros::Dispatch(Event* event) {
253   dispatch_callback_.Run(event);
254 }
255
256 void GestureInterpreterLibevdevCros::DispatchMouseButton(unsigned int modifier,
257                                                          bool down) {
258   const gfx::PointF& loc = cursor_->location();
259   int flag = modifiers_->GetEventFlagFromModifier(modifier);
260   EventType type = (down ? ET_MOUSE_PRESSED : ET_MOUSE_RELEASED);
261   modifiers_->UpdateModifier(modifier, down);
262   MouseEvent event(type, loc, loc, modifiers_->GetModifierFlags() | flag, flag);
263   Dispatch(&event);
264 }
265
266 }  // namespace ui