Landing Recent QUIC Changes.
[chromium-blink-merge.git] / ui / events / ozone / evdev / libgestures_glue / gesture_interpreter_libevdev_cros.cc
blobd0892599d855286d2fd0d41e3e75ebf256f214ae
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/keycodes/dom4/keycode_converter.h"
15 #include "ui/events/ozone/evdev/cursor_delegate_evdev.h"
16 #include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h"
17 #include "ui/events/ozone/evdev/event_device_info.h"
18 #include "ui/events/ozone/evdev/event_device_util.h"
19 #include "ui/events/ozone/evdev/keyboard_util_evdev.h"
20 #include "ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.h"
21 #include "ui/events/ozone/evdev/libgestures_glue/gesture_timer_provider.h"
22 #include "ui/gfx/geometry/point_f.h"
24 namespace ui {
26 namespace {
28 // Convert libevdev device class to libgestures device class.
29 GestureInterpreterDeviceClass GestureDeviceClass(Evdev* evdev) {
30 switch (evdev->info.evdev_class) {
31 case EvdevClassMouse:
32 return GESTURES_DEVCLASS_MOUSE;
33 case EvdevClassMultitouchMouse:
34 return GESTURES_DEVCLASS_MULTITOUCH_MOUSE;
35 case EvdevClassTouchpad:
36 return GESTURES_DEVCLASS_TOUCHPAD;
37 case EvdevClassTouchscreen:
38 return GESTURES_DEVCLASS_TOUCHSCREEN;
39 default:
40 return GESTURES_DEVCLASS_UNKNOWN;
44 // Convert libevdev state to libgestures hardware properties.
45 HardwareProperties GestureHardwareProperties(
46 Evdev* evdev,
47 const GestureDeviceProperties* props) {
48 HardwareProperties hwprops;
49 hwprops.left = props->area_left;
50 hwprops.top = props->area_top;
51 hwprops.right = props->area_right;
52 hwprops.bottom = props->area_bottom;
53 hwprops.res_x = props->res_x;
54 hwprops.res_y = props->res_y;
55 hwprops.screen_x_dpi = 133;
56 hwprops.screen_y_dpi = 133;
57 hwprops.orientation_minimum = props->orientation_minimum;
58 hwprops.orientation_maximum = props->orientation_maximum;
59 hwprops.max_finger_cnt = Event_Get_Slot_Count(evdev);
60 hwprops.max_touch_cnt = Event_Get_Touch_Count_Max(evdev);
61 hwprops.supports_t5r2 = Event_Get_T5R2(evdev);
62 hwprops.support_semi_mt = Event_Get_Semi_MT(evdev);
63 /* buttonpad means a physical button under the touch surface */
64 hwprops.is_button_pad = Event_Get_Button_Pad(evdev);
65 return hwprops;
68 // Callback from libgestures when a gesture is ready.
69 void OnGestureReadyHelper(void* client_data, const Gesture* gesture) {
70 GestureInterpreterLibevdevCros* interpreter =
71 static_cast<GestureInterpreterLibevdevCros*>(client_data);
72 interpreter->OnGestureReady(gesture);
75 // Convert gestures timestamp (stime_t) to ui::Event timestamp.
76 base::TimeDelta StimeToTimedelta(stime_t timestamp) {
77 return base::TimeDelta::FromMicroseconds(timestamp *
78 base::Time::kMicrosecondsPerSecond);
81 // Number of fingers for scroll gestures.
82 const int kGestureScrollFingerCount = 2;
84 // Number of fingers for swipe gestures.
85 const int kGestureSwipeFingerCount = 3;
87 } // namespace
89 GestureInterpreterLibevdevCros::GestureInterpreterLibevdevCros(
90 int id,
91 CursorDelegateEvdev* cursor,
92 GesturePropertyProvider* property_provider,
93 DeviceEventDispatcherEvdev* dispatcher)
94 : id_(id),
95 is_mouse_(false),
96 cursor_(cursor),
97 property_provider_(property_provider),
98 dispatcher_(dispatcher),
99 interpreter_(NULL),
100 evdev_(NULL),
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.
111 if (interpreter_) {
112 // Unset callbacks.
113 GestureInterpreterSetCallback(interpreter_, NULL, NULL);
114 GestureInterpreterSetPropProvider(interpreter_, NULL, NULL);
115 GestureInterpreterSetTimerProvider(interpreter_, NULL, NULL);
116 DeleteGestureInterpreter(interpreter_);
117 interpreter_ = NULL;
120 // Unregister device from the gesture property provider.
121 GesturesPropFunctionsWrapper::UnregisterDevice(this);
124 void GestureInterpreterLibevdevCros::OnLibEvdevCrosOpen(
125 Evdev* evdev,
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.
131 evdev_ = evdev;
132 GesturesPropFunctionsWrapper::InitializeDeviceProperties(
133 this, device_properties_.get());
134 HardwareProperties hwprops =
135 GestureHardwareProperties(evdev, device_properties_.get());
136 GestureInterpreterDeviceClass devclass = GestureDeviceClass(evdev);
137 is_mouse_ = property_provider_->IsDeviceIdOfType(id_, DT_MOUSE);
139 // Create & initialize GestureInterpreter.
140 DCHECK(!interpreter_);
141 interpreter_ = NewGestureInterpreter();
142 GestureInterpreterSetPropProvider(
143 interpreter_,
144 const_cast<GesturesPropProvider*>(&kGesturePropProvider),
145 this);
146 GestureInterpreterInitialize(interpreter_, devclass);
147 GestureInterpreterSetHardwareProperties(interpreter_, &hwprops);
148 GestureInterpreterSetTimerProvider(
149 interpreter_,
150 const_cast<GesturesTimerProvider*>(&kGestureTimerProvider),
151 this);
152 GestureInterpreterSetCallback(interpreter_, OnGestureReadyHelper, this);
155 void GestureInterpreterLibevdevCros::OnLibEvdevCrosEvent(Evdev* evdev,
156 EventStateRec* evstate,
157 const timeval& time) {
158 // If the device has keys no it, dispatch any presses/release.
159 DispatchChangedKeys(evdev, time);
161 HardwareState hwstate;
162 memset(&hwstate, 0, sizeof(hwstate));
163 hwstate.timestamp = StimeFromTimeval(&time);
165 // Mouse.
166 hwstate.rel_x = evstate->rel_x;
167 hwstate.rel_y = evstate->rel_y;
168 hwstate.rel_wheel = evstate->rel_wheel;
169 hwstate.rel_hwheel = evstate->rel_hwheel;
171 // Touch.
172 FingerState fingers[Event_Get_Slot_Count(evdev)];
173 memset(&fingers, 0, sizeof(fingers));
174 int current_finger = 0;
175 for (int i = 0; i < evstate->slot_count; i++) {
176 MtSlotPtr slot = &evstate->slots[i];
177 if (slot->tracking_id == -1)
178 continue;
179 fingers[current_finger].touch_major = slot->touch_major;
180 fingers[current_finger].touch_minor = slot->touch_minor;
181 fingers[current_finger].width_major = slot->width_major;
182 fingers[current_finger].width_minor = slot->width_minor;
183 fingers[current_finger].pressure = slot->pressure;
184 fingers[current_finger].orientation = slot->orientation;
185 fingers[current_finger].position_x = slot->position_x;
186 fingers[current_finger].position_y = slot->position_y;
187 fingers[current_finger].tracking_id = slot->tracking_id;
188 current_finger++;
190 hwstate.touch_cnt = Event_Get_Touch_Count(evdev);
191 hwstate.finger_cnt = current_finger;
192 hwstate.fingers = fingers;
194 // Buttons.
195 if (Event_Get_Button_Left(evdev))
196 hwstate.buttons_down |= GESTURES_BUTTON_LEFT;
197 if (Event_Get_Button_Middle(evdev))
198 hwstate.buttons_down |= GESTURES_BUTTON_MIDDLE;
199 if (Event_Get_Button_Right(evdev))
200 hwstate.buttons_down |= GESTURES_BUTTON_RIGHT;
202 GestureInterpreterPushHardwareState(interpreter_, &hwstate);
205 void GestureInterpreterLibevdevCros::SetAllowedKeys(
206 scoped_ptr<std::set<DomCode>> allowed_keys) {
207 if (!allowed_keys) {
208 allowed_keys_.reset();
209 return;
212 allowed_keys_.reset(new std::set<int>());
213 for (const auto& it : *allowed_keys) {
214 int evdev_code =
215 NativeCodeToEvdevCode(KeycodeConverter::DomCodeToNativeKeycode(it));
216 allowed_keys_->insert(evdev_code);
220 void GestureInterpreterLibevdevCros::AllowAllKeys() {
221 allowed_keys_.reset();
224 void GestureInterpreterLibevdevCros::OnGestureReady(const Gesture* gesture) {
225 switch (gesture->type) {
226 case kGestureTypeMove:
227 OnGestureMove(gesture, &gesture->details.move);
228 break;
229 case kGestureTypeScroll:
230 OnGestureScroll(gesture, &gesture->details.scroll);
231 break;
232 case kGestureTypeButtonsChange:
233 OnGestureButtonsChange(gesture, &gesture->details.buttons);
234 break;
235 case kGestureTypeContactInitiated:
236 OnGestureContactInitiated(gesture);
237 break;
238 case kGestureTypeFling:
239 OnGestureFling(gesture, &gesture->details.fling);
240 break;
241 case kGestureTypeSwipe:
242 OnGestureSwipe(gesture, &gesture->details.swipe);
243 break;
244 case kGestureTypeSwipeLift:
245 OnGestureSwipeLift(gesture, &gesture->details.swipe_lift);
246 break;
247 case kGestureTypePinch:
248 OnGesturePinch(gesture, &gesture->details.pinch);
249 break;
250 case kGestureTypeMetrics:
251 OnGestureMetrics(gesture, &gesture->details.metrics);
252 break;
253 default:
254 LOG(WARNING) << base::StringPrintf("Unrecognized gesture type (%u)",
255 gesture->type);
256 break;
260 void GestureInterpreterLibevdevCros::OnGestureMove(const Gesture* gesture,
261 const GestureMove* move) {
262 DVLOG(3) << base::StringPrintf("Gesture Move: (%f, %f) [%f, %f]",
263 move->dx,
264 move->dy,
265 move->ordinal_dx,
266 move->ordinal_dy);
267 if (!cursor_)
268 return; // No cursor!
270 cursor_->MoveCursor(gfx::Vector2dF(move->dx, move->dy));
271 // TODO(spang): Use move->ordinal_dx, move->ordinal_dy
272 // TODO(spang): Use move->start_time, move->end_time
273 dispatcher_->DispatchMouseMoveEvent(
274 MouseMoveEventParams(id_, cursor_->GetLocation()));
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 // TODO(spang): Use scroll->start_time
289 if (is_mouse_) {
290 dispatcher_->DispatchMouseWheelEvent(MouseWheelEventParams(
291 id_, cursor_->GetLocation(), gfx::Vector2d(scroll->dx, scroll->dy)));
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 // TODO(spang): Use buttons->start_time, buttons->end_time
312 if (buttons->down & GESTURES_BUTTON_LEFT)
313 DispatchMouseButton(BTN_LEFT, true);
314 if (buttons->down & GESTURES_BUTTON_MIDDLE)
315 DispatchMouseButton(BTN_MIDDLE, true);
316 if (buttons->down & GESTURES_BUTTON_RIGHT)
317 DispatchMouseButton(BTN_RIGHT, true);
318 if (buttons->up & GESTURES_BUTTON_LEFT)
319 DispatchMouseButton(BTN_LEFT, false);
320 if (buttons->up & GESTURES_BUTTON_MIDDLE)
321 DispatchMouseButton(BTN_MIDDLE, false);
322 if (buttons->up & GESTURES_BUTTON_RIGHT)
323 DispatchMouseButton(BTN_RIGHT, false);
326 void GestureInterpreterLibevdevCros::OnGestureContactInitiated(
327 const Gesture* gesture) {
328 // TODO(spang): handle contact initiated.
331 void GestureInterpreterLibevdevCros::OnGestureFling(const Gesture* gesture,
332 const GestureFling* fling) {
333 DVLOG(3) << base::StringPrintf(
334 "Gesture Fling: (%f, %f) [%f, %f] fling_state=%d",
335 fling->vx,
336 fling->vy,
337 fling->ordinal_vx,
338 fling->ordinal_vy,
339 fling->fling_state);
341 if (!cursor_)
342 return; // No cursor!
344 EventType type =
345 (fling->fling_state == GESTURES_FLING_START ? ET_SCROLL_FLING_START
346 : ET_SCROLL_FLING_CANCEL);
348 // Fling is like 2-finger scrolling but with velocity instead of displacement.
349 dispatcher_->DispatchScrollEvent(ScrollEventParams(
350 id_, type, cursor_->GetLocation(), gfx::Vector2dF(fling->vx, fling->vy),
351 gfx::Vector2dF(fling->ordinal_vx, fling->ordinal_vy),
352 kGestureScrollFingerCount, StimeToTimedelta(gesture->end_time)));
355 void GestureInterpreterLibevdevCros::OnGestureSwipe(const Gesture* gesture,
356 const GestureSwipe* swipe) {
357 DVLOG(3) << base::StringPrintf("Gesture Swipe: (%f, %f) [%f, %f]",
358 swipe->dx,
359 swipe->dy,
360 swipe->ordinal_dx,
361 swipe->ordinal_dy);
363 if (!cursor_)
364 return; // No cursor!
366 // Swipe is 3-finger scrolling.
367 dispatcher_->DispatchScrollEvent(ScrollEventParams(
368 id_, ET_SCROLL, cursor_->GetLocation(),
369 gfx::Vector2dF(swipe->dx, swipe->dy),
370 gfx::Vector2dF(swipe->ordinal_dx, swipe->ordinal_dy),
371 kGestureSwipeFingerCount, StimeToTimedelta(gesture->end_time)));
374 void GestureInterpreterLibevdevCros::OnGestureSwipeLift(
375 const Gesture* gesture,
376 const GestureSwipeLift* swipelift) {
377 DVLOG(3) << base::StringPrintf("Gesture Swipe Lift");
379 if (!cursor_)
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 dispatcher_->DispatchScrollEvent(ScrollEventParams(
386 id_, ET_SCROLL_FLING_START, cursor_->GetLocation(),
387 gfx::Vector2dF() /* delta */, gfx::Vector2dF() /* ordinal_delta */,
388 kGestureScrollFingerCount, StimeToTimedelta(gesture->end_time)));
391 void GestureInterpreterLibevdevCros::OnGesturePinch(const Gesture* gesture,
392 const GesturePinch* pinch) {
393 DVLOG(3) << base::StringPrintf(
394 "Gesture Pinch: dz=%f [%f]", pinch->dz, pinch->ordinal_dz);
396 if (!cursor_)
397 return; // No cursor!
399 NOTIMPLEMENTED();
402 void GestureInterpreterLibevdevCros::OnGestureMetrics(
403 const Gesture* gesture,
404 const GestureMetrics* metrics) {
405 DVLOG(3) << base::StringPrintf("Gesture Metrics: [%f, %f] type=%d",
406 metrics->data[0],
407 metrics->data[1],
408 metrics->type);
409 NOTIMPLEMENTED();
412 void GestureInterpreterLibevdevCros::DispatchMouseButton(unsigned int button,
413 bool down) {
414 bool allow_remap = is_mouse_;
415 dispatcher_->DispatchMouseButtonEvent(MouseButtonEventParams(
416 id_, cursor_->GetLocation(), button, down, allow_remap));
419 void GestureInterpreterLibevdevCros::DispatchChangedKeys(Evdev* evdev,
420 const timeval& time) {
421 unsigned long key_state_diff[EVDEV_BITS_TO_LONGS(KEY_CNT)];
423 // Find changed keys.
424 for (unsigned long i = 0; i < arraysize(key_state_diff); ++i)
425 key_state_diff[i] = evdev->key_state_bitmask[i] ^ prev_key_state_[i];
427 // Dispatch events for changed keys.
428 for (unsigned long key = 0; key < KEY_CNT; ++key) {
429 if (EvdevBitIsSet(key_state_diff, key)) {
430 bool value = EvdevBitIsSet(evdev->key_state_bitmask, key);
432 // Mouse buttons are handled by DispatchMouseButton.
433 if (key >= BTN_MOUSE && key < BTN_JOYSTICK)
434 continue;
436 // Ignore digi buttons (e.g. BTN_TOOL_FINGER).
437 if (key >= BTN_DIGI && key < BTN_WHEEL)
438 continue;
440 if (allowed_keys_ && !allowed_keys_->count(key))
441 continue;
443 // Dispatch key press or release to keyboard.
444 dispatcher_->DispatchKeyEvent(KeyEventParams(id_, key, value));
448 // Update internal key state.
449 for (unsigned long i = 0; i < EVDEV_BITS_TO_LONGS(KEY_CNT); ++i)
450 prev_key_state_[i] = evdev->key_state_bitmask[i];
453 } // namespace ui