diff options
author | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-02 22:33:46 +0000 |
---|---|---|
committer | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-02 22:33:46 +0000 |
commit | 8e6a45cde3a16754f07584b1f4e231796a3aa55e (patch) | |
tree | d1843159571a7bbed41b9f27b67ebd480d4d3efc /views | |
parent | 22f98ef5aa98b9d7d2d54f2ab9635f6e1d3ed5f9 (diff) | |
download | chromium_src-8e6a45cde3a16754f07584b1f4e231796a3aa55e.zip chromium_src-8e6a45cde3a16754f07584b1f4e231796a3aa55e.tar.gz chromium_src-8e6a45cde3a16754f07584b1f4e231796a3aa55e.tar.bz2 |
Get the correct touch identifiers from an X event.
Getting the correct touch identifiers makes it possible to do multi-finger
tracking.
BUG=none
TEST=manually
Review URL: http://codereview.chromium.org/6905074
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@83811 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r-- | views/events/event_x.cc | 51 | ||||
-rw-r--r-- | views/focus/accelerator_handler_touch.cc | 20 | ||||
-rw-r--r-- | views/touchui/touch_factory.cc | 19 | ||||
-rw-r--r-- | views/touchui/touch_factory.h | 36 |
4 files changed, 99 insertions, 27 deletions
diff --git a/views/events/event_x.cc b/views/events/event_x.cc index 5441282..74b6ca3 100644 --- a/views/events/event_x.cc +++ b/views/events/event_x.cc @@ -84,30 +84,43 @@ int GetButtonMaskForX2Event(XIDeviceEvent* xievent) { ui::EventType GetTouchEventType(XEvent* xev) { XGenericEventCookie* cookie = &xev->xcookie; - switch (cookie->evtype) { - case XI_ButtonPress: - return ui::ET_TOUCH_PRESSED; - case XI_ButtonRelease: - return ui::ET_TOUCH_RELEASED; - case XI_Motion: - return ui::ET_TOUCH_MOVED; - - // Note: We will not generate a _STATIONARY event here. It will be created, - // when necessary, by a RWHVV. - - // TODO(sad): When do we trigger a _CANCELLED event? Maybe that will also be - // done by a RWHVV, e.g. when it gets destroyed in the middle of a - // touch-sequence? + DCHECK_EQ(cookie->evtype, ui::ET_TOUCH_MOVED); + + // Note: We will not generate a _STATIONARY event here. It will be created, + // when necessary, by a RWHVV. + // TODO(sad): When should _CANCELLED be generated? + + TouchFactory* factory = TouchFactory::GetInstance(); + float slot; + if (!factory->ExtractTouchParam(*xev, TouchFactory::TP_SLOT_ID, &slot)) + return ui::ET_UNKNOWN; + + if (!factory->IsSlotUsed(slot)) { + // This is a new touch point. + factory->SetSlotUsed(slot, true); + return ui::ET_TOUCH_PRESSED; } - return ui::ET_UNKNOWN; + float tracking; + if (!factory->ExtractTouchParam(*xev, TouchFactory::TP_TRACKING_ID, + &tracking)) + return ui::ET_UNKNOWN; + + if (tracking == 0l) { + // The touch point has been released. + factory->SetSlotUsed(slot, false); + return ui::ET_TOUCH_RELEASED; + } + + return ui::ET_TOUCH_MOVED; } int GetTouchIDFromXEvent(XEvent* xev) { - // TODO(sad): How we determine the touch-id from the event is as yet - // undecided. - XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev->xcookie.data); - return xiev->sourceid; + float slot = 0; + if (!TouchFactory::GetInstance()->ExtractTouchParam( + *xev, TouchFactory::TP_SLOT_ID, &slot)) + LOG(ERROR) << "Could not get the slot ID for the event. Using 0."; + return slot; } #endif // HAVE_XINPUT2 diff --git a/views/focus/accelerator_handler_touch.cc b/views/focus/accelerator_handler_touch.cc index 2709e70..032b29d 100644 --- a/views/focus/accelerator_handler_touch.cc +++ b/views/focus/accelerator_handler_touch.cc @@ -65,19 +65,32 @@ bool DispatchX2Event(Widget* widget, XEvent* xev) { return widget->OnMouseEvent(wheelev); } - MouseEvent mouseev(xev, from_native); - // TODO(sad): Determine if the captured event is a touch-event. // Is the event coming from a touch device? if (TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid)) { // Hide the cursor when a touch event comes in. TouchFactory::GetInstance()->SetCursorVisible(false, false); + + // With XInput 2.0, XI_ButtonPress and XI_ButtonRelease events are + // ignored, as XI_Motion events contain enough data to detect finger + // press and release. See more notes in TouchFactory::TouchParam. + if (cookie->evtype == XI_ButtonPress || + cookie->evtype == XI_ButtonRelease) + return false; + // If the TouchEvent is processed by |root|, then return. Otherwise let // it fall through so it can be used as a MouseEvent, if desired. TouchEvent touch(xev, from_native); RootView* root = widget->GetRootView(); if (root->OnTouchEvent(touch) != views::View::TOUCH_STATUS_UNKNOWN) return true; + + // We do not want to generate a mouse event for an unprocessed touch + // event here. That is already done by the gesture manager in + // RootView::OnTouchEvent. + return false; } else { + MouseEvent mouseev(xev, from_native); + // Show the cursor. Start a timer to hide the cursor after a delay on // move (not drag) events, or if the only button pressed is released. bool start_timer = mouseev.type() == ui::ET_MOUSE_MOVED; @@ -86,8 +99,9 @@ bool DispatchX2Event(Widget* widget, XEvent* xev) { mouseev.IsOnlyMiddleMouseButton() || mouseev.IsOnlyRightMouseButton()); TouchFactory::GetInstance()->SetCursorVisible(true, start_timer); + + return widget->OnMouseEvent(mouseev); } - return widget->OnMouseEvent(mouseev); } } return false; diff --git a/views/touchui/touch_factory.cc b/views/touchui/touch_factory.cc index f9b859c..fefe35f 100644 --- a/views/touchui/touch_factory.cc +++ b/views/touchui/touch_factory.cc @@ -28,6 +28,9 @@ char FindTPValuator(Display* display, views::TouchFactory::TouchParam touch_param) { // Lookup table for mapping TouchParam to Atom string used in X. // A full set of Atom strings can be found at xserver-properties.h. + // For Slot ID, See this chromeos revision: http://git.chromium.org/gitweb/? + // p=chromiumos/overlays/chromiumos-overlay.git; + // a=commit;h=9164d0a75e48c4867e4ef4ab51f743ae231c059a static struct { views::TouchFactory::TouchParam tp; const char* atom; @@ -35,6 +38,8 @@ char FindTPValuator(Display* display, { views::TouchFactory::TP_TOUCH_MAJOR, "Abs MT Touch Major" }, { views::TouchFactory::TP_TOUCH_MINOR, "Abs MT Touch Minor" }, { views::TouchFactory::TP_ORIENTATION, "Abs MT Orientation" }, + { views::TouchFactory::TP_SLOT_ID, "Abs MT Slot ID" }, + { views::TouchFactory::TP_TRACKING_ID, "Abs MT Tracking ID" }, { views::TouchFactory::TP_LAST_ENTRY, NULL }, }; @@ -57,7 +62,6 @@ char FindTPValuator(Display* display, reinterpret_cast<XIValuatorClassInfo*>(info->classes[i]); const char* atom = XGetAtomName(display, v->label); - if (atom && strcmp(atom, atom_tp) == 0) return v->number; } @@ -120,7 +124,8 @@ TouchFactory::TouchFactory() : is_cursor_visible_(true), cursor_timer_(), pointer_device_lookup_(), - touch_device_list_() { + touch_device_list_(), + slots_used_() { char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; XColor black; black.red = black.green = black.blue = 0; @@ -265,6 +270,16 @@ bool TouchFactory::IsTouchDevice(unsigned deviceid) const { touch_device_lookup_[deviceid] : false; } +bool TouchFactory::IsSlotUsed(int slot) const { + CHECK_LT(slot, kMaxTouchPoints); + return slots_used_[slot]; +} + +void TouchFactory::SetSlotUsed(int slot, bool used) { + CHECK_LT(slot, kMaxTouchPoints); + slots_used_[slot] = used; +} + bool TouchFactory::GrabTouchDevices(Display* display, ::Window window) { if (touch_device_list_.empty()) return true; diff --git a/views/touchui/touch_factory.h b/views/touchui/touch_factory.h index e3a8042..e16879d 100644 --- a/views/touchui/touch_factory.h +++ b/views/touchui/touch_factory.h @@ -24,9 +24,27 @@ class TouchFactory { public: // Define the touch params following the Multi-touch Protocol. enum TouchParam { - TP_TOUCH_MAJOR = 0, - TP_TOUCH_MINOR, - TP_ORIENTATION, + TP_TOUCH_MAJOR = 0, // Length of the touch area. + TP_TOUCH_MINOR, // Width of the touch area. + TP_ORIENTATION, // Angle between the X-axis and the major axis of the + // touch area. + + // NOTE: A touch event can have multiple touch points. So when we receive a + // touch event, we need to determine which point triggered the event. + // A touch point can have both a 'Slot ID' and a 'Tracking ID', and they can + // be (in fact, usually are) different. The 'Slot ID' ranges between 0 and + // (X - 1), where X is the maximum touch points supported by the device. The + // 'Tracking ID' can be any 16-bit value. With XInput 2.0, an XI_Motion + // event that comes from a currently-unused 'Slot ID' indicates the creation + // of a new touch point, and any event that comes with a 0 value for + // 'Tracking ID' marks the removal of a touch point. During the lifetime of + // a touchpoint, we use the 'Slot ID' as its identifier. The XI_ButtonPress + // and XI_ButtonRelease events are ignored. + TP_SLOT_ID, // ID of the finger that triggered a touch event + // (useful when tracking multiple simultaneous + // touches) + TP_TRACKING_ID, // ID of the touch point. + TP_LAST_ENTRY }; @@ -51,6 +69,12 @@ class TouchFactory { // Is the device a touch-device? bool IsTouchDevice(unsigned int deviceid) const; + // Is the slot ID currently used? + bool IsSlotUsed(int slot) const; + + // Marks a slot as being used/unused. + void SetSlotUsed(int slot, bool used); + // Grabs the touch devices for the specified window on the specified display. // Returns if grab was successful for all touch devices. bool GrabTouchDevices(Display* display, ::Window window); @@ -131,6 +155,12 @@ class TouchFactory { // hash map. char valuator_lookup_[kMaxDeviceNum][TP_LAST_ENTRY]; + // Maximum simultaneous touch points. + static const int kMaxTouchPoints = 32; + + // A lookup table for slots in use for a touch event. + std::bitset<kMaxTouchPoints> slots_used_; + DISALLOW_COPY_AND_ASSIGN(TouchFactory); }; |