Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ui / events / ozone / evdev / libgestures_glue / gesture_interpreter_libevdev_cros.cc
blobe49082bd88b8645a6be0099faed2c2056f31b264
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.
5 #include "ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.h"
7 #include <gestures/gestures.h>
8 #include <libevdev/libevdev.h>
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"
18 namespace ui {
20 namespace {
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;
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;
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);
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);
73 // Number of fingers for scroll gestures.
74 const int kGestureScrollFingerCount = 2;
76 // Number of fingers for swipe gestures.
77 const int kGestureSwipeFingerCount = 3;
79 } // namespace
81 GestureInterpreterLibevdevCros::GestureInterpreterLibevdevCros(
82 EventModifiersEvdev* modifiers,
83 CursorDelegateEvdev* cursor,
84 const EventDispatchCallback& callback)
85 : modifiers_(modifiers),
86 cursor_(cursor),
87 dispatch_callback_(callback),
88 interpreter_(NULL) {}
90 GestureInterpreterLibevdevCros::~GestureInterpreterLibevdevCros() {
91 if (interpreter_) {
92 DeleteGestureInterpreter(interpreter_);
93 interpreter_ = NULL;
97 void GestureInterpreterLibevdevCros::OnLibEvdevCrosOpen(
98 Evdev* evdev,
99 EventStateRec* evstate) {
100 CHECK(evdev->info.is_monotonic) << "libevdev must use monotonic timestamps";
101 VLOG(9) << "HACK DO NOT REMOVE OR LINK WILL FAIL" << (void*)gestures_log;
103 HardwareProperties hwprops = GestureHardwareProperties(evdev);
104 GestureInterpreterDeviceClass devclass = GestureDeviceClass(evdev);
106 // Create & initialize GestureInterpreter.
107 CHECK(!interpreter_);
108 interpreter_ = NewGestureInterpreter();
109 GestureInterpreterInitialize(interpreter_, devclass);
110 GestureInterpreterSetHardwareProperties(interpreter_, &hwprops);
111 GestureInterpreterSetTimerProvider(
112 interpreter_,
113 const_cast<GesturesTimerProvider*>(&kGestureTimerProvider),
114 this);
115 GestureInterpreterSetCallback(interpreter_, OnGestureReadyHelper, this);
118 void GestureInterpreterLibevdevCros::OnLibEvdevCrosEvent(Evdev* evdev,
119 EventStateRec* evstate,
120 const timeval& time) {
121 HardwareState hwstate;
122 memset(&hwstate, 0, sizeof(hwstate));
123 hwstate.timestamp = StimeFromTimeval(&time);
125 // Mouse.
126 hwstate.rel_x = evstate->rel_x;
127 hwstate.rel_y = evstate->rel_y;
128 hwstate.rel_wheel = evstate->rel_wheel;
129 hwstate.rel_hwheel = evstate->rel_hwheel;
131 // Touch.
132 FingerState fingers[Event_Get_Slot_Count(evdev)];
133 memset(&fingers, 0, sizeof(fingers));
134 int current_finger = 0;
135 for (int i = 0; i < evstate->slot_count; i++) {
136 MtSlotPtr slot = &evstate->slots[i];
137 if (slot->tracking_id == -1)
138 continue;
139 fingers[current_finger].touch_major = slot->touch_major;
140 fingers[current_finger].touch_minor = slot->touch_minor;
141 fingers[current_finger].width_major = slot->width_major;
142 fingers[current_finger].width_minor = slot->width_minor;
143 fingers[current_finger].pressure = slot->pressure;
144 fingers[current_finger].orientation = slot->orientation;
145 fingers[current_finger].position_x = slot->position_x;
146 fingers[current_finger].position_y = slot->position_y;
147 fingers[current_finger].tracking_id = slot->tracking_id;
148 current_finger++;
150 hwstate.touch_cnt = Event_Get_Touch_Count(evdev);
151 hwstate.finger_cnt = current_finger;
152 hwstate.fingers = fingers;
154 // Buttons.
155 if (Event_Get_Button_Left(evdev))
156 hwstate.buttons_down |= GESTURES_BUTTON_LEFT;
157 if (Event_Get_Button_Middle(evdev))
158 hwstate.buttons_down |= GESTURES_BUTTON_MIDDLE;
159 if (Event_Get_Button_Right(evdev))
160 hwstate.buttons_down |= GESTURES_BUTTON_RIGHT;
162 GestureInterpreterPushHardwareState(interpreter_, &hwstate);
165 void GestureInterpreterLibevdevCros::OnGestureReady(const Gesture* gesture) {
166 switch (gesture->type) {
167 case kGestureTypeMove:
168 OnGestureMove(gesture, &gesture->details.move);
169 break;
170 case kGestureTypeScroll:
171 OnGestureScroll(gesture, &gesture->details.scroll);
172 break;
173 case kGestureTypeButtonsChange:
174 OnGestureButtonsChange(gesture, &gesture->details.buttons);
175 break;
176 case kGestureTypeContactInitiated:
177 OnGestureContactInitiated(gesture);
178 break;
179 case kGestureTypeFling:
180 OnGestureFling(gesture, &gesture->details.fling);
181 break;
182 case kGestureTypeSwipe:
183 OnGestureSwipe(gesture, &gesture->details.swipe);
184 break;
185 case kGestureTypeSwipeLift:
186 OnGestureSwipeLift(gesture, &gesture->details.swipe_lift);
187 break;
188 case kGestureTypePinch:
189 OnGesturePinch(gesture, &gesture->details.pinch);
190 break;
191 case kGestureTypeMetrics:
192 OnGestureMetrics(gesture, &gesture->details.metrics);
193 break;
194 default:
195 LOG(WARNING) << base::StringPrintf("Unrecognized gesture type (%u)",
196 gesture->type);
197 break;
201 void GestureInterpreterLibevdevCros::OnGestureMove(const Gesture* gesture,
202 const GestureMove* move) {
203 DVLOG(3) << base::StringPrintf("Gesture Move: (%f, %f) [%f, %f]",
204 move->dx,
205 move->dy,
206 move->ordinal_dx,
207 move->ordinal_dy);
208 if (!cursor_)
209 return; // No cursor!
211 cursor_->MoveCursor(gfx::Vector2dF(move->dx, move->dy));
212 // TODO(spang): Use move->ordinal_dx, move->ordinal_dy
213 // TODO(spang): Use move->start_time, move->end_time
214 MouseEvent event(ET_MOUSE_MOVED,
215 cursor_->location(),
216 cursor_->location(),
217 modifiers_->GetModifierFlags(),
218 /* changed_button_flags */ 0);
219 Dispatch(&event);
222 void GestureInterpreterLibevdevCros::OnGestureScroll(
223 const Gesture* gesture,
224 const GestureScroll* scroll) {
225 DVLOG(3) << base::StringPrintf("Gesture Scroll: (%f, %f) [%f, %f]",
226 scroll->dx,
227 scroll->dy,
228 scroll->ordinal_dx,
229 scroll->ordinal_dy);
230 if (!cursor_)
231 return; // No cursor!
233 // TODO(spang): Support SetNaturalScroll
234 // TODO(spang): Use scroll->start_time
235 ScrollEvent event(ET_SCROLL,
236 cursor_->location(),
237 StimeToTimedelta(gesture->end_time),
238 modifiers_->GetModifierFlags(),
239 scroll->dx,
240 scroll->dy,
241 scroll->ordinal_dx,
242 scroll->ordinal_dy,
243 kGestureScrollFingerCount);
244 Dispatch(&event);
247 void GestureInterpreterLibevdevCros::OnGestureButtonsChange(
248 const Gesture* gesture,
249 const GestureButtonsChange* buttons) {
250 DVLOG(3) << base::StringPrintf("Gesture Button Change: down=0x%02x up=0x%02x",
251 buttons->down,
252 buttons->up);
254 if (!cursor_)
255 return; // No cursor!
257 // HACK for disabling TTC (actually, all clicks) on hidden cursor.
258 // This is normally plumbed via properties and can be removed soon.
259 // TODO(spang): Remove this.
260 if (buttons->down == GESTURES_BUTTON_LEFT &&
261 buttons->up == GESTURES_BUTTON_LEFT &&
262 !cursor_->IsCursorVisible())
263 return;
265 // TODO(spang): Use buttons->start_time, buttons->end_time
266 if (buttons->down & GESTURES_BUTTON_LEFT)
267 DispatchMouseButton(EVDEV_MODIFIER_LEFT_MOUSE_BUTTON, true);
268 if (buttons->down & GESTURES_BUTTON_MIDDLE)
269 DispatchMouseButton(EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON, true);
270 if (buttons->down & GESTURES_BUTTON_RIGHT)
271 DispatchMouseButton(EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON, true);
272 if (buttons->up & GESTURES_BUTTON_LEFT)
273 DispatchMouseButton(EVDEV_MODIFIER_LEFT_MOUSE_BUTTON, false);
274 if (buttons->up & GESTURES_BUTTON_MIDDLE)
275 DispatchMouseButton(EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON, false);
276 if (buttons->up & GESTURES_BUTTON_RIGHT)
277 DispatchMouseButton(EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON, false);
280 void GestureInterpreterLibevdevCros::OnGestureContactInitiated(
281 const Gesture* gesture) {
282 // TODO(spang): handle contact initiated.
285 void GestureInterpreterLibevdevCros::OnGestureFling(const Gesture* gesture,
286 const GestureFling* fling) {
287 DVLOG(3) << base::StringPrintf(
288 "Gesture Fling: (%f, %f) [%f, %f] fling_state=%d",
289 fling->vx,
290 fling->vy,
291 fling->ordinal_vx,
292 fling->ordinal_vy,
293 fling->fling_state);
295 if (!cursor_)
296 return; // No cursor!
298 EventType type =
299 (fling->fling_state == GESTURES_FLING_START ? ET_SCROLL_FLING_START
300 : ET_SCROLL_FLING_CANCEL);
302 // Fling is like 2-finger scrolling but with velocity instead of displacement.
303 ScrollEvent event(type,
304 cursor_->location(),
305 StimeToTimedelta(gesture->end_time),
306 modifiers_->GetModifierFlags(),
307 fling->vx,
308 fling->vy,
309 fling->ordinal_vx,
310 fling->ordinal_vy,
311 kGestureScrollFingerCount);
312 Dispatch(&event);
315 void GestureInterpreterLibevdevCros::OnGestureSwipe(const Gesture* gesture,
316 const GestureSwipe* swipe) {
317 DVLOG(3) << base::StringPrintf("Gesture Swipe: (%f, %f) [%f, %f]",
318 swipe->dx,
319 swipe->dy,
320 swipe->ordinal_dx,
321 swipe->ordinal_dy);
323 if (!cursor_)
324 return; // No cursor!
326 // Swipe is 3-finger scrolling.
327 ScrollEvent event(ET_SCROLL,
328 cursor_->location(),
329 StimeToTimedelta(gesture->end_time),
330 modifiers_->GetModifierFlags(),
331 swipe->dx,
332 swipe->dy,
333 swipe->ordinal_dx,
334 swipe->ordinal_dy,
335 kGestureSwipeFingerCount);
336 Dispatch(&event);
339 void GestureInterpreterLibevdevCros::OnGestureSwipeLift(
340 const Gesture* gesture,
341 const GestureSwipeLift* swipelift) {
342 DVLOG(3) << base::StringPrintf("Gesture Swipe Lift");
344 if (!cursor_)
345 return; // No cursor!
347 // Turn a swipe lift into a fling start.
348 // TODO(spang): Figure out why and put it in this comment.
350 ScrollEvent event(ET_SCROLL_FLING_START,
351 cursor_->location(),
352 StimeToTimedelta(gesture->end_time),
353 modifiers_->GetModifierFlags(),
354 /* x_offset */ 0,
355 /* y_offset */ 0,
356 /* x_offset_ordinal */ 0,
357 /* y_offset_ordinal */ 0,
358 kGestureScrollFingerCount);
359 Dispatch(&event);
363 void GestureInterpreterLibevdevCros::OnGesturePinch(const Gesture* gesture,
364 const GesturePinch* pinch) {
365 DVLOG(3) << base::StringPrintf(
366 "Gesture Pinch: dz=%f [%f]", pinch->dz, pinch->ordinal_dz);
368 if (!cursor_)
369 return; // No cursor!
371 NOTIMPLEMENTED();
374 void GestureInterpreterLibevdevCros::OnGestureMetrics(
375 const Gesture* gesture,
376 const GestureMetrics* metrics) {
377 DVLOG(3) << base::StringPrintf("Gesture Metrics: [%f, %f] type=%d",
378 metrics->data[0],
379 metrics->data[1],
380 metrics->type);
381 NOTIMPLEMENTED();
384 void GestureInterpreterLibevdevCros::Dispatch(Event* event) {
385 dispatch_callback_.Run(event);
388 void GestureInterpreterLibevdevCros::DispatchMouseButton(unsigned int modifier,
389 bool down) {
390 const gfx::PointF& loc = cursor_->location();
391 int flag = modifiers_->GetEventFlagFromModifier(modifier);
392 EventType type = (down ? ET_MOUSE_PRESSED : ET_MOUSE_RELEASED);
393 modifiers_->UpdateModifier(modifier, down);
394 MouseEvent event(type, loc, loc, modifiers_->GetModifierFlags() | flag, flag);
396 // This hack is necessary to trigger setting the repeat count.
397 // TODO(spang): Fix it.
398 MouseEvent event2(&event);
399 Dispatch(&event2);
402 } // namespace ui