mousetweaks r126 - in trunk: . data src



Author: gerdk
Date: Sat Mar 29 20:33:23 2008
New Revision: 126
URL: http://svn.gnome.org/viewvc/mousetweaks?rev=126&view=rev

Log:
2008-03-29 Gerd Kohlberger <gerdk svn gnome org>

	* src/mt-cusor.c/h: Initial commit.
	* src/mt-cusor-manager.c/h: Initial commit.
	* src/Makefile.am: Add new cursor files.
	* src/mt-main.c/h: Use new objects. Add cursor drawing code.
	* src/mt-common.h: New animate_cursor option.
	* data/mousetwaks.schemas.in: New animate_cursor option.

	Add cursor animation to give visual feedback for the internal
	state of the timers. For dwell-click this means - how long the 
	cursor has been motionless, for secondary clicks - how long the
	primary button has been pressed.



Added:
   trunk/src/mt-cursor-manager.c
   trunk/src/mt-cursor-manager.h
   trunk/src/mt-cursor.c
   trunk/src/mt-cursor.h
Modified:
   trunk/ChangeLog
   trunk/data/mousetweaks.schemas.in
   trunk/src/Makefile.am
   trunk/src/mt-common.h
   trunk/src/mt-main.c
   trunk/src/mt-main.h

Modified: trunk/data/mousetweaks.schemas.in
==============================================================================
--- trunk/data/mousetweaks.schemas.in	(original)
+++ trunk/data/mousetweaks.schemas.in	Sat Mar 29 20:33:23 2008
@@ -133,5 +133,16 @@
           <long>Button style in click type window ("0" = Text, "1" = Icon, "2" = Both)</long>
         </locale>
       </schema>
+      <schema>
+        <key>/schemas/desktop/gnome/accessibility/mouse/animate_cursor</key>
+	<applyto>/desktop/gnome/accessibility/mouse/animate_cursor</applyto>
+        <owner>mousetweaks</owner>
+        <type>bool</type>
+        <default>true</default>
+        <locale name="C">
+          <short>Animate cursor</short>
+          <long>Show elapsed time as cursor overlay.</long>
+        </locale>
+      </schema>
     </schemalist>
 </gconfschemafile>

Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am	(original)
+++ trunk/src/Makefile.am	Sat Mar 29 20:33:23 2008
@@ -13,19 +13,23 @@
 
 bin_PROGRAMS = mousetweaks $(pca_bin) $(dca_bin)
 
-mousetweaks_SOURCES =	\
-	mt-main.c	\
-	mt-main.h	\
-	mt-common.c	\
-	mt-common.h	\
-	mt-pidfile.c	\
-	mt-pidfile.h	\
-	mt-service.c	\
-	mt-service.h	\
-	mt-ctw.c	\
-	mt-ctw.h	\
-	mt-timer.c	\
-	mt-timer.h
+mousetweaks_SOURCES =	    \
+	mt-main.c	    \
+	mt-main.h	    \
+	mt-common.c	    \
+	mt-common.h	    \
+	mt-pidfile.c	    \
+	mt-pidfile.h	    \
+	mt-service.c	    \
+	mt-service.h	    \
+	mt-ctw.c	    \
+	mt-ctw.h	    \
+	mt-timer.c	    \
+	mt-timer.h	    \
+	mt-cursor.c	    \
+	mt-cursor.h	    \
+	mt-cursor-manager.c \
+	mt-cursor-manager.h
 
 mousetweaks_LDFLAGS = $(DEPENDENCIES_LIBS)
 

Modified: trunk/src/mt-common.h
==============================================================================
--- trunk/src/mt-common.h	(original)
+++ trunk/src/mt-common.h	Sat Mar 29 20:33:23 2008
@@ -43,6 +43,7 @@
 #define OPT_G_DRAG    MT_GCONF_HOME "/dwell_gesture_drag"
 #define OPT_G_RIGHT   MT_GCONF_HOME "/dwell_gesture_secondary"
 #define OPT_STYLE     MT_GCONF_HOME "/button_layout"
