Home | History | Annotate | Download | only in libgestures_glue
      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