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"
22 // Convert libevdev device class to libgestures device class.
23 GestureInterpreterDeviceClass
GestureDeviceClass(Evdev
* evdev
) {
24 switch (evdev
->info
.evdev_class
) {
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
;
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
);
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;
81 GestureInterpreterLibevdevCros::GestureInterpreterLibevdevCros(
82 EventModifiersEvdev
* modifiers
,
83 CursorDelegateEvdev
* cursor
,
84 const EventDispatchCallback
& callback
)
85 : modifiers_(modifiers
),
87 dispatch_callback_(callback
),
90 GestureInterpreterLibevdevCros::~GestureInterpreterLibevdevCros() {
92 DeleteGestureInterpreter(interpreter_
);
97 void GestureInterpreterLibevdevCros::OnLibEvdevCrosOpen(
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(
113 const_cast<GesturesTimerProvider
*>(&kGestureTimerProvider
),
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
);
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
;
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)
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
;
150 hwstate
.touch_cnt
= Event_Get_Touch_Count(evdev
);
151 hwstate
.finger_cnt
= current_finger
;
152 hwstate
.fingers
= fingers
;
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
);
170 case kGestureTypeScroll
:
171 OnGestureScroll(gesture
, &gesture
->details
.scroll
);
173 case kGestureTypeButtonsChange
:
174 OnGestureButtonsChange(gesture
, &gesture
->details
.buttons
);
176 case kGestureTypeContactInitiated
:
177 OnGestureContactInitiated(gesture
);
179 case kGestureTypeFling
:
180 OnGestureFling(gesture
, &gesture
->details
.fling
);
182 case kGestureTypeSwipe
:
183 OnGestureSwipe(gesture
, &gesture
->details
.swipe
);
185 case kGestureTypeSwipeLift
:
186 OnGestureSwipeLift(gesture
, &gesture
->details
.swipe_lift
);
188 case kGestureTypePinch
:
189 OnGesturePinch(gesture
, &gesture
->details
.pinch
);
191 case kGestureTypeMetrics
:
192 OnGestureMetrics(gesture
, &gesture
->details
.metrics
);
195 LOG(WARNING
) << base::StringPrintf("Unrecognized gesture type (%u)",
201 void GestureInterpreterLibevdevCros::OnGestureMove(const Gesture
* gesture
,
202 const GestureMove
* move
) {
203 DVLOG(3) << base::StringPrintf("Gesture Move: (%f, %f) [%f, %f]",
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
,
217 modifiers_
->GetModifierFlags(),
218 /* changed_button_flags */ 0);
222 void GestureInterpreterLibevdevCros::OnGestureScroll(
223 const Gesture
* gesture
,
224 const GestureScroll
* scroll
) {
225 DVLOG(3) << base::StringPrintf("Gesture Scroll: (%f, %f) [%f, %f]",
231 return; // No cursor!
233 // TODO(spang): Support SetNaturalScroll
234 // TODO(spang): Use scroll->start_time
235 ScrollEvent
event(ET_SCROLL
,
237 StimeToTimedelta(gesture
->end_time
),
238 modifiers_
->GetModifierFlags(),
243 kGestureScrollFingerCount
);
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",
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())
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",
296 return; // No cursor!
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
,
305 StimeToTimedelta(gesture
->end_time
),
306 modifiers_
->GetModifierFlags(),
311 kGestureScrollFingerCount
);
315 void GestureInterpreterLibevdevCros::OnGestureSwipe(const Gesture
* gesture
,
316 const GestureSwipe
* swipe
) {
317 DVLOG(3) << base::StringPrintf("Gesture Swipe: (%f, %f) [%f, %f]",
324 return; // No cursor!
326 // Swipe is 3-finger scrolling.
327 ScrollEvent
event(ET_SCROLL
,
329 StimeToTimedelta(gesture
->end_time
),
330 modifiers_
->GetModifierFlags(),
335 kGestureSwipeFingerCount
);
339 void GestureInterpreterLibevdevCros::OnGestureSwipeLift(
340 const Gesture
* gesture
,
341 const GestureSwipeLift
* swipelift
) {
342 DVLOG(3) << base::StringPrintf("Gesture Swipe Lift");
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
,
352 StimeToTimedelta(gesture
->end_time
),
353 modifiers_
->GetModifierFlags(),
356 /* x_offset_ordinal */ 0,
357 /* y_offset_ordinal */ 0,
358 kGestureScrollFingerCount
);
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
);
369 return; // No cursor!
374 void GestureInterpreterLibevdevCros::OnGestureMetrics(
375 const Gesture
* gesture
,
376 const GestureMetrics
* metrics
) {
377 DVLOG(3) << base::StringPrintf("Gesture Metrics: [%f, %f] type=%d",
384 void GestureInterpreterLibevdevCros::Dispatch(Event
* event
) {
385 dispatch_callback_
.Run(event
);
388 void GestureInterpreterLibevdevCros::DispatchMouseButton(unsigned int modifier
,
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
);