summaryrefslogtreecommitdiffstats
path: root/views
diff options
context:
space:
mode:
authorsadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-26 22:24:20 +0000
committersadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-26 22:24:20 +0000
commitcdfc519ae46a03b916535c891cd60a5a1cf53376 (patch)
treea57fc6fb86cafa2f55e5344b7f57467ab6e2139a /views
parentc931d526dc0b7c7c871e6fc408775feb63493fd1 (diff)
downloadchromium_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.cc66
-rw-r--r--views/touchui/touch_factory.cc53
-rw-r--r--views/touchui/touch_factory.h30
-rw-r--r--views/widget/root_view.cc15
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
}