aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac4
-rw-r--r--example/Makefile.am14
-rw-r--r--example/gesture.c173
-rw-r--r--gtk-doc.make14
-rw-r--r--src/Makefile.am5
-rw-r--r--src/idogesturemanager.c688
-rw-r--r--src/idogesturemanager.h162
7 files changed, 1055 insertions, 5 deletions
diff --git a/configure.ac b/configure.ac
index cdab267..b53afa7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -72,6 +72,10 @@ PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.19.7)
AC_SUBST(GTK_CFLAGS)
AC_SUBST(GTK_LIBS)
+PKG_CHECK_MODULES(GEIS, libutouch-geis >= 0.3)
+AC_SUBST(GEIS_CFLAGS)
+AC_SUBST(GEIS_LIBS)
+
dnl ===========================================================================
if test "x$GCC" = "xyes"; then
diff --git a/example/Makefile.am b/example/Makefile.am
index bd96642..702cc8f 100644
--- a/example/Makefile.am
+++ b/example/Makefile.am
@@ -1,7 +1,19 @@
noinst_PROGRAMS = \
+ gesture \
messagedialog \
menus
+gesture_SOURCES = \
+ gesture.c
+
+gesture_CPPFLAGS = \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/src \
+ -I$(top_builddir)/src \
+ $(GCC_FLAGS) \
+ $(GTK_CFLAGS) \
+ $(MAINTAINER_CFLAGS)
+
messagedialog_SOURCES = \
messagedialog.c
@@ -24,6 +36,8 @@ menus_CPPFLAGS = \
$(GTK_CFLAGS) \
$(MAINTAINER_CFLAGS)
+gesture_LDADD = $(top_builddir)/src/libido-0.1.la
+
messagedialog_LDADD = $(top_builddir)/src/libido-0.1.la
menus_LDADD = $(top_builddir)/src/libido-0.1.la
diff --git a/example/gesture.c b/example/gesture.c
new file mode 100644
index 0000000..57c4c24
--- /dev/null
+++ b/example/gesture.c
@@ -0,0 +1,173 @@
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+
+#include "idogesturemanager.h"
+
+static gint rotate = 0;
+static gdouble scale = 1.0;
+static gdouble translate[2] = { 200, 200 };
+static gint in_touch = 0;
+
+static gboolean
+expose_event (GtkWidget *widget,
+ GdkEventExpose *event,
+ gpointer data)
+{
+ cairo_t *cr;
+ gdouble radians;
+ gint width = (in_touch > 0) ? 10 : 1;
+
+ cr = gdk_cairo_create (widget->window);
+
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_set_line_width (cr, width);
+
+ radians = rotate * (G_PI / 180);
+ cairo_translate (cr, translate[0], translate[1]);
+ cairo_scale (cr, scale, scale);
+ cairo_rotate (cr, radians);
+
+ cairo_rectangle (cr, -50, -50, 100, 100);
+ cairo_stroke_preserve (cr);
+ cairo_set_source_rgb (cr, 1, 0, 1);
+ cairo_fill (cr);
+
+ cairo_destroy (cr);
+
+ return FALSE;
+}
+
+GtkWidget *
+create_window (void)
+{
+ GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ GtkWidget *da;
+ const GdkColor white = { 0, 0xffff, 0xffff, 0xffff };
+
+ gtk_window_set_title (GTK_WINDOW (window), "Touch Demo");
+ gtk_window_set_default_size (GTK_WINDOW (window), 600, 600);
+ g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window);
+
+ da = gtk_drawing_area_new ();
+ gtk_container_add (GTK_CONTAINER (window), da);
+
+ gtk_widget_modify_bg (da, GTK_STATE_NORMAL, &white);
+
+ g_signal_connect (da, "expose-event",
+ G_CALLBACK (expose_event), NULL);
+
+ return window;
+}
+
+static void
+gesture_start (GtkWindow *window,
+ IdoGestureEvent *event)
+{
+ in_touch++;
+
+ gtk_widget_queue_draw (GTK_WIDGET (window));
+}
+
+static void
+gesture_end (GtkWindow *window,
+ IdoGestureEvent *event)
+{
+ in_touch--;
+
+ gtk_widget_queue_draw (GTK_WIDGET (window));
+}
+
+static void
+rotate_update (GtkWindow *window,
+ IdoGestureEvent *event)
+{
+ IdoEventGestureRotate *e = (IdoEventGestureRotate *)event;
+
+ rotate += e->angle_delta * 100;
+
+ gtk_widget_queue_draw (GTK_WIDGET (window));
+}
+
+static void
+pinch_update (GtkWindow *window,
+ IdoGestureEvent *event)
+{
+ IdoEventGesturePinch *e = (IdoEventGesturePinch *)event;
+
+ scale += e->radius_delta / 100;
+
+ gtk_widget_queue_draw (GTK_WIDGET (window));
+}
+
+static void
+drag_update (GtkWindow *window,
+ IdoGestureEvent *event)
+{
+ IdoEventGestureDrag *e = (IdoEventGestureDrag *)event;
+
+ translate[0] += e->delta_x;
+ translate[1] += e->delta_y;
+
+ gtk_widget_queue_draw (GTK_WIDGET (window));
+}
+
+static void
+window_mapped (GtkWidget *widget)
+{
+ IdoGestureManager *manager = ido_gesture_manager_get ();
+ GtkWindow *window = GTK_WINDOW (widget);
+
+ ido_gesture_manager_register_window (manager,
+ window,
+ IDO_GESTURE_PINCH2,
+ gesture_start,
+ pinch_update,
+ gesture_end);
+
+ ido_gesture_manager_register_window (manager,
+ window,
+ IDO_GESTURE_ROTATE2,
+ gesture_start,
+ rotate_update,
+ gesture_end);
+
+ ido_gesture_manager_register_window (manager,
+ window,
+ IDO_GESTURE_DRAG2,
+ gesture_start,
+ drag_update,
+ gesture_end);
+}
+
+static void
+abort_handler (int x)
+{
+ g_print (" **** ABORT ****\n");
+
+ exit (1);
+}
+
+int
+main (int argc, char **argv)
+{
+ GtkWidget *window;
+
+ gtk_init (&argc, &argv);
+
+ /* Don't crash X if we're using some shitty Intel graphics like
+ * my Dell XT2 has in it. */
+ signal (SIGABRT, abort_handler);
+
+ window = create_window ();
+
+ g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+ g_signal_connect (window, "map-event", G_CALLBACK (window_mapped), NULL);
+
+ gtk_widget_show_all (window);
+
+ gtk_main ();
+
+ return 0;
+}
+
diff --git a/gtk-doc.make b/gtk-doc.make
index 63adaed..57fab98 100644
--- a/gtk-doc.make
+++ b/gtk-doc.make
@@ -75,8 +75,11 @@ $(REPORT_FILES): sgml-build.stamp
scan-build.stamp: $(HFILE_GLOB) $(CFILE_GLOB)
@echo 'gtk-doc: Scanning header files'
@-chmod -R u+w $(srcdir)
- @cd $(srcdir) && \
- gtkdoc-scan --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --ignore-headers="$(IGNORE_HFILES)" $(SCAN_OPTIONS) $(EXTRA_HFILES)
+ @_source_dir='' ; for i in $(DOC_SOURCE_DIR) ; do \
+ _source_dir="$${_source_dir} --source-dir=$$i" ; \
+ done ; \
+ cd $(srcdir) && \
+ gtkdoc-scan --module=$(DOC_MODULE) --ignore-headers="$(IGNORE_HFILES)" $${_source_dir} $(SCAN_OPTIONS) $(EXTRA_HFILES)
@if grep -l '^..*$$' $(srcdir)/$(DOC_MODULE).types > /dev/null 2>&1 ; then \
CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" gtkdoc-scangobj $(SCANGOBJ_OPTIONS) --module=$(DOC_MODULE) --output-dir=$(srcdir) ; \
else \
@@ -109,8 +112,11 @@ $(srcdir)/tmpl/*.sgml:
sgml-build.stamp: tmpl.stamp $(DOC_MODULE)-sections.txt $(srcdir)/tmpl/*.sgml $(expand_content_files)
@echo 'gtk-doc: Building XML'
@-chmod -R u+w $(srcdir)
- @cd $(srcdir) && \
- gtkdoc-mkdb --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $(MKDB_OPTIONS)
+ @_source_dir='' ; for i in $(DOC_SOURCE_DIR) ; do \
+ _source_dir="$${_source_dir} --source-dir=$$i" ; \
+ done ; \
+ cd $(srcdir) && \
+ gtkdoc-mkdb --module=$(DOC_MODULE) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $${_source_dir} $(MKDB_OPTIONS)
@touch sgml-build.stamp
sgml.stamp: sgml-build.stamp
diff --git a/src/Makefile.am b/src/Makefile.am
index 1485019..d17482d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,6 +8,7 @@ stamp_files = \
sources_h = \
idocalendarmenuitem.h \
idoentrymenuitem.h \
+ idogesturemanager.h \
idomessagedialog.h \
idorange.h \
idoscalemenuitem.h \
@@ -46,6 +47,7 @@ INCLUDES = \
AM_CPPFLAGS = \
$(GCC_FLAGS) \
$(GTK_CFLAGS) \
+ $(GEIS_CFLAGS) \
$(MAINTAINER_CFLAGS)
lib_LTLIBRARIES = libido-0.1.la
@@ -54,6 +56,7 @@ libido_0_1_la_SOURCES = \
idotypebuiltins.c \
idocalendarmenuitem.c \
idoentrymenuitem.c \
+ idogesturemanager.c \
idomessagedialog.c \
idorange.c \
idoscalemenuitem.c \
@@ -70,7 +73,7 @@ libidoinclude_HEADERS = \
idotimeline.h \
libido.h
-libido_0_1_la_LIBADD = $(GTK_LIBS)
+libido_0_1_la_LIBADD = $(GTK_LIBS) $(GEIS_LIBS)
libido_0_1_la_LDFLAGS = $(GTK_LT_LDFLAGS)
idoheadersdir = $(includedir)/ido-0.1/ido
diff --git a/src/idogesturemanager.c b/src/idogesturemanager.c
new file mode 100644
index 0000000..f603816
--- /dev/null
+++ b/src/idogesturemanager.c
@@ -0,0 +1,688 @@
+/*
+ * Copyright 2010 Canonical, Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of either or both of the following licenses:
+ *
+ * 1) the GNU Lesser General Public License version 3, as published by the
+ * Free Software Foundation; and/or
+ * 2) the GNU Lesser General Public License version 2.1, as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the applicable version of the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of both the GNU Lesser General Public
+ * License version 3 and version 2.1 along with this program. If not, see
+ * <http://www.gnu.org/licenses/>
+ *
+ * Authors:
+ * Cody Russell <crussell@canonical.com>
+ */
+
+#include "idogesturemanager.h"
+
+#include <gdk/gdkx.h>
+#include <geis/geis.h>
+
+typedef struct _IdoGestureRegistration IdoGestureRegistration;
+typedef struct _IdoGestureBinding IdoGestureBinding;
+
+struct _IdoGestureManagerPrivate
+{
+ GHashTable *hash;
+};
+
+struct _IdoGestureBinding
+{
+ IdoGestureType type;
+ IdoGestureCallback start;
+ IdoGestureCallback update;
+ IdoGestureCallback end;
+};
+
+struct _IdoGestureRegistration
+{
+ GtkWindow *window;
+ GList *bindings;
+ GeisInstance instance;
+};
+
+static void gesture_added (void *cookie,
+ GeisGestureType gesture_type,
+ GeisGestureId gesture_id,
+ GeisSize attr_count,
+ GeisGestureAttr *attrs);
+
+static void gesture_removed (void *cookie,
+ GeisGestureType gesture_type,
+ GeisGestureId gesture_id,
+ GeisSize attr_count,
+ GeisGestureAttr *attrs);
+
+static void gesture_start (void *cookie,
+ GeisGestureType gesture_type,
+ GeisGestureId gesture_id,
+ GeisSize attr_count,
+ GeisGestureAttr *attrs);
+
+static void gesture_update (void *cookie,
+ GeisGestureType gesture_type,
+ GeisGestureId gesture_id,
+ GeisSize attr_count,
+ GeisGestureAttr *attrs);
+
+static void gesture_finish (void *cookie,
+ GeisGestureType gesture_type,
+ GeisGestureId gesture_id,
+ GeisSize attr_count,
+ GeisGestureAttr *attrs);
+
+static IdoGestureManager *manager_singleton = NULL;
+static GeisGestureFuncs gesture_funcs = {
+ gesture_added,
+ gesture_removed,
+ gesture_start,
+ gesture_update,
+ gesture_finish
+};
+
+G_DEFINE_TYPE (IdoGestureManager, ido_gesture_manager, G_TYPE_OBJECT)
+
+#define IDO_GESTURE_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), IDO_TYPE_GESTURE_MANAGER, IdoGestureManagerPrivate))
+
+static void
+ido_gesture_manager_dispose (GObject *object)
+{
+ IdoGestureManagerPrivate *priv = IDO_GESTURE_MANAGER (object)->priv;
+
+ if (priv->hash != NULL)
+ {
+ g_hash_table_unref (priv->hash);
+ }
+}
+
+static GObject *
+ido_gesture_manager_constructor (GType type,
+ guint n_params,
+ GObjectConstructParam *params)
+{
+ GObject *object;
+
+ if (manager_singleton != NULL)
+ {
+ object = g_object_ref (manager_singleton);
+ }
+ else
+ {
+ object = G_OBJECT_CLASS (ido_gesture_manager_parent_class)->constructor (type,
+ n_params,
+ params);
+
+ manager_singleton = IDO_GESTURE_MANAGER (object);
+ g_object_add_weak_pointer (object, (gpointer) &manager_singleton);
+ }
+
+ return object;
+}
+
+static void
+ido_gesture_manager_class_init (IdoGestureManagerClass *class)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (class);
+
+ ido_gesture_manager_parent_class = g_type_class_peek_parent (class);
+
+ g_type_class_add_private (gobject_class, sizeof (IdoGestureManagerPrivate));
+
+ gobject_class->constructor = ido_gesture_manager_constructor;
+ gobject_class->dispose = ido_gesture_manager_dispose;
+}
+
+/*
+static void
+print_attr (GeisGestureAttr *attr)
+{
+ return;
+
+ g_print ("\tattr '%s'=", attr->name);
+ switch (attr->type)
+ {
+ case GEIS_ATTR_TYPE_BOOLEAN:
+ g_print ("%s\n", attr->boolean_val ? "true" : "false");
+ break;
+ case GEIS_ATTR_TYPE_FLOAT:
+ g_print ("%f\n", attr->float_val);
+ break;
+ case GEIS_ATTR_TYPE_INTEGER:
+ g_print ("%d\n", (gint)attr->integer_val);
+ break;
+ case GEIS_ATTR_TYPE_STRING:
+ g_print ("\"%s\"\n", attr->string_val);
+ break;
+ default:
+ g_print ("<unknown>\n");
+ break;
+ }
+}
+*/
+
+static void
+pinch_gesture_handle_properties (IdoEventGesturePinch *event,
+ GeisSize attr_count,
+ GeisGestureAttr *attrs)
+{
+ gint i = 0;
+
+ for (i = 0; i < attr_count; ++i)
+ {
+ if (g_strcmp0 (attrs[i].name, "timestamp") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
+ {
+ event->timestamp = attrs[i].integer_val;
+ }
+ else if (g_strcmp0 (attrs[i].name, "focus X") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
+ {
+ event->focus_x = attrs[i].float_val;
+ }
+ else if (g_strcmp0 (attrs[i].name, "focus Y") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
+ {
+ event->focus_y = attrs[i].float_val;
+ }
+ else if (g_strcmp0 (attrs[i].name, "radius delta") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
+ {
+ event->radius_delta = attrs[i].float_val;
+ }
+ else if (g_strcmp0 (attrs[i].name, "radial velocity") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
+ {
+ event->radial_velocity = attrs[i].float_val;
+ }
+ else if (g_strcmp0 (attrs[i].name, "radius") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
+ {
+ event->radius = attrs[i].float_val;
+ }
+ }
+}
+
+static void
+drag_gesture_handle_properties (IdoEventGestureDrag *event,
+ GeisSize attr_count,
+ GeisGestureAttr *attrs)
+{
+ gint i;
+
+ for (i = 0; i < attr_count; ++i)
+ {
+ if (g_strcmp0 (attrs[i].name, "timestamp") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
+ {
+ event->timestamp = attrs[i].integer_val;
+ }
+ else if (g_strcmp0 (attrs[i].name, "focus X") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
+ {
+ event->focus_x = attrs[i].float_val;
+ }
+ else if (g_strcmp0 (attrs[i].name, "focus Y") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
+ {
+ event->focus_y = attrs[i].float_val;
+ }
+ else if (g_strcmp0 (attrs[i].name, "delta X") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
+ {
+ event->delta_x = attrs[i].float_val;
+ }
+ else if (g_strcmp0 (attrs[i].name, "delta Y") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
+ {
+ event->delta_y = attrs[i].float_val;
+ }
+ else if (g_strcmp0 (attrs[i].name, "velocity X") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
+ {
+ event->velocity_x = attrs[i].float_val;
+ }
+ else if (g_strcmp0 (attrs[i].name, "velocity Y") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
+ {
+ event->velocity_y = attrs[i].float_val;
+ }
+ else if (g_strcmp0 (attrs[i].name, "position X") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
+ {
+ event->position_x = attrs[i].float_val;
+ }
+ else if (g_strcmp0 (attrs[i].name, "position Y") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
+ {
+ event->position_y = attrs[i].float_val;
+ }
+ }
+}
+
+static void
+rotate_gesture_handle_properties (IdoEventGestureRotate *event,
+ GeisSize attr_count,
+ GeisGestureAttr *attrs)
+{
+ gint i;
+
+ for (i = 0; i < attr_count; ++i)
+ {
+ if (g_strcmp0 (attrs[i].name, "timestamp") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
+ {
+ event->timestamp = attrs[i].integer_val;
+ }
+ else if (g_strcmp0 (attrs[i].name, "focus X") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
+ {
+ event->focus_x = attrs[i].float_val;
+ }
+ else if (g_strcmp0 (attrs[i].name, "focus Y") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
+ {
+ event->focus_y = attrs[i].float_val;
+ }
+ else if (g_strcmp0 (attrs[i].name, "angle delta") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
+ {
+ event->angle_delta = attrs[i].float_val;
+ }
+ else if (g_strcmp0 (attrs[i].name, "angular velocity") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
+ {
+ event->angular_velocity = attrs[i].float_val;
+ }
+ else if (g_strcmp0 (attrs[i].name, "angle") == 0 &&
+ attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
+ {
+ event->angle = attrs[i].float_val;
+ }
+ }
+}
+
+
+static void
+gesture_added (void *cookie,
+ GeisGestureType gesture_type,
+ GeisGestureId gesture_id,
+ GeisSize attr_count,
+ GeisGestureAttr *attrs)
+{
+}
+
+static void
+gesture_removed (void *cookie,
+ GeisGestureType gesture_type,
+ GeisGestureId gesture_id,
+ GeisSize attr_count,
+ GeisGestureAttr *attrs)
+{
+}
+
+static void
+gesture_start (void *cookie,
+ GeisGestureType type,
+ GeisGestureId id,
+ GeisSize attr_count,
+ GeisGestureAttr *attrs)
+{
+ IdoGestureRegistration *reg = (IdoGestureRegistration *)cookie;
+ GList *l = NULL;
+
+ for (l = reg->bindings; l != NULL; l = l->next)
+ {
+ IdoGestureBinding *binding = (IdoGestureBinding *)l->data;
+
+ if (binding->type == type)
+ {
+ if (type == IDO_GESTURE_DRAG1 ||
+ type == IDO_GESTURE_DRAG2 ||
+ type == IDO_GESTURE_DRAG3 ||
+ type == IDO_GESTURE_DRAG4 ||
+ type == IDO_GESTURE_DRAG5)
+ {
+ IdoEventGestureDrag drag;
+
+ drag.type = type;
+ drag.id = id;
+
+ drag_gesture_handle_properties (&drag,
+ attr_count,
+ attrs);
+
+ binding->start (reg->window,
+ ((IdoGestureEvent*)&drag));
+ }
+ else if (type == IDO_GESTURE_PINCH1 ||
+ type == IDO_GESTURE_PINCH2 ||
+ type == IDO_GESTURE_PINCH3 ||
+ type == IDO_GESTURE_PINCH4 ||
+ type == IDO_GESTURE_PINCH5)
+ {
+ IdoEventGesturePinch pinch;
+
+ pinch.type = type;
+ pinch.id = id;
+
+ pinch_gesture_handle_properties (&pinch,
+ attr_count,
+ attrs);
+
+ binding->start (reg->window,
+ ((IdoGestureEvent*)&pinch));
+ }
+ else if (type == IDO_GESTURE_ROTATE1 ||
+ type == IDO_GESTURE_ROTATE2 ||
+ type == IDO_GESTURE_ROTATE3 ||
+ type == IDO_GESTURE_ROTATE4 ||
+ type == IDO_GESTURE_ROTATE5)
+ {
+ IdoEventGestureRotate rotate;
+
+ rotate.type = type;
+ rotate.id = id;
+
+ rotate_gesture_handle_properties (&rotate,
+ attr_count,
+ attrs);
+
+ binding->start (reg->window,
+ ((IdoGestureEvent*)&rotate));
+ }
+
+ return;
+ }
+ }
+}
+
+static void
+gesture_update (void *cookie,
+ GeisGestureType type,
+ GeisGestureId id,
+ GeisSize attr_count,
+ GeisGestureAttr *attrs)
+{
+ IdoGestureRegistration *reg = (IdoGestureRegistration *)cookie;
+ GList *l = NULL;
+
+ for (l = reg->bindings; l != NULL; l = l->next)
+ {
+ IdoGestureBinding *binding = (IdoGestureBinding *)l->data;
+
+ if (binding->type == type)
+ {
+ if (type == IDO_GESTURE_DRAG1 ||
+ type == IDO_GESTURE_DRAG2 ||
+ type == IDO_GESTURE_DRAG3 ||
+ type == IDO_GESTURE_DRAG4 ||
+ type == IDO_GESTURE_DRAG5)
+ {
+ IdoEventGestureDrag drag;
+
+ drag.type = type;
+ drag.id = id;
+
+ drag_gesture_handle_properties (&drag,
+ attr_count,
+ attrs);
+
+ binding->update (reg->window,
+ ((IdoGestureEvent*)&drag));
+ }
+ else if (type == IDO_GESTURE_PINCH1 ||
+ type == IDO_GESTURE_PINCH2 ||
+ type == IDO_GESTURE_PINCH3 ||
+ type == IDO_GESTURE_PINCH4 ||
+ type == IDO_GESTURE_PINCH5)
+ {
+ IdoEventGesturePinch pinch;
+
+ pinch.type = type;
+ pinch.id = id;
+
+ pinch_gesture_handle_properties (&pinch,
+ attr_count,
+ attrs);
+
+ binding->update (reg->window,
+ ((IdoGestureEvent*)&pinch));
+ }
+ else if (type == IDO_GESTURE_ROTATE1 ||
+ type == IDO_GESTURE_ROTATE2 ||
+ type == IDO_GESTURE_ROTATE3 ||
+ type == IDO_GESTURE_ROTATE4 ||
+ type == IDO_GESTURE_ROTATE5)
+ {
+ IdoEventGestureRotate rotate;
+
+ rotate.type = type;
+ rotate.id = id;
+
+ rotate_gesture_handle_properties (&rotate,
+ attr_count,
+ attrs);
+
+ binding->update (reg->window,
+ ((IdoGestureEvent*)&rotate));
+ }
+ }
+ }
+}
+
+static void
+gesture_finish (void *cookie,
+ GeisGestureType type,
+ GeisGestureId id,
+ GeisSize attr_count,
+ GeisGestureAttr *attrs)
+{
+ IdoGestureRegistration *reg = (IdoGestureRegistration *)cookie;
+ GList *l = NULL;
+
+ for (l = reg->bindings; l != NULL; l = l->next)
+ {
+ IdoGestureBinding *binding = (IdoGestureBinding *)l->data;
+
+ if (binding->type == type)
+ {
+ if (type == IDO_GESTURE_DRAG1 ||
+ type == IDO_GESTURE_DRAG2 ||
+ type == IDO_GESTURE_DRAG3 ||
+ type == IDO_GESTURE_DRAG4 ||
+ type == IDO_GESTURE_DRAG5)
+ {
+ IdoEventGestureDrag drag;
+
+ drag.type = type;
+ drag.id = id;
+
+ drag_gesture_handle_properties (&drag,
+ attr_count,
+ attrs);
+
+ binding->end (reg->window,
+ ((IdoGestureEvent*)&drag));
+ }
+ else if (type == IDO_GESTURE_PINCH1 ||
+ type == IDO_GESTURE_PINCH2 ||
+ type == IDO_GESTURE_PINCH3 ||
+ type == IDO_GESTURE_PINCH4 ||
+ type == IDO_GESTURE_PINCH5)
+ {
+ IdoEventGesturePinch pinch;
+
+ pinch.type = type;
+ pinch.id = id;
+
+ pinch_gesture_handle_properties (&pinch,
+ attr_count,
+ attrs);
+
+ binding->end (reg->window,
+ ((IdoGestureEvent*)&pinch));
+ }
+ else if (type == IDO_GESTURE_ROTATE1 ||
+ type == IDO_GESTURE_ROTATE2 ||
+ type == IDO_GESTURE_ROTATE3 ||
+ type == IDO_GESTURE_ROTATE4 ||
+ type == IDO_GESTURE_ROTATE5)
+ {
+ IdoEventGestureRotate rotate;
+
+ rotate.type = type;
+ rotate.id = id;
+
+ rotate_gesture_handle_properties (&rotate,
+ attr_count,
+ attrs);
+
+ binding->end (reg->window,
+ ((IdoGestureEvent*)&rotate));
+ }
+ }
+ }
+}
+
+static void
+ido_gesture_manager_init (IdoGestureManager *item)
+{
+ IdoGestureManagerPrivate *priv;
+
+ priv = item->priv = IDO_GESTURE_MANAGER_GET_PRIVATE (item);
+
+ priv->hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+}
+
+static gboolean
+io_callback (GIOChannel *source,
+ GIOCondition condition,
+ gpointer data)
+{
+ IdoGestureRegistration *reg = (IdoGestureRegistration *)data;
+
+ geis_event_dispatch (reg->instance);
+
+ return TRUE;
+}
+
+/* Public API */
+IdoGestureManager *
+ido_gesture_manager_get (void)
+{
+ return g_object_new (IDO_TYPE_GESTURE_MANAGER, NULL);
+}
+
+/**
+ * ido_gesture_manager_register_window:
+ * @window: A #GtkWindow to register the gesture event for.
+ * @gesture_type: The type of gesture event to register.
+ * @start: Called when a user initiates a gesture.
+ * @update: Called each time the user updates the gesture.
+ * @end: Called when the user ends the gesture.
+ *
+ * Registers a toplevel window to receive gesture events.
+ * The callback parameters provided will be called by the
+ * #IdoGestureManager whenever the user initiates a gesture
+ * on the specified window.
+ */
+void
+ido_gesture_manager_register_window (IdoGestureManager *manager,
+ GtkWindow *window,
+ IdoGestureType gesture_type,
+ IdoGestureCallback start,
+ IdoGestureCallback update,
+ IdoGestureCallback end)
+{
+ IdoGestureManagerPrivate *priv;
+ IdoGestureRegistration *reg;
+ IdoGestureBinding *binding;
+
+ g_return_if_fail (IDO_IS_GESTURE_MANAGER (manager));
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (window)));
+
+ priv = manager->priv;
+
+ if (!(reg = g_hash_table_lookup (priv->hash, window)))
+ {
+ GeisInstance instance;
+ GIOChannel *iochannel;
+ gint fd = -1;
+ GeisXcbWinInfo xcb_win_info = {
+ .display_name = NULL,
+ .screenp = NULL,
+ .window_id = GDK_DRAWABLE_XID (GTK_WIDGET (window)->window)
+ };
+ GeisWinInfo win_info = {
+ GEIS_XCB_FULL_WINDOW,
+ &xcb_win_info
+ };
+
+ if (geis_init (&win_info, &instance) != GEIS_STATUS_SUCCESS)
+ {
+ g_warning ("Failed to initialize gesture manager.");
+ return;
+ }
+
+ if (geis_configuration_supported (instance,
+ GEIS_CONFIG_UNIX_FD) != GEIS_STATUS_SUCCESS)
+ {
+ g_warning ("Gesture manager does not support UNIX fd.");
+ return;
+ }
+
+ if (geis_configuration_get_value (instance,
+ GEIS_CONFIG_UNIX_FD,
+ &fd) != GEIS_STATUS_SUCCESS)
+ {
+ g_error ("Gesture manager failed to obtain UNIX fd.");
+ return;
+ }
+
+ reg = g_new0 (IdoGestureRegistration, 1);
+
+ reg->window = window;
+ reg->instance = instance;
+
+ geis_subscribe (reg->instance,
+ GEIS_ALL_INPUT_DEVICES,
+ GEIS_ALL_GESTURES,
+ &gesture_funcs,
+ reg);
+
+ iochannel = g_io_channel_unix_new (fd);
+ g_io_add_watch (iochannel,
+ G_IO_IN,
+ io_callback,
+ reg);
+ }
+
+ /* XXX - check for duplicates in reg->bindings first */
+ binding = g_new0 (IdoGestureBinding, 1);
+
+ g_print (" *** Adding binding type %d\n", (gint)gesture_type);
+
+ binding->type = gesture_type;
+ binding->start = start;
+ binding->update = update;
+ binding->end = end;
+
+ reg->bindings = g_list_append (reg->bindings, binding);
+
+ g_hash_table_insert (priv->hash,
+ window,
+ reg);
+}
diff --git a/src/idogesturemanager.h b/src/idogesturemanager.h
new file mode 100644
index 0000000..bc3ad33
--- /dev/null
+++ b/src/idogesturemanager.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2010 Canonical, Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of either or both of the following licenses:
+ *
+ * 1) the GNU Lesser General Public License version 3, as published by the
+ * Free Software Foundation; and/or
+ * 2) the GNU Lesser General Public License version 2.1, as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the applicable version of the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of both the GNU Lesser General Public
+ * License version 3 and version 2.1 along with this program. If not, see
+ * <http://www.gnu.org/licenses/>
+ *
+ * Authors:
+ * Cody Russell <crussell@canonical.com>
+ */
+
+#ifndef __IDO_GESTURE_MANAGER_H__
+#define __IDO_GESTURE_MANAGER_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define IDO_TYPE_GESTURE_MANAGER (ido_gesture_manager_get_type ())
+#define IDO_GESTURE_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), IDO_TYPE_GESTURE_MANAGER, IdoGestureManager))
+#define IDO_GESTURE_MANAGER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), IDO_TYPE_GESTURE_MANAGER, IdoGestureManagerClass))
+#define IDO_IS_GESTURE_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), IDO_TYPE_GESTURE_MANAGER))
+#define IDO_IS_GESTURE_MANAGER_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), IDO_TYPE_GESTURE_MANAGER))
+#define IDO_GESTURE_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), IDO_TYPE_GESTURE_MANAGER, IdoGestureManagerClass))
+
+typedef struct _IdoGestureManager IdoGestureManager;
+typedef struct _IdoGestureManagerClass IdoGestureManagerClass;
+typedef struct _IdoGestureManagerPrivate IdoGestureManagerPrivate;
+
+typedef union _IdoGestureEvent IdoGestureEvent;
+typedef struct _IdoEventGestureDrag IdoEventGestureDrag;
+typedef struct _IdoEventGesturePinch IdoEventGesturePinch;
+typedef struct _IdoEventGestureRotate IdoEventGestureRotate;
+
+typedef enum {
+ IDO_GESTURE_DRAG1,
+ IDO_GESTURE_PINCH1,
+ IDO_GESTURE_ROTATE1,
+
+ IDO_GESTURE_DRAG2,
+ IDO_GESTURE_PINCH2,
+ IDO_GESTURE_ROTATE2,
+
+ IDO_GESTURE_DRAG3,
+ IDO_GESTURE_PINCH3,
+ IDO_GESTURE_ROTATE3,
+
+ IDO_GESTURE_DRAG4,
+ IDO_GESTURE_PINCH4,
+ IDO_GESTURE_ROTATE4,
+
+ IDO_GESTURE_DRAG5,
+ IDO_GESTURE_PINCH5,
+ IDO_GESTURE_ROTATE5,
+
+ IDO_GESTURE_TAP1,
+ IDO_GESTURE_TAP2,
+ IDO_GESTURE_TAP3,
+ IDO_GESTURE_TAP4,
+ IDO_GESTURE_TAP5
+} IdoGestureType;
+
+struct _IdoEventGestureDrag
+{
+ IdoGestureType type;
+ guint id;
+ GdkWindow *window;
+ GdkWindow *root;
+ GdkWindow *child;
+ guint32 timestamp;
+ gint fingers;
+ gdouble focus_x;
+ gdouble focus_y;
+ gint delta_x;
+ gint delta_y;
+ gdouble velocity_x;
+ gdouble velocity_y;
+ gdouble position_x;
+ gdouble position_y;
+};
+
+struct _IdoEventGesturePinch
+{
+ IdoGestureType type;
+ guint id;
+ GdkWindow *window;
+ GdkWindow *root;
+ GdkWindow *child;
+ guint32 timestamp;
+ guint fingers;
+ gdouble focus_x;
+ gdouble focus_y;
+ gdouble radius_delta;
+ gdouble radial_velocity;
+ gdouble radius;
+};
+
+struct _IdoEventGestureRotate
+{
+ IdoGestureType type;
+ guint id;
+ GdkWindow *window;
+ GdkWindow *root;
+ GdkWindow *child;
+ guint32 timestamp;
+ guint fingers;
+ gdouble focus_x;
+ gdouble focus_y;
+ gdouble angle_delta;
+ gdouble angular_velocity;
+ gdouble angle;
+};
+
+union _IdoGestureEvent
+{
+ IdoGestureType type;
+ IdoEventGestureDrag drag;
+ IdoEventGesturePinch pinch;
+ IdoEventGestureRotate rotate;
+};
+
+struct _IdoGestureManager
+{
+ GObject parent_instance;
+
+ IdoGestureManagerPrivate *priv;
+};
+
+struct _IdoGestureManagerClass
+{
+ GObjectClass parent_class;
+};
+
+typedef void (* IdoGestureCallback) (GtkWindow *window,
+ IdoGestureEvent *gesture);
+
+GType ido_gesture_manager_get_type (void) G_GNUC_CONST;
+IdoGestureManager *ido_gesture_manager_get (void);
+void ido_gesture_manager_register_window (IdoGestureManager *manager,
+ GtkWindow *window,
+ IdoGestureType gesture_type,
+ IdoGestureCallback start,
+ IdoGestureCallback update,
+ IdoGestureCallback end);
+
+G_END_DECLS
+
+#endif /* __IDO_GESTURE_MANAGER_H__ */