Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / ui / events / ozone / evdev / libgestures_glue / gesture_interpreter_libevdev_cros.cc
blob0947ad48cc86031937bc2663a9c6d9e81cbc3a12
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>
9 #include <linux/input.h>
11 #include "base/strings/stringprintf.h"
12 #include "base/timer/timer.h"
13 #include "ui/events/event.h"
14 #include "ui/events/event_utils.h"
15 #include "ui/events/keycodes/dom/keycode_converter.h"
16 #include "ui/events/ozone/evdev/cursor_delegate_evdev.h"
17 #include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h"
18 #include "ui/events/ozone/evdev/event_device_info.h"
19 #include "ui/events/ozone/evdev/event_device_util.h"
20 #include "ui/events/ozone/evdev/keyboard_util_evdev.h"
21 #include "ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.h"
22 #include "ui/events/ozone/evdev/libgestures_glue/gesture_timer_provider.h"
23 #include "ui/gfx/geometry/point_f.h"
25 namespace ui {
27 namespace {
29 // Convert libevdev device class to libgestures device class.
30 GestureInterpreterDeviceClass GestureDeviceClass(Evdev* evdev) {
31 switch (evdev->info.evdev_class) {
32 case EvdevClassMouse:
33 return GESTURES_DEVCLASS_MOUSE;
34 case EvdevClassMultitouchMouse:
35 return GESTURES_DEVCLASS_MULTITOUCH_MOUSE;
36 case EvdevClassTouchpad:
37 return GESTURES_DEVCLASS_TOUCHPAD;
38 case EvdevClassTouchscreen:
39 return GESTURES_DEVCLASS_TOUCHSCREEN;
40 default:
41 return GESTURES_DEVCLASS_UNKNOWN;
45 // Convert libevdev state to libgestures hardware properties.
46 HardwareProperties GestureHardwareProperties(
47 Evdev* evdev,
48 const GestureDeviceProperties* props) {
49 HardwareProperties hwprops;
50 hwprops.left = props->area_left;
51 hwprops.top = props->area_top;
52 hwprops.right = props->area_right;
53 hwprops.bottom = props->area_bottom;
54 hwprops.res_x = props->res_x;
55 hwprops.res_y = props->res_y;
56 hwprops.screen_x_dpi = 133;
57 hwprops.screen_y_dpi = 133;
58 hwprops.orientation_minimum = props->orientation_minimum;
59 hwprops.orientation_maximum = props->orientation_maximum;
60 hwprops.max_finger_cnt = Event_Get_Slot_Count(evdev);
61 hwprops.max_touch_cnt = Event_Get_Touch_Count_Max(evdev);
62 hwprops.supports_t5r2 = Event_Get_T5R2(evdev);
63 hwprops.support_semi_mt = Event_Get_Semi_MT(evdev);
64 /* buttonpad means a physical button under the touch surface */
65 hwprops.is_button_pad = Event_Get_Button_Pad(evdev);
66 hwprops.has_wheel = EvdevBitIsSet(evdev->info.rel_bitmask, REL_WHEEL) ||
67 EvdevBitIsSet(evdev->info.rel_bitmask, REL_HWHEEL);
69 return hwprops;
72 // Callback from libgestures when a gesture is ready.
73 void OnGestureReadyHelper(void* client_data, const Gesture* gesture) {
74 GestureInterpreterLibevdevCros* interpreter =
75 static_cast<GestureInterpreterLibevdevCros*>(client_data);
76 interpreter->OnGestureReady(gesture);
79 // Convert gestures timestamp (stime_t) to ui::Event timestamp.
80 base::TimeDelta StimeToTimedelta(stime_t timestamp) {
81 return base::TimeDelta::FromMicroseconds(timestamp *
82 base::Time::kMicrosecondsPerSecond);
85 // Number of fingers for scroll gestures.
86 const int kGestureScrollFingerCount = 2;
88 // Number of fingers for swipe gestures.
89 const int kGestureSwipeFingerCount = 3;
91 } // namespace
93 GestureInterpreterLibevdevCros::GestureInterpreterLibevdevCros(
94 int id,
95 CursorDelegateEvdev* cursor,
96 GesturePropertyProvider* property_provider,
97 DeviceEventDispatcherEvdev* dispatcher)
98 : id_(id),
99 cursor_(cursor),
100 property_provider_(property_provider),
101 dispatcher_(dispatcher),
102 device_properties_(new GestureDeviceProperties) {
103 memset(&prev_key_state_, 0, sizeof(prev_key_state_));
106 GestureInterpreterLibevdevCros::~GestureInterpreterLibevdevCros() {
107 // Note that this destructor got called after the evdev device node has been
108 // closed. Therefore, all clean-up codes here shouldn't depend on the device
109 // information (except for the pointer address itself).
111 // Clean-up if the gesture interpreter has been successfully created.
112 if (interpreter_) {
113 // Unset callbacks.
114 GestureInterpreterSetCallback(interpreter_, NULL, NULL);
115 GestureInterpreterSetPropProvider(interpreter_, NULL, NULL);
116 GestureInterpreterSetTimerProvider(interpreter_, NULL, NULL);
117 DeleteGestureInterpreter(interpreter_);
118 interpreter_ = NULL;
121 // Unregister device from the gesture property provider.
122 GesturesPropFunctionsWrapper::UnregisterDevice(this);
125 void GestureInterpreterLibevdevCros::OnLibEvdevCrosOpen(
126 Evdev* evdev,
127 EventStateRec* evstate) {
128 DCHECK(evdev->info.is_monotonic) << "libevdev must use monotonic timestamps";
129 VLOG(9) << "HACK DO NOT REMOVE OR LINK WILL FAIL" << (void*)gestures_log;
131 // Set device pointer and initialize properties.
132 evdev_ = evdev;
133 GesturesPropFunctionsWrapper::InitializeDeviceProperties(
134 this, device_properties_.get());
135 HardwareProperties hwprops =
136 GestureHardwareProperties(evdev, device_properties_.get());
137 GestureInterpreterDeviceClass devclass = GestureDeviceClass(evdev);
138 is_mouse_ = property_provider_->IsDeviceIdOfType(id_, DT_MOUSE);
140 // Create & initialize GestureInterpreter.
141 DCHECK(!interpreter_);
142 interpreter_ = NewGestureInterpreter();
143 GestureInterpreterSetPropProvider(
144 interpreter_,
145 const_cast<GesturesPropProvider*>(&kGesturePropProvider),
146 this);
147 GestureInterpreterInitialize(interpreter_, devclass);
148 GestureInterpreterSetHardwareProperties(interpreter_, &hwprops);
149 GestureInterpreterSetTimerProvider(
150 interpreter_,
151 const_cast<GesturesTimerProvider*>(&kGestureTimerProvider),
152 this);
153 GestureInterpreterSetCallback(interpreter_, OnGestureReadyHelper, this);
156 void GestureInterpreterLibevdevCros::OnLibEvdevCrosEvent(Evdev* evdev,
157 EventStateRec* evstate,
158 const timeval& time) {
159 stime_t timestamp = StimeFromTimeval(&time);
161 // If the device has keys on it, dispatch any presses/release.
162 DispatchChangedKeys(evdev->key_state_bitmask, timestamp);
164 HardwareState hwstate;
165 memset(&hwstate, 0, sizeof(hwstate));
166 hwstate.timestamp = timestamp;
168 // Mouse.
169 hwstate.rel_x = evstate->rel_x;
170 hwstate.rel_y = evstate->rel_y;
171 hwstate.rel_wheel = evstate->rel_wheel;
172 hwstate.rel_hwheel = evstate->rel_hwheel;
174 // Touch.
175 FingerState fingers[Event_Get_Slot_Count(evdev)];
176 memset(&fingers, 0, sizeof(fingers));
177 int current_finger = 0;
178 for (int i = 0; i < evstate->slot_count; i++) {
179 MtSlotPtr slot = &evstate->slots[i];
180 if (slot->tracking_id == -1)
181 continue;
182 fingers[current_finger].touch_major = slot->touch_major;
183 fingers[current_finger].touch_minor = slot->touch_minor;
184 fingers[current_finger].width_major = slot->width_major;
185 fingers[current_finger].width_minor = slot->width_minor;
186 fingers[current_finger].pressure = slot->pressure;
187 fingers[current_finger].orientation = slot->orientation;
188 fingers[current_finger].position_x = slot->position_x;
189 fingers[current_finger].position_y = slot->position_y;
190 fingers[current_finger].tracking_id = slot->tracking_id;
191 current_finger++;
193 hwstate.touch_cnt = Event_Get_Touch_Count(evdev);
194 hwstate.finger_cnt = current_finger;
195 hwstate.fingers = fingers;
197 // Buttons.
198 if (Event_Get_Button_Left(evdev))
199 hwstate.buttons_down |= GESTURES_BUTTON_LEFT;
200 if (Event_Get_Button_Middle(evdev))
201 hwstate.buttons_down |= GESTURES_BUTTON_MIDDLE;
202 if (Event_Get_Button_Right(evdev))
203 hwstate.buttons_down |= GESTURES_BUTTON_RIGHT;
204 if (Event_Get_Button(evdev, BTN_SIDE) ||
205 Event_Get_Button(evdev, BTN_BACK)) {
206 hwstate.buttons_down |= GESTURES_BUTTON_BACK;
208 if (Event_Get_Button(evdev, BTN_EXTRA) ||
209 Event_Get_Button(evdev, BTN_FORWARD)) {
210 hwstate.buttons_down |= GESTURES_BUTTON_FORWARD;
213 GestureInterpreterPushHardwareState(interpreter_, &hwstate);
216 void GestureInterpreterLibevdevCros::OnLibEvdevCrosStopped(
217 Evdev* evdev,
218 EventStateRec* state) {
219 stime_t timestamp = StimeNow();
221 ReleaseKeys(timestamp);
222 ReleaseMouseButtons(timestamp);
225 void GestureInterpreterLibevdevCros::OnGestureReady(const Gesture* gesture) {
226 switch (gesture->type) {
227 case kGestureTypeMove:
228 OnGestureMove(gesture, &gesture->details.move);
229 break;
230 case kGestureTypeScroll:
231 OnGestureScroll(gesture, &gesture->details.scroll);
232 break;
233 case kGestureTypeButtonsChange:
234 OnGestureButtonsChange(gesture, &gesture->details.buttons);
235 break;
236 case kGestureTypeContactInitiated:
237 OnGestureContactInitiated(gesture);
238 break;
239 case kGestureTypeFling:
240 OnGestureFling(gesture, &gesture->details.fling);
241 break;
242 case kGestureTypeSwipe:
243 OnGestureSwipe(gesture, &gesture->details.swipe);
244 break;
245 case kGestureTypeSwipeLift:
246 OnGestureSwipeLift(gesture, &gesture->details.swipe_lift);
247 break;
248 case kGestureTypePinch:
249 OnGesturePinch(gesture, &gesture->details.pinch);
250 break;
251 case kGestureTypeMetrics:
252 OnGestureMetrics(gesture, &gesture->details.metrics);
253 break;
254 default:
255 LOG(WARNING) << base::StringPrintf("Unrecognized gesture type (%u)",
256 gesture->type);
257 break;
261 void GestureInterpreterLibevdevCros::OnGestureMove(const Gesture* gesture,
262 const GestureMove* move) {
263 DVLOG(3) << base::StringPrintf("Gesture Move: (%f, %f) [%f, %f]",
264 move->dx,
265 move->dy,
266 move->ordinal_dx,
267 move->ordinal_dy);
268 if (!cursor_)
269 return; // No cursor!
271 cursor_->MoveCursor(gfx::Vector2dF(move->dx, move->dy));
272 // TODO(spang): Use move->ordinal_dx, move->ordinal_dy
273 dispatcher_->DispatchMouseMoveEvent(MouseMoveEventParams(
274 id_, cursor_->GetLocation(), StimeToTimedelta(gesture->end_time)));
277 void GestureInterpreterLibevdevCros::OnGestureScroll(
278 const Gesture* gesture,
279 const GestureScroll* scroll) {
280 DVLOG(3) << base::StringPrintf("Gesture Scroll: (%f, %f) [%f, %f]",
281 scroll->dx,
282 scroll->dy,
283 scroll->ordinal_dx,
284 scroll->ordinal_dy);
285 if (!cursor_)
286 return; // No cursor!
288 if (is_mouse_) {
289 dispatcher_->DispatchMouseWheelEvent(MouseWheelEventParams(
290 id_, cursor_->GetLocation(), gfx::Vector2d(scroll->dx, scroll->dy),
291 StimeToTimedelta(gesture->end_time)));
292 } else {
293 dispatcher_->DispatchScrollEvent(ScrollEventParams(
294 id_, ET_SCROLL, cursor_->GetLocation(),
295 gfx::Vector2dF(scroll->dx, scroll->dy),
296 gfx::Vector2dF(scroll->ordinal_dx, scroll->ordinal_dy),
297 kGestureScrollFingerCount, StimeToTimedelta(gesture->end_time)));
301 void GestureInterpreterLibevdevCros::OnGestureButtonsChange(
302 const Gesture* gesture,
303 const GestureButtonsChange* buttons) {
304 DVLOG(3) << base::StringPrintf("Gesture Button Change: down=0x%02x up=0x%02x",
305 buttons->down,
306 buttons->up);
308 if (!cursor_)
309 return; // No cursor!
311 DispatchChangedMouseButtons(buttons->down, true, gesture->end_time);
312 DispatchChangedMouseButtons(buttons->up, false, gesture->end_time);
315 void GestureInterpreterLibevdevCros::OnGestureContactInitiated(
316 const Gesture* gesture) {
317 // TODO(spang): handle contact initiated.
320 void GestureInterpreterLibevdevCros::OnGestureFling(const Gesture* gesture,
321 const GestureFling* fling) {
322 DVLOG(3) << base::StringPrintf(
323 "Gesture Fling: (%f, %f) [%f, %f] fling_state=%d",
324 fling->vx,
325 fling->vy,
326 fling->ordinal_vx,
327 fling->ordinal_vy,
328 fling->fling_state);
330 if (!cursor_)
331 return; // No cursor!
333 EventType type =
334 (fling->fling_state == GESTURES_FLING_START ? ET_SCROLL_FLING_START
335 : ET_SCROLL_FLING_CANCEL);
337 // Fling is like 2-finger scrolling but with velocity instead of displacement.
338 dispatcher_->DispatchScrollEvent(ScrollEventParams(
339 id_, type, cursor_->GetLocation(), gfx::Vector2dF(fling->vx, fling->vy),
340 gfx::Vector2dF(fling->ordinal_vx, fling->ordinal_vy),
341 kGestureScrollFingerCount, StimeToTimedelta(gesture->end_time)));
344 void GestureInterpreterLibevdevCros::OnGestureSwipe(const Gesture* gesture,
345 const GestureSwipe* swipe) {
346 DVLOG(3) << base::StringPrintf("Gesture Swipe: (%f, %f) [%f, %f]",
347 swipe->dx,
348 swipe->dy,
349 swipe->ordinal_dx,
350 swipe->ordinal_dy);
352 if (!cursor_)
353 return; // No cursor!
355 // Swipe is 3-finger scrolling.
356 dispatcher_->DispatchScrollEvent(ScrollEventParams(
357 id_, ET_SCROLL, cursor_->GetLocation(),
358 gfx::Vector2dF(swipe->dx, swipe->dy),
359 gfx::Vector2dF(swipe->ordinal_dx, swipe->ordinal_dy),
360 kGestureSwipeFingerCount, StimeToTimedelta(gesture->end_time)));
363 void GestureInterpreterLibevdevCros::OnGestureSwipeLift(
364 const Gesture* gesture,
365 const GestureSwipeLift* swipelift) {
366 DVLOG(3) << base::StringPrintf("Gesture Swipe Lift");
368 if (!cursor_)
369 return; // No cursor!
371 // Turn a swipe lift into a fling start.
372 // TODO(spang): Figure out why and put it in this comment.
374 dispatcher_->DispatchScrollEvent(ScrollEventParams(
375 id_, ET_SCROLL_FLING_START, cursor_->GetLocation(),
376 gfx::Vector2dF() /* delta */, gfx::Vector2dF() /* ordinal_delta */,
377 kGestureScrollFingerCount, StimeToTimedelta(gesture->end_time)));
380 void GestureInterpreterLibevdevCros::OnGesturePinch(const Gesture* gesture,
381 const GesturePinch* pinch) {
382 DVLOG(3) << base::StringPrintf(
383 "Gesture Pinch: dz=%f [%f]", pinch->dz, pinch->ordinal_dz);
385 if (!cursor_)
386 return; // No cursor!
388 NOTIMPLEMENTED();
391 void GestureInterpreterLibevdevCros::OnGestureMetrics(
392 const Gesture* gesture,
393 const GestureMetrics* metrics) {
394 DVLOG(3) << base::StringPrintf("Gesture Metrics: [%f, %f] type=%d",
395 metrics->data[0],
396 metrics->data[1],
397 metrics->type);
399 // TODO(spang): Hook up metrics.
402 void GestureInterpreterLibevdevCros::DispatchChangedMouseButtons(
403 unsigned int changed_buttons, bool down, stime_t time) {
404 if (changed_buttons & GESTURES_BUTTON_LEFT)
405 DispatchMouseButton(BTN_LEFT, down, time);
406 if (changed_buttons & GESTURES_BUTTON_MIDDLE)
407 DispatchMouseButton(BTN_MIDDLE, down, time);
408 if (changed_buttons & GESTURES_BUTTON_RIGHT)
409 DispatchMouseButton(BTN_RIGHT, down, time);
410 if (changed_buttons & GESTURES_BUTTON_BACK)
411 DispatchMouseButton(BTN_BACK, down, time);
412 if (changed_buttons & GESTURES_BUTTON_FORWARD)
413 DispatchMouseButton(BTN_FORWARD, down, time);
416 void GestureInterpreterLibevdevCros::DispatchMouseButton(unsigned int button,
417 bool down,
418 stime_t time) {
419 if (!SetMouseButtonState(button, down))
420 return; // No change.
422 bool allow_remap = is_mouse_;
423 dispatcher_->DispatchMouseButtonEvent(
424 MouseButtonEventParams(id_, cursor_->GetLocation(), button, down,
425 allow_remap, StimeToTimedelta(time)));
428 void GestureInterpreterLibevdevCros::DispatchChangedKeys(
429 unsigned long* new_key_state,
430 stime_t timestamp) {
431 unsigned long key_state_diff[EVDEV_BITS_TO_LONGS(KEY_CNT)];
433 // Find changed keys.
434 for (unsigned long i = 0; i < arraysize(key_state_diff); ++i)
435 key_state_diff[i] = new_key_state[i] ^ prev_key_state_[i];
437 // Dispatch events for changed keys.
438 for (unsigned long key = 0; key < KEY_CNT; ++key) {
439 if (EvdevBitIsSet(key_state_diff, key)) {
440 bool value = EvdevBitIsSet(new_key_state, key);
442 // Mouse buttons are handled by DispatchMouseButton.
443 if (key >= BTN_MOUSE && key < BTN_JOYSTICK)
444 continue;
446 // Ignore digi buttons (e.g. BTN_TOOL_FINGER).
447 if (key >= BTN_DIGI && key < BTN_WHEEL)
448 continue;
450 // Dispatch key press or release to keyboard.
451 dispatcher_->DispatchKeyEvent(
452 KeyEventParams(id_, key, value, false /* suppress_auto_repeat */,
453 StimeToTimedelta(timestamp)));
457 // Update internal key state.
458 for (unsigned long i = 0; i < EVDEV_BITS_TO_LONGS(KEY_CNT); ++i)
459 prev_key_state_[i] = new_key_state[i];
462 void GestureInterpreterLibevdevCros::ReleaseKeys(stime_t timestamp) {
463 unsigned long new_key_state[EVDEV_BITS_TO_LONGS(KEY_CNT)];
464 memset(&new_key_state, 0, sizeof(new_key_state));
466 DispatchChangedKeys(new_key_state, timestamp);
469 bool GestureInterpreterLibevdevCros::SetMouseButtonState(unsigned int button,
470 bool down) {
471 DCHECK(BTN_MOUSE <= button && button < BTN_JOYSTICK);
472 int button_offset = button - BTN_MOUSE;
474 if (mouse_button_state_.test(button_offset) == down)
475 return false;
477 // State transition: !(down) -> (down)
478 mouse_button_state_.set(button_offset, down);
480 return true;
483 void GestureInterpreterLibevdevCros::ReleaseMouseButtons(stime_t timestamp) {
484 DispatchMouseButton(BTN_LEFT, false /* down */, timestamp);
485 DispatchMouseButton(BTN_MIDDLE, false /* down */, timestamp);
486 DispatchMouseButton(BTN_RIGHT, false /* down */, timestamp);
487 DispatchMouseButton(BTN_BACK, false /* down */, timestamp);
488 DispatchMouseButton(BTN_FORWARD, false /* down */, timestamp);
491 } // namespace ui