diff options
author | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-26 22:24:20 +0000 |
---|---|---|
committer | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-26 22:24:20 +0000 |
commit | cdfc519ae46a03b916535c891cd60a5a1cf53376 (patch) | |
tree | a57fc6fb86cafa2f55e5344b7f57467ab6e2139a /views | |
parent | c931d526dc0b7c7c871e6fc408775feb63493fd1 (diff) | |
download | chromium_src-cdfc519ae46a03b916535c891cd60a5a1cf53376.zip chromium_src-cdfc519ae46a03b916535c891cd60a5a1cf53376.tar.gz chromium_src-cdfc519ae46a03b916535c891cd60a5a1cf53376.tar.bz2 |
touch: Hide the X cursor when not in use.
The default X cursor is hidden at startup, and when not in use for 5 seconds. It
is immediately displayed if there is an event from a mouse device, and it's
immediately hidden if there is an event from a touch device.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/6242012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@72702 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r-- | views/focus/accelerator_handler_touch.cc | 66 | ||||
-rw-r--r-- | views/touchui/touch_factory.cc | 53 | ||||
-rw-r--r-- | views/touchui/touch_factory.h | 30 | ||||
-rw-r--r-- | views/widget/root_view.cc | 15 |
4 files changed, 145 insertions, 19 deletions
diff --git a/views/focus/accelerator_handler_touch.cc b/views/focus/accelerator_handler_touch.cc index b24d8f0..4532034f 100644 --- a/views/focus/accelerator_handler_touch.cc +++ b/views/focus/accelerator_handler_touch.cc @@ -62,18 +62,22 @@ bool X2EventIsTouchEvent(XEvent* xev) { #if defined(HAVE_XINPUT2) bool DispatchX2Event(RootView* root, XEvent* xev) { + XGenericEventCookie* cookie = &xev->xcookie; + bool touch_event = false; + if (X2EventIsTouchEvent(xev)) { + // Hide the cursor when a touch event comes in. + TouchFactory::GetInstance()->SetCursorVisible(false, false); + touch_event = true; + // 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) != views::View::TOUCH_STATUS_UNKNOWN) return true; } - XGenericEventCookie* cookie = &xev->xcookie; - switch (cookie->evtype) { case XI_KeyPress: case XI_KeyRelease: { @@ -81,25 +85,51 @@ bool DispatchX2Event(RootView* root, XEvent* xev) { break; } case XI_ButtonPress: - case XI_ButtonRelease: { + case XI_ButtonRelease: + case XI_Motion: { MouseEvent mouseev(xev); - if (cookie->evtype == XI_ButtonPress) { - return root->OnMousePressed(mouseev); - } else { - root->OnMouseReleased(mouseev, false); - return true; + if (!touch_event) { + // Show the cursor, and decide whether or not the cursor should be + // automatically hidden after a certain time of inactivity. + int button_flags = mouseev.GetFlags() & (Event::EF_RIGHT_BUTTON_DOWN | + Event::EF_MIDDLE_BUTTON_DOWN | Event::EF_LEFT_BUTTON_DOWN); + bool start_timer = false; + + switch (cookie->evtype) { + case XI_ButtonPress: + start_timer = false; + break; + case XI_ButtonRelease: + // For a release, start the timer if this was only button pressed + // that is being released. + if (button_flags == Event::EF_RIGHT_BUTTON_DOWN || + button_flags == Event::EF_LEFT_BUTTON_DOWN || + button_flags == Event::EF_MIDDLE_BUTTON_DOWN) + start_timer = true; + break; + case XI_Motion: + start_timer = !button_flags; + break; + } + TouchFactory::GetInstance()->SetCursorVisible(true, start_timer); } - } - case XI_Motion: { - MouseEvent mouseev(xev); - if (mouseev.GetType() == Event::ET_MOUSE_DRAGGED) { - return root->OnMouseDragged(mouseev); - } else { - root->OnMouseMoved(mouseev); - return true; + // Dispatch the event. + switch (cookie->evtype) { + case XI_ButtonPress: + return root->OnMousePressed(mouseev); + case XI_ButtonRelease: + root->OnMouseReleased(mouseev, false); + return true; + case XI_Motion: { + if (mouseev.GetType() == Event::ET_MOUSE_DRAGGED) { + return root->OnMouseDragged(mouseev); + } else { + root->OnMouseMoved(mouseev); + return true; + } + } } - break; } } diff --git a/views/touchui/touch_factory.cc b/views/touchui/touch_factory.cc index 8608782..472f456 100644 --- a/views/touchui/touch_factory.cc +++ b/views/touchui/touch_factory.cc @@ -7,7 +7,12 @@ #include <gdk/gdkx.h> #include <X11/extensions/XInput2.h> +#include "base/compiler_specific.h" #include "base/logging.h" +#include "ui/base/x/x11_util.h" + +// The X cursor is hidden if it is idle for kCursorIdleSeconds seconds. +static int kCursorIdleSeconds = 5; namespace views { @@ -17,8 +22,25 @@ TouchFactory* TouchFactory::GetInstance() { } TouchFactory::TouchFactory() - : touch_device_lookup_(), + : is_cursor_visible_(true), + cursor_timer_(), touch_device_list_() { + Pixmap blank; + XColor black; + static char nodata[] = { 0,0,0,0,0,0,0,0 }; + black.red = black.green = black.blue = 0; + Display* display = ui::GetXDisplay(); + + blank = XCreateBitmapFromData(display, ui::GetX11RootWindow(), nodata, 8, 8); + invisible_cursor_ = XCreatePixmapCursor(display, blank, blank, + &black, &black, 0, 0); + + SetCursorVisible(false, false); +} + +TouchFactory::~TouchFactory() { + SetCursorVisible(true, false); + XFreeCursor(ui::GetXDisplay(), invisible_cursor_); } void TouchFactory::SetTouchDeviceList( @@ -76,4 +98,33 @@ bool TouchFactory::UngrabTouchDevices(Display* display) { return success; } +void TouchFactory::SetCursorVisible(bool show, bool start_timer) { + // The cursor is going to be shown. Reset the timer for hiding it. + if (show && start_timer) { + cursor_timer_.Stop(); + cursor_timer_.Start(base::TimeDelta::FromSeconds(kCursorIdleSeconds), + this, &TouchFactory::HideCursorForInactivity), + } else { + cursor_timer_.Stop(); + } + + if (show == is_cursor_visible_) + return; + + is_cursor_visible_ = show; + + GdkDisplay* display = gdk_display_get_default(); + if (!display) + return; + + Display* xdisplay = GDK_DISPLAY_XDISPLAY(display); + Window window = DefaultRootWindow(xdisplay); + + if (is_cursor_visible_) { + XUndefineCursor(xdisplay, window); + } else { + XDefineCursor(xdisplay, window, invisible_cursor_); + } +} + } // namespace views diff --git a/views/touchui/touch_factory.h b/views/touchui/touch_factory.h index 04114be..228812a 100644 --- a/views/touchui/touch_factory.h +++ b/views/touchui/touch_factory.h @@ -10,7 +10,9 @@ #include <vector> #include "base/singleton.h" +#include "base/timer.h" +typedef unsigned long Cursor; typedef unsigned long Window; typedef struct _XDisplay Display; @@ -38,12 +40,40 @@ class TouchFactory { // devices. bool UngrabTouchDevices(Display* display); + // Update the root window to show (or hide) the cursor. Also indicate whether + // the timer should be started to automatically hide the cursor after a + // certain duration of inactivity (i.e. it is ignored if |show| is false). + void SetCursorVisible(bool show, bool start_timer); + + // Whether the cursor is currently visible or not. + bool is_cursor_visible() { + return is_cursor_visible_; + } + private: TouchFactory(); + ~TouchFactory(); + + void HideCursorForInactivity() { + SetCursorVisible(false, false); + } + // Requirement for Signleton friend struct DefaultSingletonTraits<TouchFactory>; + // The default cursor is hidden after startup, and when the mouse pointer is + // idle for a while. Once there is some event from a mouse device, the cursor + // is immediately displayed. + bool is_cursor_visible_; + + // The cursor is hidden if it is idle for a certain amount time. This timer + // is used to keep track of the idleness. + base::OneShotTimer<TouchFactory> cursor_timer_; + + // The invisible cursor. + Cursor invisible_cursor_; + // NOTE: To keep track of touch devices, we currently maintain a lookup table // to quickly decide if a device is a touch device or not. We also maintain a // list of the touch devices. Ideally, there will be only one touch device, diff --git a/views/widget/root_view.cc b/views/widget/root_view.cc index ba60fbc..d9c1ae2 100644 --- a/views/widget/root_view.cc +++ b/views/widget/root_view.cc @@ -6,6 +6,10 @@ #include <algorithm> +#if defined(TOUCH_UI) && defined(HAVE_XINPUT2) +#include <gdk/gdkx.h> +#endif + #include "base/logging.h" #include "base/message_loop.h" #include "gfx/canvas_skia.h" @@ -18,6 +22,10 @@ #if defined(TOUCH_UI) #include "views/touchui/gesture_manager.h" +#if defined(HAVE_XINPUT2) +#include "gfx/gtk_util.h" +#include "views/touchui/touch_factory.h" +#endif #endif #if defined(OS_LINUX) @@ -794,6 +802,13 @@ void RootView::SetActiveCursor(gfx::NativeCursor cursor) { static_cast<WidgetGtk*>(GetWidget())->window_contents(); if (!native_view) return; + +#if defined(TOUCH_UI) && defined(HAVE_XINPUT2) + if (!TouchFactory::GetInstance()->is_cursor_visible()) { + cursor = gfx::GetCursor(GDK_BLANK_CURSOR); + } +#endif + gdk_window_set_cursor(native_view->window, cursor); #endif } |