Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1025)

Side by Side Diff: ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc

Issue 851853002: It is time. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Trying to reup because the last upload failed. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cr os.h"
6
7 #include <gestures/gestures.h>
8 #include <libevdev/libevdev.h>
9
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_device_util.h"
15 #include "ui/events/ozone/evdev/event_modifiers_evdev.h"
16 #include "ui/events/ozone/evdev/keyboard_evdev.h"
17 #include "ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.h"
18 #include "ui/events/ozone/evdev/libgestures_glue/gesture_timer_provider.h"
19 #include "ui/gfx/geometry/point_f.h"
20
21 namespace ui {
22
23 namespace {
24
25 // Convert libevdev device class to libgestures device class.
26 GestureInterpreterDeviceClass GestureDeviceClass(Evdev* evdev) {
27 switch (evdev->info.evdev_class) {
28 case EvdevClassMouse:
29 return GESTURES_DEVCLASS_MOUSE;
30 case EvdevClassMultitouchMouse:
31 return GESTURES_DEVCLASS_MULTITOUCH_MOUSE;
32 case EvdevClassTouchpad:
33 return GESTURES_DEVCLASS_TOUCHPAD;
34 case EvdevClassTouchscreen:
35 return GESTURES_DEVCLASS_TOUCHSCREEN;
36 default:
37 return GESTURES_DEVCLASS_UNKNOWN;
38 }
39 }
40
41 // Convert libevdev state to libgestures hardware properties.
42 HardwareProperties GestureHardwareProperties(
43 Evdev* evdev,
44 const GestureDeviceProperties* props) {
45 HardwareProperties hwprops;
46 hwprops.left = props->area_left;
47 hwprops.top = props->area_top;
48 hwprops.right = props->area_right;
49 hwprops.bottom = props->area_bottom;
50 hwprops.res_x = props->res_x;
51 hwprops.res_y = props->res_y;
52 hwprops.screen_x_dpi = 133;
53 hwprops.screen_y_dpi = 133;
54 hwprops.orientation_minimum = props->orientation_minimum;
55 hwprops.orientation_maximum = props->orientation_maximum;
56 hwprops.max_finger_cnt = Event_Get_Slot_Count(evdev);
57 hwprops.max_touch_cnt = Event_Get_Touch_Count_Max(evdev);
58 hwprops.supports_t5r2 = Event_Get_T5R2(evdev);
59 hwprops.support_semi_mt = Event_Get_Semi_MT(evdev);
60 /* buttonpad means a physical button under the touch surface */
61 hwprops.is_button_pad = Event_Get_Button_Pad(evdev);
62 return hwprops;
63 }
64
65 // Callback from libgestures when a gesture is ready.
66 void OnGestureReadyHelper(void* client_data, const Gesture* gesture) {
67 GestureInterpreterLibevdevCros* interpreter =
68 static_cast<GestureInterpreterLibevdevCros*>(client_data);
69 interpreter->OnGestureReady(gesture);
70 }
71
72 // Convert gestures timestamp (stime_t) to ui::Event timestamp.
73 base::TimeDelta StimeToTimedelta(stime_t timestamp) {
74 return base::TimeDelta::FromMicroseconds(timestamp *
75 base::Time::kMicrosecondsPerSecond);
76 }
77
78 // Number of fingers for scroll gestures.
79 const int kGestureScrollFingerCount = 2;
80
81 // Number of fingers for swipe gestures.
82 const int kGestureSwipeFingerCount = 3;
83
84 } // namespace
85
86 GestureInterpreterLibevdevCros::GestureInterpreterLibevdevCros(
87 int id,
88 EventModifiersEvdev* modifiers,
89 CursorDelegateEvdev* cursor,
90 KeyboardEvdev* keyboard,
91 GesturePropertyProvider* property_provider,
92 const EventDispatchCallback& callback)
93 : id_(id),
94 modifiers_(modifiers),
95 cursor_(cursor),
96 keyboard_(keyboard),
97 property_provider_(property_provider),
98 dispatch_callback_(callback),
99 interpreter_(NULL),
100 evdev_(NULL),
101 device_properties_(new GestureDeviceProperties) {
102 memset(&prev_key_state_, 0, sizeof(prev_key_state_));
103 }
104
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).
109
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;
118 }
119
120 // Unregister device from the gesture property provider.
121 GesturesPropFunctionsWrapper::UnregisterDevice(this);
122 }
123
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;
129
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
138 // Create & initialize GestureInterpreter.
139 DCHECK(!interpreter_);
140 interpreter_ = NewGestureInterpreter();
141 GestureInterpreterSetPropProvider(
142 interpreter_,
143 const_cast<GesturesPropProvider*>(&kGesturePropProvider),
144 this);
145 GestureInterpreterInitialize(interpreter_, devclass);
146 GestureInterpreterSetHardwareProperties(interpreter_, &hwprops);
147 GestureInterpreterSetTimerProvider(
148 interpreter_,
149 const_cast<GesturesTimerProvider*>(&kGestureTimerProvider),
150 this);
151 GestureInterpreterSetCallback(interpreter_, OnGestureReadyHelper, this);
152 }
153
154 void GestureInterpreterLibevdevCros::OnLibEvdevCrosEvent(Evdev* evdev,
155 EventStateRec* evstate,
156 const timeval& time) {
157 // If the device has keys no it, dispatch any presses/release.
158 DispatchChangedKeys(evdev, time);
159
160 HardwareState hwstate;
161 memset(&hwstate, 0, sizeof(hwstate));
162 hwstate.timestamp = StimeFromTimeval(&time);
163
164 // Mouse.
165 hwstate.rel_x = evstate->rel_x;
166 hwstate.rel_y = evstate->rel_y;
167 hwstate.rel_wheel = evstate->rel_wheel;
168 hwstate.rel_hwheel = evstate->rel_hwheel;
169
170 // Touch.
171 FingerState fingers[Event_Get_Slot_Count(evdev)];
172 memset(&fingers, 0, sizeof(fingers));
173 int current_finger = 0;
174 for (int i = 0; i < evstate->slot_count; i++) {
175 MtSlotPtr slot = &evstate->slots[i];
176 if (slot->tracking_id == -1)
177 continue;
178 fingers[current_finger].touch_major = slot->touch_major;
179 fingers[current_finger].touch_minor = slot->touch_minor;
180 fingers[current_finger].width_major = slot->width_major;
181 fingers[current_finger].width_minor = slot->width_minor;
182 fingers[current_finger].pressure = slot->pressure;
183 fingers[current_finger].orientation = slot->orientation;
184 fingers[current_finger].position_x = slot->position_x;
185 fingers[current_finger].position_y = slot->position_y;
186 fingers[current_finger].tracking_id = slot->tracking_id;
187 current_finger++;
188 }
189 hwstate.touch_cnt = Event_Get_Touch_Count(evdev);
190 hwstate.finger_cnt = current_finger;
191 hwstate.fingers = fingers;
192
193 // Buttons.
194 if (Event_Get_Button_Left(evdev))
195 hwstate.buttons_down |= GESTURES_BUTTON_LEFT;
196 if (Event_Get_Button_Middle(evdev))
197 hwstate.buttons_down |= GESTURES_BUTTON_MIDDLE;
198 if (Event_Get_Button_Right(evdev))
199 hwstate.buttons_down |= GESTURES_BUTTON_RIGHT;
200
201 GestureInterpreterPushHardwareState(interpreter_, &hwstate);
202 }
203
204 void GestureInterpreterLibevdevCros::OnGestureReady(const Gesture* gesture) {
205 switch (gesture->type) {
206 case kGestureTypeMove:
207 OnGestureMove(gesture, &gesture->details.move);
208 break;
209 case kGestureTypeScroll:
210 OnGestureScroll(gesture, &gesture->details.scroll);
211 break;
212 case kGestureTypeButtonsChange:
213 OnGestureButtonsChange(gesture, &gesture->details.buttons);
214 break;
215 case kGestureTypeContactInitiated:
216 OnGestureContactInitiated(gesture);
217 break;
218 case kGestureTypeFling:
219 OnGestureFling(gesture, &gesture->details.fling);
220 break;
221 case kGestureTypeSwipe:
222 OnGestureSwipe(gesture, &gesture->details.swipe);
223 break;
224 case kGestureTypeSwipeLift:
225 OnGestureSwipeLift(gesture, &gesture->details.swipe_lift);
226 break;
227 case kGestureTypePinch:
228 OnGesturePinch(gesture, &gesture->details.pinch);
229 break;
230 case kGestureTypeMetrics:
231 OnGestureMetrics(gesture, &gesture->details.metrics);
232 break;
233 default:
234 LOG(WARNING) << base::StringPrintf("Unrecognized gesture type (%u)",
235 gesture->type);
236 break;
237 }
238 }
239
240 void GestureInterpreterLibevdevCros::OnGestureMove(const Gesture* gesture,
241 const GestureMove* move) {
242 DVLOG(3) << base::StringPrintf("Gesture Move: (%f, %f) [%f, %f]",
243 move->dx,
244 move->dy,
245 move->ordinal_dx,
246 move->ordinal_dy);
247 if (!cursor_)
248 return; // No cursor!
249
250 cursor_->MoveCursor(gfx::Vector2dF(move->dx, move->dy));
251 // TODO(spang): Use move->ordinal_dx, move->ordinal_dy
252 // TODO(spang): Use move->start_time, move->end_time
253 Dispatch(make_scoped_ptr(new MouseEvent(ET_MOUSE_MOVED,
254 cursor_->location(),
255 cursor_->location(),
256 modifiers_->GetModifierFlags(),
257 /* changed_button_flags */ 0)));
258 }
259
260 void GestureInterpreterLibevdevCros::OnGestureScroll(
261 const Gesture* gesture,
262 const GestureScroll* scroll) {
263 DVLOG(3) << base::StringPrintf("Gesture Scroll: (%f, %f) [%f, %f]",
264 scroll->dx,
265 scroll->dy,
266 scroll->ordinal_dx,
267 scroll->ordinal_dy);
268 if (!cursor_)
269 return; // No cursor!
270
271 // TODO(spang): Support SetNaturalScroll
272 // TODO(spang): Use scroll->start_time
273 Dispatch(make_scoped_ptr(new ScrollEvent(ET_SCROLL,
274 cursor_->location(),
275 StimeToTimedelta(gesture->end_time),
276 modifiers_->GetModifierFlags(),
277 scroll->dx,
278 scroll->dy,
279 scroll->ordinal_dx,
280 scroll->ordinal_dy,
281 kGestureScrollFingerCount)));
282 }
283
284 void GestureInterpreterLibevdevCros::OnGestureButtonsChange(
285 const Gesture* gesture,
286 const GestureButtonsChange* buttons) {
287 DVLOG(3) << base::StringPrintf("Gesture Button Change: down=0x%02x up=0x%02x",
288 buttons->down,
289 buttons->up);
290
291 if (!cursor_)
292 return; // No cursor!
293
294 // HACK for disabling TTC (actually, all clicks) on hidden cursor.
295 // This is normally plumbed via properties and can be removed soon.
296 // TODO(spang): Remove this.
297 if (buttons->down == GESTURES_BUTTON_LEFT &&
298 buttons->up == GESTURES_BUTTON_LEFT &&
299 !cursor_->IsCursorVisible())
300 return;
301
302 // TODO(spang): Use buttons->start_time, buttons->end_time
303 if (buttons->down & GESTURES_BUTTON_LEFT)
304 DispatchMouseButton(EVDEV_MODIFIER_LEFT_MOUSE_BUTTON, true);
305 if (buttons->down & GESTURES_BUTTON_MIDDLE)
306 DispatchMouseButton(EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON, true);
307 if (buttons->down & GESTURES_BUTTON_RIGHT)
308 DispatchMouseButton(EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON, true);
309 if (buttons->up & GESTURES_BUTTON_LEFT)
310 DispatchMouseButton(EVDEV_MODIFIER_LEFT_MOUSE_BUTTON, false);
311 if (buttons->up & GESTURES_BUTTON_MIDDLE)
312 DispatchMouseButton(EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON, false);
313 if (buttons->up & GESTURES_BUTTON_RIGHT)
314 DispatchMouseButton(EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON, false);
315 }
316
317 void GestureInterpreterLibevdevCros::OnGestureContactInitiated(
318 const Gesture* gesture) {
319 // TODO(spang): handle contact initiated.
320 }
321
322 void GestureInterpreterLibevdevCros::OnGestureFling(const Gesture* gesture,
323 const GestureFling* fling) {
324 DVLOG(3) << base::StringPrintf(
325 "Gesture Fling: (%f, %f) [%f, %f] fling_state=%d",
326 fling->vx,
327 fling->vy,
328 fling->ordinal_vx,
329 fling->ordinal_vy,
330 fling->fling_state);
331
332 if (!cursor_)
333 return; // No cursor!
334
335 EventType type =
336 (fling->fling_state == GESTURES_FLING_START ? ET_SCROLL_FLING_START
337 : ET_SCROLL_FLING_CANCEL);
338
339 // Fling is like 2-finger scrolling but with velocity instead of displacement.
340 Dispatch(make_scoped_ptr(new ScrollEvent(type,
341 cursor_->location(),
342 StimeToTimedelta(gesture->end_time),
343 modifiers_->GetModifierFlags(),
344 fling->vx,
345 fling->vy,
346 fling->ordinal_vx,
347 fling->ordinal_vy,
348 kGestureScrollFingerCount)));
349 }
350
351 void GestureInterpreterLibevdevCros::OnGestureSwipe(const Gesture* gesture,
352 const GestureSwipe* swipe) {
353 DVLOG(3) << base::StringPrintf("Gesture Swipe: (%f, %f) [%f, %f]",
354 swipe->dx,
355 swipe->dy,
356 swipe->ordinal_dx,
357 swipe->ordinal_dy);
358
359 if (!cursor_)
360 return; // No cursor!
361
362 // Swipe is 3-finger scrolling.
363 Dispatch(make_scoped_ptr(new ScrollEvent(ET_SCROLL,
364 cursor_->location(),
365 StimeToTimedelta(gesture->end_time),
366 modifiers_->GetModifierFlags(),
367 swipe->dx,
368 swipe->dy,
369 swipe->ordinal_dx,
370 swipe->ordinal_dy,
371 kGestureSwipeFingerCount)));
372 }
373
374 void GestureInterpreterLibevdevCros::OnGestureSwipeLift(
375 const Gesture* gesture,
376 const GestureSwipeLift* swipelift) {
377 DVLOG(3) << base::StringPrintf("Gesture Swipe Lift");
378
379 if (!cursor_)
380 return; // No cursor!
381
382 // Turn a swipe lift into a fling start.
383 // TODO(spang): Figure out why and put it in this comment.
384
385 Dispatch(make_scoped_ptr(new ScrollEvent(ET_SCROLL_FLING_START,
386 cursor_->location(),
387 StimeToTimedelta(gesture->end_time),
388 modifiers_->GetModifierFlags(),
389 /* x_offset */ 0,
390 /* y_offset */ 0,
391 /* x_offset_ordinal */ 0,
392 /* y_offset_ordinal */ 0,
393 kGestureScrollFingerCount)));
394 }
395
396 void GestureInterpreterLibevdevCros::OnGesturePinch(const Gesture* gesture,
397 const GesturePinch* pinch) {
398 DVLOG(3) << base::StringPrintf(
399 "Gesture Pinch: dz=%f [%f]", pinch->dz, pinch->ordinal_dz);
400
401 if (!cursor_)
402 return; // No cursor!
403
404 NOTIMPLEMENTED();
405 }
406
407 void GestureInterpreterLibevdevCros::OnGestureMetrics(
408 const Gesture* gesture,
409 const GestureMetrics* metrics) {
410 DVLOG(3) << base::StringPrintf("Gesture Metrics: [%f, %f] type=%d",
411 metrics->data[0],
412 metrics->data[1],
413 metrics->type);
414 NOTIMPLEMENTED();
415 }
416
417 void GestureInterpreterLibevdevCros::Dispatch(scoped_ptr<Event> event) {
418 dispatch_callback_.Run(event.Pass());
419 }
420
421 void GestureInterpreterLibevdevCros::DispatchMouseButton(unsigned int modifier,
422 bool down) {
423 const gfx::PointF& loc = cursor_->location();
424 int flag = modifiers_->GetEventFlagFromModifier(modifier);
425 EventType type = (down ? ET_MOUSE_PRESSED : ET_MOUSE_RELEASED);
426 modifiers_->UpdateModifier(modifier, down);
427 Dispatch(make_scoped_ptr(new MouseEvent(
428 type, loc, loc, modifiers_->GetModifierFlags() | flag, flag)));
429 }
430
431 void GestureInterpreterLibevdevCros::DispatchChangedKeys(Evdev* evdev,
432 const timeval& time) {
433 unsigned long key_state_diff[EVDEV_BITS_TO_LONGS(KEY_CNT)];
434
435 // Find changed keys.
436 for (unsigned long i = 0; i < arraysize(key_state_diff); ++i)
437 key_state_diff[i] = evdev->key_state_bitmask[i] ^ prev_key_state_[i];
438
439 // Dispatch events for changed keys.
440 for (unsigned long i = 0; i < KEY_CNT; ++i) {
441 if (EvdevBitIsSet(key_state_diff, i)) {
442 bool value = EvdevBitIsSet(evdev->key_state_bitmask, i);
443 keyboard_->OnKeyChange(i, value);
444 }
445 }
446
447 // Update internal key state.
448 for (unsigned long i = 0; i < EVDEV_BITS_TO_LONGS(KEY_CNT); ++i)
449 prev_key_state_[i] = evdev->key_state_bitmask[i];
450 }
451
452 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698