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_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"
25 // Convert libevdev device class to libgestures device class.
26 GestureInterpreterDeviceClass GestureDeviceClass(Evdev* evdev) {
27 switch (evdev->info.evdev_class) {
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;
37 return GESTURES_DEVCLASS_UNKNOWN;
41 // Convert libevdev state to libgestures hardware properties.
42 HardwareProperties GestureHardwareProperties(
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);
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);
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);
78 // Number of fingers for scroll gestures.
79 const int kGestureScrollFingerCount = 2;
81 // Number of fingers for swipe gestures.
82 const int kGestureSwipeFingerCount = 3;
86 GestureInterpreterLibevdevCros::GestureInterpreterLibevdevCros(
88 EventModifiersEvdev* modifiers,
89 CursorDelegateEvdev* cursor,
90 KeyboardEvdev* keyboard,
91 GesturePropertyProvider* property_provider,
92 const EventDispatchCallback& callback)
94 modifiers_(modifiers),
97 property_provider_(property_provider),
98 dispatch_callback_(callback),
101 device_properties_(new GestureDeviceProperties) {
102 memset(&prev_key_state_, 0, sizeof(prev_key_state_));
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).
110 // Clean-up if the gesture interpreter has been successfully created.
113 GestureInterpreterSetCallback(interpreter_, NULL, NULL);
114 GestureInterpreterSetPropProvider(interpreter_, NULL, NULL);
115 GestureInterpreterSetTimerProvider(interpreter_, NULL, NULL);
116 DeleteGestureInterpreter(interpreter_);
120 // Unregister device from the gesture property provider.
121 GesturesPropFunctionsWrapper::UnregisterDevice(this);
124 void GestureInterpreterLibevdevCros::OnLibEvdevCrosOpen(
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;
130 // Set device pointer and initialize properties.
132 GesturesPropFunctionsWrapper::InitializeDeviceProperties(
133 this, device_properties_.get());
134 HardwareProperties hwprops =
135 GestureHardwareProperties(evdev, device_properties_.get());
136 GestureInterpreterDeviceClass devclass = GestureDeviceClass(evdev);
138 // Create & initialize GestureInterpreter.
139 DCHECK(!interpreter_);
140 interpreter_ = NewGestureInterpreter();
141 GestureInterpreterSetPropProvider(
143 const_cast<GesturesPropProvider*>(&kGesturePropProvider),
145 GestureInterpreterInitialize(interpreter_, devclass);
146 GestureInterpreterSetHardwareProperties(interpreter_, &hwprops);
147 GestureInterpreterSetTimerProvider(
149 const_cast<GesturesTimerProvider*>(&kGestureTimerProvider),
151 GestureInterpreterSetCallback(interpreter_, OnGestureReadyHelper, this);
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);
160 HardwareState hwstate;
161 memset(&hwstate, 0, sizeof(hwstate));
162 hwstate.timestamp = StimeFromTimeval(&time);
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;
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)
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;
189 hwstate.touch_cnt = Event_Get_Touch_Count(evdev);
190 hwstate.finger_cnt = current_finger;
191 hwstate.fingers = fingers;
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;
201 GestureInterpreterPushHardwareState(interpreter_, &hwstate);
204 void GestureInterpreterLibevdevCros::OnGestureReady(const Gesture* gesture) {
205 switch (gesture->type) {
206 case kGestureTypeMove:
207 OnGestureMove(gesture, &gesture->details.move);
209 case kGestureTypeScroll:
210 OnGestureScroll(gesture, &gesture->details.scroll);
212 case kGestureTypeButtonsChange:
213 OnGestureButtonsChange(gesture, &gesture->details.buttons);
215 case kGestureTypeContactInitiated:
216 OnGestureContactInitiated(gesture);
218 case kGestureTypeFling:
219 OnGestureFling(gesture, &gesture->details.fling);
221 case kGestureTypeSwipe:
222 OnGestureSwipe(gesture, &gesture->details.swipe);
224 case kGestureTypeSwipeLift:
225 OnGestureSwipeLift(gesture, &gesture->details.swipe_lift);
227 case kGestureTypePinch:
228 OnGesturePinch(gesture, &gesture->details.pinch);
230 case kGestureTypeMetrics:
231 OnGestureMetrics(gesture, &gesture->details.metrics);
234 LOG(WARNING) << base::StringPrintf("Unrecognized gesture type (%u)",
240 void GestureInterpreterLibevdevCros::OnGestureMove(const Gesture* gesture,
241 const GestureMove* move) {
242 DVLOG(3) << base::StringPrintf("Gesture Move: (%f, %f) [%f, %f]",
248 return; // No cursor!
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,
256 modifiers_->GetModifierFlags(),
257 /* changed_button_flags */ 0)));
260 void GestureInterpreterLibevdevCros::OnGestureScroll(
261 const Gesture* gesture,
262 const GestureScroll* scroll) {
263 DVLOG(3) << base::StringPrintf("Gesture Scroll: (%f, %f) [%f, %f]",
269 return; // No cursor!
271 // TODO(spang): Support SetNaturalScroll
272 // TODO(spang): Use scroll->start_time
273 Dispatch(make_scoped_ptr(new ScrollEvent(ET_SCROLL,
275 StimeToTimedelta(gesture->end_time),
276 modifiers_->GetModifierFlags(),
281 kGestureScrollFingerCount)));
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",
292 return; // No cursor!
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())
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);
317 void GestureInterpreterLibevdevCros::OnGestureContactInitiated(
318 const Gesture* gesture) {
319 // TODO(spang): handle contact initiated.
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",
333 return; // No cursor!
336 (fling->fling_state == GESTURES_FLING_START ? ET_SCROLL_FLING_START
337 : ET_SCROLL_FLING_CANCEL);
339 // Fling is like 2-finger scrolling but with velocity instead of displacement.
340 Dispatch(make_scoped_ptr(new ScrollEvent(type,
342 StimeToTimedelta(gesture->end_time),
343 modifiers_->GetModifierFlags(),
348 kGestureScrollFingerCount)));
351 void GestureInterpreterLibevdevCros::OnGestureSwipe(const Gesture* gesture,
352 const GestureSwipe* swipe) {
353 DVLOG(3) << base::StringPrintf("Gesture Swipe: (%f, %f) [%f, %f]",
360 return; // No cursor!
362 // Swipe is 3-finger scrolling.
363 Dispatch(make_scoped_ptr(new ScrollEvent(ET_SCROLL,
365 StimeToTimedelta(gesture->end_time),
366 modifiers_->GetModifierFlags(),
371 kGestureSwipeFingerCount)));
374 void GestureInterpreterLibevdevCros::OnGestureSwipeLift(
375 const Gesture* gesture,
376 const GestureSwipeLift* swipelift) {
377 DVLOG(3) << base::StringPrintf("Gesture Swipe Lift");
380 return; // No cursor!
382 // Turn a swipe lift into a fling start.
383 // TODO(spang): Figure out why and put it in this comment.
385 Dispatch(make_scoped_ptr(new ScrollEvent(ET_SCROLL_FLING_START,
387 StimeToTimedelta(gesture->end_time),
388 modifiers_->GetModifierFlags(),
391 /* x_offset_ordinal */ 0,
392 /* y_offset_ordinal */ 0,
393 kGestureScrollFingerCount)));
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);
402 return; // No cursor!
407 void GestureInterpreterLibevdevCros::OnGestureMetrics(
408 const Gesture* gesture,
409 const GestureMetrics* metrics) {
410 DVLOG(3) << base::StringPrintf("Gesture Metrics: [%f, %f] type=%d",
417 void GestureInterpreterLibevdevCros::Dispatch(scoped_ptr<Event> event) {
418 dispatch_callback_.Run(event.Pass());
421 void GestureInterpreterLibevdevCros::DispatchMouseButton(unsigned int modifier,
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)));
431 void GestureInterpreterLibevdevCros::DispatchChangedKeys(Evdev* evdev,
432 const timeval& time) {
433 unsigned long key_state_diff[EVDEV_BITS_TO_LONGS(KEY_CNT)];
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];
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);
444 // Mouse buttons are handled by DispatchMouseButton.
445 if (key >= BTN_MOUSE && key < BTN_JOYSTICK)
448 // Ignore digi buttons (e.g. BTN_TOOL_FINGER).
449 if (key >= BTN_DIGI && key < BTN_WHEEL)
452 // Dispatch key press or release to keyboard.
453 keyboard_->OnKeyChange(key, value);
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];