+#define OPT_ANIMATE   MT_GCONF_HOME "/animate_cursor"
 
 enum {
     DWELL_MODE_CTW = 0,

Added: trunk/src/mt-cursor-manager.c
==============================================================================
--- (empty file)
+++ trunk/src/mt-cursor-manager.c	Sat Mar 29 20:33:23 2008
@@ -0,0 +1,315 @@
+/*
+ * Copyright  2008 Gerd Kohlberger <lowfi chello at>
+ *
+ * This file is part of Mousetweaks.
+ *
+ * Mousetweaks is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mousetweaks 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <X11/Xcursor/Xcursor.h>
+#include <X11/extensions/Xfixes.h>
+
+#include "mt-cursor.h"
+#include "mt-cursor-manager.h"
+
+#define MT_CURSOR_MANAGER_GET_PRIVATE(o) \
+    (G_TYPE_INSTANCE_GET_PRIVATE ((o), MT_TYPE_CURSOR_MANAGER, MtCursorManagerPrivate))
+
+static int fixes_event = 0;
+static int fixes_error = 0;
+
+typedef struct _MtCursorManagerPrivate MtCursorManagerPrivate;
+struct _MtCursorManagerPrivate {
+    GHashTable *cache;
+    gboolean    cursor_set;
+};
+
+enum {
+    CURSOR_CHANGED,
+    LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (MtCursorManager, mt_cursor_manager, G_TYPE_OBJECT)
+
+static void            mt_cursor_manager_finalize    (GObject         *object);
+static void            mt_cursor_manager_clear_cache (MtCursorManager *manager);
+static GdkFilterReturn xfixes_filter                 (GdkXEvent       *xevent,
+						      GdkEvent        *event,
+						      gpointer         data);
+
+static void
+mt_cursor_manager_class_init (MtCursorManagerClass *klass)
+{
+    G_OBJECT_CLASS (klass)->finalize = mt_cursor_manager_finalize;
+
+    signals[CURSOR_CHANGED] =
+	g_signal_new (g_intern_static_string ("cursor_changed"),
+		      G_OBJECT_CLASS_TYPE (klass),
+		      G_SIGNAL_RUN_LAST,
+		      0, NULL, NULL,
+		      g_cclosure_marshal_VOID__STRING,
+		      G_TYPE_NONE, 1, G_TYPE_STRING);
+
+    g_type_class_add_private (klass, sizeof (MtCursorManagerPrivate));
+}
+
+static void
+mt_cursor_manager_init (MtCursorManager *manager)
+{
+    MtCursorManagerPrivate *priv = MT_CURSOR_MANAGER_GET_PRIVATE (manager);
+
+    priv->cache = NULL;
+    priv->cursor_set = FALSE;
+}
+
+static void
+mt_cursor_manager_finalize (GObject *object)
+{
+    MtCursorManagerPrivate *priv = MT_CURSOR_MANAGER_GET_PRIVATE (object);
+
+    gdk_window_remove_filter (gdk_get_default_root_window (),
+			      xfixes_filter, object);
+
+    if (priv->cache)
+	g_hash_table_destroy (priv->cache);
+
+    G_OBJECT_CLASS (mt_cursor_manager_parent_class)->finalize (object);
+}
+
+static gboolean
+mt_cursor_manager_set_xcursor (MtCursor *cursor)
+{
+    XcursorImage *ximage;
+    const guchar *image;
+    Cursor        xcursor;
+    gushort       width, height;
+    gushort       xhot, yhot;
+
+    mt_cursor_get_hotspot (cursor, &xhot, &yhot);
+    mt_cursor_get_dimension (cursor, &width, &height);
+    image = mt_cursor_get_image (cursor);
+
+    ximage = XcursorImageCreate (width, height);
+    ximage->xhot = xhot;
+    ximage->yhot = yhot;
+    ximage->delay = 0;
+    ximage->pixels = (XcursorPixel *) image;
+
+    xcursor = XcursorImageLoadCursor (GDK_DISPLAY (), ximage);
+    if (xcursor) {
+	const gchar *name;
+
+	name = mt_cursor_get_name (cursor);
+	XFixesSetCursorName (GDK_DISPLAY (), xcursor, name);
+	XFixesChangeCursorByName (GDK_DISPLAY (), xcursor, name);
+	XFreeCursor (GDK_DISPLAY (), xcursor);
+	XcursorImageDestroy (ximage);
+
+	return TRUE;
+    }
+
+    XcursorImageDestroy (ximage);
+
+    return FALSE;
+}
+
+static void
+mt_cursor_manager_restore_cursor (gpointer key,
+				  gpointer value,
+				  gpointer data)
+{
+    MtCursorManagerPrivate *priv = MT_CURSOR_MANAGER_GET_PRIVATE (data);
+
+    priv->cursor_set = mt_cursor_manager_set_xcursor (MT_CURSOR (value));
+}
+
+static void
+mt_cursor_manager_add_cursor (MtCursorManager   *manager,
+			      XFixesCursorImage *image)
+{
+    MtCursor *cursor;
+    MtCursorManagerPrivate *priv;
+
+    cursor = mt_cursor_new (image->name, (guchar *) image->pixels,
+			    image->width, image->height,
+			    image->xhot, image->yhot);
+
+    if (cursor) {
+	priv = MT_CURSOR_MANAGER_GET_PRIVATE (manager);
+	g_hash_table_insert (priv->cache, g_strdup (image->name), cursor);
+    }
+}
+
+static GdkFilterReturn
+xfixes_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data)
+{
+    XEvent *xev = (XEvent *) xevent;
+
+    if (xev->type == fixes_event + XFixesCursorNotify) {
+	XFixesCursorNotifyEvent *cn = (XFixesCursorNotifyEvent *) xev;
+	MtCursorManager *manager = (MtCursorManager *) data;
+
+	if (cn->cursor_name != None) {
+	    MtCursorManagerPrivate *priv = MT_CURSOR_MANAGER_GET_PRIVATE (manager);
+
+	    if (!priv->cursor_set) {
+		XFixesCursorImage *image;
+
+		image = XFixesGetCursorImage (GDK_DISPLAY ());
+
+		if (mt_cursor_manager_lookup_cursor (manager, image->name) == NULL)
+		    mt_cursor_manager_add_cursor (manager, image);
+
+		g_signal_emit (manager, signals[CURSOR_CHANGED], 0, image->name);
+
+		XFree (image);
+	    }
+	    else
+		priv->cursor_set = FALSE;
+	}
+	else
+	    g_signal_emit (manager, signals[CURSOR_CHANGED], 0, "");
+    }
+
+    return GDK_FILTER_CONTINUE;
+}
+
+_clear_cursor_cache (GObject    *settings,
+		     GParamSpec *pspec,
+		     gpointer    data)
+{
+    mt_cursor_manager_clear_cache (data);
+}
+
+static MtCursorManager *
+mt_cursor_manager_new (void)
+{
+    MtCursorManager *manager;
+    MtCursorManagerPrivate *priv;
+    GtkSettings *settings;
+
+    manager = g_object_new (MT_TYPE_CURSOR_MANAGER, NULL);
+    priv = MT_CURSOR_MANAGER_GET_PRIVATE (manager);
+    priv->cache = g_hash_table_new_full (g_str_hash, g_str_equal,
+					 g_free, g_object_unref);
+
+    XFixesQueryExtension (GDK_DISPLAY (), &fixes_event, &fixes_error);
+    XFixesSelectCursorInput (GDK_DISPLAY (), GDK_ROOT_WINDOW (),
+			     XFixesDisplayCursorNotifyMask);
+
+    gdk_window_add_filter (gdk_get_default_root_window (),
+			   xfixes_filter, manager);
+
+    settings = gtk_settings_get_default ();
+    g_signal_connect (settings, "notify::gtk-cursor-theme-name",
+		      G_CALLBACK (_clear_cursor_cache), manager);
+    g_signal_connect (settings, "notify::gtk-cursor-theme-size",
+		      G_CALLBACK (_clear_cursor_cache), manager);
+
+    return manager;
+}
+
+MtCursorManager *
+mt_cursor_manager_get_default (void)
+{
+    static MtCursorManager *manager = NULL;
+
+    if (manager == NULL)
+	manager = mt_cursor_manager_new ();
+
+    return manager;
+}
+
+static void
+mt_cursor_manager_clear_cache (MtCursorManager *manager)
+{
+    MtCursorManagerPrivate *priv;
+
+    g_return_if_fail (MT_IS_CURSOR_MANAGER (manager));
+
+    priv = MT_CURSOR_MANAGER_GET_PRIVATE (manager);
+    g_hash_table_remove_all (priv->cache);
+}
+
+MtCursor *
+mt_cursor_manager_current_cursor (MtCursorManager *manager)
+{
+    MtCursorManagerPrivate *priv;
+    XFixesCursorImage *image;
+    MtCursor *cursor;
+
+    g_return_val_if_fail (MT_IS_CURSOR_MANAGER (manager), NULL);
+
+    image = XFixesGetCursorImage (GDK_DISPLAY ());
+    cursor = NULL;
+
+    if (image->name && image->name[0] != '\0') {
+	cursor = mt_cursor_manager_lookup_cursor (manager, image->name);
+
+	if (cursor == NULL) {
+	    mt_cursor_manager_add_cursor (manager, image);
+	    cursor = mt_cursor_manager_lookup_cursor (manager, image->name);
+	}
+    }
+
+    XFree (image);
+
+    return cursor;
+}
+
+MtCursor *
+mt_cursor_manager_lookup_cursor (MtCursorManager *manager,
+				 const gchar     *name)
+{
+    MtCursorManagerPrivate *priv;
+
+    g_return_val_if_fail (MT_IS_CURSOR_MANAGER (manager), NULL);
+
+    if (name == NULL || name[0] == '\0')
+	return NULL;
+
+    priv = MT_CURSOR_MANAGER_GET_PRIVATE (manager);
+
+    return g_hash_table_lookup (priv->cache, name);
+}
+
+void
+mt_cursor_manager_set_cursor (MtCursorManager *manager,
+			      MtCursor        *cursor)
+{
+    MtCursorManagerPrivate *priv;
+
+    g_return_if_fail (MT_IS_CURSOR_MANAGER (manager));
+    g_return_if_fail (MT_IS_CURSOR (cursor));
+
+    priv = MT_CURSOR_MANAGER_GET_PRIVATE (manager);
+    priv->cursor_set = mt_cursor_manager_set_xcursor (cursor);
+}
+
+void
+mt_cursor_manager_restore_all (MtCursorManager *manager)
+{
+    MtCursorManagerPrivate *priv;
+
+    g_return_if_fail (MT_IS_CURSOR_MANAGER (manager));
+
+    priv = MT_CURSOR_MANAGER_GET_PRIVATE (manager);
+    g_hash_table_foreach (priv->cache,
+			  mt_cursor_manager_restore_cursor,
+			  manager);
+}

Added: trunk/src/mt-cursor-manager.h
==============================================================================
--- (empty file)
+++ trunk/src/mt-cursor-manager.h	Sat Mar 29 20:33:23 2008
@@ -0,0 +1,59 @@
+/*
+ * Copyright  2008 Gerd Kohlberger <lowfi chello at>
+ *
+ * This file is part of Mousetweaks.
+ *
+ * Mousetweaks is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mousetweaks 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MT_CURSOR_MANAGER_H__
+#define __MT_CURSOR_MANAGER_H__
+
+#include <glib-object.h>
+
+#include "mt-cursor.h"
+
+G_BEGIN_DECLS
+
+#define MT_TYPE_CURSOR_MANAGER		  (mt_cursor_manager_get_type ())
+#define MT_CURSOR_MANAGER(obj)		  (G_TYPE_CHECK_INSTANCE_CAST ((obj), MT_TYPE_CURSOR_MANAGER, MtCursor))
+#define MT_CURSOR_MANAGER_CLASS(klass)	  (G_TYPE_CHECK_CLASS_CAST ((klass), MT_TYPE_CURSOR_MANAGER, MtCursorClass))
+#define MT_IS_CURSOR_MANAGER(obj)	  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MT_TYPE_CURSOR_MANAGER))
+#define MT_IS_CURSOR_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MT_TYPE_CURSOR_MANAGER))
+#define MT_CURSOR_MANAGER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), MT_TYPE_CURSOR_MANAGER, MtCursorClass))
+
+typedef struct _MtCursorManager MtCursorManager;
+typedef struct _MtCursorManagerClass MtCursorManagerClass;
+
+struct _MtCursorManager {
+    GObject parent;
+};
+
+struct _MtCursorManagerClass {
+    GObjectClass parent;
+};
+
+GType mt_cursor_manager_get_type (void) G_GNUC_CONST;
+
+MtCursorManager * mt_cursor_manager_get_default    (void);
+MtCursor *        mt_cursor_manager_current_cursor (MtCursorManager *manager);
+MtCursor *        mt_cursor_manager_lookup_cursor  (MtCursorManager *manager,
+						    const gchar     *name);
+void              mt_cursor_manager_set_cursor     (MtCursorManager *manager,
+						    MtCursor        *cursor);
+void              mt_cursor_manager_restore_all    (MtCursorManager *manager);
+
+G_END_DECLS
+
+#endif /* __MT_CURSOR_MANAGER_H__ */

Added: trunk/src/mt-cursor.c
==============================================================================
--- (empty file)
+++ trunk/src/mt-cursor.c	Sat Mar 29 20:33:23 2008
@@ -0,0 +1,192 @@
+/*
+ * Copyright  2008 Gerd Kohlberger <lowfi chello at>
+ *
+ * This file is part of Mousetweaks.
+ *
+ * Mousetweaks is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mousetweaks 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <string.h>
+
+#include "mt-cursor.h"
+
+#define MT_CURSOR_GET_PRIVATE(o) \
+    (G_TYPE_INSTANCE_GET_PRIVATE ((o), MT_TYPE_CURSOR, MtCursorPrivate))
+
+typedef struct _MtCursorPrivate MtCursorPrivate;
+struct _MtCursorPrivate {
+    gchar  *name;
+    guchar *image;
+    gushort width;
+    gushort height;
+    gushort xhot;
+    gushort yhot;
+};
+
+G_DEFINE_TYPE (MtCursor, mt_cursor, G_TYPE_OBJECT)
+
+static void mt_cursor_finalize (GObject *object);
+
+static void
+mt_cursor_class_init (MtCursorClass *klass)
+{
+    G_OBJECT_CLASS (klass)->finalize = mt_cursor_finalize;
+
+    g_type_class_add_private (klass, sizeof (MtCursorPrivate));
+}
+
+static void
+mt_cursor_init (MtCursor *cursor)
+{
+    MtCursorPrivate *priv = MT_CURSOR_GET_PRIVATE (cursor);
+
+    priv->name   = NULL;
+    priv->image  = NULL;
+    priv->width  = 0;
+    priv->height = 0;
+    priv->xhot   = 0;
+    priv->yhot   = 0;
+}
+
+static void
+mt_cursor_finalize (GObject *object)
+{
+    MtCursorPrivate *priv = MT_CURSOR_GET_PRIVATE (object);
+
+    if (priv->name)
+	g_free (priv->name);
+
+    if (priv->image)
+	g_free (priv->image);
+
+    G_OBJECT_CLASS (mt_cursor_parent_class)->finalize (object);
+}
+
+static guchar *
+mt_cursor_copy_image (guchar *image,
+		      gushort width,
+		      gushort height)
+{
+    guchar *copy;
+    gulong n_bytes;
+
+    n_bytes = width * height * 4;
+    copy = (guchar *) g_try_malloc (n_bytes);
+
+    if (copy)
+	memcpy (copy, image, n_bytes);
+
+    return copy;
+}
+
+MtCursor *
+mt_cursor_new (const gchar *name,
+	       guchar      *image,
+	       gushort      width,
+	       gushort      height,
+	       gushort      xhot,
+	       gushort      yhot)
+{
+    MtCursor *cursor;
+    MtCursorPrivate *priv;
+    guchar *copy;
+
+    g_return_val_if_fail (name != NULL && name[0] != '\0', NULL);
+    g_return_val_if_fail (image != NULL, NULL);
+    g_return_val_if_fail (width > 0 && height > 0, NULL);
+    g_return_val_if_fail (xhot <= width && yhot <= height, NULL);
+
+    copy = mt_cursor_copy_image (image, width, height);
+
+    g_return_val_if_fail (copy != NULL, NULL);
+
+    cursor = g_object_new (MT_TYPE_CURSOR, NULL);
+    priv = MT_CURSOR_GET_PRIVATE (cursor);
+
+    priv->name   = g_strdup (name);
+    priv->image  = copy;
+    priv->width  = width;
+    priv->height = height;
+    priv->xhot   = xhot;
+    priv->yhot   = yhot;
+
+    return cursor;
+}
+
+const gchar *
+mt_cursor_get_name (MtCursor *cursor)
+{
+    g_return_val_if_fail (MT_IS_CURSOR (cursor), NULL);
+
+    return MT_CURSOR_GET_PRIVATE (cursor)->name;
+}
+
+const guchar *
+mt_cursor_get_image (MtCursor *cursor)
+{
+    g_return_val_if_fail (MT_IS_CURSOR (cursor), NULL);
+
+    return MT_CURSOR_GET_PRIVATE (cursor)->image;
+}
+
+guchar *
+mt_cursor_get_image_copy (MtCursor *cursor)
+{
+    MtCursorPrivate *priv;
+    guchar *image;
+
+    g_return_val_if_fail (MT_IS_CURSOR (cursor), NULL);
+
+    priv = MT_CURSOR_GET_PRIVATE(cursor);
+    image = mt_cursor_copy_image (priv->image, priv->width, priv->height);
+
+    return image;
+}
+
+void
+mt_cursor_get_hotspot (MtCursor *cursor,
+		       gushort  *xhot,
+		       gushort  *yhot)
+{
+    MtCursorPrivate *priv;
+
+    g_return_if_fail (MT_IS_CURSOR (cursor));
+
+    priv = MT_CURSOR_GET_PRIVATE (cursor);
+
+    if (xhot != NULL)
+	*xhot = priv->xhot;
+
+    if (yhot != NULL)
+	*yhot = priv->yhot;
+}
+
+void
+mt_cursor_get_dimension (MtCursor *cursor,
+			 gushort  *width,
+			 gushort  *height)
+{
+    MtCursorPrivate *priv;
+
+    g_return_if_fail (MT_IS_CURSOR (cursor));
+
+    priv = MT_CURSOR_GET_PRIVATE (cursor);
+
+    if (width != NULL)
+	*width = priv->width;
+
+    if (height != NULL)
+	*height = priv->height;
+}

Added: trunk/src/mt-cursor.h
==============================================================================
--- (empty file)
+++ trunk/src/mt-cursor.h	Sat Mar 29 20:33:23 2008
@@ -0,0 +1,65 @@
+/*
+ * Copyright  2008 Gerd Kohlberger <lowfi chello at>
+ *
+ * This file is part of Mousetweaks.
+ *
+ * Mousetweaks is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Mousetweaks 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MT_CURSOR_H__
+#define __MT_CURSOR_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define MT_TYPE_CURSOR		  (mt_cursor_get_type ())
+#define MT_CURSOR(obj)		  (G_TYPE_CHECK_INSTANCE_CAST ((obj), MT_TYPE_CURSOR, MtCursor))
+#define MT_CURSOR_CLASS(klass)	  (G_TYPE_CHECK_CLASS_CAST ((klass), MT_TYPE_CURSOR, MtCursorClass))
+#define MT_IS_CURSOR(obj)	  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MT_TYPE_CURSOR))
+#define MT_IS_CURSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MT_TYPE_CURSOR))
+#define MT_CURSOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), MT_TYPE_CURSOR, MtCursorClass))
+
+typedef struct _MtCursor MtCursor;
+typedef struct _MtCursorClass MtCursorClass;
+
+struct _MtCursor {
+    GObject parent;
+};
+
+struct _MtCursorClass {
+    GObjectClass parent;
+};
+
+GType mt_cursor_get_type (void) G_GNUC_CONST;
+
+MtCursor *     mt_cursor_new		(const gchar *name,
+					 guchar      *image,
+					 gushort      width,
+					 gushort      height,
+					 gushort      xhot,
+					 gushort      yhot);
+const gchar *  mt_cursor_get_name       (MtCursor    *cursor);
+const guchar * mt_cursor_get_image      (MtCursor    *cursor);
+guchar *       mt_cursor_get_image_copy (MtCursor    *cursor);
+void           mt_cursor_get_hotspot    (MtCursor    *cursor,
+					 gushort     *xhot,
+					 gushort     *yhot);
+void           mt_cursor_get_dimension  (MtCursor    *cursor,
+					 gushort     *width,
+					 gushort     *height);
+
+G_END_DECLS
+
+#endif /* __MT_CURSOR_H__ */

Modified: trunk/src/mt-main.c
==============================================================================
--- trunk/src/mt-main.c	(original)
+++ trunk/src/mt-main.c	Sat Mar 29 20:33:23 2008
@@ -22,9 +22,9 @@
 #include <string.h>
 #include <math.h>
 #include <unistd.h>
+
 #include <gtk/gtk.h>
 #include <gdk/gdkx.h>
-#include <X11/extensions/Xfixes.h>
 #include <cspi/spi.h>
 
 #include "mt-common.h"
@@ -32,10 +32,10 @@
 #include "mt-pidfile.h"
 #include "mt-ctw.h"
 #include "mt-timer.h"
+#include "mt-cursor-manager.h"
+#include "mt-cursor.h"
 #include "mt-main.h"
 
-static int fixes_event_base = 0;
-
 static void
 mt_cursor_set (GdkCursorType type)
 {
@@ -173,12 +173,13 @@
 }
 
 static void
-dwell_time_elapsed (MtTimer *timer, gpointer data)
+dwell_timer_finished (MtTimer *timer, gpointer data)
 {
     MTClosure *mt = (MTClosure *) data;
     gint x, y;
 
     gdk_display_get_pointer (gdk_display_get_default (), NULL, &x, &y, NULL);
+    mt_cursor_manager_restore_all (mt_cursor_manager_get_default ());
 
     /* stop active drag */
     if (mt->dwell_drag_started) {
@@ -210,10 +211,12 @@
 }
 
 static void
-delay_time_elapsed (MtTimer *timer, gpointer data)
+delay_timer_finished (MtTimer *timer, gpointer data)
 {
     MTClosure *mt = (MTClosure *) data;
 
+    mt_cursor_manager_restore_all (mt_cursor_manager_get_default ());
+
     SPI_generateMouseEvent (0, 0, "b1r");
     SPI_generateMouseEvent (mt->pointer_x, mt->pointer_y, "b3c");
 }
@@ -224,17 +227,21 @@
 {
     MTClosure *mt = (MTClosure *) data;
 
-    if (mt->dwell_enabled)
-	if (!within_tolerance (mt, event->detail1, event->detail2))
-	    if (!mt->dwell_gesture_started) {
-		mt->pointer_x = (gint) event->detail1;
-		mt->pointer_y = (gint) event->detail2;
-		mt_timer_start (mt->dwell_timer);
-	    }
+    if (mt->dwell_enabled) {
+	if (!within_tolerance (mt, event->detail1, event->detail2) &&
+	    !mt->dwell_gesture_started) {
+	    mt->pointer_x = (gint) event->detail1;
+	    mt->pointer_y = (gint) event->detail2;
+	    mt_timer_start (mt->dwell_timer);
+	}
+    }
 
-    if (mt_timer_is_running (mt->delay_timer))
-	if (!within_tolerance (mt, event->detail1, event->detail2))
+    if (mt_timer_is_running (mt->delay_timer)) {
+	if (!within_tolerance (mt, event->detail1, event->detail2)) {
 	    mt_timer_stop (mt->delay_timer);
+	    mt_cursor_manager_restore_all (mt_cursor_manager_get_default ());
+	}
+    }
 }
 
 static void
@@ -242,7 +249,7 @@
 {
     MTClosure *mt = (MTClosure *) data;
 
-    if (g_str_equal (event->type, "mouse:button:b1p")) {
+    if (g_str_equal (event->type, "mouse:button:1p")) {
 	if (mt->delay_enabled) {
 	    gdk_display_get_pointer (gdk_display_get_default (), NULL,
 				     &mt->pointer_x, &mt->pointer_y, NULL);
@@ -252,29 +259,108 @@
 	if (mt->dwell_gesture_started)
 	    dwell_stop_gesture (mt);
     }
-    else if (g_str_equal (event->type, "mouse:button:b1r"))
-	if (mt_timer_is_running (mt->delay_timer))
+    else if (g_str_equal (event->type, "mouse:button:1r")) {
+	if (mt->delay_enabled) {
 	    mt_timer_stop (mt->delay_timer);
+	    mt_cursor_manager_restore_all (mt_cursor_manager_get_default ());
+	}
+    }
+}
+
+static gboolean
+cursor_overlay_time (guchar  *image,
+		     gint     width,
+		     gint     height,
+		     MtTimer *timer,
+		     gdouble  time)
+{
+    cairo_surface_t *surface;
+    cairo_t *cr;
+    gdouble target;
+
+    target = mt_timer_get_target (timer);
+
+    surface = cairo_image_surface_create_for_data (image,
+						   CAIRO_FORMAT_ARGB32,
+						   width, height,
+						   width * 4);
+    if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
+	return FALSE;
+
+    cr = cairo_create (surface);
+    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
+	return FALSE;
+
+    cairo_set_operator (cr, CAIRO_OPERATOR_ATOP);
+    cairo_rectangle (cr, 0, 0, width, height / (target / time));
+    cairo_set_source_rgba (cr, 0., 0., 0., 0.75);
+    cairo_fill (cr);
+    cairo_destroy (cr);
+    cairo_surface_destroy (surface);
+
+    return TRUE;
 }
 
-static GdkFilterReturn
-cursor_changed (GdkXEvent *xevent, GdkEvent *event, gpointer data)
+void
+mt_update_cursor (MtCursor *cursor, MtTimer *timer, gdouble time)
 {
-    XEvent *xev = (XEvent *) xevent;
+    guchar *image;
+    gushort width, height;
 
-    if (xev->type == fixes_event_base + XFixesCursorNotify) {
-	MTClosure *mt = (MTClosure *) data;
-	XFixesCursorImage *ci;
+    image = mt_cursor_get_image_copy (cursor);
+    if (image == NULL)
+	return;
 
-	ci = XFixesGetCursorImage (GDK_DISPLAY());
+    mt_cursor_get_dimension (cursor, &width, &height);
 
-	if (!mt->dwell_gesture_started)
-	    mt->override_cursor = !g_str_equal (ci->name, "left_ptr");
+    if (cursor_overlay_time (image, width, height, timer, time)) {
+	MtCursorManager *manager;
+	MtCursor *new_cursor;
+	const gchar *name;
+	gushort xhot, yhot;
 
-	XFree (ci);
+	name = mt_cursor_get_name (cursor);
+	mt_cursor_get_hotspot (cursor, &xhot, &yhot);
+	new_cursor = mt_cursor_new (name, image, width, height, xhot, yhot);
+	manager = mt_cursor_manager_get_default ();
+	mt_cursor_manager_set_cursor (manager, new_cursor);
+	g_object_unref (new_cursor);
     }
 
-    return GDK_FILTER_CONTINUE;
+    g_free (image);
+}
+
+static void
+delay_timer_tick (MtTimer *timer, gdouble time, gpointer data)
+{
+    MTClosure *mt = (MTClosure *) data;
+
+    if (mt->animate_cursor && mt->cursor != NULL)
+	mt_update_cursor (mt->cursor, timer, time);
+}
+
+static void
+dwell_timer_tick (MtTimer *timer, gdouble time, gpointer data)
+{
+    MTClosure *mt = (MTClosure *) data;
+
+    if (mt->animate_cursor &&
+	mt->cursor != NULL &&
+	mt->dwell_mode == DWELL_MODE_CTW)
+	mt_update_cursor (mt->cursor, timer, time);
+}
+
+static void
+cursor_changed (MtCursorManager *manager,
+		const gchar     *name,
+		gpointer         data)
+{
+    MTClosure *mt = (MTClosure *) data;
+
+    if (!mt->dwell_gesture_started)
+	mt->override_cursor = !g_str_equal (name, "left_ptr");
+
+    mt->cursor = mt_cursor_manager_lookup_cursor (manager, name);
 }
 
 static void
@@ -324,6 +410,17 @@
 	mt->dwell_dirs[DWELL_CLICK_TYPE_DRAG] = gconf_value_get_int (value);
     else if (g_str_equal (key, OPT_G_RIGHT) && value->type == GCONF_VALUE_INT)
 	mt->dwell_dirs[DWELL_CLICK_TYPE_RIGHT] = gconf_value_get_int (value);
+    else if (g_str_equal (key, OPT_ANIMATE) && value->type == GCONF_VALUE_BOOL) {
+	MtCursorManager *manager;
+
+	manager = mt_cursor_manager_get_default ();
+	mt->animate_cursor = gconf_value_get_bool (value);
+
+	if (mt->animate_cursor)
+	    mt->cursor = mt_cursor_manager_current_cursor (manager);
+	else
+	    mt_cursor_manager_restore_all (manager);
+    }
 }
 
 static void
@@ -337,6 +434,7 @@
     mt->dwell_show_ctw = gconf_client_get_bool (mt->client, OPT_CTW, NULL);
     mt->dwell_mode = gconf_client_get_int (mt->client, OPT_MODE, NULL);
     mt->style = gconf_client_get_int (mt->client, OPT_STYLE, NULL);
+    mt->animate_cursor = gconf_client_get_bool (mt->client, OPT_ANIMATE, NULL);
 
     val = gconf_client_get_float (mt->client, OPT_DELAY_T, NULL);
     mt_timer_set_target (mt->delay_timer, val);
@@ -370,11 +468,15 @@
 
     mt->delay_timer = mt_timer_new ();
     g_signal_connect (mt->delay_timer, "finished",
-		      G_CALLBACK (delay_time_elapsed), mt);
+		      G_CALLBACK (delay_timer_finished), mt);
+    g_signal_connect (mt->delay_timer, "tick",
+		      G_CALLBACK (delay_timer_tick), mt);
 
     mt->dwell_timer = mt_timer_new ();
     g_signal_connect (mt->dwell_timer, "finished",
-		      G_CALLBACK (dwell_time_elapsed), mt);
+		      G_CALLBACK (dwell_timer_finished), mt);
+    g_signal_connect (mt->dwell_timer, "tick",
+		      G_CALLBACK (dwell_timer_tick), mt);
 
     mt->service = mt_service_get_default ();
     mt_service_set_clicktype (mt->service, DWELL_CLICK_TYPE_SINGLE, NULL);
@@ -397,8 +499,8 @@
 main (int argc, char **argv)
 {
     MTClosure *mt;
+    MtCursorManager *manager;
     AccessibleEventListener *bl, *ml;
-    int fixes_error_base;
     pid_t pid;
     gboolean shutdown = FALSE, ctw = FALSE;
     gchar *mode = NULL, *enable = NULL;
@@ -483,17 +585,6 @@
 	    goto FINISH;
 	}
 
-	/* listen for cursor changes */
-	if (XFixesQueryExtension (GDK_DISPLAY(),
-				  &fixes_event_base,
-				  &fixes_error_base)) {
-	    XFixesSelectCursorInput (GDK_DISPLAY(),
-				     GDK_ROOT_WINDOW(),
-				     XFixesDisplayCursorNotifyMask);
-	    gdk_window_add_filter (gdk_get_default_root_window (),
-				   cursor_changed, mt);
-	}
-
 	/* add at-spi listeners */
 	ml = SPI_createAccessibleEventListener (spi_motion_event, (void *) mt);
 	SPI_registerGlobalEventListener (ml, "mouse:abs");
@@ -530,7 +621,16 @@
 	if (!mt_ctw_init (mt, pos_x, pos_y))
 	    goto CLEANUP;
 
+	manager = mt_cursor_manager_get_default ();
+	g_signal_connect (manager, "cursor_changed",
+			  G_CALLBACK (cursor_changed), mt);
+
+	mt->cursor = mt_cursor_manager_current_cursor (manager);
+
 	SPI_event_main ();
+
+	mt_cursor_manager_restore_all (manager);
+	g_object_unref (manager);
     }
 
 CLEANUP:

Modified: trunk/src/mt-main.h
==============================================================================
--- trunk/src/mt-main.h	(original)
+++ trunk/src/mt-main.h	Sat Mar 29 20:33:23 2008
@@ -24,6 +24,7 @@
 
 #include "mt-timer.h"
 #include "mt-service.h"
+#include "mt-cursor.h"
 
 G_BEGIN_DECLS
 
@@ -33,6 +34,7 @@
     MtService   *service;
     MtTimer     *delay_timer;
     MtTimer     *dwell_timer;
+    MtCursor    *cursor;
 
     gboolean dwell_drag_started;
     gboolean dwell_gesture_started;
@@ -50,6 +52,7 @@
     gboolean dwell_show_ctw;
     gint     dwell_mode;
     gint     dwell_dirs[4];
+    gboolean animate_cursor;
 };
 
 G_END_DECLS



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]