diff --git a/src/sugar3/Makefile.am b/src/sugar3/Makefile.am index 1eda7d8f..f25606bb 100644 --- a/src/sugar3/Makefile.am +++ b/src/sugar3/Makefile.am @@ -47,6 +47,8 @@ libsugarext_la_SOURCES = \ gsm-xsmp.h \ sugar-grid.c \ sugar-grid.h \ + sugar-cursor-tracker.c \ + sugar-cursor-tracker.h \ sugar-gesture-grabber.c \ sugar-gesture-grabber.h \ sugar-key-grabber.c \ @@ -128,6 +130,8 @@ SugarExt_1_0_gir_FILES = \ gsm-session.h \ gsm-xsmp.c \ gsm-xsmp.h \ + sugar-cursor-tracker.c \ + sugar-cursor-tracker.h \ sugar-gesture-grabber.c \ sugar-gesture-grabber.h \ sugar-key-grabber.c \ diff --git a/src/sugar3/sugar-cursor-tracker.c b/src/sugar3/sugar-cursor-tracker.c new file mode 100644 index 00000000..a881c506 --- /dev/null +++ b/src/sugar3/sugar-cursor-tracker.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2012 One laptop per child + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Simon Schampijer + */ + +#include +#include +#include "sugar-cursor-tracker.h" + +typedef struct _SugarCursorTrackerPriv SugarCursorTrackerPriv; + +struct _SugarCursorTrackerPriv +{ + GdkWindow *root_window; + gboolean cursor_shown; +}; + +G_DEFINE_TYPE (SugarCursorTracker, sugar_cursor_tracker, G_TYPE_OBJECT) + + +static void +sugar_cursor_tracker_finalize (GObject *object) +{ + SugarCursorTrackerPriv *priv = SUGAR_CURSOR_TRACKER (object)->_priv; + + G_OBJECT_CLASS (sugar_cursor_tracker_parent_class)->finalize (object); +} + +static void +sugar_cursor_tracker_class_init (SugarCursorTrackerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = sugar_cursor_tracker_finalize; + + g_type_class_add_private (klass, sizeof (SugarCursorTrackerPriv)); +} + +static GdkWindow * +_get_default_root_window (void) +{ + GdkDisplay *display; + GdkScreen *screen; + + display = gdk_display_get_default (); + screen = gdk_display_get_default_screen (display); + + return gdk_screen_get_root_window (screen); +} + +static void +_track_raw_events (GdkWindow *window) +{ + XIEventMask mask; + guchar *evmask; + GdkDisplay *display; + + evmask = g_new0 (guchar, XIMaskLen (XI_LASTEVENT)); + XISetMask (evmask, XI_RawTouchBegin); + XISetMask (evmask, XI_RawTouchEnd); + XISetMask (evmask, XI_RawTouchUpdate); + XISetMask (evmask, XI_RawMotion); + XISetMask (evmask, XI_RawButtonPress); + + mask.deviceid = XIAllMasterDevices; + mask.mask_len = sizeof (evmask); + mask.mask = evmask; + + display = gdk_window_get_display (window); + XISelectEvents (gdk_x11_display_get_xdisplay (display), + gdk_x11_window_get_xid (window), + &mask, 1); +} + +static void +_set_cursor_visibility (SugarCursorTracker *tracker, + gboolean visible) +{ + GdkDisplay *display; + Display *xdisplay; + SugarCursorTrackerPriv *priv; + + priv = tracker->_priv; + display = gdk_display_get_default (); + xdisplay = GDK_DISPLAY_XDISPLAY (display); + + gdk_error_trap_push (); + + if (visible == TRUE) { + if (priv->cursor_shown == FALSE) { + XFixesShowCursor (xdisplay, GDK_WINDOW_XID (_get_default_root_window ())); + priv->cursor_shown = TRUE; + } + } + else { + if (priv->cursor_shown == TRUE) { + XFixesHideCursor (xdisplay, GDK_WINDOW_XID (_get_default_root_window ())); + priv->cursor_shown = False; + } + } + + if (gdk_error_trap_pop ()) { + g_warning ("An error occurred trying to %s the cursor", + FALSE ? "show" : "hide"); + } +} + +static GdkFilterReturn +filter_function (GdkXEvent *xevent, + GdkEvent *gdkevent, + gpointer user_data) +{ + XEvent *ev = xevent; + XIEvent *xiev; + SugarCursorTracker *tracker; + + if (ev->type != GenericEvent) + return GDK_FILTER_CONTINUE; + + tracker = user_data; + + xiev = ev->xcookie.data; + + switch (xiev->evtype) { + case XI_RawTouchBegin: + _set_cursor_visibility (tracker, FALSE); + return GDK_FILTER_REMOVE; + case XI_RawMotion: + _set_cursor_visibility (tracker, TRUE); + return GDK_FILTER_REMOVE; + case XI_RawButtonPress: + _set_cursor_visibility (tracker, TRUE); + return GDK_FILTER_REMOVE; + default: + return GDK_FILTER_CONTINUE; + } +} + +static void +sugar_cursor_tracker_init (SugarCursorTracker *tracker) +{ + SugarCursorTrackerPriv *priv; + tracker->_priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (tracker, + SUGAR_TYPE_CURSOR_TRACKER, + SugarCursorTrackerPriv); + priv->root_window = _get_default_root_window (); + priv->cursor_shown = True; + + tracker->_priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (tracker, + SUGAR_TYPE_CURSOR_TRACKER, + SugarCursorTrackerPriv); + priv->root_window = _get_default_root_window (); + _track_raw_events (priv->root_window); + gdk_window_add_filter (NULL, filter_function, tracker); +} + +SugarCursorTracker * +sugar_cursor_tracker_new (void) +{ + return g_object_new (SUGAR_TYPE_CURSOR_TRACKER, NULL); +} diff --git a/src/sugar3/sugar-cursor-tracker.h b/src/sugar3/sugar-cursor-tracker.h new file mode 100644 index 00000000..2ca60d15 --- /dev/null +++ b/src/sugar3/sugar-cursor-tracker.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2012 One laptop per child + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Simon Schampijer + */ + +#ifndef __SUGAR_CURSOR_TRACKER_H__ +#define __SUGAR_CURSOR_TRACKER_H__ + +#include +#include "event-controller/sugar-event-controllers.h" + +G_BEGIN_DECLS + +typedef struct _SugarCursorTracker SugarCursorTracker; +typedef struct _SugarCursorTrackerClass SugarCursorTrackerClass; + +#define SUGAR_TYPE_CURSOR_TRACKER (sugar_cursor_tracker_get_type()) +#define SUGAR_CURSOR_TRACKER(object) (G_TYPE_CHECK_INSTANCE_CAST((object), SUGAR_TYPE_CURSOR_TRACKER, SugarCursorTracker)) +#define SUGAR_CURSOR_TRACKER_CLASS(klass) (G_TYPE_CHACK_CLASS_CAST((klass), SUGAR_TYPE_CURSOR_TRACKER, SugarCursorTrackerClass)) +#define SUGAR_IS_CURSOR_TRACKER(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), SUGAR_TYPE_CURSOR_TRACKER)) +#define SUGAR_IS_CURSOR_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SUGAR_TYPE_CURSOR_TRACKER)) +#define SUGAR_CURSOR_TRACKER_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), SUGAR_TYPE_CURSOR_TRACKER, SugarCursorTrackerClass)) + +struct _SugarCursorTracker { + GObject parent_instance; + gpointer _priv; +}; + +struct _SugarCursorTrackerClass { + GObjectClass parent_class; +}; + +GType sugar_cursor_tracker_get_type (void); +SugarCursorTracker * sugar_cursor_tracker_new (void); + +G_END_DECLS + +#endif /* __SUGAR_CURSOR_TRACKER_H__ */