diff options
author | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-23 19:35:18 +0000 |
---|---|---|
committer | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-23 19:35:18 +0000 |
commit | 194bf38fe616b10b0d3c551292db6832567186d9 (patch) | |
tree | bacebff474c08a2531c2464024afbb72a90dac22 /views | |
parent | 909116fdb8f7eaaf225bdf3314fdf4e46d42f115 (diff) | |
download | chromium_src-194bf38fe616b10b0d3c551292db6832567186d9.zip chromium_src-194bf38fe616b10b0d3c551292db6832567186d9.tar.gz chromium_src-194bf38fe616b10b0d3c551292db6832567186d9.tar.bz2 |
touchui: Create touch-events.
Create and process touch-events. The touch-events are created from
pointer-events. The way to decide whether a 'pointer event' originated from a
touch-device is not yet well-defined. So for now, use the --touch-devices
command line parameter to specify which pointer devices should be treated as
touch-device. For example, you can run:
./out/Debug/chrome --touch-devices=7,8
to treat the events coming in from devices with id 7 and 8 as touch events.
(these are the slave ids you get from 'xinput list')
BUG=None
TEST=None
Review URL: http://codereview.chromium.org/4738001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@67133 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r-- | views/event.h | 4 | ||||
-rw-r--r-- | views/event_x.cc | 49 | ||||
-rw-r--r-- | views/focus/accelerator_handler.h | 9 | ||||
-rw-r--r-- | views/focus/accelerator_handler_touch.cc | 58 | ||||
-rw-r--r-- | views/widget/root_view.cc | 6 |
5 files changed, 120 insertions, 6 deletions
diff --git a/views/event.h b/views/event.h index ab9abf3..1ec666d 100644 --- a/views/event.h +++ b/views/event.h @@ -297,6 +297,10 @@ class TouchEvent : public LocatedEvent { // from 'from' coordinate system to 'to' coordinate system. TouchEvent(const TouchEvent& model, View* from, View* to); +#if defined(HAVE_XINPUT2) + explicit TouchEvent(XEvent* xev); +#endif + // Return the touch point for this event. bool identity() const { return touch_id_; diff --git a/views/event_x.cc b/views/event_x.cc index 60b0d2f..774aa7f 100644 --- a/views/event_x.cc +++ b/views/event_x.cc @@ -71,6 +71,46 @@ int GetButtonMaskForX2Event(XIDeviceEvent* xievent) { return buttonflags; } + +Event::EventType GetTouchEventType(XEvent* xev) { + XGenericEventCookie* cookie = &xev->xcookie; + switch (cookie->evtype) { + case XI_ButtonPress: + return Event::ET_TOUCH_PRESSED; + case XI_ButtonRelease: + return Event::ET_TOUCH_RELEASED; + case XI_Motion: + return Event::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? + } + + return Event::ET_UNKNOWN; +} + +gfx::Point GetTouchEventLocation(XEvent* xev) { + XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev->xcookie.data); + return gfx::Point(xiev->event_x, xiev->event_y); +} + +int GetTouchEventFlags(XEvent* xev) { + XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev->xcookie.data); + return GetButtonMaskForX2Event(xiev) | + GetEventFlagsFromXState(xiev->mods.effective); +} + +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; +} + #endif // HAVE_XINPUT2 Event::EventType GetMouseEventType(XEvent* xev) { @@ -182,4 +222,13 @@ MouseWheelEvent::MouseWheelEvent(XEvent* xev) // used for GTK+. } +#if defined(HAVE_XINPUT2) +TouchEvent::TouchEvent(XEvent* xev) + : LocatedEvent(GetTouchEventType(xev), + GetTouchEventLocation(xev), + GetTouchEventFlags(xev)), + touch_id_(GetTouchIDFromXEvent(xev)) { +} +#endif + } // namespace views diff --git a/views/focus/accelerator_handler.h b/views/focus/accelerator_handler.h index 088f3f1..2d08e47 100644 --- a/views/focus/accelerator_handler.h +++ b/views/focus/accelerator_handler.h @@ -13,6 +13,7 @@ #endif #include <set> +#include <vector> #include "base/message_loop.h" @@ -22,7 +23,13 @@ namespace views { // Dispatch an XEvent to the RootView. Return true if the event was dispatched // and handled, false otherwise. bool DispatchXEvent(XEvent* xevent); -#endif + +#if defined(HAVE_XINPUT2) +// Keep a list of touch devices so that it is possible to determine if a pointer +// event is a touch-event or a mouse-event. +void SetTouchDeviceList(std::vector<unsigned int>& devices); +#endif // HAVE_XINPUT2 +#endif // TOUCH_UI // This class delegates the key messages to the associated FocusManager class // for the window that is receiving these messages for accelerator processing. diff --git a/views/focus/accelerator_handler_touch.cc b/views/focus/accelerator_handler_touch.cc index aa971d5..a35fc45 100644 --- a/views/focus/accelerator_handler_touch.cc +++ b/views/focus/accelerator_handler_touch.cc @@ -4,6 +4,7 @@ #include "views/focus/accelerator_handler.h" +#include <bitset> #include <gtk/gtk.h> #if defined(HAVE_XINPUT2) #include <X11/extensions/XInput2.h> @@ -19,6 +20,36 @@ namespace views { +#if defined(HAVE_XINPUT2) +// Functions related to determining touch devices. +class TouchFactory { + public: + // Keep a list of touch devices so that it is possible to determine if a + // pointer event is a touch-event or a mouse-event. + static void SetTouchDeviceListInternal( + const std::vector<unsigned int>& devices) { + for (std::vector<unsigned int>::const_iterator iter = devices.begin(); + iter != devices.end(); ++iter) { + DCHECK(*iter < touch_devices.size()); + touch_devices[*iter] = true; + } + } + + // Is the device a touch-device? + static bool IsTouchDevice(unsigned int deviceid) { + return deviceid < touch_devices.size() ? touch_devices[deviceid] : false; + } + + private: + // A quick lookup table for determining if a device is a touch device. + static std::bitset<128> touch_devices; + + DISALLOW_COPY_AND_ASSIGN(TouchFactory); +}; + +std::bitset<128> TouchFactory::touch_devices; +#endif + namespace { RootView* FindRootViewForGdkWindow(GdkWindow* gdk_window) { @@ -41,7 +72,18 @@ RootView* FindRootViewForGdkWindow(GdkWindow* gdk_window) { #if defined(HAVE_XINPUT2) bool X2EventIsTouchEvent(XEvent* xev) { // TODO(sad): Determine if the captured event is a touch-event. - return false; + XGenericEventCookie* cookie = &xev->xcookie; + switch (cookie->evtype) { + case XI_ButtonPress: + case XI_ButtonRelease: + case XI_Motion: { + // Is the event coming from a touch device? + return TouchFactory::IsTouchDevice( + static_cast<XIDeviceEvent*>(cookie->data)->sourceid); + } + default: + return false; + } } #endif // HAVE_XINPUT2 @@ -50,13 +92,13 @@ bool X2EventIsTouchEvent(XEvent* xev) { #if defined(HAVE_XINPUT2) bool DispatchX2Event(RootView* root, XEvent* xev) { if (X2EventIsTouchEvent(xev)) { - // TODO(sad): Create a TouchEvent, and send it off to |root|. If the event + // Create a TouchEvent, and send it off to |root|. If the event // is processed by |root|, then return. Otherwise let it fall through so it // can be used (if desired) as a mouse event. - // TouchEvent touch(xev); - // if (root->OnTouchEvent(touch)) - // return true; + TouchEvent touch(xev); + if (root->OnTouchEvent(touch)) + return true; } XGenericEventCookie* cookie = &xev->xcookie; @@ -171,6 +213,12 @@ bool DispatchXEvent(XEvent* xev) { return false; } +#if defined(HAVE_XINPUT2) +void SetTouchDeviceList(std::vector<unsigned int>& devices) { + TouchFactory::SetTouchDeviceListInternal(devices); +} +#endif + AcceleratorHandler::AcceleratorHandler() {} bool AcceleratorHandler::Dispatch(GdkEvent* event) { diff --git a/views/widget/root_view.cc b/views/widget/root_view.cc index 753e9de..92f6cf7 100644 --- a/views/widget/root_view.cc +++ b/views/widget/root_view.cc @@ -285,6 +285,12 @@ void RootView::ViewHierarchyChanged(bool is_add, View* parent, View* child) { default_keyboard_handler_ = NULL; } +#if defined(TOUCH_UI) + if (touch_pressed_handler_) { + touch_pressed_handler_ = NULL; + } +#endif + FocusManager* focus_manager = widget_->GetFocusManager(); // An unparanted RootView does not have a FocusManager. if (focus_manager) |