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"
29 // Convert libevdev device class to libgestures device class.
30 GestureInterpreterDeviceClass
GestureDeviceClass(Evdev
* evdev
) {
31 switch (evdev
->info
.evdev_class
) {
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
;
41 return GESTURES_DEVCLASS_UNKNOWN
;
45 // Convert libevdev state to libgestures hardware properties.
46 HardwareProperties
GestureHardwareProperties(
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
);
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;
93 GestureInterpreterLibevdevCros::GestureInterpreterLibevdevCros(
95 CursorDelegateEvdev
* cursor
,
96 GesturePropertyProvider
* property_provider
,
97 DeviceEventDispatcherEvdev
* dispatcher
)
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.
114 GestureInterpreterSetCallback(interpreter_
, NULL
, NULL
);
115 GestureInterpreterSetPropProvider(interpreter_
, NULL
, NULL
);
116 GestureInterpreterSetTimerProvider(interpreter_
, NULL
, NULL
);
117 DeleteGestureInterpreter(interpreter_
);
121 // Unregister device from the gesture property provider.
122 GesturesPropFunctionsWrapper::UnregisterDevice(this);
125 void GestureInterpreterLibevdevCros::OnLibEvdevCrosOpen(
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.
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(
145 const_cast<GesturesPropProvider
*>(&kGesturePropProvider
),
147 GestureInterpreterInitialize(interpreter_
, devclass
);
148 GestureInterpreterSetHardwareProperties(interpreter_
, &hwprops
);
149 GestureInterpreterSetTimerProvider(
151 const_cast<GesturesTimerProvider
*>(&kGestureTimerProvider
),
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
;
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
;
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)
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
;
193 hwstate
.touch_cnt
= Event_Get_Touch_Count(evdev
);
194 hwstate
.finger_cnt
= current_finger
;
195 hwstate
.fingers
= fingers
;
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(
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
);
230 case kGestureTypeScroll
:
231 OnGestureScroll(gesture
, &gesture
->details
.scroll
);
233 case kGestureTypeButtonsChange
:
234 OnGestureButtonsChange(gesture
, &gesture
->details
.buttons
);
236 case kGestureTypeContactInitiated
:
237 OnGestureContactInitiated(gesture
);
239 case kGestureTypeFling
:
240 OnGestureFling(gesture
, &gesture
->details
.fling
);
242 case kGestureTypeSwipe
:
243 OnGestureSwipe(gesture
, &gesture
->details
.swipe
);
245 case kGestureTypeSwipeLift
:
246 OnGestureSwipeLift(gesture
, &gesture
->details
.swipe_lift
);
248 case kGestureTypePinch
:
249 OnGesturePinch(gesture
, &gesture
->details
.pinch
);
251 case kGestureTypeMetrics
:
252 OnGestureMetrics(gesture
, &gesture
->details
.metrics
);
255 LOG(WARNING
) << base::StringPrintf("Unrecognized gesture type (%u)",
261 void GestureInterpreterLibevdevCros::OnGestureMove(const Gesture
* gesture
,
262 const GestureMove
* move
) {
263 DVLOG(3) << base::StringPrintf("Gesture Move: (%f, %f) [%f, %f]",
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]",
286 return; // No cursor!
289 dispatcher_
->DispatchMouseWheelEvent(MouseWheelEventParams(
290 id_
, cursor_
->GetLocation(), gfx::Vector2d(scroll
->dx
, scroll
->dy
),
291 StimeToTimedelta(gesture
->end_time
)));
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",
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",
331 return; // No cursor!
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]",
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");
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
);
386 return; // No cursor!
391 void GestureInterpreterLibevdevCros::OnGestureMetrics(
392 const Gesture
* gesture
,
393 const GestureMetrics
* metrics
) {
394 DVLOG(3) << base::StringPrintf("Gesture Metrics: [%f, %f] type=%d",
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
,
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
,
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
)
446 // Ignore digi buttons (e.g. BTN_TOOL_FINGER).
447 if (key
>= BTN_DIGI
&& key
< BTN_WHEEL
)
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
,
471 DCHECK(BTN_MOUSE
<= button
&& button
< BTN_JOYSTICK
);
472 int button_offset
= button
- BTN_MOUSE
;
474 if (mouse_button_state_
.test(button_offset
) == down
)
477 // State transition: !(down) -> (down)
478 mouse_button_state_
.set(button_offset
, down
);
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
);