ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / ui / events / ozone / evdev / libgestures_glue / gesture_interpreter_libevdev_cros.cc
blob58b38a0a20fdbc8a406be17af0a000a6101d0bd6
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/dom4/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"
25 namespace ui {
27 namespace {
29 // Convert libevdev device class to libgestures device class.
30 GestureInterpreterDeviceClass GestureDeviceClass(Evdev* evdev) {
31 switch (evdev->info.evdev_class) {
32 case EvdevClassMouse:
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;
40 default:
41 return GESTURES_DEVCLASS_UNKNOWN;
45 // Convert libevdev state to libgestures hardware properties.
46 HardwareProperties GestureHardwareProperties(
47 Evdev* evdev,
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 return hwprops;
69 // Callback from libgestures when a gesture is ready.
70 void OnGestureReadyHelper(void* client_data, const Gesture* gesture) {
71 GestureInterpreterLibevdevCros* interpreter =
72 static_cast<GestureInterpreterLibevdevCros*>(client_data);
73 interpreter->OnGestureReady(gesture);
76 // Convert gestures timestamp (stime_t) to ui::Event timestamp.
77 base::TimeDelta StimeToTimedelta(stime_t timestamp) {
78 return base::TimeDelta::FromMicroseconds(timestamp *
79 base::Time::kMicrosecondsPerSecond);
82 base::TimeDelta TimeValToTimeDelta(const timeval& tv) {
83 return base::TimeDelta::FromMicroseconds(tv.tv_sec * 1000000 + tv.tv_usec);
86 // Number of fingers for scroll gestures.
87 const int kGestureScrollFingerCount = 2;
89 // Number of fingers for swipe gestures.
90 const int kGestureSwipeFingerCount = 3;
92 } // namespace
94 GestureInterpreterLibevdevCros::GestureInterpreterLibevdevCros(
95 int id,
96 CursorDelegateEvdev* cursor,
97 GesturePropertyProvider* property_provider,
98 DeviceEventDispatcherEvdev* dispatcher)
99 : id_(id),
100 is_mouse_(false),
101 cursor_(cursor),
102 property_provider_(property_provider),
103 dispatcher_(dispatcher),
104 interpreter_(NULL),
105 evdev_(NULL),
106 device_properties_(new GestureDeviceProperties) {
107 memset(&prev_key_state_, 0, sizeof(prev_key_state_));
110 GestureInterpreterLibevdevCros::~GestureInterpreterLibevdevCros() {
111 // Note that this destructor got called after the evdev device node has been
112 // closed. Therefore, all clean-up codes here shouldn't depend on the device
113 // information (except for the pointer address itself).
115 // Clean-up if the gesture interpreter has been successfully created.
116 if (interpreter_) {
117 // Unset callbacks.
118 GestureInterpreterSetCallback(interpreter_, NULL, NULL);
119 GestureInterpreterSetPropProvider(interpreter_, NULL, NULL);
120 GestureInterpreterSetTimerProvider(interpreter_, NULL, NULL);
121 DeleteGestureInterpreter(interpreter_);
122 interpreter_ = NULL;
125 // Unregister device from the gesture property provider.
126 GesturesPropFunctionsWrapper::UnregisterDevice(this);
129 void GestureInterpreterLibevdevCros::OnLibEvdevCrosOpen(
130 Evdev* evdev,
131 EventStateRec* evstate) {
132 DCHECK(evdev->info.is_monotonic) << "libevdev must use monotonic timestamps";
133 VLOG(9) << "HACK DO NOT REMOVE OR LINK WILL FAIL" << (void*)gestures_log;
135 // Set device pointer and initialize properties.
136 evdev_ = evdev;
137 GesturesPropFunctionsWrapper::InitializeDeviceProperties(
138 this, device_properties_.get());
139 HardwareProperties hwprops =
140 GestureHardwareProperties(evdev, device_properties_.get());
141 GestureInterpreterDeviceClass devclass = GestureDeviceClass(evdev);
142 is_mouse_ = property_provider_->IsDeviceIdOfType(id_, DT_MOUSE);
144 // Create & initialize GestureInterpreter.
145 DCHECK(!interpreter_);
146 interpreter_ = NewGestureInterpreter();
147 GestureInterpreterSetPropProvider(
148 interpreter_,
149 const_cast<GesturesPropProvider*>(&kGesturePropProvider),
150 this);
151 GestureInterpreterInitialize(interpreter_, devclass);
152 GestureInterpreterSetHardwareProperties(interpreter_, &hwprops);
153 GestureInterpreterSetTimerProvider(
154 interpreter_,
155 const_cast<GesturesTimerProvider*>(&kGestureTimerProvider),
156 this);
157 GestureInterpreterSetCallback(interpreter_, OnGestureReadyHelper, this);
160 void GestureInterpreterLibevdevCros::OnLibEvdevCrosEvent(Evdev* evdev,
161 EventStateRec* evstate,
162 const timeval& time) {
163 // If the device has keys no it, dispatch any presses/release.
164 DispatchChangedKeys(evdev, time);
166 HardwareState hwstate;
167 memset(&hwstate, 0, sizeof(hwstate));
168 hwstate.timestamp = StimeFromTimeval(&time);
170 // Mouse.
171 hwstate.rel_x = evstate->rel_x;
172 hwstate.rel_y = evstate->rel_y;
173 hwstate.rel_wheel = evstate->rel_wheel;
174 hwstate.rel_hwheel = evstate->rel_hwheel;
176 // Touch.
177 FingerState fingers[Event_Get_Slot_Count(evdev)];
178 memset(&fingers, 0, sizeof(fingers));
179 int current_finger = 0;
180 for (int i = 0; i < evstate->slot_count; i++) {
181 MtSlotPtr slot = &evstate->slots[i];
182 if (slot->tracking_id == -1)
183 continue;
184 fingers[current_finger].touch_major = slot->touch_major;
185 fingers[current_finger].touch_minor = slot->touch_minor;
186 fingers[current_finger].width_major = slot->width_major;
187 fingers[current_finger].width_minor = slot->width_minor;
188 fingers[current_finger].pressure = slot->pressure;
189 fingers[current_finger].orientation = slot->orientation;
190 fingers[current_finger].position_x = slot->position_x;
191 fingers[current_finger].position_y = slot->position_y;
192 fingers[current_finger].tracking_id = slot->tracking_id;
193 current_finger++;
195 hwstate.touch_cnt = Event_Get_Touch_Count(evdev);
196 hwstate.finger_cnt = current_finger;
197 hwstate.fingers = fingers;
199 // Buttons.
200 if (Event_Get_Button_Left(evdev))
201 hwstate.buttons_down |= GESTURES_BUTTON_LEFT;
202 if (Event_Get_Button_Middle(evdev))
203 hwstate.buttons_down |= GESTURES_BUTTON_MIDDLE;
204 if (Event_Get_Button_Right(evdev))
205 hwstate.buttons_down |= GESTURES_BUTTON_RIGHT;
207 GestureInterpreterPushHardwareState(interpreter_, &hwstate);
210 void GestureInterpreterLibevdevCros::SetAllowedKeys(
211 scoped_ptr<std::set<DomCode>> allowed_keys) {
212 if (!allowed_keys) {
213 allowed_keys_.reset();
214 return;
217 allowed_keys_.reset(new std::set<int>());
218 for (const auto& it : *allowed_keys) {
219 int evdev_code =
220 NativeCodeToEvdevCode(KeycodeConverter::DomCodeToNativeKeycode(it));
221 allowed_keys_->insert(evdev_code);
225 void GestureInterpreterLibevdevCros::AllowAllKeys() {
226 allowed_keys_.reset();
229 void GestureInterpreterLibevdevCros::OnGestureReady(const Gesture* gesture) {
230 switch (gesture->type) {
231 case kGestureTypeMove:
232 OnGestureMove(gesture, &gesture->details.move);
233 break;
234 case kGestureTypeScroll:
235 OnGestureScroll(gesture, &gesture->details.scroll);
236 break;
237 case kGestureTypeButtonsChange:
238 OnGestureButtonsChange(gesture, &gesture->details.buttons);
239 break;
240 case kGestureTypeContactInitiated:
241 OnGestureContactInitiated(gesture);
242 break;
243 case kGestureTypeFling:
244 OnGestureFling(gesture, &gesture->details.fling);
245 break;
246 case kGestureTypeSwipe:
247 OnGestureSwipe(gesture, &gesture->details.swipe);
248 break;
249 case kGestureTypeSwipeLift:
250 OnGestureSwipeLift(gesture, &gesture->details.swipe_lift);
251 break;
252 case kGestureTypePinch:
253 OnGesturePinch(gesture, &gesture->details.pinch);
254 break;
255 case kGestureTypeMetrics:
256 OnGestureMetrics(gesture, &gesture->details.metrics);
257 break;
258 default:
259 LOG(WARNING) << base::StringPrintf("Unrecognized gesture type (%u)",
260 gesture->type);
261 break;
265 void GestureInterpreterLibevdevCros::OnGestureMove(const Gesture* gesture,
266 const GestureMove* move) {
267 DVLOG(3) << base::StringPrintf("Gesture Move: (%f, %f) [%f, %f]",
268 move->dx,
269 move->dy,
270 move->ordinal_dx,
271 move->ordinal_dy);
272 if (!cursor_)
273 return; // No cursor!
275 cursor_->MoveCursor(gfx::Vector2dF(move->dx, move->dy));
276 // TODO(spang): Use move->ordinal_dx, move->ordinal_dy
277 dispatcher_->DispatchMouseMoveEvent(MouseMoveEventParams(
278 id_, cursor_->GetLocation(), StimeToTimedelta(gesture->end_time)));
281 void GestureInterpreterLibevdevCros::OnGestureScroll(
282 const Gesture* gesture,
283 const GestureScroll* scroll) {
284 DVLOG(3) << base::StringPrintf("Gesture Scroll: (%f, %f) [%f, %f]",
285 scroll->dx,
286 scroll->dy,
287 scroll->ordinal_dx,
288 scroll->ordinal_dy);
289 if (!cursor_)
290 return; // No cursor!
292 if (is_mouse_) {
293 dispatcher_->DispatchMouseWheelEvent(MouseWheelEventParams(
294 id_, cursor_->GetLocation(), gfx::Vector2d(scroll->dx, scroll->dy),
295 StimeToTimedelta(gesture->end_time)));
296 } else {
297 dispatcher_->DispatchScrollEvent(ScrollEventParams(
298 id_, ET_SCROLL, cursor_->GetLocation(),
299 gfx::Vector2dF(scroll->dx, scroll->dy),
300 gfx::Vector2dF(scroll->ordinal_dx, scroll->ordinal_dy),
301 kGestureScrollFingerCount, StimeToTimedelta(gesture->end_time)));
305 void GestureInterpreterLibevdevCros::OnGestureButtonsChange(
306 const Gesture* gesture,
307 const GestureButtonsChange* buttons) {
308 DVLOG(3) << base::StringPrintf("Gesture Button Change: down=0x%02x up=0x%02x",
309 buttons->down,
310 buttons->up);
312 if (!cursor_)
313 return; // No cursor!
315 if (buttons->down & GESTURES_BUTTON_LEFT)
316 DispatchMouseButton(BTN_LEFT, true, gesture->end_time);
317 if (buttons->down & GESTURES_BUTTON_MIDDLE)
318 DispatchMouseButton(BTN_MIDDLE, true, gesture->end_time);
319 if (buttons->down & GESTURES_BUTTON_RIGHT)
320 DispatchMouseButton(BTN_RIGHT, true, gesture->end_time);
321 if (buttons->up & GESTURES_BUTTON_LEFT)
322 DispatchMouseButton(BTN_LEFT, false, gesture->end_time);
323 if (buttons->up & GESTURES_BUTTON_MIDDLE)
324 DispatchMouseButton(BTN_MIDDLE, false, gesture->end_time);
325 if (buttons->up & GESTURES_BUTTON_RIGHT)
326 DispatchMouseButton(BTN_RIGHT, false, gesture->end_time);
329 void GestureInterpreterLibevdevCros::OnGestureContactInitiated(
330 const Gesture* gesture) {
331 // TODO(spang): handle contact initiated.
334 void GestureInterpreterLibevdevCros::OnGestureFling(const Gesture* gesture,
335 const GestureFling* fling) {
336 DVLOG(3) << base::StringPrintf(
337 "Gesture Fling: (%f, %f) [%f, %f] fling_state=%d",
338 fling->vx,
339 fling->vy,
340 fling->ordinal_vx,
341 fling->ordinal_vy,
342 fling->fling_state);
344 if (!cursor_)
345 return; // No cursor!
347 EventType type =
348 (fling->fling_state == GESTURES_FLING_START ? ET_SCROLL_FLING_START
349 : ET_SCROLL_FLING_CANCEL);
351 // Fling is like 2-finger scrolling but with velocity instead of displacement.
352 dispatcher_->DispatchScrollEvent(ScrollEventParams(
353 id_, type, cursor_->GetLocation(), gfx::Vector2dF(fling->vx, fling->vy),
354 gfx::Vector2dF(fling->ordinal_vx, fling->ordinal_vy),
355 kGestureScrollFingerCount, StimeToTimedelta(gesture->end_time)));
358 void GestureInterpreterLibevdevCros::OnGestureSwipe(const Gesture* gesture,
359 const GestureSwipe* swipe) {
360 DVLOG(3) << base::StringPrintf("Gesture Swipe: (%f, %f) [%f, %f]",
361 swipe->dx,
362 swipe->dy,
363 swipe->ordinal_dx,
364 swipe->ordinal_dy);
366 if (!cursor_)
367 return; // No cursor!
369 // Swipe is 3-finger scrolling.
370 dispatcher_->DispatchScrollEvent(ScrollEventParams(
371 id_, ET_SCROLL, cursor_->GetLocation(),
372 gfx::Vector2dF(swipe->dx, swipe->dy),
373 gfx::Vector2dF(swipe->ordinal_dx, swipe->ordinal_dy),
374 kGestureSwipeFingerCount, StimeToTimedelta(gesture->end_time)));
377 void GestureInterpreterLibevdevCros::OnGestureSwipeLift(
378 const Gesture* gesture,
379 const GestureSwipeLift* swipelift) {
380 DVLOG(3) << base::StringPrintf("Gesture Swipe Lift");
382 if (!cursor_)
383 return; // No cursor!
385 // Turn a swipe lift into a fling start.
386 // TODO(spang): Figure out why and put it in this comment.
388 dispatcher_->DispatchScrollEvent(ScrollEventParams(
389 id_, ET_SCROLL_FLING_START, cursor_->GetLocation(),
390 gfx::Vector2dF() /* delta */, gfx::Vector2dF() /* ordinal_delta */,
391 kGestureScrollFingerCount, StimeToTimedelta(gesture->end_time)));
394 void GestureInterpreterLibevdevCros::OnGesturePinch(const Gesture* gesture,
395 const GesturePinch* pinch) {
396 DVLOG(3) << base::StringPrintf(
397 "Gesture Pinch: dz=%f [%f]", pinch->dz, pinch->ordinal_dz);
399 if (!cursor_)
400 return; // No cursor!
402 NOTIMPLEMENTED();
405 void GestureInterpreterLibevdevCros::OnGestureMetrics(
406 const Gesture* gesture,
407 const GestureMetrics* metrics) {
408 DVLOG(3) << base::StringPrintf("Gesture Metrics: [%f, %f] type=%d",
409 metrics->data[0],
410 metrics->data[1],
411 metrics->type);
412 NOTIMPLEMENTED();
415 void GestureInterpreterLibevdevCros::DispatchMouseButton(unsigned int button,
416 bool down,
417 stime_t time) {
418 bool allow_remap = is_mouse_;
419 dispatcher_->DispatchMouseButtonEvent(
420 MouseButtonEventParams(id_, cursor_->GetLocation(), button, down,
421 allow_remap, StimeToTimedelta(time)));
424 void GestureInterpreterLibevdevCros::DispatchChangedKeys(Evdev* evdev,
425 const timeval& time) {
426 unsigned long key_state_diff[EVDEV_BITS_TO_LONGS(KEY_CNT)];
428 // Find changed keys.
429 for (unsigned long i = 0; i < arraysize(key_state_diff); ++i)
430 key_state_diff[i] = evdev->key_state_bitmask[i] ^ prev_key_state_[i];
432 // Dispatch events for changed keys.
433 for (unsigned long key = 0; key < KEY_CNT; ++key) {
434 if (EvdevBitIsSet(key_state_diff, key)) {
435 bool value = EvdevBitIsSet(evdev->key_state_bitmask, key);
437 // Mouse buttons are handled by DispatchMouseButton.
438 if (key >= BTN_MOUSE && key < BTN_JOYSTICK)
439 continue;
441 // Ignore digi buttons (e.g. BTN_TOOL_FINGER).
442 if (key >= BTN_DIGI && key < BTN_WHEEL)
443 continue;
445 if (allowed_keys_ && !allowed_keys_->count(key))
446 continue;
448 // Dispatch key press or release to keyboard.
449 dispatcher_->DispatchKeyEvent(
450 KeyEventParams(id_, key, value, TimeValToTimeDelta(time)));
454 // Update internal key state.
455 for (unsigned long i = 0; i < EVDEV_BITS_TO_LONGS(KEY_CNT); ++i)
456 prev_key_state_[i] = evdev->key_state_bitmask[i];
459 } // namespace ui