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;
78 GestureInterpreterLibevdevCros::GestureInterpreterLibevdevCros(
79 EventModifiersEvdev* modifiers,
80 CursorDelegateEvdev* cursor,
81 const EventDispatchCallback& callback)
82 : modifiers_(modifiers),
84 dispatch_callback_(callback),
87 GestureInterpreterLibevdevCros::~GestureInterpreterLibevdevCros() {
89 DeleteGestureInterpreter(interpreter_);
94 void GestureInterpreterLibevdevCros::OnLibEvdevCrosOpen(
96 EventStateRec* evstate) {
97 CHECK(evdev->info.is_monotonic) << "libevdev must use monotonic timestamps";
98 VLOG(9) << "HACK DO NOT REMOVE OR LINK WILL FAIL" << (void*)gestures_log;
100 HardwareProperties hwprops = GestureHardwareProperties(evdev);
101 GestureInterpreterDeviceClass devclass = GestureDeviceClass(evdev);
103 // Create & initialize GestureInterpreter.
104 CHECK(!interpreter_);
105 interpreter_ = NewGestureInterpreter();
106 GestureInterpreterInitialize(interpreter_, devclass);
107 GestureInterpreterSetHardwareProperties(interpreter_, &hwprops);
108 GestureInterpreterSetTimerProvider(
110 const_cast<GesturesTimerProvider*>(&kGestureTimerProvider),
112 GestureInterpreterSetCallback(interpreter_, OnGestureReadyHelper, this);
115 void GestureInterpreterLibevdevCros::OnLibEvdevCrosEvent(Evdev* evdev,
116 EventStateRec* evstate,
117 const timeval& time) {
118 HardwareState hwstate;
119 memset(&hwstate, 0, sizeof(hwstate));
120 hwstate.timestamp = StimeFromTimeval(&time);
123 hwstate.rel_x = evstate->rel_x;
124 hwstate.rel_y = evstate->rel_y;
125 hwstate.rel_wheel = evstate->rel_wheel;
126 hwstate.rel_hwheel = evstate->rel_hwheel;
129 FingerState fingers[Event_Get_Slot_Count(evdev)];
130 memset(&fingers, 0, sizeof(fingers));
131 int current_finger = 0;
132 for (int i = 0; i < evstate->slot_count; i++) {
133 MtSlotPtr slot = &evstate->slots[i];
134 if (slot->tracking_id == -1)
136 fingers[current_finger].touch_major = slot->touch_major;
137 fingers[current_finger].touch_minor = slot->touch_minor;
138 fingers[current_finger].width_major = slot->width_major;
139 fingers[current_finger].width_minor = slot->width_minor;
140 fingers[current_finger].pressure = slot->pressure;
141 fingers[current_finger].orientation = slot->orientation;
142 fingers[current_finger].position_x = slot->position_x;
143 fingers[current_finger].position_y = slot->position_y;
144 fingers[current_finger].tracking_id = slot->tracking_id;
147 hwstate.touch_cnt = Event_Get_Touch_Count(evdev);
148 hwstate.finger_cnt = current_finger;
149 hwstate.fingers = fingers;
152 if (Event_Get_Button_Left(evdev))
153 hwstate.buttons_down |= GESTURES_BUTTON_LEFT;
154 if (Event_Get_Button_Middle(evdev))
155 hwstate.buttons_down |= GESTURES_BUTTON_MIDDLE;
156 if (Event_Get_Button_Right(evdev))
157 hwstate.buttons_down |= GESTURES_BUTTON_RIGHT;
159 GestureInterpreterPushHardwareState(interpreter_, &hwstate);
162 void GestureInterpreterLibevdevCros::OnGestureReady(const Gesture* gesture) {
163 switch (gesture->type) {
164 case kGestureTypeMove:
165 OnGestureMove(gesture, &gesture->details.move);
167 case kGestureTypeScroll:
168 OnGestureScroll(gesture, &gesture->details.scroll);
170 case kGestureTypeButtonsChange:
171 OnGestureButtonsChange(gesture, &gesture->details.buttons);
173 case kGestureTypeContactInitiated:
174 case kGestureTypeFling:
175 case kGestureTypeSwipe:
176 case kGestureTypeSwipeLift:
177 case kGestureTypePinch:
178 case kGestureTypeMetrics:
179 // TODO(spang): Support remaining gestures.
183 LOG(WARNING) << base::StringPrintf("Unrecognized gesture type (%u)",
189 void GestureInterpreterLibevdevCros::OnGestureMove(const Gesture* gesture,
190 const GestureMove* move) {
191 DVLOG(3) << base::StringPrintf("Gesture Move: (%f, %f) [%f, %f]",
197 return; // No cursor!
198 cursor_->MoveCursor(gfx::Vector2dF(move->dx, move->dy));
199 // TODO(spang): Use move->ordinal_dx, move->ordinal_dy
200 // TODO(spang): Use move->start_time, move->end_time
201 MouseEvent event(ET_MOUSE_MOVED,
204 modifiers_->GetModifierFlags(),
205 /* changed_button_flags */ 0);
209 void GestureInterpreterLibevdevCros::OnGestureScroll(
210 const Gesture* gesture,
211 const GestureScroll* scroll) {
212 DVLOG(3) << base::StringPrintf("Gesture Scroll: (%f, %f) [%f, %f]",
217 // TODO(spang): Support SetNaturalScroll
218 // TODO(spang): Use scroll->start_time
219 ScrollEvent event(ET_SCROLL,
221 StimeToTimedelta(gesture->end_time),
222 modifiers_->GetModifierFlags(),
227 kGestureScrollFingerCount);
231 void GestureInterpreterLibevdevCros::OnGestureButtonsChange(
232 const Gesture* gesture,
233 const GestureButtonsChange* buttons) {
234 DVLOG(3) << base::StringPrintf("Gesture Button Change: down=0x%02x up=0x%02x",
237 // TODO(spang): Use buttons->start_time, buttons->end_time
238 if (buttons->down & GESTURES_BUTTON_LEFT)
239 DispatchMouseButton(EVDEV_MODIFIER_LEFT_MOUSE_BUTTON, true);
240 if (buttons->down & GESTURES_BUTTON_MIDDLE)
241 DispatchMouseButton(EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON, true);
242 if (buttons->down & GESTURES_BUTTON_RIGHT)
243 DispatchMouseButton(EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON, true);
244 if (buttons->up & GESTURES_BUTTON_LEFT)
245 DispatchMouseButton(EVDEV_MODIFIER_LEFT_MOUSE_BUTTON, false);
246 if (buttons->up & GESTURES_BUTTON_MIDDLE)
247 DispatchMouseButton(EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON, false);
248 if (buttons->up & GESTURES_BUTTON_RIGHT)
249 DispatchMouseButton(EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON, false);
252 void GestureInterpreterLibevdevCros::Dispatch(Event* event) {
253 dispatch_callback_.Run(event);
256 void GestureInterpreterLibevdevCros::DispatchMouseButton(unsigned int modifier,
258 const gfx::PointF& loc = cursor_->location();
259 int flag = modifiers_->GetEventFlagFromModifier(modifier);
260 EventType type = (down ? ET_MOUSE_PRESSED : ET_MOUSE_RELEASED);
261 modifiers_->UpdateModifier(modifier, down);
262 MouseEvent event(type, loc, loc, modifiers_->GetModifierFlags() | flag, flag);