summaryrefslogtreecommitdiffstats
path: root/views
diff options
context:
space:
mode:
authorsadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-02 22:33:46 +0000
committersadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-02 22:33:46 +0000
commit8e6a45cde3a16754f07584b1f4e231796a3aa55e (patch)
treed1843159571a7bbed41b9f27b67ebd480d4d3efc /views
parent22f98ef5aa98b9d7d2d54f2ab9635f6e1d3ed5f9 (diff)
downloadchromium_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.cc51
-rw-r--r--views/focus/accelerator_handler_touch.cc20
-rw-r--r--views/touchui/touch_factory.cc19
-rw-r--r--views/touchui/touch_factory.h36
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);
};