summaryrefslogtreecommitdiffstats
path: root/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc')
-rw-r--r--chromium/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc274
1 files changed, 274 insertions, 0 deletions
diff --git a/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc b/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc
new file mode 100644
index 00000000000..c41a04d2f08
--- /dev/null
+++ b/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc
@@ -0,0 +1,274 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.h"
+
+#include <gestures/gestures.h>
+#include <libevdev/libevdev.h>
+
+#include "base/strings/stringprintf.h"
+#include "base/timer/timer.h"
+#include "ui/events/event.h"
+#include "ui/events/ozone/evdev/cursor_delegate_evdev.h"
+#include "ui/events/ozone/evdev/event_modifiers_evdev.h"
+#include "ui/events/ozone/evdev/libgestures_glue/gesture_timer_provider.h"
+#include "ui/gfx/geometry/point_f.h"
+
+namespace ui {
+
+namespace {
+
+// Convert libevdev device class to libgestures device class.
+GestureInterpreterDeviceClass GestureDeviceClass(Evdev* evdev) {
+ switch (evdev->info.evdev_class) {
+ case EvdevClassMouse:
+ return GESTURES_DEVCLASS_MOUSE;
+ case EvdevClassMultitouchMouse:
+ return GESTURES_DEVCLASS_MULTITOUCH_MOUSE;
+ case EvdevClassTouchpad:
+ return GESTURES_DEVCLASS_TOUCHPAD;
+ case EvdevClassTouchscreen:
+ return GESTURES_DEVCLASS_TOUCHSCREEN;
+ default:
+ return GESTURES_DEVCLASS_UNKNOWN;
+ }
+}
+
+// Convert libevdev state to libgestures hardware properties.
+HardwareProperties GestureHardwareProperties(Evdev* evdev) {
+ HardwareProperties hwprops;
+ hwprops.left = Event_Get_Left(evdev);
+ hwprops.top = Event_Get_Top(evdev);
+ hwprops.right = Event_Get_Right(evdev);
+ hwprops.bottom = Event_Get_Bottom(evdev);
+ hwprops.res_x = Event_Get_Res_X(evdev);
+ hwprops.res_y = Event_Get_Res_Y(evdev);
+ hwprops.screen_x_dpi = 133;
+ hwprops.screen_y_dpi = 133;
+ hwprops.orientation_minimum = Event_Get_Orientation_Minimum(evdev);
+ hwprops.orientation_maximum = Event_Get_Orientation_Maximum(evdev);
+ hwprops.max_finger_cnt = Event_Get_Slot_Count(evdev);
+ hwprops.max_touch_cnt = Event_Get_Touch_Count_Max(evdev);
+ hwprops.supports_t5r2 = Event_Get_T5R2(evdev);
+ hwprops.support_semi_mt = Event_Get_Semi_MT(evdev);
+ /* buttonpad means a physical button under the touch surface */
+ hwprops.is_button_pad = Event_Get_Button_Pad(evdev);
+ return hwprops;
+}
+
+// Callback from libgestures when a gesture is ready.
+void OnGestureReadyHelper(void* client_data, const Gesture* gesture) {
+ GestureInterpreterLibevdevCros* interpreter =
+ static_cast<GestureInterpreterLibevdevCros*>(client_data);
+ interpreter->OnGestureReady(gesture);
+}
+
+// Convert gestures timestamp (stime_t) to ui::Event timestamp.
+base::TimeDelta StimeToTimedelta(stime_t timestamp) {
+ return base::TimeDelta::FromMicroseconds(timestamp *
+ base::Time::kMicrosecondsPerSecond);
+}
+
+// Number of fingers for scroll gestures.
+const int kGestureScrollFingerCount = 2;
+
+} // namespace
+
+GestureInterpreterLibevdevCros::GestureInterpreterLibevdevCros(
+ EventModifiersEvdev* modifiers,
+ CursorDelegateEvdev* cursor,
+ const EventDispatchCallback& callback)
+ : modifiers_(modifiers),
+ cursor_(cursor),
+ dispatch_callback_(callback),
+ interpreter_(NULL) {}
+
+GestureInterpreterLibevdevCros::~GestureInterpreterLibevdevCros() {
+ if (interpreter_) {
+ DeleteGestureInterpreter(interpreter_);
+ interpreter_ = NULL;
+ }
+}
+
+void GestureInterpreterLibevdevCros::OnLibEvdevCrosOpen(
+ Evdev* evdev,
+ EventStateRec* evstate) {
+ CHECK(evdev->info.is_monotonic) << "libevdev must use monotonic timestamps";
+ VLOG(9) << "HACK DO NOT REMOVE OR LINK WILL FAIL" << (void*)gestures_log;
+
+ HardwareProperties hwprops = GestureHardwareProperties(evdev);
+ GestureInterpreterDeviceClass devclass = GestureDeviceClass(evdev);
+
+ // Create & initialize GestureInterpreter.
+ CHECK(!interpreter_);
+ interpreter_ = NewGestureInterpreter();
+ GestureInterpreterInitialize(interpreter_, devclass);
+ GestureInterpreterSetHardwareProperties(interpreter_, &hwprops);
+ GestureInterpreterSetTimerProvider(
+ interpreter_,
+ const_cast<GesturesTimerProvider*>(&kGestureTimerProvider),
+ this);
+ GestureInterpreterSetCallback(interpreter_, OnGestureReadyHelper, this);
+}
+
+void GestureInterpreterLibevdevCros::OnLibEvdevCrosEvent(Evdev* evdev,
+ EventStateRec* evstate,
+ const timeval& time) {
+ HardwareState hwstate;
+ memset(&hwstate, 0, sizeof(hwstate));
+ hwstate.timestamp = StimeFromTimeval(&time);
+
+ // Mouse.
+ hwstate.rel_x = evstate->rel_x;
+ hwstate.rel_y = evstate->rel_y;
+ hwstate.rel_wheel = evstate->rel_wheel;
+ hwstate.rel_hwheel = evstate->rel_hwheel;
+
+ // Touch.
+ FingerState fingers[Event_Get_Slot_Count(evdev)];
+ memset(&fingers, 0, sizeof(fingers));
+ int current_finger = 0;
+ for (int i = 0; i < evstate->slot_count; i++) {
+ MtSlotPtr slot = &evstate->slots[i];
+ if (slot->tracking_id == -1)
+ continue;
+ fingers[current_finger].touch_major = slot->touch_major;
+ fingers[current_finger].touch_minor = slot->touch_minor;
+ fingers[current_finger].width_major = slot->width_major;
+ fingers[current_finger].width_minor = slot->width_minor;
+ fingers[current_finger].pressure = slot->pressure;
+ fingers[current_finger].orientation = slot->orientation;
+ fingers[current_finger].position_x = slot->position_x;
+ fingers[current_finger].position_y = slot->position_y;
+ fingers[current_finger].tracking_id = slot->tracking_id;
+ current_finger++;
+ }
+ hwstate.touch_cnt = Event_Get_Touch_Count(evdev);
+ hwstate.finger_cnt = current_finger;
+ hwstate.fingers = fingers;
+
+ // Buttons.
+ if (Event_Get_Button_Left(evdev))
+ hwstate.buttons_down |= GESTURES_BUTTON_LEFT;
+ if (Event_Get_Button_Middle(evdev))
+ hwstate.buttons_down |= GESTURES_BUTTON_MIDDLE;
+ if (Event_Get_Button_Right(evdev))
+ hwstate.buttons_down |= GESTURES_BUTTON_RIGHT;
+
+ GestureInterpreterPushHardwareState(interpreter_, &hwstate);
+}
+
+void GestureInterpreterLibevdevCros::OnGestureReady(const Gesture* gesture) {
+ switch (gesture->type) {
+ case kGestureTypeMove:
+ OnGestureMove(gesture, &gesture->details.move);
+ break;
+ case kGestureTypeScroll:
+ OnGestureScroll(gesture, &gesture->details.scroll);
+ break;
+ case kGestureTypeButtonsChange:
+ OnGestureButtonsChange(gesture, &gesture->details.buttons);
+ break;
+ case kGestureTypeContactInitiated:
+ case kGestureTypeFling:
+ case kGestureTypeSwipe:
+ case kGestureTypeSwipeLift:
+ case kGestureTypePinch:
+ case kGestureTypeMetrics:
+ // TODO(spang): Support remaining gestures.
+ NOTIMPLEMENTED();
+ break;
+ default:
+ LOG(WARNING) << base::StringPrintf("Unrecognized gesture type (%u)",
+ gesture->type);
+ break;
+ }
+}
+
+void GestureInterpreterLibevdevCros::OnGestureMove(const Gesture* gesture,
+ const GestureMove* move) {
+ DVLOG(3) << base::StringPrintf("Gesture Move: (%f, %f) [%f, %f]",
+ move->dx,
+ move->dy,
+ move->ordinal_dx,
+ move->ordinal_dy);
+ if (!cursor_)
+ return; // No cursor!
+ cursor_->MoveCursor(gfx::Vector2dF(move->dx, move->dy));
+ // TODO(spang): Use move->ordinal_dx, move->ordinal_dy
+ // TODO(spang): Use move->start_time, move->end_time
+ MouseEvent event(ET_MOUSE_MOVED,
+ cursor_->location(),
+ cursor_->location(),
+ modifiers_->GetModifierFlags(),
+ /* changed_button_flags */ 0);
+ Dispatch(&event);
+}
+
+void GestureInterpreterLibevdevCros::OnGestureScroll(
+ const Gesture* gesture,
+ const GestureScroll* scroll) {
+ if (!cursor_)
+ return; // No cursor!
+ DVLOG(3) << base::StringPrintf("Gesture Scroll: (%f, %f) [%f, %f]",
+ scroll->dx,
+ scroll->dy,
+ scroll->ordinal_dx,
+ scroll->ordinal_dy);
+ // TODO(spang): Support SetNaturalScroll
+ // TODO(spang): Use scroll->start_time
+ ScrollEvent event(ET_SCROLL,
+ cursor_->location(),
+ StimeToTimedelta(gesture->end_time),
+ modifiers_->GetModifierFlags(),
+ scroll->dx,
+ scroll->dy,
+ scroll->ordinal_dx,
+ scroll->ordinal_dy,
+ kGestureScrollFingerCount);
+ Dispatch(&event);
+}
+
+void GestureInterpreterLibevdevCros::OnGestureButtonsChange(
+ const Gesture* gesture,
+ const GestureButtonsChange* buttons) {
+ DVLOG(3) << base::StringPrintf("Gesture Button Change: down=0x%02x up=0x%02x",
+ buttons->down,
+ buttons->up);
+ // TODO(spang): Use buttons->start_time, buttons->end_time
+ if (buttons->down & GESTURES_BUTTON_LEFT)
+ DispatchMouseButton(EVDEV_MODIFIER_LEFT_MOUSE_BUTTON, true);
+ if (buttons->down & GESTURES_BUTTON_MIDDLE)
+ DispatchMouseButton(EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON, true);
+ if (buttons->down & GESTURES_BUTTON_RIGHT)
+ DispatchMouseButton(EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON, true);
+ if (buttons->up & GESTURES_BUTTON_LEFT)
+ DispatchMouseButton(EVDEV_MODIFIER_LEFT_MOUSE_BUTTON, false);
+ if (buttons->up & GESTURES_BUTTON_MIDDLE)
+ DispatchMouseButton(EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON, false);
+ if (buttons->up & GESTURES_BUTTON_RIGHT)
+ DispatchMouseButton(EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON, false);
+}
+
+void GestureInterpreterLibevdevCros::Dispatch(Event* event) {
+ dispatch_callback_.Run(event);
+}
+
+void GestureInterpreterLibevdevCros::DispatchMouseButton(unsigned int modifier,
+ bool down) {
+ if (!cursor_)
+ return; // No cursor!
+ const gfx::PointF& loc = cursor_->location();
+ int flag = modifiers_->GetEventFlagFromModifier(modifier);
+ EventType type = (down ? ET_MOUSE_PRESSED : ET_MOUSE_RELEASED);
+ modifiers_->UpdateModifier(modifier, down);
+ MouseEvent event(type, loc, loc, modifiers_->GetModifierFlags() | flag, flag);
+
+ // This hack is necessary to trigger setting the repeat count.
+ // TODO(spang): Fix it.
+ MouseEvent event2(&event);
+ Dispatch(&event2);
+}
+
+} // namespace ui