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

Proposed by Stephen M. Webb
Status: Merged
Approved by: Stephen M. Webb
Approved revision: 80
Merged at revision: 77
Proposed branch: lp:~bregma/libgrip/lp-1168370
Merge into: lp:libgrip
Diff against target: 2145 lines (+703/-1177)
2 files modified
src/gripgesturemanager.c (+672/-1154)
src/gripinputdevice.c (+31/-23)
To merge this branch: bzr merge lp:~bregma/libgrip/lp-1168370
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Open Input Framework Team Pending
Review via email: mp+159242@code.launchpad.net

Commit message

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

Description of the change

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.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

120 -static const gchar *geis_gesture_types[] = {

Moved?

252 + g_ptr_array_add(manager->priv->devices, input_device);
496 + g_ptr_array_foreach (priv->devices, (GFunc) g_object_unref, NULL);

Does manager->priv->devices get clean up? Or who owns input_device?

230 + goto final_exit;

333 +final_exit:
334 + return;
335 +}

Cant you just do a 'return;'? Instead of a goto?

362 + for (l = priv->classes; l != NULL; l = l->next)
363 + {

355 + switch (geis_event_type(geis_event))
356 + {

Most likely just the coding style, but how come its switched from new line style to GNU style? (or the new line + spaces style).

Hopefully these stay constant during the loop:

1172 + for (i = 0; i < geis_groupset_group_count (groupset); ++i)
1182 + for (j = 0; j < geis_group_frame_count (group); ++j)

I couldn't find them defined, or how you add to it soo I wasn't sure if:
1184 + GeisFrame frame = geis_group_frame(group, j);

Would extract, and remove anything from the group_frame. Hopefully not!

lp:~bregma/libgrip/lp-1168370 updated
79. By Stephen M. Webb

replaced gotos with something more GTK-like

80. By Stephen M. Webb

small stylistic repair

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Stephen M. Webb (bregma) wrote :

(1) manager->priv->devices gets unreffed (freed) on the next line.

(2) gotos replaced

(3) style fixed

(4) the data returned from GEIS is readonly, none of the group/frame accessor calls modifiy the data

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-04-17 15:02:24 +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,18 @@
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_foreach(priv->classes, (GFunc) g_free, NULL);
478+ g_list_free(priv->classes);
479+
480+ g_ptr_array_foreach (priv->devices, (GFunc) g_object_unref, NULL);
481+ g_ptr_array_unref (priv->devices);
482 }
483
484+
485 static GObject *
486 grip_gesture_manager_constructor (GType type,
487 guint n_params,
488@@ -332,12 +307,12 @@
489 self = G_OBJECT_CLASS (grip_gesture_manager_parent_class)->
490 constructor (type, n_params, params);
491 g_object_add_weak_pointer (self, (gpointer) &self);
492- grip_get_devices (GRIP_GESTURE_MANAGER (self));
493 }
494
495 return g_object_ref (self);
496 }
497
498+
499 static void
500 grip_gesture_manager_class_init (GripGestureManagerClass *class)
501 {
502@@ -386,7 +361,6 @@
503 G_TYPE_NONE,
504 1,
505 GRIP_TYPE_INPUT_DEVICE);
506-
507 }
508
509
510@@ -420,592 +394,306 @@
511 return input_device;
512 }
513
514-/*
515- * registration_for_input_device:
516- * @registrations: A collection of #GripGestureRegistration
517- * @input_device: A pointer to a #GripInputDevice
518- *
519- * Determines which #GripGestureRegistration to use dependeng on properties of
520- * the #GripInputDevice.
521- *
522- * Returns: a pointer to a #GripGestureRegistration or %NULL if not found.
523- */
524-static GripGestureRegistration *
525-registration_for_input_device (struct Registrations *registrations,
526- GripInputDevice *input_device)
527-{
528- GripDeviceType device_type = grip_get_device_type(input_device);
529- if (device_type == GRIP_DEVICE_TOUCHSCREEN)
530- {
531- return registrations->touchscreen;
532- }
533- else if (GRIP_DEVICE_TOUCHPAD)
534- {
535- return registrations->touchpad;
536- }
537- else if (GRIP_DEVICE_INDEPENDENT)
538- {
539- return registrations->independent;
540- }
541- return NULL;
542-}
543-
544
545 static gint
546 pinch_gesture_handle_properties (GripEventGesturePinch *event,
547- GeisSize attr_count,
548- GeisGestureAttr *attrs)
549+ GeisFrame frame)
550 {
551- guint i = 0;
552- gint touches = 0;
553-
554+ guint attr_count = geis_frame_attr_count (frame);
555+ gint num_touches = 0;
556+ guint i;
557 for (i = 0; i < attr_count; ++i)
558 {
559- if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0 &&
560- attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
561- {
562- touches = attrs[i].integer_val;
563- }
564- if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0 &&
565- attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
566- {
567- event->timestamp = attrs[i].integer_val;
568- }
569- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0 &&
570- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
571- {
572- event->focus_x = attrs[i].float_val;
573- }
574- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0 &&
575- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
576- {
577- event->focus_y = attrs[i].float_val;
578- }
579- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA) == 0 &&
580- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
581- {
582- event->radius_delta = attrs[i].float_val;
583- }
584- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_RADIAL_VELOCITY) == 0 &&
585- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
586- {
587- event->radial_velocity = attrs[i].float_val;
588- }
589- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_RADIUS) == 0 &&
590- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
591- {
592- event->radius = attrs[i].float_val;
593- }
594- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0 &&
595- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
596- {
597- event->position_x = attrs[i].float_val;
598- }
599- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0 &&
600- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
601- {
602- event->position_y = attrs[i].float_val;
603- }
604- }
605+ GeisAttr attr = geis_frame_attr(frame, i);
606+ GeisString attr_name = geis_attr_name(attr);
607
608- return touches;
609+ if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0)
610+ num_touches = geis_attr_value_to_integer(attr);
611+ if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0)
612+ event->timestamp = geis_attr_value_to_integer(attr);
613+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0)
614+ event->focus_x = geis_attr_value_to_float(attr);
615+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0)
616+ event->focus_y = geis_attr_value_to_float(attr);
617+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA) == 0)
618+ event->radius_delta = geis_attr_value_to_float(attr);
619+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_RADIAL_VELOCITY) == 0)
620+ event->radial_velocity = geis_attr_value_to_float(attr);
621+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_RADIUS) == 0)
622+ event->radius = geis_attr_value_to_float(attr);
623+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0)
624+ event->position_x = geis_attr_value_to_float(attr);
625+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0)
626+ event->position_y = geis_attr_value_to_float(attr);
627+ }
628+ return num_touches;
629 }
630
631 static gint
632 drag_gesture_handle_properties (GripEventGestureDrag *event,
633- GeisSize attr_count,
634- GeisGestureAttr *attrs)
635+ GeisFrame frame)
636 {
637+ guint attr_count = geis_frame_attr_count (frame);
638+ gint num_touches = 0;
639 guint i;
640- gint touches = 0;
641-
642 for (i = 0; i < attr_count; ++i)
643 {
644- if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0 &&
645- attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
646- {
647- touches = attrs[i].integer_val;
648- }
649- if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0 &&
650- attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
651- {
652- event->timestamp = attrs[i].integer_val;
653- }
654- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0 &&
655- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
656- {
657- event->focus_x = attrs[i].float_val;
658- }
659- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0 &&
660- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
661- {
662- event->focus_y = attrs[i].float_val;
663- }
664- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_DELTA_X) == 0 &&
665- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
666- {
667- event->delta_x = attrs[i].float_val;
668- }
669- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_DELTA_Y) == 0 &&
670- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
671- {
672- event->delta_y = attrs[i].float_val;
673- }
674- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_X) == 0 &&
675- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
676- {
677- event->velocity_x = attrs[i].float_val;
678- }
679- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y) == 0 &&
680- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
681- {
682- event->velocity_y = attrs[i].float_val;
683- }
684- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0 &&
685- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
686- {
687- event->position_x = attrs[i].float_val;
688- }
689- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0 &&
690- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
691- {
692- event->position_y = attrs[i].float_val;
693- }
694- }
695+ GeisAttr attr = geis_frame_attr(frame, i);
696+ GeisString attr_name = geis_attr_name(attr);
697
698- return touches;
699+ if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0)
700+ num_touches = geis_attr_value_to_integer(attr);
701+ if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0)
702+ event->timestamp = geis_attr_value_to_integer(attr);
703+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0)
704+ event->focus_x = geis_attr_value_to_float(attr);
705+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0)
706+ event->focus_y = geis_attr_value_to_float(attr);
707+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_DELTA_X) == 0)
708+ event->delta_x = geis_attr_value_to_float(attr);
709+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_DELTA_Y) == 0)
710+ event->delta_y = geis_attr_value_to_float(attr);
711+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_X) == 0)
712+ event->velocity_x = geis_attr_value_to_float(attr);
713+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y) == 0)
714+ event->velocity_y = geis_attr_value_to_float(attr);
715+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0)
716+ event->position_x = geis_attr_value_to_float(attr);
717+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0)
718+ event->position_y = geis_attr_value_to_float(attr);
719+ }
720+ return num_touches;
721 }
722
723+
724 static gint
725 rotate_gesture_handle_properties (GripEventGestureRotate *event,
726- GeisSize attr_count,
727- GeisGestureAttr *attrs)
728+ GeisFrame frame)
729 {
730+ guint attr_count = geis_frame_attr_count (frame);
731+ gint num_touches = 0;
732 guint i;
733- gint touches = 0;
734-
735 for (i = 0; i < attr_count; ++i)
736 {
737- if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0 &&
738- attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
739- {
740- touches = attrs[i].integer_val;
741- }
742- if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0 &&
743- attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
744- {
745- event->timestamp = attrs[i].integer_val;
746- }
747- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0 &&
748- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
749- {
750- event->focus_x = attrs[i].float_val;
751- }
752- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0 &&
753- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
754- {
755- event->focus_y = attrs[i].float_val;
756- }
757- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA) == 0 &&
758- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
759- {
760- event->angle_delta = attrs[i].float_val;
761- }
762- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_ANGULAR_VELOCITY) == 0 &&
763- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
764- {
765- event->angular_velocity = attrs[i].float_val;
766- }
767- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_ANGLE) == 0 &&
768- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
769- {
770- event->angle = attrs[i].float_val;
771- }
772- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0 &&
773- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
774- {
775- event->position_x = attrs[i].float_val;
776- }
777- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0 &&
778- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
779- {
780- event->position_y = attrs[i].float_val;
781- }
782- }
783+ GeisAttr attr = geis_frame_attr(frame, i);
784+ GeisString attr_name = geis_attr_name(attr);
785
786- return touches;
787+ if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0)
788+ num_touches = geis_attr_value_to_integer(attr);
789+ if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0)
790+ event->timestamp = geis_attr_value_to_integer(attr);
791+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0)
792+ event->focus_x = geis_attr_value_to_float(attr);
793+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0)
794+ event->focus_y = geis_attr_value_to_float(attr);
795+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA) == 0)
796+ event->angle_delta = geis_attr_value_to_float(attr);
797+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_ANGULAR_VELOCITY) == 0)
798+ event->angular_velocity = geis_attr_value_to_float(attr);
799+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_ANGLE) == 0)
800+ event->angle = geis_attr_value_to_float(attr);
801+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0)
802+ event->position_x = geis_attr_value_to_float(attr);
803+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0)
804+ event->position_y = geis_attr_value_to_float(attr);
805+ }
806+ return num_touches;
807 }
808
809+
810 static gint
811 tap_gesture_handle_properties (GripEventGestureTap *event,
812- GeisSize attr_count,
813- GeisGestureAttr *attrs)
814+ GeisFrame frame)
815 {
816+ guint attr_count = geis_frame_attr_count (frame);
817+ gint num_touches = 0;
818 guint i;
819- gint touches = 0;
820-
821 for (i = 0; i < attr_count; ++i)
822 {
823- if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0 &&
824- attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
825- {
826- touches = attrs[i].integer_val;
827- }
828- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0 &&
829- attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
830- {
831- event->timestamp = attrs[i].integer_val;
832- }
833- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0 &&
834- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
835- {
836- event->focus_x = attrs[i].float_val;
837- }
838- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0 &&
839- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
840- {
841- event->focus_y = attrs[i].float_val;
842- }
843- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0 &&
844- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
845- {
846- event->position_x = attrs[i].float_val;
847- }
848- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0 &&
849- attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
850- {
851- event->position_y = attrs[i].float_val;
852- }
853- else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TAP_TIME) == 0 &&
854- attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
855- {
856- event->tap_time = attrs[i].float_val;
857- }
858- }
859-
860- return touches;
861-}
862-
863-static void
864-gesture_added (void *cookie G_GNUC_UNUSED,
865- GeisGestureType gesture_type G_GNUC_UNUSED,
866- GeisGestureId gesture_id G_GNUC_UNUSED,
867- GeisSize attr_count G_GNUC_UNUSED,
868- GeisGestureAttr *attrs G_GNUC_UNUSED)
869-{
870-}
871-
872-static void
873-gesture_removed (void *cookie G_GNUC_UNUSED,
874- GeisGestureType gesture_type G_GNUC_UNUSED,
875- GeisGestureId gesture_id G_GNUC_UNUSED,
876- GeisSize attr_count G_GNUC_UNUSED,
877- GeisGestureAttr *attrs G_GNUC_UNUSED)
878-{
879-}
880-
881-static gboolean
882-matches_widget (GtkWidget *widget,
883- GdkWindow *window,
884- gint x,
885- gint y)
886-{
887- GtkAllocation alloc;
888- gint ax, ay;
889-
890- gtk_widget_get_allocation (widget, &alloc);
891- gdk_window_get_root_coords (window, alloc.x, alloc.y, &ax, &ay);
892-
893- return (x >= ax && x < ax + alloc.width && y >= ay && y < ay + alloc.height);
894-}
895-
896-
897-/*
898- * process_gesture:
899- * @cookie:
900- * @type:
901- * @id:
902- * @attr_count:
903- * @attrs:
904- * @time_type:
905- *
906- * The generic gesture event dispatch engine.
907- */
908-static void
909-process_gesture (void *cookie,
910- GeisGestureType type,
911- GeisGestureId id,
912- GeisSize attr_count,
913- GeisGestureAttr *attrs,
914- GripTimeType time_type)
915-{
916- GripGestureManager *manager = (GripGestureManager *) cookie;
917- GripInputDevice *input_device = NULL;
918- GtkWindow *gtk_window = NULL;
919- struct Registrations *registrations = NULL;
920- GripGestureRegistration *reg = NULL;
921- GList *l = NULL;
922+ GeisAttr attr = geis_frame_attr(frame, i);
923+ GeisString attr_name = geis_attr_name(attr);
924+
925+ if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0)
926+ num_touches = geis_attr_value_to_integer(attr);
927+ if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0)
928+ event->timestamp = geis_attr_value_to_integer(attr);
929+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0)
930+ event->focus_x = geis_attr_value_to_float(attr);
931+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0)
932+ event->focus_y = geis_attr_value_to_float(attr);
933+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0)
934+ event->position_x = geis_attr_value_to_float(attr);
935+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0)
936+ event->position_y = geis_attr_value_to_float(attr);
937+ else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TAP_TIME) == 0)
938+ event->tap_time = geis_attr_value_to_float(attr);
939+ }
940+ return num_touches;
941+}
942+
943+
944+static void
945+process_gesture_events(GripGestureManager *manager, GeisEvent geis_event)
946+{
947+ GripGestureManagerPrivate *priv = manager->priv;
948+
949+ GripTimeType time_type = GRIP_TIME_UPDATE;
950+ if (geis_event_type(geis_event) == GEIS_EVENT_GESTURE_BEGIN)
951+ time_type = GRIP_TIME_START;
952+ else if (geis_event_type(geis_event) == GEIS_EVENT_GESTURE_END)
953+ time_type = GRIP_TIME_END;
954+
955+ GeisAttr attr = geis_event_attr_by_name (geis_event, GEIS_EVENT_ATTRIBUTE_GROUPSET);
956+ g_return_if_fail (attr);
957+
958+ GeisGroupSet groupset = geis_attr_value_to_pointer (attr);
959+ g_return_if_fail (groupset);
960+
961 GeisSize i;
962-
963- for (i = 0; i < attr_count; ++i)
964- {
965- if (0 == g_strcmp0(attrs[i].name, GEIS_GESTURE_ATTRIBUTE_DEVICE_ID))
966- {
967- input_device = device_id_to_input_device(manager, attrs[i].integer_val);
968- }
969- else if (0 == g_strcmp0(attrs[i].name, GEIS_GESTURE_ATTRIBUTE_EVENT_WINDOW_ID))
970- {
971- GHashTableIter iter;
972- GtkWidget *key;
973- struct Registrations *value;
974- guint window_id = attrs[i].integer_val;
975-
976- g_hash_table_iter_init (&iter, manager->priv->registered_windows);
977- while (g_hash_table_iter_next(&iter, (gpointer *)&key, (gpointer *)&value))
978- {
979- if (GDK_WINDOW_XID (gtk_widget_get_window (key)) == window_id)
980- {
981- gtk_window = (GtkWindow *)key;
982- break;
983- }
984- }
985- }
986- }
987- g_return_if_fail(input_device != NULL);
988- g_return_if_fail(gtk_window != NULL);
989-
990- registrations = g_hash_table_lookup (manager->priv->registered_windows, gtk_window);
991- g_return_if_fail(registrations != NULL);
992- reg = registration_for_input_device (registrations, input_device);
993- g_return_if_fail(reg != NULL);
994-
995- for (l = reg->bindings; l != NULL; l = l->next)
996- {
997- GripGestureBinding *binding = (GripGestureBinding *)l->data;
998-
999- if (binding->type == type)
1000- {
1001- GripGestureEvent *event = grip_gesture_event_new (type);
1002-
1003- if (type == GRIP_GESTURE_DRAG)
1004- {
1005- GripEventGestureDrag *drag = (GripEventGestureDrag *)event;
1006-
1007- drag->type = type;
1008- drag->id = id;
1009- drag->input_device = input_device;
1010- drag->fingers = drag_gesture_handle_properties (drag,
1011- attr_count,
1012- attrs);
1013-
1014- if (drag->fingers == (gint)binding->touches)
1015- {
1016- if (matches_widget (binding->widget,
1017- gtk_widget_get_window(GTK_WIDGET (reg->window)),
1018- (gint)drag->focus_x,
1019- (gint)drag->focus_y))
1020- {
1021- binding->callback (binding->widget,
1022- time_type,
1023- event,
1024- binding->data);
1025- }
1026- }
1027- }
1028- else if (type == GRIP_GESTURE_PINCH)
1029- {
1030- GripEventGesturePinch *pinch = (GripEventGesturePinch *)event;
1031-
1032- pinch->type = type;
1033- pinch->id = id;
1034- pinch->input_device = input_device;
1035- pinch->fingers = pinch_gesture_handle_properties (pinch,
1036- attr_count,
1037- attrs);
1038-
1039- if (pinch->fingers == binding->touches)
1040- {
1041- if (matches_widget (binding->widget,
1042- gtk_widget_get_window(GTK_WIDGET (reg->window)),
1043- (gint)pinch->focus_x,
1044- (gint)pinch->focus_y))
1045- {
1046- binding->callback (binding->widget,
1047- time_type,
1048- event,
1049- binding->data);
1050- }
1051- }
1052- }
1053- else if (type == GRIP_GESTURE_ROTATE)
1054- {
1055- GripEventGestureRotate *rotate = (GripEventGestureRotate *)event;
1056-
1057- rotate->type = type;
1058- rotate->id = id;
1059- rotate->input_device = input_device;
1060- rotate->fingers = rotate_gesture_handle_properties (rotate,
1061- attr_count,
1062- attrs);
1063-
1064- if (rotate->fingers == binding->touches)
1065- {
1066- if (matches_widget (binding->widget,
1067- gtk_widget_get_window(GTK_WIDGET (reg->window)),
1068- (gint)rotate->focus_x,
1069- (gint)rotate->focus_y))
1070- {
1071- binding->callback (binding->widget,
1072- time_type,
1073- event,
1074- binding->data);
1075- }
1076- }
1077- }
1078- else if (type == GRIP_GESTURE_TAP)
1079- {
1080- GripEventGestureTap *tap = (GripEventGestureTap *)event;
1081-
1082- tap->type = type;
1083- tap->id = id;
1084- tap->input_device = input_device;
1085- tap->fingers = tap_gesture_handle_properties (tap,
1086- attr_count,
1087- attrs);
1088-
1089- if (tap->fingers == binding->touches)
1090- {
1091- if (matches_widget (binding->widget,
1092- gtk_widget_get_window(GTK_WIDGET (reg->window)),
1093- (gint)tap->focus_x,
1094- (gint)tap->focus_y))
1095- {
1096- binding->callback (binding->widget,
1097- time_type,
1098- event,
1099- binding->data);
1100- }
1101- }
1102- }
1103-
1104- grip_gesture_event_free (event);
1105- }
1106- }
1107-}
1108-
1109-static void
1110-gesture_start (void *cookie,
1111- GeisGestureType type,
1112- GeisGestureId id,
1113- GeisSize attr_count,
1114- GeisGestureAttr *attrs)
1115-{
1116- process_gesture(cookie, type, id, attr_count, attrs, GRIP_TIME_START);
1117-}
1118-
1119-static void
1120-gesture_update (void *cookie,
1121- GeisGestureType type,
1122- GeisGestureId id,
1123- GeisSize attr_count,
1124- GeisGestureAttr *attrs)
1125-{
1126- process_gesture(cookie, type, id, attr_count, attrs, GRIP_TIME_UPDATE);
1127-}
1128-
1129-static void
1130-gesture_finish (void *cookie,
1131- GeisGestureType type,
1132- GeisGestureId id,
1133- GeisSize attr_count,
1134- GeisGestureAttr *attrs)
1135-{
1136- process_gesture(cookie, type, id, attr_count, attrs, GRIP_TIME_END);
1137-}
1138-
1139-static void
1140-grip_gesture_manager_init (GripGestureManager *item)
1141-{
1142- GripGestureManagerPrivate *priv;
1143-
1144- priv = item->priv = GRIP_GESTURE_MANAGER_GET_PRIVATE (item);
1145-
1146- priv->registered_windows = g_hash_table_new (g_direct_hash, g_direct_equal);
1147-
1148+ for (i = 0; i < geis_groupset_group_count (groupset); ++i)
1149+ {
1150+ GeisGroup group = geis_groupset_group (groupset, i);
1151+ g_return_if_fail (group);
1152+
1153+ GeisSize j;
1154+ for (j = 0; j < geis_group_frame_count (group); ++j)
1155+ {
1156+ GeisFrame frame = geis_group_frame(group, j);
1157+ g_return_if_fail (frame);
1158+
1159+ GeisAttr window_attr = geis_frame_attr_by_name(frame, GEIS_GESTURE_ATTRIBUTE_EVENT_WINDOW_ID);
1160+ guint window_id = geis_attr_value_to_integer(window_attr);
1161+
1162+ GeisAttr device_attr = geis_frame_attr_by_name(frame, GEIS_GESTURE_ATTRIBUTE_DEVICE_ID);
1163+ guint device_id = geis_attr_value_to_integer(device_attr);
1164+ GripInputDevice *input_device = device_id_to_input_device (manager, device_id);
1165+
1166+ GList *l;
1167+ for (l = priv->bindings; l != NULL; l = l->next)
1168+ {
1169+ GripGestureBinding *binding = (GripGestureBinding *)l->data;
1170+ guint widget_window_id = GDK_WINDOW_XID (gtk_widget_get_window (binding->widget));
1171+ if (widget_window_id == window_id)
1172+ {
1173+ GList *class_list;
1174+ for (class_list = priv->classes; class_list != NULL; class_list = class_list->next)
1175+ {
1176+ GripGestureClassMap *p = (GripGestureClassMap *)class_list->data;
1177+ if (p->grip_type == binding->type)
1178+ {
1179+ if (geis_frame_is_class(frame, p->geis_class))
1180+ {
1181+ GripGestureEvent *grip_event = grip_gesture_event_new (p->grip_type);
1182+ if (p->grip_type == GRIP_GESTURE_DRAG)
1183+ {
1184+ GripEventGestureDrag *drag = (GripEventGestureDrag *)grip_event;
1185+ drag->type = p->grip_type;
1186+ drag->id = geis_frame_id(frame);
1187+ drag->input_device = input_device;
1188+ drag->fingers = drag_gesture_handle_properties (drag, frame);
1189+ binding->callback (binding->widget,
1190+ time_type,
1191+ grip_event,
1192+ binding->data);
1193+ }
1194+ else if (p->grip_type == GRIP_GESTURE_PINCH)
1195+ {
1196+ GripEventGesturePinch *pinch = (GripEventGesturePinch *)grip_event;
1197+ pinch->type = p->grip_type;
1198+ pinch->id = geis_frame_id(frame);
1199+ pinch->input_device = input_device;
1200+ pinch->fingers = pinch_gesture_handle_properties (pinch, frame);
1201+ binding->callback (binding->widget,
1202+ time_type,
1203+ grip_event,
1204+ binding->data);
1205+ }
1206+ else if (p->grip_type == GRIP_GESTURE_ROTATE)
1207+ {
1208+ GripEventGestureRotate *rotate = (GripEventGestureRotate *)grip_event;
1209+ rotate->type = p->grip_type;
1210+ rotate->id = geis_frame_id(frame);
1211+ rotate->input_device = input_device;
1212+ rotate->fingers = rotate_gesture_handle_properties (rotate, frame);
1213+ binding->callback (binding->widget,
1214+ time_type,
1215+ grip_event,
1216+ binding->data);
1217+ }
1218+ else if (p->grip_type == GRIP_GESTURE_TAP)
1219+ {
1220+ GripEventGestureTap *tap = (GripEventGestureTap *)grip_event;
1221+ tap->type = p->grip_type;
1222+ tap->id = geis_frame_id(frame);
1223+ tap->input_device = input_device;
1224+ tap->fingers = tap_gesture_handle_properties (tap, frame);
1225+ binding->callback (binding->widget,
1226+ time_type,
1227+ grip_event,
1228+ binding->data);
1229+ }
1230+ grip_gesture_event_free (grip_event);
1231+ }
1232+ }
1233+ }
1234+ }
1235+ }
1236+ }
1237+ }
1238+}
1239+
1240+
1241+static gboolean
1242+grip_geis_event_ready (GIOChannel *source G_GNUC_UNUSED,
1243+ GIOCondition condition G_GNUC_UNUSED,
1244+ gpointer context)
1245+{
1246+ Geis geis = (Geis)context;
1247+ GeisStatus status G_GNUC_UNUSED = geis_dispatch_events(geis);
1248+ return TRUE;
1249+}
1250+
1251+
1252+static void
1253+grip_gesture_manager_init (GripGestureManager *self)
1254+{
1255+ GripGestureManagerPrivate *priv = self->priv = GRIP_GESTURE_MANAGER_GET_PRIVATE (self);
1256 priv->devices = g_ptr_array_new ();
1257-}
1258-
1259-static gboolean
1260-io_callback (GIOChannel *source G_GNUC_UNUSED,
1261- GIOCondition condition G_GNUC_UNUSED,
1262- gpointer data)
1263-{
1264- GripGestureRegistration *reg = (GripGestureRegistration *)data;
1265-
1266- geis_event_dispatch (reg->instance);
1267-
1268- return TRUE;
1269-}
1270-
1271-static void
1272-destroy_registration(GripGestureRegistration *reg)
1273-{
1274- GList *list;
1275-
1276- for (list = reg->bindings; list != NULL; list = list->next)
1277- {
1278- GripGestureBinding *binding = (GripGestureBinding *)list->data;
1279-
1280- if (binding->destroy)
1281- {
1282- GDestroyNotify d = binding->destroy;
1283-
1284- d (binding->data);
1285- }
1286-
1287- g_free (binding);
1288- }
1289-
1290- g_list_free (reg->bindings);
1291-
1292- g_io_channel_shutdown (reg->iochannel, FALSE, NULL);
1293- g_source_remove (reg->iochannel_id);
1294- g_io_channel_unref (reg->iochannel);
1295-
1296- geis_finish (reg->instance);
1297-
1298- reg->instance = NULL;
1299- reg->iochannel = NULL;
1300-}
1301+
1302+ priv->geis = geis_new (GEIS_INIT_TRACK_DEVICES, GEIS_INIT_TRACK_GESTURE_CLASSES, NULL);
1303+ g_return_if_fail (priv->geis);
1304+
1305+ int fd;
1306+ geis_get_configuration(priv->geis, GEIS_CONFIGURATION_FD, &fd);
1307+ priv->iochannel = g_io_channel_unix_new (fd);
1308+ priv->iochannel_id = g_io_add_watch (priv->iochannel, G_IO_IN, grip_geis_event_ready, priv->geis);
1309+ geis_register_device_callback (priv->geis, grip_geis_event_callback, self);
1310+ geis_register_class_callback (priv->geis, grip_geis_event_callback, self);
1311+ geis_register_event_callback (priv->geis, grip_geis_event_callback, self);
1312+}
1313+
1314
1315 static void
1316 window_destroyed_cb (GtkWidget *object,
1317 gpointer user_data)
1318 {
1319 GripGestureManager *manager = (GripGestureManager *)user_data;
1320- GripGestureManagerPrivate *priv = manager->priv;
1321- struct Registrations *reg = g_hash_table_lookup (priv->registered_windows, object);
1322-
1323- if (!reg)
1324- return;
1325-
1326- destroy_registration(reg->touchpad);
1327- destroy_registration(reg->touchscreen);
1328- destroy_registration(reg->independent);
1329-
1330- g_hash_table_remove (priv->registered_windows, object);
1331- g_free (reg);
1332-}
1333-
1334-static const gchar *
1335-grip_type_to_geis_type (GripGestureType gesture_type,
1336- gint touch_points)
1337-{
1338- /* grail taps begin at 15, so let's convert that into something we
1339- * can index in geis_gesture_types. */
1340- int t = gesture_type == 15 ? 3 : gesture_type;
1341-
1342- return geis_gesture_types[(t * 5 + touch_points) - 1];
1343+ GList *l = manager->priv->bindings;
1344+ while (l != NULL)
1345+ {
1346+ GList *next = l->next;
1347+ GripGestureBinding *binding = l->data;
1348+ if (gtk_widget_get_toplevel (binding->widget) == object)
1349+ {
1350+ geis_subscription_delete (binding->subscription);
1351+
1352+ if (binding->destroy)
1353+ binding->destroy (binding->data);
1354+ g_free (binding);
1355+ manager->priv->bindings = g_list_delete_link (manager->priv->bindings, l);
1356+ }
1357+ l = next;
1358+ }
1359 }
1360
1361
1362@@ -1017,232 +705,207 @@
1363 }
1364
1365
1366+/*
1367+ * processed_mapped_window_request:
1368+ * @reg: a #GripRegistrationRequest (removed from the GripGestureManager
1369+ * requests listand freed).
1370+ *
1371+ * Creates a subscription for a widget mapped to a window.
1372+ */
1373 static void
1374-grip_devices_for_type (GripDeviceType type, GArray *selection,
1375- GripDevices *devices)
1376+processed_mapped_window_request (GripRegistrationRequest *req)
1377 {
1378- guint i;
1379-
1380- for (i = 0; i < devices->len; ++i)
1381+ g_return_if_fail (GRIP_IS_GESTURE_MANAGER (req->manager));
1382+ g_return_if_fail (GTK_IS_WIDGET (req->widget));
1383+
1384+ GtkWidget *toplevel = gtk_widget_get_toplevel (req->widget);
1385+ g_return_if_fail (GTK_IS_WINDOW (toplevel));
1386+
1387+ GripGestureManagerPrivate *priv = req->manager->priv;
1388+
1389+ guint window_id = GDK_WINDOW_XID (gtk_widget_get_window(req->widget));
1390+
1391+ /* XXX - check for duplicates in reg->bindings first */
1392+ GripGestureBinding *binding = g_new0 (GripGestureBinding, 1);
1393+ binding->type = req->gesture_type;
1394+ binding->widget = req->widget;
1395+ binding->touches = req->touch_points;
1396+ binding->callback = req->callback;
1397+ binding->data = req->user_data;
1398+ binding->destroy = req->destroy;
1399+
1400+ char sub_name[48];
1401+ snprintf(sub_name, 48, "sub-%x-%x-%x", window_id, req->gesture_type, req->touch_points);
1402+ binding->subscription = geis_subscription_new (priv->geis, sub_name, GEIS_SUBSCRIPTION_CONT);
1403+ g_return_if_fail (binding->subscription);
1404+
1405+ char filter_id[20];
1406+ snprintf(filter_id, 20, "grip-%x", window_id);
1407+ GeisFilter window_filter = geis_filter_new(priv->geis, filter_id);
1408+ geis_filter_add_term(window_filter, GEIS_FILTER_REGION,
1409+ GEIS_REGION_ATTRIBUTE_WINDOWID, GEIS_FILTER_OP_EQ, window_id,
1410+ NULL);
1411+
1412+ switch (req->gesture_type)
1413 {
1414- GripInputDevice *input_device = g_ptr_array_index (devices, i);
1415- GeisInputDeviceId id = grip_input_device_get_id (input_device);
1416- GripDeviceType device_type= grip_get_device_type(input_device);
1417-
1418- if ((type & GRIP_DEVICE_TOUCHSCREEN) && device_type == GRIP_DEVICE_TOUCHSCREEN)
1419- {
1420- g_array_append_val (selection, id);
1421- }
1422- if ((type & GRIP_DEVICE_TOUCHPAD) && device_type == GRIP_DEVICE_TOUCHPAD)
1423- {
1424- g_array_append_val (selection, id);
1425- }
1426- if ((type & GRIP_DEVICE_INDEPENDENT) && device_type == GRIP_DEVICE_INDEPENDENT)
1427- {
1428- g_array_append_val (selection, id);
1429- }
1430+ case GRIP_GESTURE_DRAG:
1431+ geis_filter_add_term(window_filter, GEIS_FILTER_CLASS,
1432+ GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_DRAG,
1433+ GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, req->touch_points,
1434+ NULL);
1435+ break;
1436+ case GRIP_GESTURE_PINCH:
1437+ geis_filter_add_term(window_filter, GEIS_FILTER_CLASS,
1438+ GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_PINCH,
1439+ GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, req->touch_points,
1440+ NULL);
1441+ break;
1442+ case GRIP_GESTURE_ROTATE:
1443+ geis_filter_add_term(window_filter, GEIS_FILTER_CLASS,
1444+ GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_ROTATE,
1445+ GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, req->touch_points,
1446+ NULL);
1447+ break;
1448+ case GRIP_GESTURE_TAP:
1449+ geis_filter_add_term(window_filter, GEIS_FILTER_CLASS,
1450+ GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_TAP,
1451+ GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, req->touch_points,
1452+ NULL);
1453+ break;
1454 }
1455-}
1456-
1457-/*
1458- * new_window_registration:
1459- * @manager: a GripGestureManager
1460- * @toplevel: a toplevel #GtkWindow
1461- *
1462- * Constructs a new #GripGestureRegistration for a #GtkWidget.
1463- */
1464-static GripGestureRegistration *
1465-new_window_registration(GripGestureManager *manager,
1466- GtkWidget *toplevel)
1467-{
1468- GripGestureRegistration *reg;
1469- GeisInstance instance;
1470- gint fd = -1;
1471- GeisXcbWinInfo xcb_win_info = {
1472- .display_name = NULL,
1473- .screenp = NULL,
1474- .window_id = GDK_WINDOW_XID (gtk_widget_get_window(toplevel))
1475- };
1476- GeisWinInfo win_info = {
1477- GEIS_XCB_FULL_WINDOW,
1478- &xcb_win_info
1479- };
1480-
1481- if (geis_init (&win_info, &instance) != GEIS_STATUS_SUCCESS)
1482- {
1483- g_warning ("Failed to initialize gesture manager.");
1484- return NULL;
1485- }
1486-
1487- if (geis_configuration_supported (instance,
1488- GEIS_CONFIG_UNIX_FD) != GEIS_STATUS_SUCCESS)
1489- {
1490- g_warning ("Gesture manager does not support UNIX fd.");
1491- return NULL;
1492- }
1493-
1494- if (geis_configuration_get_value (instance,
1495- GEIS_CONFIG_UNIX_FD,
1496- &fd) != GEIS_STATUS_SUCCESS)
1497- {
1498- g_error ("Gesture manager failed to obtain UNIX fd.");
1499- return NULL;
1500- }
1501-
1502- reg = g_new0 (GripGestureRegistration, 1);
1503-
1504- reg->window = GTK_WINDOW (toplevel);
1505- reg->instance = instance;
1506+
1507+ if (req->device_type & GRIP_DEVICE_TOUCHSCREEN)
1508+ {
1509+ char filter_name[32];
1510+ snprintf(filter_name, 32, "%s/touchscreen", filter_id);
1511+ GeisFilter touchscreen_filter = geis_filter_clone (window_filter, filter_name);
1512+ geis_filter_add_term(touchscreen_filter, GEIS_FILTER_DEVICE,
1513+ GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_FILTER_OP_EQ, GEIS_TRUE,
1514+ NULL);
1515+ GeisStatus status = geis_subscription_add_filter(binding->subscription, touchscreen_filter);
1516+ g_return_if_fail (status == GEIS_STATUS_SUCCESS);
1517+ }
1518+ if (req->device_type & GRIP_DEVICE_TOUCHPAD)
1519+ {
1520+ char filter_name[32];
1521+ snprintf(filter_name, 32, "%s/touchpad", filter_id);
1522+ GeisFilter touchpad_filter = geis_filter_clone (window_filter, filter_name);
1523+ geis_filter_add_term(touchpad_filter, GEIS_FILTER_DEVICE,
1524+ GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_FILTER_OP_EQ, GEIS_FALSE,
1525+ NULL);
1526+ GeisStatus status = geis_subscription_add_filter(binding->subscription, touchpad_filter);
1527+ g_return_if_fail (status == GEIS_STATUS_SUCCESS);
1528+ }
1529+ if (req->device_type & GRIP_DEVICE_INDEPENDENT)
1530+ {
1531+ char filter_name[32];
1532+ snprintf(filter_name, 32, "%s/indep", filter_id);
1533+ GeisFilter indep_filter = geis_filter_clone (window_filter, filter_name);
1534+ geis_filter_add_term(indep_filter, GEIS_FILTER_DEVICE,
1535+ GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH, GEIS_FILTER_OP_EQ, GEIS_TRUE,
1536+ NULL);
1537+ GeisStatus status = geis_subscription_add_filter(binding->subscription, indep_filter);
1538+ g_return_if_fail (status == GEIS_STATUS_SUCCESS);
1539+ }
1540+
1541+ /*
1542+ * If any device types were specified, the window_filter was cloned and needs
1543+ * to be disposed of, otehrwise it's _the_ filter.
1544+ */
1545+ if (req->device_type)
1546+ {
1547+ geis_filter_delete(window_filter);
1548+ }
1549+ else
1550+ {
1551+ GeisStatus status = geis_subscription_add_filter(binding->subscription, window_filter);
1552+ g_return_if_fail (status == GEIS_STATUS_SUCCESS);
1553+ }
1554+
1555+
1556+ GeisStatus status = geis_subscription_activate (binding->subscription);
1557+ g_return_if_fail (status == GEIS_STATUS_SUCCESS);
1558+
1559+ priv->bindings = g_list_append (priv->bindings, binding);
1560
1561 g_signal_connect (toplevel,
1562 "destroy",
1563 G_CALLBACK (window_destroyed_cb),
1564- manager);
1565-
1566- reg->iochannel = g_io_channel_unix_new (fd);
1567- reg->iochannel_id = g_io_add_watch (reg->iochannel,
1568- G_IO_IN,
1569- io_callback,
1570- reg);
1571- reg->gesture_list = g_ptr_array_new ();
1572-
1573- return reg;
1574-}
1575-
1576-static void
1577-bind_registration(GripGestureManager *manager,
1578- GripGestureRegistration *reg,
1579- GtkWidget *widget,
1580- GripGestureType gesture_type,
1581- GripDeviceType device_type,
1582- gint touch_points,
1583- GripGestureCallback callback,
1584- gpointer user_data,
1585- GDestroyNotify destroy)
1586-{
1587- GripGestureManagerPrivate *priv;
1588- GripGestureBinding *binding;
1589- GArray *devices;
1590-
1591- priv = manager->priv;
1592-
1593- if (reg->gesture_list->len)
1594- g_ptr_array_remove_index (reg->gesture_list,
1595- reg->gesture_list->len - 1);
1596-
1597- devices = g_array_new (TRUE, FALSE, sizeof(GeisInputDeviceId));
1598- grip_devices_for_type(device_type, devices, priv->devices);
1599- if (devices->len == 0) {
1600- g_array_free(devices, TRUE);
1601- return;
1602- }
1603-
1604- g_ptr_array_add (reg->gesture_list,
1605- (gchar *)grip_type_to_geis_type (gesture_type, touch_points));
1606- g_ptr_array_add (reg->gesture_list,
1607- NULL);
1608-
1609- geis_subscribe (reg->instance,
1610- (GeisInputDeviceId *)(void *)devices->data,
1611- (const char**)reg->gesture_list->pdata,
1612- &gesture_funcs,
1613- manager);
1614-
1615- g_array_unref (devices);
1616-
1617- /* XXX - check for duplicates in reg->bindings first */
1618- binding = g_new0 (GripGestureBinding, 1);
1619-
1620- binding->type = gesture_type;
1621- binding->widget = widget;
1622- binding->touches = touch_points;
1623- binding->callback = callback;
1624- binding->data = user_data;
1625- binding->destroy = destroy;
1626-
1627- reg->bindings = g_list_append (reg->bindings, binding);
1628-}
1629-
1630-/*
1631- * register_internal:
1632- * @manager: the @GripGestureManager
1633- * @widget: the GtkWidget to be bound
1634- * @gesture_type: the type of gesture to subscribe for
1635- * @device_type: the type of input device to subscribe for
1636- * @touch_points:
1637- * @callback: the callback to be invoked on gesture events
1638- * @user_data: the callbackl context to be passed back on gesture events
1639- * @destroy:
1640- *
1641- * Binds or rebinds a gesture subscription for a widget.
1642- */
1643-static void
1644-register_internal (GripGestureManager *manager,
1645- GtkWidget *widget,
1646- GripGestureType gesture_type,
1647- GripDeviceType device_type,
1648- gint touch_points,
1649- GripGestureCallback callback,
1650- gpointer user_data,
1651- GDestroyNotify destroy)
1652-{
1653- GripGestureManagerPrivate *priv;
1654- GtkWidget *toplevel;
1655- struct Registrations *registrations;
1656-
1657- g_return_if_fail (GRIP_IS_GESTURE_MANAGER (manager));
1658- g_return_if_fail (GTK_IS_WIDGET (widget));
1659-
1660- toplevel = gtk_widget_get_toplevel (widget);
1661-
1662- g_return_if_fail (GTK_IS_WINDOW (toplevel));
1663-
1664- priv = manager->priv;
1665-
1666- if (!(registrations = g_hash_table_lookup (priv->registered_windows, toplevel)))
1667- {
1668- registrations = g_new(struct Registrations, 1);
1669- registrations->touchscreen = new_window_registration(manager, toplevel);
1670- registrations->touchpad = new_window_registration(manager, toplevel);
1671- registrations->independent = new_window_registration(manager, toplevel);
1672-
1673- if (registrations->touchscreen == NULL ||
1674- registrations->touchpad == NULL ||
1675- registrations->independent == NULL)
1676- return;
1677+ req->manager);
1678+
1679+ /* remove the request from the watch list */
1680+ g_free (req);
1681+ priv->requests = g_list_remove (priv->requests, req);
1682+}
1683+
1684+
1685+/*
1686+ * register_mapped_window:
1687+ * @manager: a Grip gesture manager object
1688+ * @toplevel: a top-level widget
1689+ *
1690+ * Processes all subscriptions requests for a newly-mapped window.
1691+ */
1692+static void
1693+register_mapped_window (GripGestureManager *manager, GtkWidget *toplevel)
1694+{
1695+ g_return_if_fail (gtk_widget_is_toplevel (toplevel));
1696+
1697+ GList *pending_request = manager->priv->requests;
1698+ while (pending_request)
1699+ {
1700+ GList *next = pending_request->next;
1701+ GripRegistrationRequest *req = pending_request->data;
1702+
1703+ if (gtk_widget_get_toplevel (req->widget) == toplevel)
1704+ {
1705+ processed_mapped_window_request (req);
1706+ }
1707+ pending_request = next;
1708+ }
1709+}
1710+
1711+
1712+/*
1713+ * register_toplevel_widget:
1714+ * @manager: a Grip gesture manager object
1715+ * @toplevel: a top-level widget
1716+ *
1717+ * Handles the registration of a widget that has just become a top-level widget.
1718+ *
1719+ * If the top-level widget is mapped to a window, it;s handled right away.
1720+ * Otherwise, a callback is queued for when it does become mapped to a window.
1721+ */
1722+static void
1723+register_toplevel_widget (GripGestureManager *manager, GtkWidget *toplevel)
1724+{
1725+ g_return_if_fail (gtk_widget_is_toplevel (toplevel));
1726+
1727+ if (gtk_widget_get_mapped (GTK_WIDGET (toplevel)))
1728+ {
1729+ register_mapped_window (manager, toplevel);
1730 }
1731 else
1732 {
1733- if (device_type & GRIP_DEVICE_TOUCHSCREEN)
1734- geis_unsubscribe (registrations->touchscreen->instance,
1735- (GeisGestureType*)registrations->touchscreen->gesture_list->pdata);
1736- if (device_type & GRIP_DEVICE_TOUCHPAD)
1737- geis_unsubscribe (registrations->touchpad->instance,
1738- (GeisGestureType*)registrations->touchpad->gesture_list->pdata);
1739- if (device_type & GRIP_DEVICE_INDEPENDENT)
1740- geis_unsubscribe (registrations->independent->instance,
1741- (GeisGestureType*)registrations->independent->gesture_list->pdata);
1742+ g_signal_connect (toplevel,
1743+ "map-event",
1744+ G_CALLBACK (toplevel_mapped_cb),
1745+ manager);
1746 }
1747-
1748- if (device_type & GRIP_DEVICE_TOUCHSCREEN)
1749- bind_registration(manager,
1750- registrations->touchscreen, widget, gesture_type, GRIP_DEVICE_TOUCHSCREEN, touch_points,
1751- callback, user_data, destroy);
1752-
1753- if (device_type & GRIP_DEVICE_TOUCHPAD)
1754- bind_registration(manager,
1755- registrations->touchpad, widget, gesture_type, GRIP_DEVICE_TOUCHPAD, touch_points,
1756- callback, user_data, destroy);
1757-
1758- if (device_type & GRIP_DEVICE_INDEPENDENT)
1759- bind_registration(manager,
1760- registrations->independent, widget, gesture_type, GRIP_DEVICE_INDEPENDENT, touch_points,
1761- callback, user_data, destroy);
1762- g_hash_table_insert (priv->registered_windows,
1763- toplevel,
1764- registrations);
1765 }
1766
1767+
1768+/*
1769+ * toplevel_notify_cb:
1770+ *
1771+ * Called when a widget property has changed.
1772+ *
1773+ * The only widget property we're interested in here is the "parent" property.
1774+ * We can't subscribe to gestures on a window until the widget is mapped to a
1775+ * window. Only top-level widgets can be mapped to a window: we just keep
1776+ * queueing this callback on successive parent widgets until one is a top-level
1777+ * widget, then process that one.
1778+ */
1779 static void
1780 toplevel_notify_cb (GtkWidget *widget,
1781 GParamSpec *pspec,
1782@@ -1251,7 +914,7 @@
1783 if (pspec->name == g_intern_static_string ("parent"))
1784 {
1785 GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
1786- GripRegistrationRequest *req = (GripRegistrationRequest *)user_data;
1787+ GripGestureManager *manager = (GripGestureManager *)user_data;
1788
1789 g_signal_handlers_disconnect_by_func (widget,
1790 G_CALLBACK (toplevel_notify_cb),
1791@@ -1259,30 +922,7 @@
1792
1793 if (gtk_widget_is_toplevel (toplevel))
1794 {
1795- if (gtk_widget_get_mapped (GTK_WIDGET (toplevel)))
1796- {
1797- register_internal (req->manager,
1798- req->widget,
1799- req->gesture_type,
1800- req->device_type,
1801- req->touch_points,
1802- req->callback,
1803- req->user_data,
1804- req->destroy);
1805-
1806- g_free (req);
1807- }
1808- else
1809- {
1810- GripGestureManagerPrivate *priv = req->manager->priv;
1811-
1812- priv->requests = g_list_append (priv->requests, req);
1813-
1814- g_signal_connect (toplevel,
1815- "map-event",
1816- G_CALLBACK (toplevel_mapped_cb),
1817- req->manager);
1818- }
1819+ register_toplevel_widget (manager, toplevel);
1820 }
1821 else
1822 {
1823@@ -1294,96 +934,29 @@
1824 }
1825 }
1826
1827+
1828 /*
1829- * register_widget:
1830- *
1831- * Registers a specific widget for a specific gesture made by a specific input
1832- * device type.
1833- *
1834- * If the widget's containing window is a valid window, the widget is registered
1835- * right away, otherwise the registration is deferred until the widget actually
1836- * has a top-level window.
1837+ * toplevel_mapped_cb:
1838+ *
1839+ * A callback invoked when a toplevel widget with one or more pending gesture
1840+ * registration requests has been mapped to a window.
1841+ *
1842+ * This callback will in fact process all pending registration requests for the
1843+ * newly-mapped window.
1844 */
1845 static void
1846-register_widget (GripGestureManager *manager,
1847- GtkWidget *widget,
1848- GripGestureType gesture_type,
1849- GripDeviceType device_type,
1850- gint touch_points,
1851- GripGestureCallback callback,
1852- gpointer user_data,
1853- GDestroyNotify destroy)
1854-{
1855- GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
1856-
1857- if (gtk_widget_is_toplevel (toplevel))
1858- {
1859- register_internal (manager,
1860- widget,
1861- gesture_type,
1862- device_type,
1863- touch_points,
1864- callback,
1865- user_data,
1866- destroy);
1867- }
1868- else
1869- {
1870- GripRegistrationRequest *req = g_new0 (GripRegistrationRequest, 1);
1871-
1872- req->manager = manager;
1873- req->widget = widget;
1874- req->gesture_type = gesture_type;
1875- req->device_type = device_type;
1876- req->touch_points = touch_points;
1877- req->callback = callback;
1878- req->user_data = user_data;
1879- req->destroy = destroy;
1880-
1881- g_signal_connect (toplevel,
1882- "notify",
1883- G_CALLBACK (toplevel_notify_cb),
1884- req);
1885- }
1886-}
1887-
1888-static void
1889 toplevel_mapped_cb (GtkWidget *toplevel,
1890 GdkEvent *event G_GNUC_UNUSED,
1891 gpointer user_data)
1892 {
1893 GripGestureManager *manager = (GripGestureManager *)user_data;
1894- GripGestureManagerPrivate *priv = manager->priv;
1895- GList *request = priv->requests;
1896-
1897- while (request)
1898- {
1899- GList *next = request->next;
1900- GripRegistrationRequest *req = request->data;
1901-
1902- if (gtk_widget_get_toplevel (req->widget) == toplevel)
1903- {
1904- register_widget (req->manager,
1905- req->widget,
1906- req->gesture_type,
1907- req->device_type,
1908- req->touch_points,
1909- req->callback,
1910- req->user_data,
1911- req->destroy);
1912-
1913- priv->requests = g_list_remove_link (priv->requests, request);
1914- g_free (req);
1915- g_list_free_1 (request);
1916- }
1917- request = next;
1918- }
1919-
1920+ register_mapped_window (manager, toplevel);
1921 g_signal_handlers_disconnect_by_func (toplevel,
1922 toplevel_mapped_cb,
1923 user_data);
1924 }
1925
1926+
1927 /**
1928 * grip_gesture_manager_register_window:
1929 * @manager: A #GripGestureManager instance.
1930@@ -1411,102 +984,47 @@
1931 gpointer user_data,
1932 GDestroyNotify destroy)
1933 {
1934- GtkWidget *toplevel;
1935-
1936 g_return_if_fail (GRIP_IS_GESTURE_MANAGER (manager));
1937 g_return_if_fail (GTK_IS_WIDGET (widget));
1938
1939- toplevel = gtk_widget_get_toplevel (widget);
1940+ GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
1941+
1942+ GripRegistrationRequest *req = g_new0 (GripRegistrationRequest, 1);
1943+ req->manager = manager;
1944+ req->widget = widget;
1945+ req->gesture_type = gesture_type;
1946+ req->device_type = device_type;
1947+ req->touch_points = touch_points;
1948+ req->callback = callback;
1949+ req->user_data = user_data;
1950+ req->destroy = destroy;
1951+ manager->priv->requests = g_list_append (manager->priv->requests, req);
1952
1953 if (GTK_IS_WINDOW (toplevel))
1954 {
1955- if (gtk_widget_get_mapped (GTK_WIDGET (toplevel)))
1956- {
1957- register_internal (manager,
1958- widget,
1959- gesture_type,
1960- device_type,
1961- touch_points,
1962- callback,
1963- user_data,
1964- destroy);
1965- }
1966- else
1967- {
1968- GripRegistrationRequest *req = g_new0 (GripRegistrationRequest, 1);
1969- GripGestureManagerPrivate *priv = manager->priv;
1970-
1971- req->manager = manager;
1972- req->widget = widget;
1973- req->gesture_type = gesture_type;
1974- req->device_type = device_type;
1975- req->touch_points = touch_points;
1976- req->callback = callback;
1977- req->user_data = user_data;
1978- req->destroy = destroy;
1979-
1980- priv->requests = g_list_append (priv->requests, req);
1981-
1982- g_signal_connect (toplevel,
1983- "map-event",
1984- G_CALLBACK (toplevel_mapped_cb),
1985- manager);
1986- }
1987+ register_toplevel_widget (manager, toplevel);
1988 }
1989 else
1990 {
1991- GripRegistrationRequest *req = g_new0 (GripRegistrationRequest, 1);
1992-
1993- req->manager = manager;
1994- req->widget = widget;
1995- req->gesture_type = gesture_type;
1996- req->device_type = device_type;
1997- req->touch_points = touch_points;
1998- req->callback = callback;
1999- req->user_data = user_data;
2000- req->destroy = destroy;
2001-
2002 g_signal_connect (toplevel,
2003 "notify",
2004 G_CALLBACK (toplevel_notify_cb),
2005- req);
2006+ manager);
2007 }
2008 }
2009
2010-static void
2011-shutdown_registration(GripGestureRegistration *reg)
2012-{
2013- free_registration(reg);
2014- geis_finish(reg->instance);
2015- reg->instance = NULL;
2016- g_free(reg);
2017-}
2018
2019 void
2020-grip_gesture_manager_unregister_window (GripGestureManager *manager,
2021- GtkWidget *toplevel)
2022+grip_gesture_manager_unregister_window (GripGestureManager *manager G_GNUC_UNUSED,
2023+ GtkWidget *toplevel G_GNUC_UNUSED)
2024 {
2025- GripGestureManagerPrivate *priv = manager->priv;
2026- struct Registrations *registrations;
2027-
2028 g_return_if_fail (GRIP_IS_GESTURE_MANAGER (manager));
2029 g_return_if_fail (GTK_IS_WINDOW (toplevel));
2030
2031- /* Currently only allow unsubscribing after the window has been shown. */
2032- g_return_if_fail (gtk_widget_get_mapped (GTK_WIDGET (toplevel)));
2033- registrations = g_hash_table_lookup (priv->registered_windows, toplevel);
2034- if (!registrations) {
2035- return;
2036- }
2037-
2038- shutdown_registration(registrations->touchscreen);
2039- shutdown_registration(registrations->touchpad);
2040- shutdown_registration(registrations->independent);
2041- g_free(registrations);
2042- g_hash_table_remove(priv->registered_windows, toplevel);
2043-
2044+ window_destroyed_cb (toplevel, manager);
2045 }
2046
2047+
2048 GType
2049 grip_gesture_event_get_type (void)
2050 {
2051
2052=== modified file 'src/gripinputdevice.c'
2053--- src/gripinputdevice.c 2011-10-19 14:05:35 +0000
2054+++ src/gripinputdevice.c 2013-04-17 15:02:24 +0000
2055@@ -1,5 +1,5 @@
2056 /*
2057- * Copyright 2011 Canonical, Ltd.
2058+ * Copyright 2011, 2013 Canonical Ltd.
2059 *
2060 * This program is free software: you can redistribute it and/or modify it
2061 * under the terms of either or both of the following licenses:
2062@@ -79,53 +79,61 @@
2063 for (a = attrs; a->name; a++)
2064 {
2065 if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_NAME))
2066- {
2067 input_device->priv->name = g_strdup (a->string_val);
2068- }
2069 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_ID))
2070- {
2071 input_device->priv->device_id = a->integer_val;
2072- }
2073 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_TOUCHES))
2074- {
2075 input_device->priv->touches = a->integer_val;
2076- }
2077 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH))
2078- {
2079 input_device->priv->is_direct = a->boolean_val;
2080- }
2081 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH))
2082- {
2083 input_device->priv->is_independent = a->boolean_val;
2084- }
2085 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_MIN_X))
2086- {
2087 input_device->priv->x_extents.minimum = a->float_val;
2088- }
2089 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_MAX_X))
2090- {
2091 input_device->priv->x_extents.maximum = a->float_val;
2092- }
2093 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_RES_X))
2094- {
2095 input_device->priv->x_extents.resolution = a->float_val;
2096- }
2097 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_MIN_Y))
2098- {
2099 input_device->priv->y_extents.minimum = a->float_val;
2100- }
2101 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_MAX_Y))
2102- {
2103 input_device->priv->y_extents.maximum = a->float_val;
2104- }
2105 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_RES_Y))
2106- {
2107 input_device->priv->y_extents.resolution = a->float_val;
2108- }
2109 }
2110 }
2111 }
2112 }
2113+ else
2114+ {
2115+ guint num_attrs = geis_device_attr_count(input_device->priv->geis_device);
2116+ for (i = 0; i < num_attrs; ++i)
2117+ {
2118+ GeisAttr attr = geis_device_attr(input_device->priv->geis_device, i);
2119+ if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_NAME))
2120+ input_device->priv->name = g_strdup (geis_attr_value_to_string(attr));
2121+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_ID))
2122+ input_device->priv->device_id = geis_attr_value_to_integer(attr);
2123+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_TOUCHES))
2124+ input_device->priv->touches = geis_attr_value_to_integer(attr);
2125+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH))
2126+ input_device->priv->is_direct = geis_attr_value_to_boolean(attr);
2127+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH))
2128+ input_device->priv->is_independent = geis_attr_value_to_boolean(attr);
2129+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_MIN_X))
2130+ input_device->priv->x_extents.minimum = geis_attr_value_to_float(attr);
2131+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_MAX_X))
2132+ input_device->priv->x_extents.maximum = geis_attr_value_to_float(attr);
2133+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_RES_X))
2134+ input_device->priv->x_extents.resolution = geis_attr_value_to_float(attr);
2135+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_MIN_Y))
2136+ input_device->priv->y_extents.minimum = geis_attr_value_to_float(attr);
2137+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_MAX_Y))
2138+ input_device->priv->y_extents.maximum = geis_attr_value_to_float(attr);
2139+ else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_RES_Y))
2140+ input_device->priv->y_extents.resolution = geis_attr_value_to_float(attr);
2141+ }
2142+ }
2143
2144 return object;
2145 }

Subscribers

People subscribed via source and target branches