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_cros.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_modifiers_evdev.h" 15 #include "ui/events/ozone/evdev/libgestures_glue/gesture_timer_provider.h" 16 #include "ui/gfx/geometry/point_f.h" 17 18 namespace ui { 19 20 namespace { 21 22 // Convert libevdev device class to libgestures device class. 23 GestureInterpreterDeviceClass GestureDeviceClass(Evdev* evdev) { 24 switch (evdev->info.evdev_class) { 25 case EvdevClassMouse: 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; 33 default: 34 return GESTURES_DEVCLASS_UNKNOWN; 35 } 36 } 37 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); 57 return hwprops; 58 } 59 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); 65 } 66 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); 71 } 72 73 // Number of fingers for scroll gestures. 74 const int kGestureScrollFingerCount = 2; 75 76 // Number of fingers for swipe gestures. 77 const int kGestureSwipeFingerCount = 3; 78 79 } // namespace 80 81 GestureInterpreterLibevdevCros::GestureInterpreterLibevdevCros( 82 EventModifiersEvdev* modifiers, 83 CursorDelegateEvdev* cursor, 84 const EventDispatchCallback& callback) 85 : modifiers_(modifiers), 86 cursor_(cursor), 87 dispatch_callback_(callback), 88 interpreter_(NULL) {} 89 90 GestureInterpreterLibevdevCros::~GestureInterpreterLibevdevCros() { 91 if (interpreter_) { 92 DeleteGestureInterpreter(interpreter_); 93 interpreter_ = NULL; 94 } 95 } 96 97 void GestureInterpreterLibevdevCros::OnLibEvdevCrosOpen( 98 Evdev* evdev, 99 EventStateRec* evstate) { 100 DCHECK(evdev->info.is_monotonic) << "libevdev must use monotonic timestamps"; 101 VLOG(9) << "HACK DO NOT REMOVE OR LINK WILL FAIL" << (void*)gestures_log; 102 103 HardwareProperties hwprops = GestureHardwareProperties(evdev); 104 GestureInterpreterDeviceClass devclass = GestureDeviceClass(evdev); 105 106 // Create & initialize GestureInterpreter. 107 DCHECK(!interpreter_); 108 interpreter_ = NewGestureInterpreter(); 109 GestureInterpreterInitialize(interpreter_, devclass); 110 GestureInterpreterSetHardwareProperties(interpreter_, &hwprops); 111 GestureInterpreterSetTimerProvider( 112 interpreter_, 113 const_cast<GesturesTimerProvider*>(&kGestureTimerProvider), 114 this); 115 GestureInterpreterSetCallback(interpreter_, OnGestureReadyHelper, this); 116 } 117 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); 124 125 // Mouse. 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; 130 131 // Touch. 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) 138 continue; 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; 148 current_finger++; 149 } 150 hwstate.touch_cnt = Event_Get_Touch_Count(evdev); 151 hwstate.finger_cnt = current_finger; 152 hwstate.fingers = fingers; 153 154 // Buttons. 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; 161 162 GestureInterpreterPushHardwareState(interpreter_, &hwstate); 163 } 164 165 void GestureInterpreterLibevdevCros::OnGestureReady(const Gesture* gesture) { 166 switch (gesture->type) { 167 case kGestureTypeMove: 168 OnGestureMove(gesture, &gesture->details.move); 169 break; 170 case kGestureTypeScroll: 171 OnGestureScroll(gesture, &gesture->details.scroll); 172 break; 173 case kGestureTypeButtonsChange: 174 OnGestureButtonsChange(gesture, &gesture->details.buttons); 175 break; 176 case kGestureTypeContactInitiated: 177 OnGestureContactInitiated(gesture); 178 break; 179 case kGestureTypeFling: 180 OnGestureFling(gesture, &gesture->details.fling); 181 break; 182 case kGestureTypeSwipe: 183 OnGestureSwipe(gesture, &gesture->details.swipe); 184 break; 185 case kGestureTypeSwipeLift: 186 OnGestureSwipeLift(gesture, &gesture->details.swipe_lift); 187 break; 188 case kGestureTypePinch: 189 OnGesturePinch(gesture, &gesture->details.pinch); 190 break; 191 case kGestureTypeMetrics: 192 OnGestureMetrics(gesture, &gesture->details.metrics); 193 break; 194 default: 195 LOG(WARNING) << base::StringPrintf("Unrecognized gesture type (%u)", 196 gesture->type); 197 break; 198 } 199 } 200 201 void GestureInterpreterLibevdevCros::OnGestureMove(const Gesture* gesture, 202 const GestureMove* move) { 203 DVLOG(3) << base::StringPrintf("Gesture Move: (%f, %f) [%f, %f]", 204 move->dx, 205 move->dy, 206 move->ordinal_dx, 207 move->ordinal_dy); 208 if (!cursor_) 209 return; // No cursor! 210 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, 215 cursor_->location(), 216 cursor_->location(), 217 modifiers_->GetModifierFlags(), 218 /* changed_button_flags */ 0); 219 Dispatch(&event); 220 } 221 222 void GestureInterpreterLibevdevCros::OnGestureScroll( 223 const Gesture* gesture, 224 const GestureScroll* scroll) { 225 DVLOG(3) << base::StringPrintf("Gesture Scroll: (%f, %f) [%f, %f]", 226 scroll->dx, 227 scroll->dy, 228 scroll->ordinal_dx, 229 scroll->ordinal_dy); 230 if (!cursor_) 231 return; // No cursor! 232 233 // TODO(spang): Support SetNaturalScroll 234 // TODO(spang): Use scroll->start_time 235 ScrollEvent event(ET_SCROLL, 236 cursor_->location(), 237 StimeToTimedelta(gesture->end_time), 238 modifiers_->GetModifierFlags(), 239 scroll->dx, 240 scroll->dy, 241 scroll->ordinal_dx, 242 scroll->ordinal_dy, 243 kGestureScrollFingerCount); 244 Dispatch(&event); 245 } 246 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", 251 buttons->down, 252 buttons->up); 253 254 if (!cursor_) 255 return; // No cursor! 256 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()) 263 return; 264 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); 278 } 279 280 void GestureInterpreterLibevdevCros::OnGestureContactInitiated( 281 const Gesture* gesture) { 282 // TODO(spang): handle contact initiated. 283 } 284 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", 289 fling->vx, 290 fling->vy, 291 fling->ordinal_vx, 292 fling->ordinal_vy, 293 fling->fling_state); 294 295 if (!cursor_) 296 return; // No cursor! 297 298 EventType type = 299 (fling->fling_state == GESTURES_FLING_START ? ET_SCROLL_FLING_START 300 : ET_SCROLL_FLING_CANCEL); 301 302 // Fling is like 2-finger scrolling but with velocity instead of displacement. 303 ScrollEvent event(type, 304 cursor_->location(), 305 StimeToTimedelta(gesture->end_time), 306 modifiers_->GetModifierFlags(), 307 fling->vx, 308 fling->vy, 309 fling->ordinal_vx, 310 fling->ordinal_vy, 311 kGestureScrollFingerCount); 312 Dispatch(&event); 313 } 314 315 void GestureInterpreterLibevdevCros::OnGestureSwipe(const Gesture* gesture, 316 const GestureSwipe* swipe) { 317 DVLOG(3) << base::StringPrintf("Gesture Swipe: (%f, %f) [%f, %f]", 318 swipe->dx, 319 swipe->dy, 320 swipe->ordinal_dx, 321 swipe->ordinal_dy); 322 323 if (!cursor_) 324 return; // No cursor! 325 326 // Swipe is 3-finger scrolling. 327 ScrollEvent event(ET_SCROLL, 328 cursor_->location(), 329 StimeToTimedelta(gesture->end_time), 330 modifiers_->GetModifierFlags(), 331 swipe->dx, 332 swipe->dy, 333 swipe->ordinal_dx, 334 swipe->ordinal_dy, 335 kGestureSwipeFingerCount); 336 Dispatch(&event); 337 } 338 339 void GestureInterpreterLibevdevCros::OnGestureSwipeLift( 340 const Gesture* gesture, 341 const GestureSwipeLift* swipelift) { 342 DVLOG(3) << base::StringPrintf("Gesture Swipe Lift"); 343 344 if (!cursor_) 345 return; // No cursor! 346 347 // Turn a swipe lift into a fling start. 348 // TODO(spang): Figure out why and put it in this comment. 349 350 ScrollEvent event(ET_SCROLL_FLING_START, 351 cursor_->location(), 352 StimeToTimedelta(gesture->end_time), 353 modifiers_->GetModifierFlags(), 354 /* x_offset */ 0, 355 /* y_offset */ 0, 356 /* x_offset_ordinal */ 0, 357 /* y_offset_ordinal */ 0, 358 kGestureScrollFingerCount); 359 Dispatch(&event); 360 361 } 362 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); 367 368 if (!cursor_) 369 return; // No cursor! 370 371 NOTIMPLEMENTED(); 372 } 373 374 void GestureInterpreterLibevdevCros::OnGestureMetrics( 375 const Gesture* gesture, 376 const GestureMetrics* metrics) { 377 DVLOG(3) << base::StringPrintf("Gesture Metrics: [%f, %f] type=%d", 378 metrics->data[0], 379 metrics->data[1], 380 metrics->type); 381 NOTIMPLEMENTED(); 382 } 383 384 void GestureInterpreterLibevdevCros::Dispatch(Event* event) { 385 dispatch_callback_.Run(event); 386 } 387 388 void GestureInterpreterLibevdevCros::DispatchMouseButton(unsigned int modifier, 389 bool down) { 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); 395 Dispatch(&event); 396 } 397 398 } // namespace ui 399