Merge lp:~bregma/libgrip/lp-1168370-raring into lp:libgrip/raring

Proposed by Stephen M. Webb on 2013-05-12
Status: Merged
Approved by: Marco Trevisan (Treviño) on 2013-05-15
Approved revision: 77
Merged at revision: 76
Proposed branch: lp:~bregma/libgrip/lp-1168370-raring
Merge into: lp:libgrip/raring
Diff against target: 2144 lines (+702/-1177)
2 files modified
src/gripgesturemanager.c (+671/-1154)
src/gripinputdevice.c (+31/-23)
To merge this branch: bzr merge lp:~bregma/libgrip/lp-1168370-raring
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration 2013-05-12 Approve on 2013-05-15
Marco Trevisan (Treviño) 2013-05-12 Approve on 2013-05-15
Review via email: mp+163448@code.launchpad.net

Commit message

Moved to GEISv2 to fix an unfortunate lack of events (lp: #1168370).

Description of the change

Cherry-picked critical bug fix from trunk for SRU into 13.04.

Original description of change on trunk:

Rewrote libgrip to use GEISv2 instead of GEISv1 because libgrip's assumptions about device tracking across instances was invalid, and GEISv1 is deprecated.

To post a comment you must log in.
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:76
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~bregma/libgrip/lp-1168370-raring/+merge/163448/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/libgrip-raring-ci/1/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/libgrip-raring-raring-amd64-ci/1
    SUCCESS: http://jenkins.qa.ubuntu.com/job/libgrip-raring-raring-armhf-ci/1
    SUCCESS: http://jenkins.qa.ubuntu.com/job/libgrip-raring-raring-i386-ci/1

Click here to trigger a rebuild:
http://s-jenkins:8080/job/libgrip-raring-ci/1/rebuild

review: Needs Fixing (continuous-integration)
Marco Trevisan (Treviño) (3v1n0) wrote :

77 + g_list_foreach(priv->classes, (GFunc) g_free, NULL);

why not g_list_free_full(priv->classes, g_free) instead?

lp:~bregma/libgrip/lp-1168370-raring updated on 2013-05-14
77. By Stephen M. Webb on 2013-05-14

Used g_list_free_full() to free a GList

Marco Trevisan (Treviño) (3v1n0) wrote :

+1

review: Approve
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/gripgesturemanager.c'
2--- src/gripgesturemanager.c 2012-05-29 20:47:37 +0000
3+++ src/gripgesturemanager.c 2013-05-14 18:50:33 +0000
4@@ -1,5 +1,5 @@
5 /*
6- * Copyright 2010, 2011 Canonical, Ltd.
7+ * Copyright 2010, 2011, 2013 Canonical, Ltd.
8 *
9 * This program is free software: you can redistribute it and/or modify it
10 * under the terms of either or both of the following licenses:
11@@ -29,25 +29,49 @@
12 #include <geis/geis.h>
13 #include "gripinputdevice.h"
14
15-typedef struct _GripGestureRegistration GripGestureRegistration;
16 typedef struct _GripGestureBinding GripGestureBinding;
17 typedef struct _GripRegistrationRequest GripRegistrationRequest;
18
19 typedef GPtrArray GripDevices;
20
21-struct Registrations {
22- GripGestureRegistration *touchscreen;
23- GripGestureRegistration *touchpad;
24- GripGestureRegistration *independent;
25-};
26+/*
27+ * GripGestureClassMap:
28+ * @grip_type: the libgrip gesture type
29+ * @geis_class: the geis gesture class
30+ *
31+ * Provides a mapping between a grip gesture type and a geis gesture class.
32+ */
33+typedef struct _GripGestureClassMap
34+{
35+ GripGestureType grip_type;
36+ GeisGestureClass geis_class;
37+} GripGestureClassMap;
38
39+/*
40+ * GripGestureManagerPrivate:
41+ * @geis: the GEIS instance
42+ * @iochannel: connects the geis object with the main loop
43+ * @iochannel_id: the identifier for the iochannel
44+ * @devices: a collection of recognized input devices
45+ * @classes: a list of grip type to geis class mappings
46+ * @requests: a list of pending binding requests
47+ * @bindings: a list of current gesture bindings
48+ */
49 struct _GripGestureManagerPrivate
50 {
51- GHashTable *registered_windows;
52- GList *requests;
53- GripDevices *devices;
54+ Geis geis;
55+ GIOChannel *iochannel;
56+ int iochannel_id;
57+ GripDevices *devices;
58+ GList *classes;
59+ GList *requests;
60+ GList *bindings;
61 };
62
63+G_DEFINE_TYPE (GripGestureManager, grip_gesture_manager, G_TYPE_OBJECT)
64+
65+#define GRIP_GESTURE_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GRIP_TYPE_GESTURE_MANAGER, GripGestureManagerPrivate))
66+
67 /*
68 * GripGestureBinding:
69 * @type:
70@@ -64,32 +88,27 @@
71 GripGestureType type;
72 GtkWidget *widget;
73 guint touches;
74+ GeisSubscription subscription;
75 GripGestureCallback callback;
76 gpointer data;
77 GDestroyNotify destroy;
78 };
79
80+
81 /*
82- * GripGestureRegistration:
83- * @window: the GTK window
84- * @bindings: a list of #GripGestureBinding
85- * @gesture_list: a list the names of GEIS gestures beging subscribed to
86- * @instance:
87- * @iochannel:
88+ * GripRegistrationRequest:
89+ * @manager: the @GripGestureManager
90+ * @widget: the GtkWidget to be bound
91+ * @gesture_type: the type of gesture to subscribe for
92+ * @device_type: the type of input device to subscribe for
93+ * @touch_points: the number of touches making the gesture
94+ * @callback: the callback to be invoked on gesture events
95+ * @user_data: the callback context to be passed back on gesture events
96+ * @destroy: function to destroy the callback context (NULL for no function)
97 *
98- * A collection of all gesture subscriptions for all widgets contained within a
99- * top-level GTK window.
100+ * A collection of information required to register a callback for a
101+ * particulatr type of gestures on a window.
102 */
103-struct _GripGestureRegistration
104-{
105- GtkWindow *window;
106- GList *bindings;
107- GPtrArray *gesture_list;
108- GeisInstance instance;
109- GIOChannel *iochannel;
110- int iochannel_id;
111-};
112-
113 struct _GripRegistrationRequest
114 {
115 GripGestureManager *manager;
116@@ -102,30 +121,8 @@
117 GDestroyNotify destroy;
118 };
119
120-static const gchar *geis_gesture_types[] = {
121- GEIS_GESTURE_TYPE_DRAG1,
122- GEIS_GESTURE_TYPE_DRAG2,
123- GEIS_GESTURE_TYPE_DRAG3,
124- GEIS_GESTURE_TYPE_DRAG4,
125- GEIS_GESTURE_TYPE_DRAG5,
126- GEIS_GESTURE_TYPE_PINCH1,
127- GEIS_GESTURE_TYPE_PINCH2,
128- GEIS_GESTURE_TYPE_PINCH3,
129- GEIS_GESTURE_TYPE_PINCH4,
130- GEIS_GESTURE_TYPE_PINCH5,
131- GEIS_GESTURE_TYPE_ROTATE1,
132- GEIS_GESTURE_TYPE_ROTATE2,
133- GEIS_GESTURE_TYPE_ROTATE3,
134- GEIS_GESTURE_TYPE_ROTATE4,
135- GEIS_GESTURE_TYPE_ROTATE5,
136- GEIS_GESTURE_TYPE_TAP1,
137- GEIS_GESTURE_TYPE_TAP2,
138- GEIS_GESTURE_TYPE_TAP3,
139- GEIS_GESTURE_TYPE_TAP4,
140- GEIS_GESTURE_TYPE_TAP5,
141-};
142-
143-enum {
144+enum
145+{
146 DEVICE_AVAILABLE,
147 DEVICE_UNAVAILABLE,
148 SIGNAL_LAST
149@@ -133,132 +130,151 @@
150
151 static guint signals[SIGNAL_LAST];
152
153-static void gesture_added (void *cookie,
154- GeisGestureType gesture_type,
155- GeisGestureId gesture_id,
156- GeisSize attr_count,
157- GeisGestureAttr *attrs);
158-
159-static void gesture_removed (void *cookie,
160- GeisGestureType gesture_type,
161- GeisGestureId gesture_id,
162- GeisSize attr_count,
163- GeisGestureAttr *attrs);
164-
165-static void gesture_start (void *cookie,
166- GeisGestureType gesture_type,
167- GeisGestureId gesture_id,
168- GeisSize attr_count,
169- GeisGestureAttr *attrs);
170-
171-static void gesture_update (void *cookie,
172- GeisGestureType gesture_type,
173- GeisGestureId gesture_id,
174- GeisSize attr_count,
175- GeisGestureAttr *attrs);
176-
177-static void gesture_finish (void *cookie,
178- GeisGestureType gesture_type,
179- GeisGestureId gesture_id,
180- GeisSize attr_count,
181- GeisGestureAttr *attrs);
182+static void process_gesture_events (GripGestureManager *manager,
183+ GeisEvent geis_event);
184
185 static void toplevel_mapped_cb (GtkWidget *toplevel,
186 GdkEvent *event,
187 gpointer user_data);
188
189-static GeisGestureFuncs gesture_funcs = {
190- gesture_added,
191- gesture_removed,
192- gesture_start,
193- gesture_update,
194- gesture_finish
195-};
196-
197-
198-static void
199-device_added (void *cookie, GeisInputDeviceId id G_GNUC_UNUSED, void *attrs)
200-{
201- GripGestureManager *gesture_manager = (GripGestureManager *) cookie;
202- GripInputDevice *input_device = g_object_new (GRIP_TYPE_INPUT_DEVICE,
203- "device-attrs", attrs,
204- NULL);
205-
206- g_ptr_array_add(gesture_manager->priv->devices, input_device);
207- g_signal_emit (gesture_manager, signals[DEVICE_AVAILABLE], 0, input_device);
208-}
209-
210-
211-static void
212-device_removed (void *cookie, GeisInputDeviceId id, void *attrs G_GNUC_UNUSED)
213-{
214- guint i;
215- GripGestureManager *gesture_manager = (GripGestureManager *) cookie;
216- GripDevices *devices = gesture_manager->priv->devices;
217-
218- for (i = 0; i < devices->len; ++i)
219- {
220- GripInputDevice *input_device = g_ptr_array_index (devices, i);
221- if (id == grip_input_device_get_id (input_device))
222- {
223- g_signal_emit (gesture_manager, signals[DEVICE_UNAVAILABLE], 0,
224- input_device);
225- g_ptr_array_remove_index (devices, i);
226- break;
227- }
228- }
229-}
230-
231-
232-static GeisInputFuncs input_funcs = {
233- device_added,
234- NULL,
235- device_removed,
236-};
237-
238-
239-static void
240-grip_get_devices (GripGestureManager *gesture_manager)
241-{
242- GeisXcbWinInfo xcb_win_info = {
243- .display_name = NULL,
244- .screenp = NULL,
245- .window_id = 0,
246- };
247- GeisWinInfo win_info = {
248- GEIS_XCB_FULL_WINDOW,
249- &xcb_win_info,
250- };
251- GeisInstance instance;
252- GeisStatus status;
253-
254- status = geis_init (&win_info, &instance);
255- if (status != GEIS_STATUS_SUCCESS)
256- {
257- g_warning ("failed to determine device types\n");
258- return;
259- }
260-
261- status = geis_input_devices (instance, &input_funcs, gesture_manager);
262- if (status != GEIS_STATUS_SUCCESS)
263- {
264- g_warning ("failed to determine device types\n");
265- return;
266- }
267-
268- status = geis_event_dispatch (instance);
269- if (status != GEIS_STATUS_SUCCESS)
270- {
271- g_warning ("failed to determine device types\n");
272- return;
273- }
274-
275- geis_finish (instance);
276-}
277-
278-G_DEFINE_TYPE (GripGestureManager, grip_gesture_manager, G_TYPE_OBJECT)
279-
280-#define GRIP_GESTURE_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GRIP_TYPE_GESTURE_MANAGER, GripGestureManagerPrivate))
281+
282+static void
283+grip_geis_device_added(GripGestureManager *manager G_GNUC_UNUSED, GeisEvent geis_event)
284+{
285+ GeisAttr attr = geis_event_attr_by_name(geis_event, GEIS_EVENT_ATTRIBUTE_DEVICE);
286+ g_return_if_fail (attr);
287+
288+ GeisDevice device = geis_attr_value_to_pointer(attr);
289+ g_return_if_fail (device);
290+
291+ switch (geis_event_type(geis_event))
292+ {
293+ case GEIS_EVENT_DEVICE_AVAILABLE:
294+ {
295+ GripInputDevice *input_device = g_object_new (GRIP_TYPE_INPUT_DEVICE,
296+ "geis-device", device,
297+ NULL);
298+
299+ g_ptr_array_add(manager->priv->devices, input_device);
300+ g_signal_emit (manager, signals[DEVICE_AVAILABLE], 0, input_device);
301+ }
302+ break;
303+
304+ case GEIS_EVENT_DEVICE_UNAVAILABLE:
305+ {
306+ guint device_id = geis_device_id (device);
307+ GripDevices *devices = manager->priv->devices;
308+ guint i;
309+ for (i = 0; i < devices->len; ++i)
310+ {
311+ GripInputDevice *input_device = g_ptr_array_index (devices, i);
312+ if (device_id == grip_input_device_get_id (input_device))
313+ {
314+ g_signal_emit (manager, signals[DEVICE_UNAVAILABLE], 0,
315+ input_device);
316+ g_ptr_array_remove_index (devices, i);
317+ break;
318+ }
319+ }
320+ }
321+ break;
322+
323+ default:
324+ break;
325+ }
326+}
327+
328+
329+static void
330+process_class_event(GripGestureManagerPrivate *priv G_GNUC_UNUSED, GeisEvent geis_event)
331+{
332+ GeisAttr attr = geis_event_attr_by_name (geis_event,
333+ GEIS_EVENT_ATTRIBUTE_CLASS);
334+ g_return_if_fail (attr);
335+
336+ GeisGestureClass gesture_class = geis_attr_value_to_pointer (attr);
337+ g_return_if_fail (gesture_class);
338+
339+ switch (geis_event_type (geis_event))
340+ {
341+ case GEIS_EVENT_CLASS_AVAILABLE:
342+ {
343+ gchar const *class_name = geis_gesture_class_name (gesture_class);
344+ /* check for dups */
345+ GList *l;
346+ for (l = priv->classes; l != NULL; l = l->next)
347+ {
348+ GripGestureClassMap *p = (GripGestureClassMap *)l->data;
349+ if (0 == g_strcmp0 (geis_gesture_class_name (p->geis_class),
350+ class_name))
351+ {
352+ g_warning ("multiple class definitions for '%s' received",
353+ class_name);
354+ return;
355+ }
356+ }
357+
358+ GripGestureClassMap *m = g_new0 (GripGestureClassMap, 1);
359+ if (0 == g_strcmp0 (class_name, "Drag"))
360+ m->grip_type = GRIP_GESTURE_DRAG;
361+ else if (0 == g_strcmp0 (class_name, "Pinch"))
362+ m->grip_type = GRIP_GESTURE_PINCH;
363+ else if (0 == g_strcmp0 (class_name, "Rotate"))
364+ m->grip_type = GRIP_GESTURE_ROTATE;
365+ else if (0 == g_strcmp0 (class_name, "Tap"))
366+ m->grip_type = GRIP_GESTURE_TAP;
367+ else
368+ m->grip_type = (GripGestureType)100;
369+ m->geis_class = gesture_class;
370+ priv->classes = g_list_append (priv->classes, m);
371+ }
372+ break;
373+
374+ default:
375+ /* @todo handle class-changed and class-unavailable events */
376+ g_warning ("gesture class event ignored");
377+ break;
378+ }
379+}
380+
381+
382+static void
383+grip_geis_event_callback(Geis geis G_GNUC_UNUSED, GeisEvent geis_event, void *context)
384+{
385+ GripGestureManager *self = GRIP_GESTURE_MANAGER (context);
386+ GripGestureManagerPrivate *priv = GRIP_GESTURE_MANAGER_GET_PRIVATE (self);
387+
388+ switch (geis_event_type(geis_event))
389+ {
390+ case GEIS_EVENT_DEVICE_AVAILABLE:
391+ case GEIS_EVENT_DEVICE_UNAVAILABLE:
392+ grip_geis_device_added (self, geis_event);
393+ break;
394+
395+ case GEIS_EVENT_CLASS_AVAILABLE:
396+ case GEIS_EVENT_CLASS_CHANGED:
397+ case GEIS_EVENT_CLASS_UNAVAILABLE:
398+ process_class_event(priv, geis_event);
399+ break;
400+
401+ case GEIS_EVENT_INIT_COMPLETE:
402+ break;
403+
404+ case GEIS_EVENT_GESTURE_BEGIN:
405+ case GEIS_EVENT_GESTURE_UPDATE:
406+ case GEIS_EVENT_GESTURE_END:
407+ process_gesture_events(self, geis_event);
408+ break;
409+
410+ default:
411+ g_warning ("event ignored");
412+ break;
413+ }
414+
415+ geis_event_delete(geis_event);
416+ return;
417+}
418+
419
420 static void
421 grip_gesture_manager_dispose (GObject *object G_GNUC_UNUSED)
422@@ -267,59 +283,17 @@
423
424
425 static void
426-free_registration(GripGestureRegistration *reg)
427-{
428- GList *tmp = NULL;
429-
430- if (!reg)
431- return;
432-
433- geis_unsubscribe (reg->instance,
434- (GeisGestureType*)reg->gesture_list->pdata);
435-
436- /* We don't need to free the values in the GPtrArray. */
437- g_ptr_array_free (reg->gesture_list, TRUE);
438-
439- for (tmp = reg->bindings; tmp != NULL; tmp = tmp->next)
440- {
441- g_free (tmp->data);
442- }
443-
444- g_list_free (reg->bindings);
445-}
446-
447-/* Helper function needed to make things work with GTK. */
448-
449-static void
450-free_registration_adapter (gpointer key G_GNUC_UNUSED,
451- gpointer value,
452- gpointer user_data G_GNUC_UNUSED)
453-{
454- struct Registrations *regs = (struct Registrations *)value;
455- free_registration(regs->touchscreen);
456- free_registration(regs->touchpad);
457- free_registration(regs->independent);
458-}
459-
460-static void
461 grip_gesture_manager_finalize (GObject *object)
462 {
463 GripGestureManagerPrivate *priv = GRIP_GESTURE_MANAGER_GET_PRIVATE (object);
464
465- if (priv->registered_windows != NULL)
466- {
467- g_hash_table_foreach (priv->registered_windows,
468- free_registration_adapter,
469- NULL);
470-
471- g_hash_table_unref (priv->registered_windows);
472- priv->registered_windows = NULL;
473-
474- g_ptr_array_foreach (priv->devices, (GFunc) g_object_unref, NULL);
475- g_ptr_array_unref (priv->devices);
476- }
477+ g_list_free_full (priv->classes, g_free);
478+
479+ g_ptr_array_foreach (priv->devices, (GFunc) g_object_unref, NULL);
480+ g_ptr_array_unref (priv->devices);
481 }
482
483+
484 static GObject *
485 grip_gesture_manager_constructor (GType type,
486 guint n_params,
487@@ -332,12 +306,12 @@
488 self = G_OBJECT_CLASS (grip_gesture_manager_parent_class)->
489 constructor (type, n_params, params);
490 g_object_add_weak_pointer (self, (gpointer) &self);
491- grip_get_devices (GRIP_GESTURE_MANAGER (self));
492 }
493
494 return g_object_ref (self);
495 }
496
497+
498 static void
499 grip_gesture_manager_class_init (GripGestureManagerClass *class)
500 {
501@@ -386,7 +360,6 @@
502 G_TYPE_NONE,
503 1,
504 GRIP_TYPE_INPUT_DEVICE);
505-
506 }
507
508
509@@ -420,592 +393,306 @@
510 return input_device;
511 }
512
513-/*
514- * registration_for_input_device:
515- * @registrations: A collection of #GripGestureRegistration
516- * @input_device: A pointer to a #GripInputDevice
517- *
518- * Determines which #GripGestureRegistration to use dependeng on properties of
519- * the #GripInputDevice.
520- *
521- * Returns: a pointer to a #GripGestureRegistration or %NULL if not found.
522- */
523-static GripGestureRegistration *
524-registration_for_input_device (struct Registrations *registrations,
525- GripInputDevice *input_device)
526-{
527- GripDeviceType device_type = grip_get_device_type(input_device);
528- if (device_type == GRIP_DEVICE_TOUCHSCREEN)
529- {
530- return registrations->touchscreen;
531- }
532- else if (GRIP_DEVICE_TOUCHPAD)
533- {
534- return registrations->touchpad;
535- }
536- else if (GRIP_DEVICE_INDEPENDENT)
537- {
538- return registrations->independent;
539- }
540- return NULL;
541-}
542-
543
544 static gint
545 pinch_gesture_handle_properties (GripEventGesturePinch *event,
546- GeisSize attr_count,
547- GeisGestureAttr *attrs)
548+ GeisFrame frame)
549 {
550- guint i = 0;
551- gint touches = 0;
552-
553+ guint attr_count = geis_frame_attr_count (frame);
554+ gint num_touches = 0;
555+ guint i;
556 for (i = 0; i < attr_count; ++i)
557 {
558- if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0 &&
559- attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
560- {
561- touches = attrs[i].integer_val;
562- }
563- if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0 &&
564- attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
565- {
566- event->timestamp = attrs[i].integer_val;
567- }
568- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0 &&
569- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
570- {
571- event->focus_x = attrs[i].float_val;
572- }
573- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0 &&
574- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
575- {
576- event->focus_y = attrs[i].float_val;
577- }
578- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA) == 0 &&
579- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
580- {
581- event->radius_delta = attrs[i].float_val;
582- }
583- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_RADIAL_VELOCITY) == 0 &&
584- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
585- {
586- event->radial_velocity = attrs[i].float_val;
587- }
588- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_RADIUS) == 0 &&
589- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
590- {
591- event->radius = attrs[i].float_val;
592- }
593- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0 &&
594- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
595- {
596- event->position_x = attrs[i].float_val;
597- }
598- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0 &&
599- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
600- {
601- event->position_y = attrs[i].float_val;
602- }
603- }
604+ GeisAttr attr = geis_frame_attr(frame, i);
605+ GeisString attr_name = geis_attr_name(attr);
606
607- return touches;
608+ if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0)
609+ num_touches = geis_attr_value_to_integer(attr);
610+ if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0)
611+ event->timestamp = geis_attr_value_to_integer(attr);
612+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0)
613+ event->focus_x = geis_attr_value_to_float(attr);
614+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0)
615+ event->focus_y = geis_attr_value_to_float(attr);
616+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA) == 0)
617+ event->radius_delta = geis_attr_value_to_float(attr);
618+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_RADIAL_VELOCITY) == 0)
619+ event->radial_velocity = geis_attr_value_to_float(attr);
620+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_RADIUS) == 0)
621+ event->radius = geis_attr_value_to_float(attr);
622+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0)
623+ event->position_x = geis_attr_value_to_float(attr);
624+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0)
625+ event->position_y = geis_attr_value_to_float(attr);
626+ }
627+ return num_touches;
628 }
629
630 static gint
631 drag_gesture_handle_properties (GripEventGestureDrag *event,
632- GeisSize attr_count,
633- GeisGestureAttr *attrs)
634+ GeisFrame frame)
635 {
636+ guint attr_count = geis_frame_attr_count (frame);
637+ gint num_touches = 0;
638 guint i;
639- gint touches = 0;
640-
641 for (i = 0; i < attr_count; ++i)
642 {
643- if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0 &&
644- attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
645- {
646- touches = attrs[i].integer_val;
647- }
648- if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0 &&
649- attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
650- {
651- event->timestamp = attrs[i].integer_val;
652- }
653- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0 &&
654- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
655- {
656- event->focus_x = attrs[i].float_val;
657- }
658- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0 &&
659- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
660- {
661- event->focus_y = attrs[i].float_val;
662- }
663- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_DELTA_X) == 0 &&
664- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
665- {
666- event->delta_x = attrs[i].float_val;
667- }
668- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_DELTA_Y) == 0 &&
669- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
670- {
671- event->delta_y = attrs[i].float_val;
672- }
673- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_X) == 0 &&
674- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
675- {
676- event->velocity_x = attrs[i].float_val;
677- }
678- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y) == 0 &&
679- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
680- {
681- event->velocity_y = attrs[i].float_val;
682- }
683- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0 &&
684- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
685- {
686- event->position_x = attrs[i].float_val;
687- }
688- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0 &&
689- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
690- {
691- event->position_y = attrs[i].float_val;
692- }
693- }
694+ GeisAttr attr = geis_frame_attr(frame, i);
695+ GeisString attr_name = geis_attr_name(attr);
696
697- return touches;
698+ if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0)
699+ num_touches = geis_attr_value_to_integer(attr);
700+ if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0)
701+ event->timestamp = geis_attr_value_to_integer(attr);
702+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0)
703+ event->focus_x = geis_attr_value_to_float(attr);
704+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0)
705+ event->focus_y = geis_attr_value_to_float(attr);
706+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_DELTA_X) == 0)
707+ event->delta_x = geis_attr_value_to_float(attr);
708+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_DELTA_Y) == 0)
709+ event->delta_y = geis_attr_value_to_float(attr);
710+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_X) == 0)
711+ event->velocity_x = geis_attr_value_to_float(attr);
712+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y) == 0)
713+ event->velocity_y = geis_attr_value_to_float(attr);
714+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0)
715+ event->position_x = geis_attr_value_to_float(attr);
716+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0)
717+ event->position_y = geis_attr_value_to_float(attr);
718+ }
719+ return num_touches;
720 }
721
722+
723 static gint
724 rotate_gesture_handle_properties (GripEventGestureRotate *event,
725- GeisSize attr_count,
726- GeisGestureAttr *attrs)
727+ GeisFrame frame)
728 {
729+ guint attr_count = geis_frame_attr_count (frame);
730+ gint num_touches = 0;
731 guint i;
732- gint touches = 0;
733-
734 for (i = 0; i < attr_count; ++i)
735 {
736- if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0 &&
737- attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
738- {
739- touches = attrs[i].integer_val;
740- }
741- if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0 &&
742- attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
743- {
744- event->timestamp = attrs[i].integer_val;
745- }
746- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0 &&
747- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
748- {
749- event->focus_x = attrs[i].float_val;
750- }
751- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0 &&
752- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
753- {
754- event->focus_y = attrs[i].float_val;
755- }
756- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA) == 0 &&
757- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
758- {
759- event->angle_delta = attrs[i].float_val;
760- }
761- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_ANGULAR_VELOCITY) == 0 &&
762- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
763- {
764- event->angular_velocity = attrs[i].float_val;
765- }
766- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_ANGLE) == 0 &&
767- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
768- {
769- event->angle = attrs[i].float_val;
770- }
771- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0 &&
772- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
773- {
774- event->position_x = attrs[i].float_val;
775- }
776- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0 &&
777- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
778- {
779- event->position_y = attrs[i].float_val;
780- }
781- }
782+ GeisAttr attr = geis_frame_attr(frame, i);
783+ GeisString attr_name = geis_attr_name(attr);
784
785- return touches;
786+ if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0)
787+ num_touches = geis_attr_value_to_integer(attr);
788+ if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0)
789+ event->timestamp = geis_attr_value_to_integer(attr);
790+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0)
791+ event->focus_x = geis_attr_value_to_float(attr);
792+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0)
793+ event->focus_y = geis_attr_value_to_float(attr);
794+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA) == 0)
795+ event->angle_delta = geis_attr_value_to_float(attr);
796+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_ANGULAR_VELOCITY) == 0)
797+ event->angular_velocity = geis_attr_value_to_float(attr);
798+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_ANGLE) == 0)
799+ event->angle = geis_attr_value_to_float(attr);
800+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0)
801+ event->position_x = geis_attr_value_to_float(attr);
802+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0)
803+ event->position_y = geis_attr_value_to_float(attr);
804+ }
805+ return num_touches;
806 }
807
808+
809 static gint
810 tap_gesture_handle_properties (GripEventGestureTap *event,
811- GeisSize attr_count,
812- GeisGestureAttr *attrs)
813+ GeisFrame frame)
814 {
815+ guint attr_count = geis_frame_attr_count (frame);
816+ gint num_touches = 0;
817 guint i;
818- gint touches = 0;
819-
820 for (i = 0; i < attr_count; ++i)
821 {
822- if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0 &&
823- attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
824- {
825- touches = attrs[i].integer_val;
826- }
827- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0 &&
828- attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
829- {
830- event->timestamp = attrs[i].integer_val;
831- }
832- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0 &&
833- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
834- {
835- event->focus_x = attrs[i].float_val;
836- }
837- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0 &&
838- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
839- {
840- event->focus_y = attrs[i].float_val;
841- }
842- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0 &&
843- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
844- {
845- event->position_x = attrs[i].float_val;
846- }
847- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0 &&
848- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
849- {
850- event->position_y = attrs[i].float_val;
851- }
852- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TAP_TIME) == 0 &&
853- attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
854- {
855- event->tap_time = attrs[i].float_val;
856- }
857- }
858-
859- return touches;
860-}
861-
862-static void
863-gesture_added (void *cookie G_GNUC_UNUSED,
864- GeisGestureType gesture_type G_GNUC_UNUSED,
865- GeisGestureId gesture_id G_GNUC_UNUSED,
866- GeisSize attr_count G_GNUC_UNUSED,
867- GeisGestureAttr *attrs G_GNUC_UNUSED)
868-{
869-}
870-
871-static void
872-gesture_removed (void *cookie G_GNUC_UNUSED,
873- GeisGestureType gesture_type G_GNUC_UNUSED,
874- GeisGestureId gesture_id G_GNUC_UNUSED,
875- GeisSize attr_count G_GNUC_UNUSED,
876- GeisGestureAttr *attrs G_GNUC_UNUSED)
877-{
878-}
879-
880-static gboolean
881-matches_widget (GtkWidget *widget,
882- GdkWindow *window,
883- gint x,
884- gint y)
885-{
886- GtkAllocation alloc;
887- gint ax, ay;
888-
889- gtk_widget_get_allocation (widget, &alloc);
890- gdk_window_get_root_coords (window, alloc.x, alloc.y, &ax, &ay);
891-
892- return (x >= ax && x < ax + alloc.width && y >= ay && y < ay + alloc.height);
893-}
894-
895-
896-/*
897- * process_gesture:
898- * @cookie:
899- * @type:
900- * @id:
901- * @attr_count:
902- * @attrs:
903- * @time_type:
904- *
905- * The generic gesture event dispatch engine.
906- */
907-static void
908-process_gesture (void *cookie,
909- GeisGestureType type,
910- GeisGestureId id,
911- GeisSize attr_count,
912- GeisGestureAttr *attrs,
913- GripTimeType time_type)
914-{
915- GripGestureManager *manager = (GripGestureManager *) cookie;
916- GripInputDevice *input_device = NULL;
917- GtkWindow *gtk_window = NULL;
918- struct Registrations *registrations = NULL;
919- GripGestureRegistration *reg = NULL;
920- GList *l = NULL;
921+ GeisAttr attr = geis_frame_attr(frame, i);
922+ GeisString attr_name = geis_attr_name(attr);
923+
924+ if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0)
925+ num_touches = geis_attr_value_to_integer(attr);
926+ if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0)
927+ event->timestamp = geis_attr_value_to_integer(attr);
928+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0)
929+ event->focus_x = geis_attr_value_to_float(attr);
930+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0)
931+ event->focus_y = geis_attr_value_to_float(attr);
932+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0)
933+ event->position_x = geis_attr_value_to_float(attr);
934+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0)
935+ event->position_y = geis_attr_value_to_float(attr);
936+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TAP_TIME) == 0)
937+ event->tap_time = geis_attr_value_to_float(attr);
938+ }
939+ return num_touches;
940+}
941+
942+
943+static void
944+process_gesture_events(GripGestureManager *manager, GeisEvent geis_event)
945+{
946+ GripGestureManagerPrivate *priv = manager->priv;
947+
948+ GripTimeType time_type = GRIP_TIME_UPDATE;
949+ if (geis_event_type(geis_event) == GEIS_EVENT_GESTURE_BEGIN)
950+ time_type = GRIP_TIME_START;
951+ else if (geis_event_type(geis_event) == GEIS_EVENT_GESTURE_END)
952+ time_type = GRIP_TIME_END;
953+
954+ GeisAttr attr = geis_event_attr_by_name (geis_event, GEIS_EVENT_ATTRIBUTE_GROUPSET);
955+ g_return_if_fail (attr);
956+
957+ GeisGroupSet groupset = geis_attr_value_to_pointer (attr);
958+ g_return_if_fail (groupset);
959+
960 GeisSize i;
961-
962- for (i = 0; i < attr_count; ++i)
963- {
964- if (0 == g_strcmp0(attrs[i].name, GEIS_GESTURE_ATTRIBUTE_DEVICE_ID))
965- {
966- input_device = device_id_to_input_device(manager, attrs[i].integer_val);
967- }
968- else if (0 == g_strcmp0(attrs[i].name, GEIS_GESTURE_ATTRIBUTE_EVENT_WINDOW_ID))
969- {
970- GHashTableIter iter;
971- GtkWidget *key;
972- struct Registrations *value;
973- guint window_id = attrs[i].integer_val;
974-
975- g_hash_table_iter_init (&iter, manager->priv->registered_windows);
976- while (g_hash_table_iter_next(&iter, (gpointer *)&key, (gpointer *)&value))
977- {
978- if (GDK_WINDOW_XID (gtk_widget_get_window (key)) == window_id)
979- {
980- gtk_window = (GtkWindow *)key;
981- break;
982- }
983- }
984- }
985- }
986- g_return_if_fail(input_device != NULL);
987- g_return_if_fail(gtk_window != NULL);
988-
989- registrations = g_hash_table_lookup (manager->priv->registered_windows, gtk_window);
990- g_return_if_fail(registrations != NULL);
991- reg = registration_for_input_device (registrations, input_device);
992- g_return_if_fail(reg != NULL);
993-
994- for (l = reg->bindings; l != NULL; l = l->next)
995- {
996- GripGestureBinding *binding = (GripGestureBinding *)l->data;
997-
998- if (binding->type == type)
999- {
1000- GripGestureEvent *event = grip_gesture_event_new (type);
1001-
1002- if (type == GRIP_GESTURE_DRAG)
1003- {
1004- GripEventGestureDrag *drag = (GripEventGestureDrag *)event;
1005-
1006- drag->type = type;
1007- drag->id = id;
1008- drag->input_device = input_device;
1009- drag->fingers = drag_gesture_handle_properties (drag,
1010- attr_count,
1011- attrs);
1012-
1013- if (drag->fingers == (gint)binding->touches)
1014- {
1015- if (matches_widget (binding->widget,
1016- gtk_widget_get_window(GTK_WIDGET (reg->window)),
1017- (gint)drag->focus_x,
1018- (gint)drag->focus_y))
1019- {
1020- binding->callback (binding->widget,
1021- time_type,
1022- event,
1023- binding->data);
1024- }
1025- }
1026- }
1027- else if (type == GRIP_GESTURE_PINCH)
1028- {
1029- GripEventGesturePinch *pinch = (GripEventGesturePinch *)event;
1030-
1031- pinch->type = type;
1032- pinch->id = id;
1033- pinch->input_device = input_device;
1034- pinch->fingers = pinch_gesture_handle_properties (pinch,
1035- attr_count,
1036- attrs);
1037-
1038- if (pinch->fingers == binding->touches)
1039- {
1040- if (matches_widget (binding->widget,
1041- gtk_widget_get_window(GTK_WIDGET (reg->window)),
1042- (gint)pinch->focus_x,
1043- (gint)pinch->focus_y))
1044- {
1045- binding->callback (binding->widget,
1046- time_type,
1047- event,
1048- binding->data);
1049- }
1050- }
1051- }
1052- else if (type == GRIP_GESTURE_ROTATE)
1053- {
1054- GripEventGestureRotate *rotate = (GripEventGestureRotate *)event;
1055-
1056- rotate->type = type;
1057- rotate->id = id;
1058- rotate->input_device = input_device;
1059- rotate->fingers = rotate_gesture_handle_properties (rotate,
1060- attr_count,
1061- attrs);
1062-
1063- if (rotate->fingers == binding->touches)
1064- {
1065- if (matches_widget (binding->widget,
1066- gtk_widget_get_window(GTK_WIDGET (reg->window)),
1067- (gint)rotate->focus_x,
1068- (gint)rotate->focus_y))
1069- {
1070- binding->callback (binding->widget,
1071- time_type,
1072- event,
1073- binding->data);
1074- }
1075- }
1076- }
1077- else if (type == GRIP_GESTURE_TAP)
1078- {
1079- GripEventGestureTap *tap = (GripEventGestureTap *)event;
1080-
1081- tap->type = type;
1082- tap->id = id;
1083- tap->input_device = input_device;
1084- tap->fingers = tap_gesture_handle_properties (tap,
1085- attr_count,
1086- attrs);
1087-
1088- if (tap->fingers == binding->touches)
1089- {
1090- if (matches_widget (binding->widget,
1091- gtk_widget_get_window(GTK_WIDGET (reg->window)),
1092- (gint)tap->focus_x,
1093- (gint)tap->focus_y))
1094- {
1095- binding->callback (binding->widget,
1096- time_type,
1097- event,
1098- binding->data);
1099- }
1100- }
1101- }
1102-
1103- grip_gesture_event_free (event);
1104- }
1105- }
1106-}
1107-
1108-static void
1109-gesture_start (void *cookie,
1110- GeisGestureType type,
1111- GeisGestureId id,
1112- GeisSize attr_count,
1113- GeisGestureAttr *attrs)
1114-{
1115- process_gesture(cookie, type, id, attr_count, attrs, GRIP_TIME_START);
1116-}
1117-
1118-static void
1119-gesture_update (void *cookie,
1120- GeisGestureType type,
1121- GeisGestureId id,
1122- GeisSize attr_count,
1123- GeisGestureAttr *attrs)
1124-{
1125- process_gesture(cookie, type, id, attr_count, attrs, GRIP_TIME_UPDATE);
1126-}
1127-
1128-static void
1129-gesture_finish (void *cookie,
1130- GeisGestureType type,
1131- GeisGestureId id,
1132- GeisSize attr_count,
1133- GeisGestureAttr *attrs)
1134-{
1135- process_gesture(cookie, type, id, attr_count, attrs, GRIP_TIME_END);
1136-}
1137-
1138-static void
1139-grip_gesture_manager_init (GripGestureManager *item)
1140-{
1141- GripGestureManagerPrivate *priv;
1142-
1143- priv = item->priv = GRIP_GESTURE_MANAGER_GET_PRIVATE (item);
1144-
1145- priv->registered_windows = g_hash_table_new (g_direct_hash, g_direct_equal);
1146-
1147+ for (i = 0; i < geis_groupset_group_count (groupset); ++i)
1148+ {
1149+ GeisGroup group = geis_groupset_group (groupset, i);
1150+ g_return_if_fail (group);
1151+
1152+ GeisSize j;
1153+ for (j = 0; j < geis_group_frame_count (group); ++j)
1154+ {
1155+ GeisFrame frame = geis_group_frame(group, j);
1156+ g_return_if_fail (frame);
1157+
1158+ GeisAttr window_attr = geis_frame_attr_by_name(frame, GEIS_GESTURE_ATTRIBUTE_EVENT_WINDOW_ID);
1159+ guint window_id = geis_attr_value_to_integer(window_attr);
1160+
1161+ GeisAttr device_attr = geis_frame_attr_by_name(frame, GEIS_GESTURE_ATTRIBUTE_DEVICE_ID);
1162+ guint device_id = geis_attr_value_to_integer(device_attr);
1163+ GripInputDevice *input_device = device_id_to_input_device (manager, device_id);
1164+
1165+ GList *l;
1166+ for (l = priv->bindings; l != NULL; l = l->next)
1167+ {
1168+ GripGestureBinding *binding = (GripGestureBinding *)l->data;
1169+ guint widget_window_id = GDK_WINDOW_XID (gtk_widget_get_window (binding->widget));
1170+ if (widget_window_id == window_id)
1171+ {
1172+ GList *class_list;
1173+ for (class_list = priv->classes; class_list != NULL; class_list = class_list->next)
1174+ {
1175+ GripGestureClassMap *p = (GripGestureClassMap *)class_list->data;
1176+ if (p->grip_type == binding->type)
1177+ {
1178+ if (geis_frame_is_class(frame, p->geis_class))
1179+ {
1180+ GripGestureEvent *grip_event = grip_gesture_event_new (p->grip_type);
1181+ if (p->grip_type == GRIP_GESTURE_DRAG)
1182+ {
1183+ GripEventGestureDrag *drag = (GripEventGestureDrag *)grip_event;
1184+ drag->type = p->grip_type;
1185+ drag->id = geis_frame_id(frame);
1186+ drag->input_device = input_device;
1187+ drag->fingers = drag_gesture_handle_properties (drag, frame);
1188+ binding->callback (binding->widget,
1189+ time_type,
1190+ grip_event,
1191+ binding->data);
1192+ }
1193+ else if (p->grip_type == GRIP_GESTURE_PINCH)
1194+ {
1195+ GripEventGesturePinch *pinch = (GripEventGesturePinch *)grip_event;
1196+ pinch->type = p->grip_type;
1197+ pinch->id = geis_frame_id(frame);
1198+ pinch->input_device = input_device;
1199+ pinch->fingers = pinch_gesture_handle_properties (pinch, frame);
1200+ binding->callback (binding->widget,
1201+ time_type,
1202+ grip_event,
1203+ binding->data);
1204+ }
1205+ else if (p->grip_type == GRIP_GESTURE_ROTATE)
1206+ {
1207+ GripEventGestureRotate *rotate = (GripEventGestureRotate *)grip_event;
1208+ rotate->type = p->grip_type;
1209+ rotate->id = geis_frame_id(frame);
1210+ rotate->input_device = input_device;
1211+ rotate->fingers = rotate_gesture_handle_properties (rotate, frame);
1212+ binding->callback (binding->widget,
1213+ time_type,
1214+ grip_event,
1215+ binding->data);
1216+ }
1217+ else if (p->grip_type == GRIP_GESTURE_TAP)
1218+ {
1219+ GripEventGestureTap *tap = (GripEventGestureTap *)grip_event;
1220+ tap->type = p->grip_type;
1221+ tap->id = geis_frame_id(frame);
1222+ tap->input_device = input_device;
1223+ tap->fingers = tap_gesture_handle_properties (tap, frame);
1224+ binding->callback (binding->widget,
1225+ time_type,
1226+ grip_event,
1227+ binding->data);
1228+ }
1229+ grip_gesture_event_free (grip_event);
1230+ }
1231+ }
1232+ }
1233+ }
1234+ }
1235+ }
1236+ }
1237+}
1238+
1239+
1240+static gboolean
1241+grip_geis_event_ready (GIOChannel *source G_GNUC_UNUSED,
1242+ GIOCondition condition G_GNUC_UNUSED,
1243+ gpointer context)
1244+{
1245+ Geis geis = (Geis)context;
1246+ GeisStatus status G_GNUC_UNUSED = geis_dispatch_events(geis);
1247+ return TRUE;
1248+}
1249+
1250+
1251+static void
1252+grip_gesture_manager_init (GripGestureManager *self)
1253+{
1254+ GripGestureManagerPrivate *priv = self->priv = GRIP_GESTURE_MANAGER_GET_PRIVATE (self);
1255 priv->devices = g_ptr_array_new ();
1256-}
1257-
1258-static gboolean
1259-io_callback (GIOChannel *source G_GNUC_UNUSED,
1260- GIOCondition condition G_GNUC_UNUSED,
1261- gpointer data)
1262-{
1263- GripGestureRegistration *reg = (GripGestureRegistration *)data;
1264-
1265- geis_event_dispatch (reg->instance);
1266-
1267- return TRUE;
1268-}
1269-
1270-static void
1271-destroy_registration(GripGestureRegistration *reg)
1272-{
1273- GList *list;
1274-
1275- for (list = reg->bindings; list != NULL; list = list->next)
1276- {
1277- GripGestureBinding *binding = (GripGestureBinding *)list->data;
1278-
1279- if (binding->destroy)
1280- {
1281- GDestroyNotify d = binding->destroy;
1282-
1283- d (binding->data);
1284- }
1285-
1286- g_free (binding);
1287- }
1288-
1289- g_list_free (reg->bindings);
1290-
1291- g_io_channel_shutdown (reg->iochannel, FALSE, NULL);
1292- g_source_remove (reg->iochannel_id);
1293- g_io_channel_unref (reg->iochannel);
1294-
1295- geis_finish (reg->instance);
1296-
1297- reg->instance = NULL;
1298- reg->iochannel = NULL;
1299-}
1300+
1301+ priv->geis = geis_new (GEIS_INIT_TRACK_DEVICES, GEIS_INIT_TRACK_GESTURE_CLASSES, NULL);
1302+ g_return_if_fail (priv->geis);
1303+
1304+ int fd;
1305+ geis_get_configuration(priv->geis, GEIS_CONFIGURATION_FD, &fd);
1306+ priv->iochannel = g_io_channel_unix_new (fd);
1307+ priv->iochannel_id = g_io_add_watch (priv->iochannel, G_IO_IN, grip_geis_event_ready, priv->geis);
1308+ geis_register_device_callback (priv->geis, grip_geis_event_callback, self);
1309+ geis_register_class_callback (priv->geis, grip_geis_event_callback, self);
1310+ geis_register_event_callback (priv->geis, grip_geis_event_callback, self);
1311+}
1312+
1313
1314 static void
1315 window_destroyed_cb (GtkWidget *object,
1316 gpointer user_data)
1317 {
1318 GripGestureManager *manager = (GripGestureManager *)user_data;
1319- GripGestureManagerPrivate *priv = manager->priv;
1320- struct Registrations *reg = g_hash_table_lookup (priv->registered_windows, object);
1321-
1322- if (!reg)
1323- return;
1324-
1325- destroy_registration(reg->touchpad);
1326- destroy_registration(reg->touchscreen);
1327- destroy_registration(reg->independent);
1328-
1329- g_hash_table_remove (priv->registered_windows, object);
1330- g_free (reg);
1331-}
1332-
1333-static const gchar *
1334-grip_type_to_geis_type (GripGestureType gesture_type,
1335- gint touch_points)
1336-{
1337- /* grail taps begin at 15, so let's convert that into something we
1338- * can index in geis_gesture_types. */
1339- int t = gesture_type == 15 ? 3 : gesture_type;
1340-
1341- return geis_gesture_types[(t * 5 + touch_points) - 1];
1342+ GList *l = manager->priv->bindings;
1343+ while (l != NULL)
1344+ {
1345+ GList *next = l->next;
1346+ GripGestureBinding *binding = l->data;
1347+ if (gtk_widget_get_toplevel (binding->widget) == object)
1348+ {
1349+ geis_subscription_delete (binding->subscription);
1350+
1351+ if (binding->destroy)
1352+ binding->destroy (binding->data);
1353+ g_free (binding);
1354+ manager->priv->bindings = g_list_delete_link (manager->priv->bindings, l);
1355+ }
1356+ l = next;
1357+ }
1358 }
1359
1360
1361@@ -1017,232 +704,207 @@
1362 }
1363
1364
1365+/*
1366+ * processed_mapped_window_request:
1367+ * @reg: a #GripRegistrationRequest (removed from the GripGestureManager
1368+ * requests listand freed).
1369+ *
1370+ * Creates a subscription for a widget mapped to a window.
1371+ */
1372 static void
1373-grip_devices_for_type (GripDeviceType type, GArray *selection,
1374- GripDevices *devices)
1375+processed_mapped_window_request (GripRegistrationRequest *req)
1376 {
1377- guint i;
1378-
1379- for (i = 0; i < devices->len; ++i)
1380+ g_return_if_fail (GRIP_IS_GESTURE_MANAGER (req->manager));
1381+ g_return_if_fail (GTK_IS_WIDGET (req->widget));
1382+
1383+ GtkWidget *toplevel = gtk_widget_get_toplevel (req->widget);
1384+ g_return_if_fail (GTK_IS_WINDOW (toplevel));
1385+
1386+ GripGestureManagerPrivate *priv = req->manager->priv;
1387+
1388+ guint window_id = GDK_WINDOW_XID (gtk_widget_get_window(req->widget));
1389+
1390+ /* XXX - check for duplicates in reg->bindings first */
1391+ GripGestureBinding *binding = g_new0 (GripGestureBinding, 1);
1392+ binding->type = req->gesture_type;
1393+ binding->widget = req->widget;
1394+ binding->touches = req->touch_points;
1395+ binding->callback = req->callback;
1396+ binding->data = req->user_data;
1397+ binding->destroy = req->destroy;
1398+
1399+ char sub_name[48];
1400+ snprintf(sub_name, 48, "sub-%x-%x-%x", window_id, req->gesture_type, req->touch_points);
1401+ binding->subscription = geis_subscription_new (priv->geis, sub_name, GEIS_SUBSCRIPTION_CONT);
1402+ g_return_if_fail (binding->subscription);
1403+
1404+ char filter_id[20];
1405+ snprintf(filter_id, 20, "grip-%x", window_id);
1406+ GeisFilter window_filter = geis_filter_new(priv->geis, filter_id);
1407+ geis_filter_add_term(window_filter, GEIS_FILTER_REGION,
1408+ GEIS_REGION_ATTRIBUTE_WINDOWID, GEIS_FILTER_OP_EQ, window_id,
1409+ NULL);
1410+
1411+ switch (req->gesture_type)
1412 {
1413- GripInputDevice *input_device = g_ptr_array_index (devices, i);
1414- GeisInputDeviceId id = grip_input_device_get_id (input_device);
1415- GripDeviceType device_type= grip_get_device_type(input_device);
1416-
1417- if ((type & GRIP_DEVICE_TOUCHSCREEN) && device_type == GRIP_DEVICE_TOUCHSCREEN)
1418- {
1419- g_array_append_val (selection, id);
1420- }
1421- if ((type & GRIP_DEVICE_TOUCHPAD) && device_type == GRIP_DEVICE_TOUCHPAD)
1422- {
1423- g_array_append_val (selection, id);
1424- }
1425- if ((type & GRIP_DEVICE_INDEPENDENT) && device_type == GRIP_DEVICE_INDEPENDENT)
1426- {
1427- g_array_append_val (selection, id);
1428- }
1429+ case GRIP_GESTURE_DRAG:
1430+ geis_filter_add_term(window_filter, GEIS_FILTER_CLASS,
1431+ GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_DRAG,
1432+ GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, req->touch_points,
1433+ NULL);
1434+ break;
1435+ case GRIP_GESTURE_PINCH:
1436+ geis_filter_add_term(window_filter, GEIS_FILTER_CLASS,
1437+ GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_PINCH,
1438+ GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, req->touch_points,
1439+ NULL);
1440+ break;
1441+ case GRIP_GESTURE_ROTATE:
1442+ geis_filter_add_term(window_filter, GEIS_FILTER_CLASS,
1443+ GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_ROTATE,
1444+ GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, req->touch_points,
1445+ NULL);
1446+ break;
1447+ case GRIP_GESTURE_TAP:
1448+ geis_filter_add_term(window_filter, GEIS_FILTER_CLASS,
1449+ GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_TAP,
1450+ GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, req->touch_points,
1451+ NULL);
1452+ break;
1453 }
1454-}
1455-
1456-/*
1457- * new_window_registration:
1458- * @manager: a GripGestureManager
1459- * @toplevel: a toplevel #GtkWindow
1460- *
1461- * Constructs a new #GripGestureRegistration for a #GtkWidget.
1462- */
1463-static GripGestureRegistration *
1464-new_window_registration(GripGestureManager *manager,
1465- GtkWidget *toplevel)
1466-{
1467- GripGestureRegistration *reg;
1468- GeisInstance instance;
1469- gint fd = -1;
1470- GeisXcbWinInfo xcb_win_info = {
1471- .display_name = NULL,
1472- .screenp = NULL,
1473- .window_id = GDK_WINDOW_XID (gtk_widget_get_window(toplevel))
1474- };
1475- GeisWinInfo win_info = {
1476- GEIS_XCB_FULL_WINDOW,
1477- &xcb_win_info
1478- };
1479-
1480- if (geis_init (&win_info, &instance) != GEIS_STATUS_SUCCESS)
1481- {
1482- g_warning ("Failed to initialize gesture manager.");
1483- return NULL;
1484- }
1485-
1486- if (geis_configuration_supported (instance,
1487- GEIS_CONFIG_UNIX_FD) != GEIS_STATUS_SUCCESS)
1488- {
1489- g_warning ("Gesture manager does not support UNIX fd.");
1490- return NULL;
1491- }
1492-
1493- if (geis_configuration_get_value (instance,
1494- GEIS_CONFIG_UNIX_FD,
1495- &fd) != GEIS_STATUS_SUCCESS)
1496- {
1497- g_error ("Gesture manager failed to obtain UNIX fd.");
1498- return NULL;
1499- }
1500-
1501- reg = g_new0 (GripGestureRegistration, 1);
1502-
1503- reg->window = GTK_WINDOW (toplevel);
1504- reg->instance = instance;
1505+
1506+ if (req->device_type & GRIP_DEVICE_TOUCHSCREEN)
1507+ {
1508+ char filter_name[32];
1509+ snprintf(filter_name, 32, "%s/touchscreen", filter_id);
1510+ GeisFilter touchscreen_filter = geis_filter_clone (window_filter, filter_name);
1511+ geis_filter_add_term(touchscreen_filter, GEIS_FILTER_DEVICE,
1512+ GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_FILTER_OP_EQ, GEIS_TRUE,
1513+ NULL);
1514+ GeisStatus status = geis_subscription_add_filter(binding->subscription, touchscreen_filter);
1515+ g_return_if_fail (status == GEIS_STATUS_SUCCESS);
1516+ }
1517+ if (req->device_type & GRIP_DEVICE_TOUCHPAD)
1518+ {
1519+ char filter_name[32];
1520+ snprintf(filter_name, 32, "%s/touchpad", filter_id);
1521+ GeisFilter touchpad_filter = geis_filter_clone (window_filter, filter_name);
1522+ geis_filter_add_term(touchpad_filter, GEIS_FILTER_DEVICE,
1523+ GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_FILTER_OP_EQ, GEIS_FALSE,
1524+ NULL);
1525+ GeisStatus status = geis_subscription_add_filter(binding->subscription, touchpad_filter);
1526+ g_return_if_fail (status == GEIS_STATUS_SUCCESS);
1527+ }
1528+ if (req->device_type & GRIP_DEVICE_INDEPENDENT)
1529+ {
1530+ char filter_name[32];
1531+ snprintf(filter_name, 32, "%s/indep", filter_id);
1532+ GeisFilter indep_filter = geis_filter_clone (window_filter, filter_name);
1533+ geis_filter_add_term(indep_filter, GEIS_FILTER_DEVICE,
1534+ GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH, GEIS_FILTER_OP_EQ, GEIS_TRUE,
1535+ NULL);
1536+ GeisStatus status = geis_subscription_add_filter(binding->subscription, indep_filter);
1537+ g_return_if_fail (status == GEIS_STATUS_SUCCESS);
1538+ }
1539+
1540+ /*
1541+ * If any device types were specified, the window_filter was cloned and needs
1542+ * to be disposed of, otehrwise it's _the_ filter.
1543+ */
1544+ if (req->device_type)
1545+ {
1546+ geis_filter_delete(window_filter);
1547+ }
1548+ else
1549+ {
1550+ GeisStatus status = geis_subscription_add_filter(binding->subscription, window_filter);
1551+ g_return_if_fail (status == GEIS_STATUS_SUCCESS);
1552+ }
1553+
1554+
1555+ GeisStatus status = geis_subscription_activate (binding->subscription);
1556+ g_return_if_fail (status == GEIS_STATUS_SUCCESS);
1557+
1558+ priv->bindings = g_list_append (priv->bindings, binding);
1559
1560 g_signal_connect (toplevel,
1561 "destroy",
1562 G_CALLBACK (window_destroyed_cb),
1563- manager);
1564-
1565- reg->iochannel = g_io_channel_unix_new (fd);
1566- reg->iochannel_id = g_io_add_watch (reg->iochannel,
1567- G_IO_IN,
1568- io_callback,
1569- reg);
1570- reg->gesture_list = g_ptr_array_new ();
1571-
1572- return reg;
1573-}
1574-
1575-static void
1576-bind_registration(GripGestureManager *manager,
1577- GripGestureRegistration *reg,
1578- GtkWidget *widget,
1579- GripGestureType gesture_type,
1580- GripDeviceType device_type,
1581- gint touch_points,
1582- GripGestureCallback callback,
1583- gpointer user_data,
1584- GDestroyNotify destroy)
1585-{
1586- GripGestureManagerPrivate *priv;
1587- GripGestureBinding *binding;
1588- GArray *devices;
1589-
1590- priv = manager->priv;
1591-
1592- if (reg->gesture_list->len)
1593- g_ptr_array_remove_index (reg->gesture_list,
1594- reg->gesture_list->len - 1);
1595-
1596- devices = g_array_new (TRUE, FALSE, sizeof(GeisInputDeviceId));
1597- grip_devices_for_type(device_type, devices, priv->devices);
1598- if (devices->len == 0) {
1599- g_array_free(devices, TRUE);
1600- return;
1601- }
1602-
1603- g_ptr_array_add (reg->gesture_list,
1604- (gchar *)grip_type_to_geis_type (gesture_type, touch_points));
1605- g_ptr_array_add (reg->gesture_list,
1606- NULL);
1607-
1608- geis_subscribe (reg->instance,
1609- (GeisInputDeviceId *)(void *)devices->data,
1610- (const char**)reg->gesture_list->pdata,
1611- &gesture_funcs,
1612- manager);
1613-
1614- g_array_unref (devices);
1615-
1616- /* XXX - check for duplicates in reg->bindings first */
1617- binding = g_new0 (GripGestureBinding, 1);
1618-
1619- binding->type = gesture_type;
1620- binding->widget = widget;
1621- binding->touches = touch_points;
1622- binding->callback = callback;
1623- binding->data = user_data;
1624- binding->destroy = destroy;
1625-
1626- reg->bindings = g_list_append (reg->bindings, binding);
1627-}
1628-
1629-/*
1630- * register_internal:
1631- * @manager: the @GripGestureManager
1632- * @widget: the GtkWidget to be bound
1633- * @gesture_type: the type of gesture to subscribe for
1634- * @device_type: the type of input device to subscribe for
1635- * @touch_points:
1636- * @callback: the callback to be invoked on gesture events
1637- * @user_data: the callbackl context to be passed back on gesture events
1638- * @destroy:
1639- *
1640- * Binds or rebinds a gesture subscription for a widget.
1641- */
1642-static void
1643-register_internal (GripGestureManager *manager,
1644- GtkWidget *widget,
1645- GripGestureType gesture_type,
1646- GripDeviceType device_type,
1647- gint touch_points,
1648- GripGestureCallback callback,
1649- gpointer user_data,
1650- GDestroyNotify destroy)
1651-{
1652- GripGestureManagerPrivate *priv;
1653- GtkWidget *toplevel;
1654- struct Registrations *registrations;
1655-
1656- g_return_if_fail (GRIP_IS_GESTURE_MANAGER (manager));
1657- g_return_if_fail (GTK_IS_WIDGET (widget));
1658-
1659- toplevel = gtk_widget_get_toplevel (widget);
1660-
1661- g_return_if_fail (GTK_IS_WINDOW (toplevel));
1662-
1663- priv = manager->priv;
1664-
1665- if (!(registrations = g_hash_table_lookup (priv->registered_windows, toplevel)))
1666- {
1667- registrations = g_new(struct Registrations, 1);
1668- registrations->touchscreen = new_window_registration(manager, toplevel);
1669- registrations->touchpad = new_window_registration(manager, toplevel);
1670- registrations->independent = new_window_registration(manager, toplevel);
1671-
1672- if (registrations->touchscreen == NULL ||
1673- registrations->touchpad == NULL ||
1674- registrations->independent == NULL)
1675- return;
1676+ req->manager);
1677+
1678+ /* remove the request from the watch list */
1679+ g_free (req);
1680+ priv->requests = g_list_remove (priv->requests, req);
1681+}
1682+
1683+
1684+/*
1685+ * register_mapped_window:
1686+ * @manager: a Grip gesture manager object
1687+ * @toplevel: a top-level widget
1688+ *
1689+ * Processes all subscriptions requests for a newly-mapped window.
1690+ */
1691+static void
1692+register_mapped_window (GripGestureManager *manager, GtkWidget *toplevel)
1693+{
1694+ g_return_if_fail (gtk_widget_is_toplevel (toplevel));
1695+
1696+ GList *pending_request = manager->priv->requests;
1697+ while (pending_request)
1698+ {
1699+ GList *next = pending_request->next;
1700+ GripRegistrationRequest *req = pending_request->data;
1701+
1702+ if (gtk_widget_get_toplevel (req->widget) == toplevel)
1703+ {
1704+ processed_mapped_window_request (req);
1705+ }
1706+ pending_request = next;
1707+ }
1708+}
1709+
1710+
1711+/*
1712+ * register_toplevel_widget:
1713+ * @manager: a Grip gesture manager object
1714+ * @toplevel: a top-level widget
1715+ *
1716+ * Handles the registration of a widget that has just become a top-level widget.
1717+ *
1718+ * If the top-level widget is mapped to a window, it;s handled right away.
1719+ * Otherwise, a callback is queued for when it does become mapped to a window.
1720+ */
1721+static void
1722+register_toplevel_widget (GripGestureManager *manager, GtkWidget *toplevel)
1723+{
1724+ g_return_if_fail (gtk_widget_is_toplevel (toplevel));
1725+
1726+ if (gtk_widget_get_mapped (GTK_WIDGET (toplevel)))
1727+ {
1728+ register_mapped_window (manager, toplevel);
1729 }
1730 else
1731 {
1732- if (device_type & GRIP_DEVICE_TOUCHSCREEN)
1733- geis_unsubscribe (registrations->touchscreen->instance,
1734- (GeisGestureType*)registrations->touchscreen->gesture_list->pdata);
1735- if (device_type & GRIP_DEVICE_TOUCHPAD)
1736- geis_unsubscribe (registrations->touchpad->instance,
1737- (GeisGestureType*)registrations->touchpad->gesture_list->pdata);
1738- if (device_type & GRIP_DEVICE_INDEPENDENT)
1739- geis_unsubscribe (registrations->independent->instance,
1740- (GeisGestureType*)registrations->independent->gesture_list->pdata);
1741+ g_signal_connect (toplevel,
1742+ "map-event",
1743+ G_CALLBACK (toplevel_mapped_cb),
1744+ manager);
1745 }
1746-
1747- if (device_type & GRIP_DEVICE_TOUCHSCREEN)
1748- bind_registration(manager,
1749- registrations->touchscreen, widget, gesture_type, GRIP_DEVICE_TOUCHSCREEN, touch_points,
1750- callback, user_data, destroy);
1751-
1752- if (device_type & GRIP_DEVICE_TOUCHPAD)
1753- bind_registration(manager,
1754- registrations->touchpad, widget, gesture_type, GRIP_DEVICE_TOUCHPAD, touch_points,
1755- callback, user_data, destroy);
1756-
1757- if (device_type & GRIP_DEVICE_INDEPENDENT)
1758- bind_registration(manager,
1759- registrations->independent, widget, gesture_type, GRIP_DEVICE_INDEPENDENT, touch_points,
1760- callback, user_data, destroy);
1761- g_hash_table_insert (priv->registered_windows,
1762- toplevel,
1763- registrations);
1764 }
1765
1766+
1767+/*
1768+ * toplevel_notify_cb:
1769+ *
1770+ * Called when a widget property has changed.
1771+ *
1772+ * The only widget property we're interested in here is the "parent" property.
1773+ * We can't subscribe to gestures on a window until the widget is mapped to a
1774+ * window. Only top-level widgets can be mapped to a window: we just keep
1775+ * queueing this callback on successive parent widgets until one is a top-level
1776+ * widget, then process that one.
1777+ */
1778 static void
1779 toplevel_notify_cb (GtkWidget *widget,
1780 GParamSpec *pspec,
1781@@ -1251,7 +913,7 @@
1782 if (pspec->name == g_intern_static_string ("parent"))
1783 {
1784 GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
1785- GripRegistrationRequest *req = (GripRegistrationRequest *)user_data;
1786+ GripGestureManager *manager = (GripGestureManager *)user_data;
1787
1788 g_signal_handlers_disconnect_by_func (widget,
1789 G_CALLBACK (toplevel_notify_cb),
1790@@ -1259,30 +921,7 @@
1791
1792 if (gtk_widget_is_toplevel (toplevel))
1793 {
1794- if (gtk_widget_get_mapped (GTK_WIDGET (toplevel)))
1795- {
1796- register_internal (req->manager,
1797- req->widget,
1798- req->gesture_type,
1799- req->device_type,
1800- req->touch_points,
1801- req->callback,
1802- req->user_data,
1803- req->destroy);
1804-
1805- g_free (req);
1806- }
1807- else
1808- {
1809- GripGestureManagerPrivate *priv = req->manager->priv;
1810-
1811- priv->requests = g_list_append (priv->requests, req);
1812-
1813- g_signal_connect (toplevel,
1814- "map-event",
1815- G_CALLBACK (toplevel_mapped_cb),
1816- req->manager);
1817- }
1818+ register_toplevel_widget (manager, toplevel);
1819 }
1820 else
1821 {
1822@@ -1294,96 +933,29 @@
1823 }
1824 }
1825
1826+
1827 /*
1828- * register_widget:
1829- *
1830- * Registers a specific widget for a specific gesture made by a specific input
1831- * device type.
1832- *
1833- * If the widget's containing window is a valid window, the widget is registered
1834- * right away, otherwise the registration is deferred until the widget actually
1835- * has a top-level window.
1836+ * toplevel_mapped_cb:
1837+ *
1838+ * A callback invoked when a toplevel widget with one or more pending gesture
1839+ * registration requests has been mapped to a window.
1840+ *
1841+ * This callback will in fact process all pending registration requests for the
1842+ * newly-mapped window.
1843 */
1844 static void
1845-register_widget (GripGestureManager *manager,
1846- GtkWidget *widget,
1847- GripGestureType gesture_type,
1848- GripDeviceType device_type,
1849- gint touch_points,
1850- GripGestureCallback callback,
1851- gpointer user_data,
1852- GDestroyNotify destroy)
1853-{
1854- GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
1855-
1856- if (gtk_widget_is_toplevel (toplevel))
1857- {
1858- register_internal (manager,
1859- widget,
1860- gesture_type,
1861- device_type,
1862- touch_points,
1863- callback,
1864- user_data,
1865- destroy);
1866- }
1867- else
1868- {
1869- GripRegistrationRequest *req = g_new0 (GripRegistrationRequest, 1);
1870-
1871- req->manager = manager;
1872- req->widget = widget;
1873- req->gesture_type = gesture_type;
1874- req->device_type = device_type;
1875- req->touch_points = touch_points;
1876- req->callback = callback;
1877- req->user_data = user_data;
1878- req->destroy = destroy;
1879-
1880- g_signal_connect (toplevel,
1881- "notify",
1882- G_CALLBACK (toplevel_notify_cb),
1883- req);
1884- }
1885-}
1886-
1887-static void
1888 toplevel_mapped_cb (GtkWidget *toplevel,
1889 GdkEvent *event G_GNUC_UNUSED,
1890 gpointer user_data)
1891 {
1892 GripGestureManager *manager = (GripGestureManager *)user_data;
1893- GripGestureManagerPrivate *priv = manager->priv;
1894- GList *request = priv->requests;
1895-
1896- while (request)
1897- {
1898- GList *next = request->next;
1899- GripRegistrationRequest *req = request->data;
1900-
1901- if (gtk_widget_get_toplevel (req->widget) == toplevel)
1902- {
1903- register_widget (req->manager,
1904- req->widget,
1905- req->gesture_type,
1906- req->device_type,
1907- req->touch_points,
1908- req->callback,
1909- req->user_data,
1910- req->destroy);
1911-
1912- priv->requests = g_list_remove_link (priv->requests, request);
1913- g_free (req);
1914- g_list_free_1 (request);
1915- }
1916- request = next;
1917- }
1918-
1919+ register_mapped_window (manager, toplevel);
1920 g_signal_handlers_disconnect_by_func (toplevel,
1921 toplevel_mapped_cb,
1922 user_data);
1923 }
1924
1925+
1926 /**
1927 * grip_gesture_manager_register_window:
1928 * @manager: A #GripGestureManager instance.
1929@@ -1411,102 +983,47 @@
1930 gpointer user_data,
1931 GDestroyNotify destroy)
1932 {
1933- GtkWidget *toplevel;
1934-
1935 g_return_if_fail (GRIP_IS_GESTURE_MANAGER (manager));
1936 g_return_if_fail (GTK_IS_WIDGET (widget));
1937
1938- toplevel = gtk_widget_get_toplevel (widget);
1939+ GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
1940+
1941+ GripRegistrationRequest *req = g_new0 (GripRegistrationRequest, 1);
1942+ req->manager = manager;
1943+ req->widget = widget;
1944+ req->gesture_type = gesture_type;
1945+ req->device_type = device_type;
1946+ req->touch_points = touch_points;
1947+ req->callback = callback;
1948+ req->user_data = user_data;
1949+ req->destroy = destroy;
1950+ manager->priv->requests = g_list_append (manager->priv->requests, req);
1951
1952 if (GTK_IS_WINDOW (toplevel))
1953 {
1954- if (gtk_widget_get_mapped (GTK_WIDGET (toplevel)))
1955- {
1956- register_internal (manager,
1957- widget,
1958- gesture_type,
1959- device_type,
1960- touch_points,
1961- callback,
1962- user_data,
1963- destroy);
1964- }
1965- else
1966- {
1967- GripRegistrationRequest *req = g_new0 (GripRegistrationRequest, 1);
1968- GripGestureManagerPrivate *priv = manager->priv;
1969-
1970- req->manager = manager;
1971- req->widget = widget;
1972- req->gesture_type = gesture_type;
1973- req->device_type = device_type;
1974- req->touch_points = touch_points;
1975- req->callback = callback;
1976- req->user_data = user_data;
1977- req->destroy = destroy;
1978-
1979- priv->requests = g_list_append (priv->requests, req);
1980-
1981- g_signal_connect (toplevel,
1982- "map-event",
1983- G_CALLBACK (toplevel_mapped_cb),
1984- manager);
1985- }
1986+ register_toplevel_widget (manager, toplevel);
1987 }
1988 else
1989 {
1990- GripRegistrationRequest *req = g_new0 (GripRegistrationRequest, 1);
1991-
1992- req->manager = manager;
1993- req->widget = widget;
1994- req->gesture_type = gesture_type;
1995- req->device_type = device_type;
1996- req->touch_points = touch_points;
1997- req->callback = callback;
1998- req->user_data = user_data;
1999- req->destroy = destroy;
2000-
2001 g_signal_connect (toplevel,
2002 "notify",
2003 G_CALLBACK (toplevel_notify_cb),
2004- req);
2005+ manager);
2006 }
2007 }
2008
2009-static void
2010-shutdown_registration(GripGestureRegistration *reg)
2011-{
2012- free_registration(reg);
2013- geis_finish(reg->instance);
2014- reg->instance = NULL;
2015- g_free(reg);
2016-}
2017
2018 void
2019-grip_gesture_manager_unregister_window (GripGestureManager *manager,
2020- GtkWidget *toplevel)
2021+grip_gesture_manager_unregister_window (GripGestureManager *manager G_GNUC_UNUSED,
2022+ GtkWidget *toplevel G_GNUC_UNUSED)
2023 {
2024- GripGestureManagerPrivate *priv = manager->priv;
2025- struct Registrations *registrations;
2026-
2027 g_return_if_fail (GRIP_IS_GESTURE_MANAGER (manager));
2028 g_return_if_fail (GTK_IS_WINDOW (toplevel));
2029
2030- /* Currently only allow unsubscribing after the window has been shown. */
2031- g_return_if_fail (gtk_widget_get_mapped (GTK_WIDGET (toplevel)));
2032- registrations = g_hash_table_lookup (priv->registered_windows, toplevel);
2033- if (!registrations) {
2034- return;
2035- }
2036-
2037- shutdown_registration(registrations->touchscreen);
2038- shutdown_registration(registrations->touchpad);
2039- shutdown_registration(registrations->independent);
2040- g_free(registrations);
2041- g_hash_table_remove(priv->registered_windows, toplevel);
2042-
2043+ window_destroyed_cb (toplevel, manager);
2044 }
2045
2046+
2047 GType
2048 grip_gesture_event_get_type (void)
2049 {
2050
2051=== modified file 'src/gripinputdevice.c'
2052--- src/gripinputdevice.c 2011-10-19 14:05:35 +0000
2053+++ src/gripinputdevice.c 2013-05-14 18:50:33 +0000
2054@@ -1,5 +1,5 @@
2055 /*
2056- * Copyright 2011 Canonical, Ltd.
2057+ * Copyright 2011, 2013 Canonical Ltd.
2058 *
2059 * This program is free software: you can redistribute it and/or modify it
2060 * under the terms of either or both of the following licenses:
2061@@ -79,53 +79,61 @@
2062 for (a = attrs; a->name; a++)
2063 {
2064 if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_NAME))
2065- {
2066 input_device->priv->name = g_strdup (a->string_val);
2067- }
2068 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_ID))
2069- {
2070 input_device->priv->device_id = a->integer_val;
2071- }
2072 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_TOUCHES))
2073- {
2074 input_device->priv->touches = a->integer_val;
2075- }
2076 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH))
2077- {
2078 input_device->priv->is_direct = a->boolean_val;
2079- }
2080 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH))
2081- {
2082 input_device->priv->is_independent = a->boolean_val;
2083- }
2084 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_MIN_X))
2085- {
2086 input_device->priv->x_extents.minimum = a->float_val;
2087- }
2088 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_MAX_X))
2089- {
2090 input_device->priv->x_extents.maximum = a->float_val;
2091- }
2092 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_RES_X))
2093- {
2094 input_device->priv->x_extents.resolution = a->float_val;
2095- }
2096 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_MIN_Y))
2097- {
2098 input_device->priv->y_extents.minimum = a->float_val;
2099- }
2100 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_MAX_Y))
2101- {
2102 input_device->priv->y_extents.maximum = a->float_val;
2103- }
2104 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_RES_Y))
2105- {
2106 input_device->priv->y_extents.resolution = a->float_val;
2107- }
2108 }
2109 }
2110 }
2111 }
2112+ else
2113+ {
2114+ guint num_attrs = geis_device_attr_count(input_device->priv->geis_device);
2115+ for (i = 0; i < num_attrs; ++i)
2116+ {
2117+ GeisAttr attr = geis_device_attr(input_device->priv->geis_device, i);
2118+ if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_NAME))
2119+ input_device->priv->name = g_strdup (geis_attr_value_to_string(attr));
2120+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_ID))
2121+ input_device->priv->device_id = geis_attr_value_to_integer(attr);
2122+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_TOUCHES))
2123+ input_device->priv->touches = geis_attr_value_to_integer(attr);
2124+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH))
2125+ input_device->priv->is_direct = geis_attr_value_to_boolean(attr);
2126+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH))
2127+ input_device->priv->is_independent = geis_attr_value_to_boolean(attr);
2128+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_MIN_X))
2129+ input_device->priv->x_extents.minimum = geis_attr_value_to_float(attr);
2130+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_MAX_X))
2131+ input_device->priv->x_extents.maximum = geis_attr_value_to_float(attr);
2132+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_RES_X))
2133+ input_device->priv->x_extents.resolution = geis_attr_value_to_float(attr);
2134+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_MIN_Y))
2135+ input_device->priv->y_extents.minimum = geis_attr_value_to_float(attr);
2136+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_MAX_Y))
2137+ input_device->priv->y_extents.maximum = geis_attr_value_to_float(attr);
2138+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_RES_Y))
2139+ input_device->priv->y_extents.resolution = geis_attr_value_to_float(attr);
2140+ }
2141+ }
2142
2143 return object;
2144 }

Subscribers

People subscribed via source and target branches

to all changes: