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
=== modified file 'src/gripgesturemanager.c'
--- src/gripgesturemanager.c 2012-05-29 20:47:37 +0000
+++ src/gripgesturemanager.c 2013-04-17 15:02:24 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright 2010, 2011 Canonical, Ltd.2 * Copyright 2010, 2011, 2013 Canonical, Ltd.
3 *3 *
4 * This program is free software: you can redistribute it and/or modify it4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of either or both of the following licenses:5 * under the terms of either or both of the following licenses:
@@ -29,25 +29,49 @@
29#include <geis/geis.h>29#include <geis/geis.h>
30#include "gripinputdevice.h"30#include "gripinputdevice.h"
3131
32typedef struct _GripGestureRegistration GripGestureRegistration;
33typedef struct _GripGestureBinding GripGestureBinding;32typedef struct _GripGestureBinding GripGestureBinding;
34typedef struct _GripRegistrationRequest GripRegistrationRequest;33typedef struct _GripRegistrationRequest GripRegistrationRequest;
3534
36typedef GPtrArray GripDevices;35typedef GPtrArray GripDevices;
3736
38struct Registrations {37/*
39 GripGestureRegistration *touchscreen;38 * GripGestureClassMap:
40 GripGestureRegistration *touchpad;39 * @grip_type: the libgrip gesture type
41 GripGestureRegistration *independent;40 * @geis_class: the geis gesture class
42};41 *
42 * Provides a mapping between a grip gesture type and a geis gesture class.
43 */
44typedef struct _GripGestureClassMap
45{
46 GripGestureType grip_type;
47 GeisGestureClass geis_class;
48} GripGestureClassMap;
4349
50/*
51 * GripGestureManagerPrivate:
52 * @geis: the GEIS instance
53 * @iochannel: connects the geis object with the main loop
54 * @iochannel_id: the identifier for the iochannel
55 * @devices: a collection of recognized input devices
56 * @classes: a list of grip type to geis class mappings
57 * @requests: a list of pending binding requests
58 * @bindings: a list of current gesture bindings
59 */
44struct _GripGestureManagerPrivate60struct _GripGestureManagerPrivate
45{61{
46 GHashTable *registered_windows;62 Geis geis;
47 GList *requests;63 GIOChannel *iochannel;
48 GripDevices *devices;64 int iochannel_id;
65 GripDevices *devices;
66 GList *classes;
67 GList *requests;
68 GList *bindings;
49};69};
5070
71G_DEFINE_TYPE (GripGestureManager, grip_gesture_manager, G_TYPE_OBJECT)
72
73#define GRIP_GESTURE_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GRIP_TYPE_GESTURE_MANAGER, GripGestureManagerPrivate))
74
51/*75/*
52 * GripGestureBinding:76 * GripGestureBinding:
53 * @type:77 * @type:
@@ -64,32 +88,27 @@
64 GripGestureType type;88 GripGestureType type;
65 GtkWidget *widget;89 GtkWidget *widget;
66 guint touches;90 guint touches;
91 GeisSubscription subscription;
67 GripGestureCallback callback;92 GripGestureCallback callback;
68 gpointer data;93 gpointer data;
69 GDestroyNotify destroy;94 GDestroyNotify destroy;
70};95};
7196
97
72/*98/*
73 * GripGestureRegistration:99 * GripRegistrationRequest:
74 * @window: the GTK window100 * @manager: the @GripGestureManager
75 * @bindings: a list of #GripGestureBinding101 * @widget: the GtkWidget to be bound
76 * @gesture_list: a list the names of GEIS gestures beging subscribed to 102 * @gesture_type: the type of gesture to subscribe for
77 * @instance:103 * @device_type: the type of input device to subscribe for
78 * @iochannel:104 * @touch_points: the number of touches making the gesture
105 * @callback: the callback to be invoked on gesture events
106 * @user_data: the callback context to be passed back on gesture events
107 * @destroy: function to destroy the callback context (NULL for no function)
79 *108 *
80 * A collection of all gesture subscriptions for all widgets contained within a109 * A collection of information required to register a callback for a
81 * top-level GTK window.110 * particulatr type of gestures on a window.
82 */111 */
83struct _GripGestureRegistration
84{
85 GtkWindow *window;
86 GList *bindings;
87 GPtrArray *gesture_list;
88 GeisInstance instance;
89 GIOChannel *iochannel;
90 int iochannel_id;
91};
92
93struct _GripRegistrationRequest112struct _GripRegistrationRequest
94{113{
95 GripGestureManager *manager;114 GripGestureManager *manager;
@@ -102,30 +121,8 @@
102 GDestroyNotify destroy;121 GDestroyNotify destroy;
103};122};
104123
105static const gchar *geis_gesture_types[] = {124enum
106 GEIS_GESTURE_TYPE_DRAG1,125{
107 GEIS_GESTURE_TYPE_DRAG2,
108 GEIS_GESTURE_TYPE_DRAG3,
109 GEIS_GESTURE_TYPE_DRAG4,
110 GEIS_GESTURE_TYPE_DRAG5,
111 GEIS_GESTURE_TYPE_PINCH1,
112 GEIS_GESTURE_TYPE_PINCH2,
113 GEIS_GESTURE_TYPE_PINCH3,
114 GEIS_GESTURE_TYPE_PINCH4,
115 GEIS_GESTURE_TYPE_PINCH5,
116 GEIS_GESTURE_TYPE_ROTATE1,
117 GEIS_GESTURE_TYPE_ROTATE2,
118 GEIS_GESTURE_TYPE_ROTATE3,
119 GEIS_GESTURE_TYPE_ROTATE4,
120 GEIS_GESTURE_TYPE_ROTATE5,
121 GEIS_GESTURE_TYPE_TAP1,
122 GEIS_GESTURE_TYPE_TAP2,
123 GEIS_GESTURE_TYPE_TAP3,
124 GEIS_GESTURE_TYPE_TAP4,
125 GEIS_GESTURE_TYPE_TAP5,
126};
127
128enum {
129 DEVICE_AVAILABLE,126 DEVICE_AVAILABLE,
130 DEVICE_UNAVAILABLE,127 DEVICE_UNAVAILABLE,
131 SIGNAL_LAST128 SIGNAL_LAST
@@ -133,132 +130,151 @@
133130
134static guint signals[SIGNAL_LAST];131static guint signals[SIGNAL_LAST];
135132
136static void gesture_added (void *cookie,133static void process_gesture_events (GripGestureManager *manager,
137 GeisGestureType gesture_type,134 GeisEvent geis_event);
138 GeisGestureId gesture_id,
139 GeisSize attr_count,
140 GeisGestureAttr *attrs);
141
142static void gesture_removed (void *cookie,
143 GeisGestureType gesture_type,
144 GeisGestureId gesture_id,
145 GeisSize attr_count,
146 GeisGestureAttr *attrs);
147
148static void gesture_start (void *cookie,
149 GeisGestureType gesture_type,
150 GeisGestureId gesture_id,
151 GeisSize attr_count,
152 GeisGestureAttr *attrs);
153
154static void gesture_update (void *cookie,
155 GeisGestureType gesture_type,
156 GeisGestureId gesture_id,
157 GeisSize attr_count,
158 GeisGestureAttr *attrs);
159
160static void gesture_finish (void *cookie,
161 GeisGestureType gesture_type,
162 GeisGestureId gesture_id,
163 GeisSize attr_count,
164 GeisGestureAttr *attrs);
165135
166static void toplevel_mapped_cb (GtkWidget *toplevel,136static void toplevel_mapped_cb (GtkWidget *toplevel,
167 GdkEvent *event,137 GdkEvent *event,
168 gpointer user_data);138 gpointer user_data);
169139
170static GeisGestureFuncs gesture_funcs = {140
171 gesture_added,141static void
172 gesture_removed,142grip_geis_device_added(GripGestureManager *manager G_GNUC_UNUSED, GeisEvent geis_event)
173 gesture_start,143{
174 gesture_update,144 GeisAttr attr = geis_event_attr_by_name(geis_event, GEIS_EVENT_ATTRIBUTE_DEVICE);
175 gesture_finish145 g_return_if_fail (attr);
176};146
177147 GeisDevice device = geis_attr_value_to_pointer(attr);
178148 g_return_if_fail (device);
179static void149
180device_added (void *cookie, GeisInputDeviceId id G_GNUC_UNUSED, void *attrs)150 switch (geis_event_type(geis_event))
181{151 {
182 GripGestureManager *gesture_manager = (GripGestureManager *) cookie;152 case GEIS_EVENT_DEVICE_AVAILABLE:
183 GripInputDevice *input_device = g_object_new (GRIP_TYPE_INPUT_DEVICE,153 {
184 "device-attrs", attrs,154 GripInputDevice *input_device = g_object_new (GRIP_TYPE_INPUT_DEVICE,
185 NULL);155 "geis-device", device,
186156 NULL);
187 g_ptr_array_add(gesture_manager->priv->devices, input_device);157
188 g_signal_emit (gesture_manager, signals[DEVICE_AVAILABLE], 0, input_device);158 g_ptr_array_add(manager->priv->devices, input_device);
189}159 g_signal_emit (manager, signals[DEVICE_AVAILABLE], 0, input_device);
190160 }
191161 break;
192static void162
193device_removed (void *cookie, GeisInputDeviceId id, void *attrs G_GNUC_UNUSED)163 case GEIS_EVENT_DEVICE_UNAVAILABLE:
194{164 {
195 guint i;165 guint device_id = geis_device_id (device);
196 GripGestureManager *gesture_manager = (GripGestureManager *) cookie;166 GripDevices *devices = manager->priv->devices;
197 GripDevices *devices = gesture_manager->priv->devices;167 guint i;
198168 for (i = 0; i < devices->len; ++i)
199 for (i = 0; i < devices->len; ++i)169 {
200 {170 GripInputDevice *input_device = g_ptr_array_index (devices, i);
201 GripInputDevice *input_device = g_ptr_array_index (devices, i);171 if (device_id == grip_input_device_get_id (input_device))
202 if (id == grip_input_device_get_id (input_device))172 {
203 {173 g_signal_emit (manager, signals[DEVICE_UNAVAILABLE], 0,
204 g_signal_emit (gesture_manager, signals[DEVICE_UNAVAILABLE], 0,174 input_device);
205 input_device);175 g_ptr_array_remove_index (devices, i);
206 g_ptr_array_remove_index (devices, i);176 break;
207 break;177 }
208 }178 }
209 }179 }
210}180 break;
211181
212182 default:
213static GeisInputFuncs input_funcs = {183 break;
214 device_added,184 }
215 NULL,185}
216 device_removed,186
217};187
218188static void
219189process_class_event(GripGestureManagerPrivate *priv G_GNUC_UNUSED, GeisEvent geis_event)
220static void190{
221grip_get_devices (GripGestureManager *gesture_manager)191 GeisAttr attr = geis_event_attr_by_name (geis_event,
222{192 GEIS_EVENT_ATTRIBUTE_CLASS);
223 GeisXcbWinInfo xcb_win_info = {193 g_return_if_fail (attr);
224 .display_name = NULL,194
225 .screenp = NULL,195 GeisGestureClass gesture_class = geis_attr_value_to_pointer (attr);
226 .window_id = 0,196 g_return_if_fail (gesture_class);
227 };197
228 GeisWinInfo win_info = {198 switch (geis_event_type (geis_event))
229 GEIS_XCB_FULL_WINDOW,199 {
230 &xcb_win_info,200 case GEIS_EVENT_CLASS_AVAILABLE:
231 };201 {
232 GeisInstance instance;202 gchar const *class_name = geis_gesture_class_name (gesture_class);
233 GeisStatus status;203 /* check for dups */
234204 GList *l;
235 status = geis_init (&win_info, &instance);205 for (l = priv->classes; l != NULL; l = l->next)
236 if (status != GEIS_STATUS_SUCCESS)206 {
237 {207 GripGestureClassMap *p = (GripGestureClassMap *)l->data;
238 g_warning ("failed to determine device types\n");208 if (0 == g_strcmp0 (geis_gesture_class_name (p->geis_class),
239 return;209 class_name))
240 }210 {
241211 g_warning ("multiple class definitions for '%s' received",
242 status = geis_input_devices (instance, &input_funcs, gesture_manager);212 class_name);
243 if (status != GEIS_STATUS_SUCCESS)213 return;
244 {214 }
245 g_warning ("failed to determine device types\n");215 }
246 return;216
247 }217 GripGestureClassMap *m = g_new0 (GripGestureClassMap, 1);
248218 if (0 == g_strcmp0 (class_name, "Drag"))
249 status = geis_event_dispatch (instance);219 m->grip_type = GRIP_GESTURE_DRAG;
250 if (status != GEIS_STATUS_SUCCESS)220 else if (0 == g_strcmp0 (class_name, "Pinch"))
251 {221 m->grip_type = GRIP_GESTURE_PINCH;
252 g_warning ("failed to determine device types\n");222 else if (0 == g_strcmp0 (class_name, "Rotate"))
253 return;223 m->grip_type = GRIP_GESTURE_ROTATE;
254 }224 else if (0 == g_strcmp0 (class_name, "Tap"))
255225 m->grip_type = GRIP_GESTURE_TAP;
256 geis_finish (instance);226 else
257}227 m->grip_type = (GripGestureType)100;
258228 m->geis_class = gesture_class;
259G_DEFINE_TYPE (GripGestureManager, grip_gesture_manager, G_TYPE_OBJECT)229 priv->classes = g_list_append (priv->classes, m);
260230 }
261#define GRIP_GESTURE_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GRIP_TYPE_GESTURE_MANAGER, GripGestureManagerPrivate))231 break;
232
233 default:
234 /* @todo handle class-changed and class-unavailable events */
235 g_warning ("gesture class event ignored");
236 break;
237 }
238}
239
240
241static void
242grip_geis_event_callback(Geis geis G_GNUC_UNUSED, GeisEvent geis_event, void *context)
243{
244 GripGestureManager *self = GRIP_GESTURE_MANAGER (context);
245 GripGestureManagerPrivate *priv = GRIP_GESTURE_MANAGER_GET_PRIVATE (self);
246
247 switch (geis_event_type(geis_event))
248 {
249 case GEIS_EVENT_DEVICE_AVAILABLE:
250 case GEIS_EVENT_DEVICE_UNAVAILABLE:
251 grip_geis_device_added (self, geis_event);
252 break;
253
254 case GEIS_EVENT_CLASS_AVAILABLE:
255 case GEIS_EVENT_CLASS_CHANGED:
256 case GEIS_EVENT_CLASS_UNAVAILABLE:
257 process_class_event(priv, geis_event);
258 break;
259
260 case GEIS_EVENT_INIT_COMPLETE:
261 break;
262
263 case GEIS_EVENT_GESTURE_BEGIN:
264 case GEIS_EVENT_GESTURE_UPDATE:
265 case GEIS_EVENT_GESTURE_END:
266 process_gesture_events(self, geis_event);
267 break;
268
269 default:
270 g_warning ("event ignored");
271 break;
272 }
273
274 geis_event_delete(geis_event);
275 return;
276}
277
262278
263static void279static void
264grip_gesture_manager_dispose (GObject *object G_GNUC_UNUSED)280grip_gesture_manager_dispose (GObject *object G_GNUC_UNUSED)
@@ -267,59 +283,18 @@
267283
268284
269static void285static void
270free_registration(GripGestureRegistration *reg)
271{
272 GList *tmp = NULL;
273
274 if (!reg)
275 return;
276
277 geis_unsubscribe (reg->instance,
278 (GeisGestureType*)reg->gesture_list->pdata);
279
280 /* We don't need to free the values in the GPtrArray. */
281 g_ptr_array_free (reg->gesture_list, TRUE);
282
283 for (tmp = reg->bindings; tmp != NULL; tmp = tmp->next)
284 {
285 g_free (tmp->data);
286 }
287
288 g_list_free (reg->bindings);
289}
290
291/* Helper function needed to make things work with GTK. */
292
293static void
294free_registration_adapter (gpointer key G_GNUC_UNUSED,
295 gpointer value,
296 gpointer user_data G_GNUC_UNUSED)
297{
298 struct Registrations *regs = (struct Registrations *)value;
299 free_registration(regs->touchscreen);
300 free_registration(regs->touchpad);
301 free_registration(regs->independent);
302}
303
304static void
305grip_gesture_manager_finalize (GObject *object)286grip_gesture_manager_finalize (GObject *object)
306{287{
307 GripGestureManagerPrivate *priv = GRIP_GESTURE_MANAGER_GET_PRIVATE (object);288 GripGestureManagerPrivate *priv = GRIP_GESTURE_MANAGER_GET_PRIVATE (object);
308289
309 if (priv->registered_windows != NULL)290 g_list_foreach(priv->classes, (GFunc) g_free, NULL);
310 {291 g_list_free(priv->classes);
311 g_hash_table_foreach (priv->registered_windows,292
312 free_registration_adapter,293 g_ptr_array_foreach (priv->devices, (GFunc) g_object_unref, NULL);
313 NULL);294 g_ptr_array_unref (priv->devices);
314
315 g_hash_table_unref (priv->registered_windows);
316 priv->registered_windows = NULL;
317
318 g_ptr_array_foreach (priv->devices, (GFunc) g_object_unref, NULL);
319 g_ptr_array_unref (priv->devices);
320 }
321}295}
322296
297
323static GObject *298static GObject *
324grip_gesture_manager_constructor (GType type,299grip_gesture_manager_constructor (GType type,
325 guint n_params,300 guint n_params,
@@ -332,12 +307,12 @@
332 self = G_OBJECT_CLASS (grip_gesture_manager_parent_class)->307 self = G_OBJECT_CLASS (grip_gesture_manager_parent_class)->
333 constructor (type, n_params, params);308 constructor (type, n_params, params);
334 g_object_add_weak_pointer (self, (gpointer) &self);309 g_object_add_weak_pointer (self, (gpointer) &self);
335 grip_get_devices (GRIP_GESTURE_MANAGER (self));
336 }310 }
337311
338 return g_object_ref (self);312 return g_object_ref (self);
339}313}
340314
315
341static void316static void
342grip_gesture_manager_class_init (GripGestureManagerClass *class)317grip_gesture_manager_class_init (GripGestureManagerClass *class)
343{318{
@@ -386,7 +361,6 @@
386 G_TYPE_NONE,361 G_TYPE_NONE,
387 1,362 1,
388 GRIP_TYPE_INPUT_DEVICE);363 GRIP_TYPE_INPUT_DEVICE);
389
390}364}
391365
392366
@@ -420,592 +394,306 @@
420 return input_device;394 return input_device;
421}395}
422396
423/*
424 * registration_for_input_device:
425 * @registrations: A collection of #GripGestureRegistration
426 * @input_device: A pointer to a #GripInputDevice
427 *
428 * Determines which #GripGestureRegistration to use dependeng on properties of
429 * the #GripInputDevice.
430 *
431 * Returns: a pointer to a #GripGestureRegistration or %NULL if not found.
432 */
433static GripGestureRegistration *
434registration_for_input_device (struct Registrations *registrations,
435 GripInputDevice *input_device)
436{
437 GripDeviceType device_type = grip_get_device_type(input_device);
438 if (device_type == GRIP_DEVICE_TOUCHSCREEN)
439 {
440 return registrations->touchscreen;
441 }
442 else if (GRIP_DEVICE_TOUCHPAD)
443 {
444 return registrations->touchpad;
445 }
446 else if (GRIP_DEVICE_INDEPENDENT)
447 {
448 return registrations->independent;
449 }
450 return NULL;
451}
452
453397
454static gint398static gint
455pinch_gesture_handle_properties (GripEventGesturePinch *event,399pinch_gesture_handle_properties (GripEventGesturePinch *event,
456 GeisSize attr_count,400 GeisFrame frame)
457 GeisGestureAttr *attrs)
458{401{
459 guint i = 0;402 guint attr_count = geis_frame_attr_count (frame);
460 gint touches = 0;403 gint num_touches = 0;
461404 guint i;
462 for (i = 0; i < attr_count; ++i)405 for (i = 0; i < attr_count; ++i)
463 {406 {
464 if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0 &&407 GeisAttr attr = geis_frame_attr(frame, i);
465 attrs[i].type == GEIS_ATTR_TYPE_INTEGER)408 GeisString attr_name = geis_attr_name(attr);
466 {
467 touches = attrs[i].integer_val;
468 }
469 if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0 &&
470 attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
471 {
472 event->timestamp = attrs[i].integer_val;
473 }
474 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0 &&
475 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
476 {
477 event->focus_x = attrs[i].float_val;
478 }
479 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0 &&
480 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
481 {
482 event->focus_y = attrs[i].float_val;
483 }
484 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA) == 0 &&
485 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
486 {
487 event->radius_delta = attrs[i].float_val;
488 }
489 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_RADIAL_VELOCITY) == 0 &&
490 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
491 {
492 event->radial_velocity = attrs[i].float_val;
493 }
494 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_RADIUS) == 0 &&
495 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
496 {
497 event->radius = attrs[i].float_val;
498 }
499 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0 &&
500 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
501 {
502 event->position_x = attrs[i].float_val;
503 }
504 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0 &&
505 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
506 {
507 event->position_y = attrs[i].float_val;
508 }
509 }
510409
511 return touches;410 if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0)
411 num_touches = geis_attr_value_to_integer(attr);
412 if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0)
413 event->timestamp = geis_attr_value_to_integer(attr);
414 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0)
415 event->focus_x = geis_attr_value_to_float(attr);
416 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0)
417 event->focus_y = geis_attr_value_to_float(attr);
418 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA) == 0)
419 event->radius_delta = geis_attr_value_to_float(attr);
420 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_RADIAL_VELOCITY) == 0)
421 event->radial_velocity = geis_attr_value_to_float(attr);
422 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_RADIUS) == 0)
423 event->radius = geis_attr_value_to_float(attr);
424 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0)
425 event->position_x = geis_attr_value_to_float(attr);
426 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0)
427 event->position_y = geis_attr_value_to_float(attr);
428 }
429 return num_touches;
512}430}
513431
514static gint432static gint
515drag_gesture_handle_properties (GripEventGestureDrag *event,433drag_gesture_handle_properties (GripEventGestureDrag *event,
516 GeisSize attr_count,434 GeisFrame frame)
517 GeisGestureAttr *attrs)
518{435{
436 guint attr_count = geis_frame_attr_count (frame);
437 gint num_touches = 0;
519 guint i;438 guint i;
520 gint touches = 0;
521
522 for (i = 0; i < attr_count; ++i)439 for (i = 0; i < attr_count; ++i)
523 {440 {
524 if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0 &&441 GeisAttr attr = geis_frame_attr(frame, i);
525 attrs[i].type == GEIS_ATTR_TYPE_INTEGER)442 GeisString attr_name = geis_attr_name(attr);
526 {
527 touches = attrs[i].integer_val;
528 }
529 if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0 &&
530 attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
531 {
532 event->timestamp = attrs[i].integer_val;
533 }
534 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0 &&
535 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
536 {
537 event->focus_x = attrs[i].float_val;
538 }
539 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0 &&
540 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
541 {
542 event->focus_y = attrs[i].float_val;
543 }
544 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_DELTA_X) == 0 &&
545 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
546 {
547 event->delta_x = attrs[i].float_val;
548 }
549 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_DELTA_Y) == 0 &&
550 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
551 {
552 event->delta_y = attrs[i].float_val;
553 }
554 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_X) == 0 &&
555 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
556 {
557 event->velocity_x = attrs[i].float_val;
558 }
559 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y) == 0 &&
560 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
561 {
562 event->velocity_y = attrs[i].float_val;
563 }
564 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0 &&
565 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
566 {
567 event->position_x = attrs[i].float_val;
568 }
569 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0 &&
570 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
571 {
572 event->position_y = attrs[i].float_val;
573 }
574 }
575443
576 return touches;444 if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0)
445 num_touches = geis_attr_value_to_integer(attr);
446 if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0)
447 event->timestamp = geis_attr_value_to_integer(attr);
448 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0)
449 event->focus_x = geis_attr_value_to_float(attr);
450 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0)
451 event->focus_y = geis_attr_value_to_float(attr);
452 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_DELTA_X) == 0)
453 event->delta_x = geis_attr_value_to_float(attr);
454 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_DELTA_Y) == 0)
455 event->delta_y = geis_attr_value_to_float(attr);
456 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_X) == 0)
457 event->velocity_x = geis_attr_value_to_float(attr);
458 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y) == 0)
459 event->velocity_y = geis_attr_value_to_float(attr);
460 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0)
461 event->position_x = geis_attr_value_to_float(attr);
462 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0)
463 event->position_y = geis_attr_value_to_float(attr);
464 }
465 return num_touches;
577}466}
578467
468
579static gint469static gint
580rotate_gesture_handle_properties (GripEventGestureRotate *event,470rotate_gesture_handle_properties (GripEventGestureRotate *event,
581 GeisSize attr_count,471 GeisFrame frame)
582 GeisGestureAttr *attrs)
583{472{
473 guint attr_count = geis_frame_attr_count (frame);
474 gint num_touches = 0;
584 guint i;475 guint i;
585 gint touches = 0;
586
587 for (i = 0; i < attr_count; ++i)476 for (i = 0; i < attr_count; ++i)
588 {477 {
589 if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0 &&478 GeisAttr attr = geis_frame_attr(frame, i);
590 attrs[i].type == GEIS_ATTR_TYPE_INTEGER)479 GeisString attr_name = geis_attr_name(attr);
591 {
592 touches = attrs[i].integer_val;
593 }
594 if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0 &&
595 attrs[i].type == GEIS_ATTR_TYPE_INTEGER)
596 {
597 event->timestamp = attrs[i].integer_val;
598 }
599 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0 &&
600 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
601 {
602 event->focus_x = attrs[i].float_val;
603 }
604 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0 &&
605 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
606 {
607 event->focus_y = attrs[i].float_val;
608 }
609 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA) == 0 &&
610 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
611 {
612 event->angle_delta = attrs[i].float_val;
613 }
614 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_ANGULAR_VELOCITY) == 0 &&
615 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
616 {
617 event->angular_velocity = attrs[i].float_val;
618 }
619 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_ANGLE) == 0 &&
620 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
621 {
622 event->angle = attrs[i].float_val;
623 }
624 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0 &&
625 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
626 {
627 event->position_x = attrs[i].float_val;
628 }
629 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0 &&
630 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)
631 {
632 event->position_y = attrs[i].float_val;
633 }
634 }
635480
636 return touches;481 if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0)
482 num_touches = geis_attr_value_to_integer(attr);
483 if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0)
484 event->timestamp = geis_attr_value_to_integer(attr);
485 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0)
486 event->focus_x = geis_attr_value_to_float(attr);
487 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0)
488 event->focus_y = geis_attr_value_to_float(attr);
489 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA) == 0)
490 event->angle_delta = geis_attr_value_to_float(attr);
491 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_ANGULAR_VELOCITY) == 0)
492 event->angular_velocity = geis_attr_value_to_float(attr);
493 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_ANGLE) == 0)
494 event->angle = geis_attr_value_to_float(attr);
495 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0)
496 event->position_x = geis_attr_value_to_float(attr);
497 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0)
498 event->position_y = geis_attr_value_to_float(attr);
499 }
500 return num_touches;
637}501}
638502
503
639static gint504static gint
640tap_gesture_handle_properties (GripEventGestureTap *event,505tap_gesture_handle_properties (GripEventGestureTap *event,
641 GeisSize attr_count,506 GeisFrame frame)
642 GeisGestureAttr *attrs)
643{507{
508 guint attr_count = geis_frame_attr_count (frame);
509 gint num_touches = 0;
644 guint i;510 guint i;
645 gint touches = 0;
646
647 for (i = 0; i < attr_count; ++i)511 for (i = 0; i < attr_count; ++i)
648 {512 {
649 if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0 &&513 GeisAttr attr = geis_frame_attr(frame, i);
650 attrs[i].type == GEIS_ATTR_TYPE_INTEGER)514 GeisString attr_name = geis_attr_name(attr);
651 {515
652 touches = attrs[i].integer_val;516 if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0)
653 }517 num_touches = geis_attr_value_to_integer(attr);
654 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0 &&518 if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0)
655 attrs[i].type == GEIS_ATTR_TYPE_INTEGER)519 event->timestamp = geis_attr_value_to_integer(attr);
656 {520 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0)
657 event->timestamp = attrs[i].integer_val;521 event->focus_x = geis_attr_value_to_float(attr);
658 }522 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0)
659 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0 &&523 event->focus_y = geis_attr_value_to_float(attr);
660 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)524 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0)
661 {525 event->position_x = geis_attr_value_to_float(attr);
662 event->focus_x = attrs[i].float_val;526 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0)
663 }527 event->position_y = geis_attr_value_to_float(attr);
664 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0 &&528 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TAP_TIME) == 0)
665 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)529 event->tap_time = geis_attr_value_to_float(attr);
666 {530 }
667 event->focus_y = attrs[i].float_val;531 return num_touches;
668 }532}
669 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0 &&533
670 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)534
671 {535static void
672 event->position_x = attrs[i].float_val;536process_gesture_events(GripGestureManager *manager, GeisEvent geis_event)
673 }537{
674 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0 &&538 GripGestureManagerPrivate *priv = manager->priv;
675 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)539
676 {540 GripTimeType time_type = GRIP_TIME_UPDATE;
677 event->position_y = attrs[i].float_val;541 if (geis_event_type(geis_event) == GEIS_EVENT_GESTURE_BEGIN)
678 }542 time_type = GRIP_TIME_START;
679 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TAP_TIME) == 0 &&543 else if (geis_event_type(geis_event) == GEIS_EVENT_GESTURE_END)
680 attrs[i].type == GEIS_ATTR_TYPE_INTEGER)544 time_type = GRIP_TIME_END;
681 {545
682 event->tap_time = attrs[i].float_val;546 GeisAttr attr = geis_event_attr_by_name (geis_event, GEIS_EVENT_ATTRIBUTE_GROUPSET);
683 }547 g_return_if_fail (attr);
684 }548
685549 GeisGroupSet groupset = geis_attr_value_to_pointer (attr);
686 return touches;550 g_return_if_fail (groupset);
687}551
688
689static void
690gesture_added (void *cookie G_GNUC_UNUSED,
691 GeisGestureType gesture_type G_GNUC_UNUSED,
692 GeisGestureId gesture_id G_GNUC_UNUSED,
693 GeisSize attr_count G_GNUC_UNUSED,
694 GeisGestureAttr *attrs G_GNUC_UNUSED)
695{
696}
697
698static void
699gesture_removed (void *cookie G_GNUC_UNUSED,
700 GeisGestureType gesture_type G_GNUC_UNUSED,
701 GeisGestureId gesture_id G_GNUC_UNUSED,
702 GeisSize attr_count G_GNUC_UNUSED,
703 GeisGestureAttr *attrs G_GNUC_UNUSED)
704{
705}
706
707static gboolean
708matches_widget (GtkWidget *widget,
709 GdkWindow *window,
710 gint x,
711 gint y)
712{
713 GtkAllocation alloc;
714 gint ax, ay;
715
716 gtk_widget_get_allocation (widget, &alloc);
717 gdk_window_get_root_coords (window, alloc.x, alloc.y, &ax, &ay);
718
719 return (x >= ax && x < ax + alloc.width && y >= ay && y < ay + alloc.height);
720}
721
722
723/*
724 * process_gesture:
725 * @cookie:
726 * @type:
727 * @id:
728 * @attr_count:
729 * @attrs:
730 * @time_type:
731 *
732 * The generic gesture event dispatch engine.
733 */
734static void
735process_gesture (void *cookie,
736 GeisGestureType type,
737 GeisGestureId id,
738 GeisSize attr_count,
739 GeisGestureAttr *attrs,
740 GripTimeType time_type)
741{
742 GripGestureManager *manager = (GripGestureManager *) cookie;
743 GripInputDevice *input_device = NULL;
744 GtkWindow *gtk_window = NULL;
745 struct Registrations *registrations = NULL;
746 GripGestureRegistration *reg = NULL;
747 GList *l = NULL;
748 GeisSize i;552 GeisSize i;
749553 for (i = 0; i < geis_groupset_group_count (groupset); ++i)
750 for (i = 0; i < attr_count; ++i)554 {
751 {555 GeisGroup group = geis_groupset_group (groupset, i);
752 if (0 == g_strcmp0(attrs[i].name, GEIS_GESTURE_ATTRIBUTE_DEVICE_ID))556 g_return_if_fail (group);
753 {557
754 input_device = device_id_to_input_device(manager, attrs[i].integer_val);558 GeisSize j;
755 }559 for (j = 0; j < geis_group_frame_count (group); ++j)
756 else if (0 == g_strcmp0(attrs[i].name, GEIS_GESTURE_ATTRIBUTE_EVENT_WINDOW_ID))560 {
757 {561 GeisFrame frame = geis_group_frame(group, j);
758 GHashTableIter iter;562 g_return_if_fail (frame);
759 GtkWidget *key;563
760 struct Registrations *value;564 GeisAttr window_attr = geis_frame_attr_by_name(frame, GEIS_GESTURE_ATTRIBUTE_EVENT_WINDOW_ID);
761 guint window_id = attrs[i].integer_val;565 guint window_id = geis_attr_value_to_integer(window_attr);
762566
763 g_hash_table_iter_init (&iter, manager->priv->registered_windows);567 GeisAttr device_attr = geis_frame_attr_by_name(frame, GEIS_GESTURE_ATTRIBUTE_DEVICE_ID);
764 while (g_hash_table_iter_next(&iter, (gpointer *)&key, (gpointer *)&value)) 568 guint device_id = geis_attr_value_to_integer(device_attr);
765 {569 GripInputDevice *input_device = device_id_to_input_device (manager, device_id);
766 if (GDK_WINDOW_XID (gtk_widget_get_window (key)) == window_id)570
767 {571 GList *l;
768 gtk_window = (GtkWindow *)key;572 for (l = priv->bindings; l != NULL; l = l->next)
769 break;573 {
770 }574 GripGestureBinding *binding = (GripGestureBinding *)l->data;
771 }575 guint widget_window_id = GDK_WINDOW_XID (gtk_widget_get_window (binding->widget));
772 }576 if (widget_window_id == window_id)
773 }577 {
774 g_return_if_fail(input_device != NULL);578 GList *class_list;
775 g_return_if_fail(gtk_window != NULL);579 for (class_list = priv->classes; class_list != NULL; class_list = class_list->next)
776580 {
777 registrations = g_hash_table_lookup (manager->priv->registered_windows, gtk_window);581 GripGestureClassMap *p = (GripGestureClassMap *)class_list->data;
778 g_return_if_fail(registrations != NULL);582 if (p->grip_type == binding->type)
779 reg = registration_for_input_device (registrations, input_device);583 {
780 g_return_if_fail(reg != NULL);584 if (geis_frame_is_class(frame, p->geis_class))
781585 {
782 for (l = reg->bindings; l != NULL; l = l->next)586 GripGestureEvent *grip_event = grip_gesture_event_new (p->grip_type);
783 {587 if (p->grip_type == GRIP_GESTURE_DRAG)
784 GripGestureBinding *binding = (GripGestureBinding *)l->data;588 {
785589 GripEventGestureDrag *drag = (GripEventGestureDrag *)grip_event;
786 if (binding->type == type)590 drag->type = p->grip_type;
787 {591 drag->id = geis_frame_id(frame);
788 GripGestureEvent *event = grip_gesture_event_new (type);592 drag->input_device = input_device;
789593 drag->fingers = drag_gesture_handle_properties (drag, frame);
790 if (type == GRIP_GESTURE_DRAG)594 binding->callback (binding->widget,
791 {595 time_type,
792 GripEventGestureDrag *drag = (GripEventGestureDrag *)event;596 grip_event,
793597 binding->data);
794 drag->type = type;598 }
795 drag->id = id;599 else if (p->grip_type == GRIP_GESTURE_PINCH)
796 drag->input_device = input_device;600 {
797 drag->fingers = drag_gesture_handle_properties (drag,601 GripEventGesturePinch *pinch = (GripEventGesturePinch *)grip_event;
798 attr_count,602 pinch->type = p->grip_type;
799 attrs);603 pinch->id = geis_frame_id(frame);
800604 pinch->input_device = input_device;
801 if (drag->fingers == (gint)binding->touches)605 pinch->fingers = pinch_gesture_handle_properties (pinch, frame);
802 {606 binding->callback (binding->widget,
803 if (matches_widget (binding->widget,607 time_type,
804 gtk_widget_get_window(GTK_WIDGET (reg->window)),608 grip_event,
805 (gint)drag->focus_x,609 binding->data);
806 (gint)drag->focus_y))610 }
807 {611 else if (p->grip_type == GRIP_GESTURE_ROTATE)
808 binding->callback (binding->widget,612 {
809 time_type,613 GripEventGestureRotate *rotate = (GripEventGestureRotate *)grip_event;
810 event,614 rotate->type = p->grip_type;
811 binding->data);615 rotate->id = geis_frame_id(frame);
812 }616 rotate->input_device = input_device;
813 }617 rotate->fingers = rotate_gesture_handle_properties (rotate, frame);
814 }618 binding->callback (binding->widget,
815 else if (type == GRIP_GESTURE_PINCH)619 time_type,
816 {620 grip_event,
817 GripEventGesturePinch *pinch = (GripEventGesturePinch *)event;621 binding->data);
818622 }
819 pinch->type = type;623 else if (p->grip_type == GRIP_GESTURE_TAP)
820 pinch->id = id;624 {
821 pinch->input_device = input_device;625 GripEventGestureTap *tap = (GripEventGestureTap *)grip_event;
822 pinch->fingers = pinch_gesture_handle_properties (pinch,626 tap->type = p->grip_type;
823 attr_count,627 tap->id = geis_frame_id(frame);
824 attrs);628 tap->input_device = input_device;
825629 tap->fingers = tap_gesture_handle_properties (tap, frame);
826 if (pinch->fingers == binding->touches)630 binding->callback (binding->widget,
827 {631 time_type,
828 if (matches_widget (binding->widget,632 grip_event,
829 gtk_widget_get_window(GTK_WIDGET (reg->window)),633 binding->data);
830 (gint)pinch->focus_x,634 }
831 (gint)pinch->focus_y))635 grip_gesture_event_free (grip_event);
832 {636 }
833 binding->callback (binding->widget,637 }
834 time_type,638 }
835 event,639 }
836 binding->data);640 }
837 }641 }
838 }642 }
839 }643}
840 else if (type == GRIP_GESTURE_ROTATE)644
841 {645
842 GripEventGestureRotate *rotate = (GripEventGestureRotate *)event;646static gboolean
843647grip_geis_event_ready (GIOChannel *source G_GNUC_UNUSED,
844 rotate->type = type;648 GIOCondition condition G_GNUC_UNUSED,
845 rotate->id = id;649 gpointer context)
846 rotate->input_device = input_device;650{
847 rotate->fingers = rotate_gesture_handle_properties (rotate,651 Geis geis = (Geis)context;
848 attr_count,652 GeisStatus status G_GNUC_UNUSED = geis_dispatch_events(geis);
849 attrs);653 return TRUE;
850654}
851 if (rotate->fingers == binding->touches)655
852 {656
853 if (matches_widget (binding->widget,657static void
854 gtk_widget_get_window(GTK_WIDGET (reg->window)),658grip_gesture_manager_init (GripGestureManager *self)
855 (gint)rotate->focus_x,659{
856 (gint)rotate->focus_y))660 GripGestureManagerPrivate *priv = self->priv = GRIP_GESTURE_MANAGER_GET_PRIVATE (self);
857 {
858 binding->callback (binding->widget,
859 time_type,
860 event,
861 binding->data);
862 }
863 }
864 }
865 else if (type == GRIP_GESTURE_TAP)
866 {
867 GripEventGestureTap *tap = (GripEventGestureTap *)event;
868
869 tap->type = type;
870 tap->id = id;
871 tap->input_device = input_device;
872 tap->fingers = tap_gesture_handle_properties (tap,
873 attr_count,
874 attrs);
875
876 if (tap->fingers == binding->touches)
877 {
878 if (matches_widget (binding->widget,
879 gtk_widget_get_window(GTK_WIDGET (reg->window)),
880 (gint)tap->focus_x,
881 (gint)tap->focus_y))
882 {
883 binding->callback (binding->widget,
884 time_type,
885 event,
886 binding->data);
887 }
888 }
889 }
890
891 grip_gesture_event_free (event);
892 }
893 }
894}
895
896static void
897gesture_start (void *cookie,
898 GeisGestureType type,
899 GeisGestureId id,
900 GeisSize attr_count,
901 GeisGestureAttr *attrs)
902{
903 process_gesture(cookie, type, id, attr_count, attrs, GRIP_TIME_START);
904}
905
906static void
907gesture_update (void *cookie,
908 GeisGestureType type,
909 GeisGestureId id,
910 GeisSize attr_count,
911 GeisGestureAttr *attrs)
912{
913 process_gesture(cookie, type, id, attr_count, attrs, GRIP_TIME_UPDATE);
914}
915
916static void
917gesture_finish (void *cookie,
918 GeisGestureType type,
919 GeisGestureId id,
920 GeisSize attr_count,
921 GeisGestureAttr *attrs)
922{
923 process_gesture(cookie, type, id, attr_count, attrs, GRIP_TIME_END);
924}
925
926static void
927grip_gesture_manager_init (GripGestureManager *item)
928{
929 GripGestureManagerPrivate *priv;
930
931 priv = item->priv = GRIP_GESTURE_MANAGER_GET_PRIVATE (item);
932
933 priv->registered_windows = g_hash_table_new (g_direct_hash, g_direct_equal);
934
935 priv->devices = g_ptr_array_new ();661 priv->devices = g_ptr_array_new ();
936}662
937663 priv->geis = geis_new (GEIS_INIT_TRACK_DEVICES, GEIS_INIT_TRACK_GESTURE_CLASSES, NULL);
938static gboolean664 g_return_if_fail (priv->geis);
939io_callback (GIOChannel *source G_GNUC_UNUSED,665
940 GIOCondition condition G_GNUC_UNUSED,666 int fd;
941 gpointer data)667 geis_get_configuration(priv->geis, GEIS_CONFIGURATION_FD, &fd);
942{668 priv->iochannel = g_io_channel_unix_new (fd);
943 GripGestureRegistration *reg = (GripGestureRegistration *)data;669 priv->iochannel_id = g_io_add_watch (priv->iochannel, G_IO_IN, grip_geis_event_ready, priv->geis);
944670 geis_register_device_callback (priv->geis, grip_geis_event_callback, self);
945 geis_event_dispatch (reg->instance);671 geis_register_class_callback (priv->geis, grip_geis_event_callback, self);
946672 geis_register_event_callback (priv->geis, grip_geis_event_callback, self);
947 return TRUE;673}
948}674
949
950static void
951destroy_registration(GripGestureRegistration *reg)
952{
953 GList *list;
954
955 for (list = reg->bindings; list != NULL; list = list->next)
956 {
957 GripGestureBinding *binding = (GripGestureBinding *)list->data;
958
959 if (binding->destroy)
960 {
961 GDestroyNotify d = binding->destroy;
962
963 d (binding->data);
964 }
965
966 g_free (binding);
967 }
968
969 g_list_free (reg->bindings);
970
971 g_io_channel_shutdown (reg->iochannel, FALSE, NULL);
972 g_source_remove (reg->iochannel_id);
973 g_io_channel_unref (reg->iochannel);
974
975 geis_finish (reg->instance);
976
977 reg->instance = NULL;
978 reg->iochannel = NULL;
979}
980675
981static void676static void
982window_destroyed_cb (GtkWidget *object,677window_destroyed_cb (GtkWidget *object,
983 gpointer user_data)678 gpointer user_data)
984{679{
985 GripGestureManager *manager = (GripGestureManager *)user_data;680 GripGestureManager *manager = (GripGestureManager *)user_data;
986 GripGestureManagerPrivate *priv = manager->priv;681 GList *l = manager->priv->bindings;
987 struct Registrations *reg = g_hash_table_lookup (priv->registered_windows, object);682 while (l != NULL)
988683 {
989 if (!reg)684 GList *next = l->next;
990 return;685 GripGestureBinding *binding = l->data;
991686 if (gtk_widget_get_toplevel (binding->widget) == object)
992 destroy_registration(reg->touchpad);687 {
993 destroy_registration(reg->touchscreen);688 geis_subscription_delete (binding->subscription);
994 destroy_registration(reg->independent);689
995690 if (binding->destroy)
996 g_hash_table_remove (priv->registered_windows, object);691 binding->destroy (binding->data);
997 g_free (reg);692 g_free (binding);
998}693 manager->priv->bindings = g_list_delete_link (manager->priv->bindings, l);
999694 }
1000static const gchar *695 l = next;
1001grip_type_to_geis_type (GripGestureType gesture_type,696 }
1002 gint touch_points)
1003{
1004 /* grail taps begin at 15, so let's convert that into something we
1005 * can index in geis_gesture_types. */
1006 int t = gesture_type == 15 ? 3 : gesture_type;
1007
1008 return geis_gesture_types[(t * 5 + touch_points) - 1];
1009}697}
1010698
1011699
@@ -1017,232 +705,207 @@
1017}705}
1018706
1019707
708/*
709 * processed_mapped_window_request:
710 * @reg: a #GripRegistrationRequest (removed from the GripGestureManager
711 * requests listand freed).
712 *
713 * Creates a subscription for a widget mapped to a window.
714 */
1020static void715static void
1021grip_devices_for_type (GripDeviceType type, GArray *selection,716processed_mapped_window_request (GripRegistrationRequest *req)
1022 GripDevices *devices)
1023{717{
1024 guint i;718 g_return_if_fail (GRIP_IS_GESTURE_MANAGER (req->manager));
1025719 g_return_if_fail (GTK_IS_WIDGET (req->widget));
1026 for (i = 0; i < devices->len; ++i)720
721 GtkWidget *toplevel = gtk_widget_get_toplevel (req->widget);
722 g_return_if_fail (GTK_IS_WINDOW (toplevel));
723
724 GripGestureManagerPrivate *priv = req->manager->priv;
725
726 guint window_id = GDK_WINDOW_XID (gtk_widget_get_window(req->widget));
727
728 /* XXX - check for duplicates in reg->bindings first */
729 GripGestureBinding *binding = g_new0 (GripGestureBinding, 1);
730 binding->type = req->gesture_type;
731 binding->widget = req->widget;
732 binding->touches = req->touch_points;
733 binding->callback = req->callback;
734 binding->data = req->user_data;
735 binding->destroy = req->destroy;
736
737 char sub_name[48];
738 snprintf(sub_name, 48, "sub-%x-%x-%x", window_id, req->gesture_type, req->touch_points);
739 binding->subscription = geis_subscription_new (priv->geis, sub_name, GEIS_SUBSCRIPTION_CONT);
740 g_return_if_fail (binding->subscription);
741
742 char filter_id[20];
743 snprintf(filter_id, 20, "grip-%x", window_id);
744 GeisFilter window_filter = geis_filter_new(priv->geis, filter_id);
745 geis_filter_add_term(window_filter, GEIS_FILTER_REGION,
746 GEIS_REGION_ATTRIBUTE_WINDOWID, GEIS_FILTER_OP_EQ, window_id,
747 NULL);
748
749 switch (req->gesture_type)
1027 {750 {
1028 GripInputDevice *input_device = g_ptr_array_index (devices, i);751 case GRIP_GESTURE_DRAG:
1029 GeisInputDeviceId id = grip_input_device_get_id (input_device);752 geis_filter_add_term(window_filter, GEIS_FILTER_CLASS,
1030 GripDeviceType device_type= grip_get_device_type(input_device);753 GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_DRAG,
1031754 GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, req->touch_points,
1032 if ((type & GRIP_DEVICE_TOUCHSCREEN) && device_type == GRIP_DEVICE_TOUCHSCREEN)755 NULL);
1033 {756 break;
1034 g_array_append_val (selection, id);757 case GRIP_GESTURE_PINCH:
1035 }758 geis_filter_add_term(window_filter, GEIS_FILTER_CLASS,
1036 if ((type & GRIP_DEVICE_TOUCHPAD) && device_type == GRIP_DEVICE_TOUCHPAD)759 GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_PINCH,
1037 {760 GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, req->touch_points,
1038 g_array_append_val (selection, id);761 NULL);
1039 }762 break;
1040 if ((type & GRIP_DEVICE_INDEPENDENT) && device_type == GRIP_DEVICE_INDEPENDENT)763 case GRIP_GESTURE_ROTATE:
1041 {764 geis_filter_add_term(window_filter, GEIS_FILTER_CLASS,
1042 g_array_append_val (selection, id);765 GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_ROTATE,
1043 }766 GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, req->touch_points,
767 NULL);
768 break;
769 case GRIP_GESTURE_TAP:
770 geis_filter_add_term(window_filter, GEIS_FILTER_CLASS,
771 GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_TAP,
772 GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, req->touch_points,
773 NULL);
774 break;
1044 }775 }
1045}776
1046777 if (req->device_type & GRIP_DEVICE_TOUCHSCREEN)
1047/*778 {
1048 * new_window_registration:779 char filter_name[32];
1049 * @manager: a GripGestureManager780 snprintf(filter_name, 32, "%s/touchscreen", filter_id);
1050 * @toplevel: a toplevel #GtkWindow781 GeisFilter touchscreen_filter = geis_filter_clone (window_filter, filter_name);
1051 *782 geis_filter_add_term(touchscreen_filter, GEIS_FILTER_DEVICE,
1052 * Constructs a new #GripGestureRegistration for a #GtkWidget.783 GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_FILTER_OP_EQ, GEIS_TRUE,
1053 */784 NULL);
1054static GripGestureRegistration *785 GeisStatus status = geis_subscription_add_filter(binding->subscription, touchscreen_filter);
1055new_window_registration(GripGestureManager *manager,786 g_return_if_fail (status == GEIS_STATUS_SUCCESS);
1056 GtkWidget *toplevel)787 }
1057{788 if (req->device_type & GRIP_DEVICE_TOUCHPAD)
1058 GripGestureRegistration *reg;789 {
1059 GeisInstance instance;790 char filter_name[32];
1060 gint fd = -1;791 snprintf(filter_name, 32, "%s/touchpad", filter_id);
1061 GeisXcbWinInfo xcb_win_info = {792 GeisFilter touchpad_filter = geis_filter_clone (window_filter, filter_name);
1062 .display_name = NULL,793 geis_filter_add_term(touchpad_filter, GEIS_FILTER_DEVICE,
1063 .screenp = NULL,794 GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_FILTER_OP_EQ, GEIS_FALSE,
1064 .window_id = GDK_WINDOW_XID (gtk_widget_get_window(toplevel))795 NULL);
1065 };796 GeisStatus status = geis_subscription_add_filter(binding->subscription, touchpad_filter);
1066 GeisWinInfo win_info = {797 g_return_if_fail (status == GEIS_STATUS_SUCCESS);
1067 GEIS_XCB_FULL_WINDOW,798 }
1068 &xcb_win_info799 if (req->device_type & GRIP_DEVICE_INDEPENDENT)
1069 };800 {
1070801 char filter_name[32];
1071 if (geis_init (&win_info, &instance) != GEIS_STATUS_SUCCESS)802 snprintf(filter_name, 32, "%s/indep", filter_id);
1072 {803 GeisFilter indep_filter = geis_filter_clone (window_filter, filter_name);
1073 g_warning ("Failed to initialize gesture manager.");804 geis_filter_add_term(indep_filter, GEIS_FILTER_DEVICE,
1074 return NULL;805 GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH, GEIS_FILTER_OP_EQ, GEIS_TRUE,
1075 }806 NULL);
1076807 GeisStatus status = geis_subscription_add_filter(binding->subscription, indep_filter);
1077 if (geis_configuration_supported (instance,808 g_return_if_fail (status == GEIS_STATUS_SUCCESS);
1078 GEIS_CONFIG_UNIX_FD) != GEIS_STATUS_SUCCESS)809 }
1079 {810
1080 g_warning ("Gesture manager does not support UNIX fd.");811 /*
1081 return NULL;812 * If any device types were specified, the window_filter was cloned and needs
1082 }813 * to be disposed of, otehrwise it's _the_ filter.
1083814 */
1084 if (geis_configuration_get_value (instance,815 if (req->device_type)
1085 GEIS_CONFIG_UNIX_FD,816 {
1086 &fd) != GEIS_STATUS_SUCCESS)817 geis_filter_delete(window_filter);
1087 {818 }
1088 g_error ("Gesture manager failed to obtain UNIX fd.");819 else
1089 return NULL;820 {
1090 }821 GeisStatus status = geis_subscription_add_filter(binding->subscription, window_filter);
1091822 g_return_if_fail (status == GEIS_STATUS_SUCCESS);
1092 reg = g_new0 (GripGestureRegistration, 1);823 }
1093824
1094 reg->window = GTK_WINDOW (toplevel);825
1095 reg->instance = instance;826 GeisStatus status = geis_subscription_activate (binding->subscription);
827 g_return_if_fail (status == GEIS_STATUS_SUCCESS);
828
829 priv->bindings = g_list_append (priv->bindings, binding);
1096830
1097 g_signal_connect (toplevel,831 g_signal_connect (toplevel,
1098 "destroy",832 "destroy",
1099 G_CALLBACK (window_destroyed_cb),833 G_CALLBACK (window_destroyed_cb),
1100 manager);834 req->manager);
1101835
1102 reg->iochannel = g_io_channel_unix_new (fd);836 /* remove the request from the watch list */
1103 reg->iochannel_id = g_io_add_watch (reg->iochannel,837 g_free (req);
1104 G_IO_IN,838 priv->requests = g_list_remove (priv->requests, req);
1105 io_callback,839}
1106 reg);840
1107 reg->gesture_list = g_ptr_array_new ();841
1108842/*
1109 return reg;843 * register_mapped_window:
1110}844 * @manager: a Grip gesture manager object
1111845 * @toplevel: a top-level widget
1112static void846 *
1113bind_registration(GripGestureManager *manager,847 * Processes all subscriptions requests for a newly-mapped window.
1114 GripGestureRegistration *reg,848 */
1115 GtkWidget *widget,849static void
1116 GripGestureType gesture_type,850register_mapped_window (GripGestureManager *manager, GtkWidget *toplevel)
1117 GripDeviceType device_type,851{
1118 gint touch_points,852 g_return_if_fail (gtk_widget_is_toplevel (toplevel));
1119 GripGestureCallback callback,853
1120 gpointer user_data,854 GList *pending_request = manager->priv->requests;
1121 GDestroyNotify destroy)855 while (pending_request)
1122{856 {
1123 GripGestureManagerPrivate *priv;857 GList *next = pending_request->next;
1124 GripGestureBinding *binding;858 GripRegistrationRequest *req = pending_request->data;
1125 GArray *devices;859
1126860 if (gtk_widget_get_toplevel (req->widget) == toplevel)
1127 priv = manager->priv;861 {
1128862 processed_mapped_window_request (req);
1129 if (reg->gesture_list->len)863 }
1130 g_ptr_array_remove_index (reg->gesture_list,864 pending_request = next;
1131 reg->gesture_list->len - 1);865 }
1132866}
1133 devices = g_array_new (TRUE, FALSE, sizeof(GeisInputDeviceId));867
1134 grip_devices_for_type(device_type, devices, priv->devices);868
1135 if (devices->len == 0) {869/*
1136 g_array_free(devices, TRUE);870 * register_toplevel_widget:
1137 return;871 * @manager: a Grip gesture manager object
1138 }872 * @toplevel: a top-level widget
1139873 *
1140 g_ptr_array_add (reg->gesture_list,874 * Handles the registration of a widget that has just become a top-level widget.
1141 (gchar *)grip_type_to_geis_type (gesture_type, touch_points));875 *
1142 g_ptr_array_add (reg->gesture_list,876 * If the top-level widget is mapped to a window, it;s handled right away.
1143 NULL);877 * Otherwise, a callback is queued for when it does become mapped to a window.
1144878 */
1145 geis_subscribe (reg->instance,879static void
1146 (GeisInputDeviceId *)(void *)devices->data,880register_toplevel_widget (GripGestureManager *manager, GtkWidget *toplevel)
1147 (const char**)reg->gesture_list->pdata,881{
1148 &gesture_funcs,882 g_return_if_fail (gtk_widget_is_toplevel (toplevel));
1149 manager);883
1150884 if (gtk_widget_get_mapped (GTK_WIDGET (toplevel)))
1151 g_array_unref (devices);885 {
1152886 register_mapped_window (manager, toplevel);
1153 /* XXX - check for duplicates in reg->bindings first */
1154 binding = g_new0 (GripGestureBinding, 1);
1155
1156 binding->type = gesture_type;
1157 binding->widget = widget;
1158 binding->touches = touch_points;
1159 binding->callback = callback;
1160 binding->data = user_data;
1161 binding->destroy = destroy;
1162
1163 reg->bindings = g_list_append (reg->bindings, binding);
1164}
1165
1166/*
1167 * register_internal:
1168 * @manager: the @GripGestureManager
1169 * @widget: the GtkWidget to be bound
1170 * @gesture_type: the type of gesture to subscribe for
1171 * @device_type: the type of input device to subscribe for
1172 * @touch_points:
1173 * @callback: the callback to be invoked on gesture events
1174 * @user_data: the callbackl context to be passed back on gesture events
1175 * @destroy:
1176 *
1177 * Binds or rebinds a gesture subscription for a widget.
1178 */
1179static void
1180register_internal (GripGestureManager *manager,
1181 GtkWidget *widget,
1182 GripGestureType gesture_type,
1183 GripDeviceType device_type,
1184 gint touch_points,
1185 GripGestureCallback callback,
1186 gpointer user_data,
1187 GDestroyNotify destroy)
1188{
1189 GripGestureManagerPrivate *priv;
1190 GtkWidget *toplevel;
1191 struct Registrations *registrations;
1192
1193 g_return_if_fail (GRIP_IS_GESTURE_MANAGER (manager));
1194 g_return_if_fail (GTK_IS_WIDGET (widget));
1195
1196 toplevel = gtk_widget_get_toplevel (widget);
1197
1198 g_return_if_fail (GTK_IS_WINDOW (toplevel));
1199
1200 priv = manager->priv;
1201
1202 if (!(registrations = g_hash_table_lookup (priv->registered_windows, toplevel)))
1203 {
1204 registrations = g_new(struct Registrations, 1);
1205 registrations->touchscreen = new_window_registration(manager, toplevel);
1206 registrations->touchpad = new_window_registration(manager, toplevel);
1207 registrations->independent = new_window_registration(manager, toplevel);
1208
1209 if (registrations->touchscreen == NULL ||
1210 registrations->touchpad == NULL ||
1211 registrations->independent == NULL)
1212 return;
1213 }887 }
1214 else888 else
1215 {889 {
1216 if (device_type & GRIP_DEVICE_TOUCHSCREEN)890 g_signal_connect (toplevel,
1217 geis_unsubscribe (registrations->touchscreen->instance,891 "map-event",
1218 (GeisGestureType*)registrations->touchscreen->gesture_list->pdata);892 G_CALLBACK (toplevel_mapped_cb),
1219 if (device_type & GRIP_DEVICE_TOUCHPAD)893 manager);
1220 geis_unsubscribe (registrations->touchpad->instance,
1221 (GeisGestureType*)registrations->touchpad->gesture_list->pdata);
1222 if (device_type & GRIP_DEVICE_INDEPENDENT)
1223 geis_unsubscribe (registrations->independent->instance,
1224 (GeisGestureType*)registrations->independent->gesture_list->pdata);
1225 }894 }
1226
1227 if (device_type & GRIP_DEVICE_TOUCHSCREEN)
1228 bind_registration(manager,
1229 registrations->touchscreen, widget, gesture_type, GRIP_DEVICE_TOUCHSCREEN, touch_points,
1230 callback, user_data, destroy);
1231
1232 if (device_type & GRIP_DEVICE_TOUCHPAD)
1233 bind_registration(manager,
1234 registrations->touchpad, widget, gesture_type, GRIP_DEVICE_TOUCHPAD, touch_points,
1235 callback, user_data, destroy);
1236
1237 if (device_type & GRIP_DEVICE_INDEPENDENT)
1238 bind_registration(manager,
1239 registrations->independent, widget, gesture_type, GRIP_DEVICE_INDEPENDENT, touch_points,
1240 callback, user_data, destroy);
1241 g_hash_table_insert (priv->registered_windows,
1242 toplevel,
1243 registrations);
1244}895}
1245896
897
898/*
899 * toplevel_notify_cb:
900 *
901 * Called when a widget property has changed.
902 *
903 * The only widget property we're interested in here is the "parent" property.
904 * We can't subscribe to gestures on a window until the widget is mapped to a
905 * window. Only top-level widgets can be mapped to a window: we just keep
906 * queueing this callback on successive parent widgets until one is a top-level
907 * widget, then process that one.
908 */
1246static void909static void
1247toplevel_notify_cb (GtkWidget *widget,910toplevel_notify_cb (GtkWidget *widget,
1248 GParamSpec *pspec,911 GParamSpec *pspec,
@@ -1251,7 +914,7 @@
1251 if (pspec->name == g_intern_static_string ("parent"))914 if (pspec->name == g_intern_static_string ("parent"))
1252 {915 {
1253 GtkWidget *toplevel = gtk_widget_get_toplevel (widget);916 GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
1254 GripRegistrationRequest *req = (GripRegistrationRequest *)user_data;917 GripGestureManager *manager = (GripGestureManager *)user_data;
1255918
1256 g_signal_handlers_disconnect_by_func (widget,919 g_signal_handlers_disconnect_by_func (widget,
1257 G_CALLBACK (toplevel_notify_cb),920 G_CALLBACK (toplevel_notify_cb),
@@ -1259,30 +922,7 @@
1259922
1260 if (gtk_widget_is_toplevel (toplevel))923 if (gtk_widget_is_toplevel (toplevel))
1261 {924 {
1262 if (gtk_widget_get_mapped (GTK_WIDGET (toplevel)))925 register_toplevel_widget (manager, toplevel);
1263 {
1264 register_internal (req->manager,
1265 req->widget,
1266 req->gesture_type,
1267 req->device_type,
1268 req->touch_points,
1269 req->callback,
1270 req->user_data,
1271 req->destroy);
1272
1273 g_free (req);
1274 }
1275 else
1276 {
1277 GripGestureManagerPrivate *priv = req->manager->priv;
1278
1279 priv->requests = g_list_append (priv->requests, req);
1280
1281 g_signal_connect (toplevel,
1282 "map-event",
1283 G_CALLBACK (toplevel_mapped_cb),
1284 req->manager);
1285 }
1286 }926 }
1287 else927 else
1288 {928 {
@@ -1294,96 +934,29 @@
1294 }934 }
1295}935}
1296936
937
1297/*938/*
1298 * register_widget:939 * toplevel_mapped_cb:
1299 *940 *
1300 * Registers a specific widget for a specific gesture made by a specific input941 * A callback invoked when a toplevel widget with one or more pending gesture
1301 * device type.942 * registration requests has been mapped to a window.
1302 *943 *
1303 * If the widget's containing window is a valid window, the widget is registered944 * This callback will in fact process all pending registration requests for the
1304 * right away, otherwise the registration is deferred until the widget actually945 * newly-mapped window.
1305 * has a top-level window.
1306 */946 */
1307static void947static void
1308register_widget (GripGestureManager *manager,
1309 GtkWidget *widget,
1310 GripGestureType gesture_type,
1311 GripDeviceType device_type,
1312 gint touch_points,
1313 GripGestureCallback callback,
1314 gpointer user_data,
1315 GDestroyNotify destroy)
1316{
1317 GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
1318
1319 if (gtk_widget_is_toplevel (toplevel))
1320 {
1321 register_internal (manager,
1322 widget,
1323 gesture_type,
1324 device_type,
1325 touch_points,
1326 callback,
1327 user_data,
1328 destroy);
1329 }
1330 else
1331 {
1332 GripRegistrationRequest *req = g_new0 (GripRegistrationRequest, 1);
1333
1334 req->manager = manager;
1335 req->widget = widget;
1336 req->gesture_type = gesture_type;
1337 req->device_type = device_type;
1338 req->touch_points = touch_points;
1339 req->callback = callback;
1340 req->user_data = user_data;
1341 req->destroy = destroy;
1342
1343 g_signal_connect (toplevel,
1344 "notify",
1345 G_CALLBACK (toplevel_notify_cb),
1346 req);
1347 }
1348}
1349
1350static void
1351toplevel_mapped_cb (GtkWidget *toplevel,948toplevel_mapped_cb (GtkWidget *toplevel,
1352 GdkEvent *event G_GNUC_UNUSED,949 GdkEvent *event G_GNUC_UNUSED,
1353 gpointer user_data)950 gpointer user_data)
1354{951{
1355 GripGestureManager *manager = (GripGestureManager *)user_data;952 GripGestureManager *manager = (GripGestureManager *)user_data;
1356 GripGestureManagerPrivate *priv = manager->priv;953 register_mapped_window (manager, toplevel);
1357 GList *request = priv->requests;
1358
1359 while (request)
1360 {
1361 GList *next = request->next;
1362 GripRegistrationRequest *req = request->data;
1363
1364 if (gtk_widget_get_toplevel (req->widget) == toplevel)
1365 {
1366 register_widget (req->manager,
1367 req->widget,
1368 req->gesture_type,
1369 req->device_type,
1370 req->touch_points,
1371 req->callback,
1372 req->user_data,
1373 req->destroy);
1374
1375 priv->requests = g_list_remove_link (priv->requests, request);
1376 g_free (req);
1377 g_list_free_1 (request);
1378 }
1379 request = next;
1380 }
1381
1382 g_signal_handlers_disconnect_by_func (toplevel,954 g_signal_handlers_disconnect_by_func (toplevel,
1383 toplevel_mapped_cb,955 toplevel_mapped_cb,
1384 user_data);956 user_data);
1385}957}
1386958
959
1387/**960/**
1388 * grip_gesture_manager_register_window:961 * grip_gesture_manager_register_window:
1389 * @manager: A #GripGestureManager instance.962 * @manager: A #GripGestureManager instance.
@@ -1411,102 +984,47 @@
1411 gpointer user_data,984 gpointer user_data,
1412 GDestroyNotify destroy)985 GDestroyNotify destroy)
1413{986{
1414 GtkWidget *toplevel;
1415
1416 g_return_if_fail (GRIP_IS_GESTURE_MANAGER (manager));987 g_return_if_fail (GRIP_IS_GESTURE_MANAGER (manager));
1417 g_return_if_fail (GTK_IS_WIDGET (widget));988 g_return_if_fail (GTK_IS_WIDGET (widget));
1418989
1419 toplevel = gtk_widget_get_toplevel (widget);990 GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
991
992 GripRegistrationRequest *req = g_new0 (GripRegistrationRequest, 1);
993 req->manager = manager;
994 req->widget = widget;
995 req->gesture_type = gesture_type;
996 req->device_type = device_type;
997 req->touch_points = touch_points;
998 req->callback = callback;
999 req->user_data = user_data;
1000 req->destroy = destroy;
1001 manager->priv->requests = g_list_append (manager->priv->requests, req);
14201002
1421 if (GTK_IS_WINDOW (toplevel))1003 if (GTK_IS_WINDOW (toplevel))
1422 {1004 {
1423 if (gtk_widget_get_mapped (GTK_WIDGET (toplevel)))1005 register_toplevel_widget (manager, toplevel);
1424 {
1425 register_internal (manager,
1426 widget,
1427 gesture_type,
1428 device_type,
1429 touch_points,
1430 callback,
1431 user_data,
1432 destroy);
1433 }
1434 else
1435 {
1436 GripRegistrationRequest *req = g_new0 (GripRegistrationRequest, 1);
1437 GripGestureManagerPrivate *priv = manager->priv;
1438
1439 req->manager = manager;
1440 req->widget = widget;
1441 req->gesture_type = gesture_type;
1442 req->device_type = device_type;
1443 req->touch_points = touch_points;
1444 req->callback = callback;
1445 req->user_data = user_data;
1446 req->destroy = destroy;
1447
1448 priv->requests = g_list_append (priv->requests, req);
1449
1450 g_signal_connect (toplevel,
1451 "map-event",
1452 G_CALLBACK (toplevel_mapped_cb),
1453 manager);
1454 }
1455 }1006 }
1456 else1007 else
1457 {1008 {
1458 GripRegistrationRequest *req = g_new0 (GripRegistrationRequest, 1);
1459
1460 req->manager = manager;
1461 req->widget = widget;
1462 req->gesture_type = gesture_type;
1463 req->device_type = device_type;
1464 req->touch_points = touch_points;
1465 req->callback = callback;
1466 req->user_data = user_data;
1467 req->destroy = destroy;
1468
1469 g_signal_connect (toplevel,1009 g_signal_connect (toplevel,
1470 "notify",1010 "notify",
1471 G_CALLBACK (toplevel_notify_cb),1011 G_CALLBACK (toplevel_notify_cb),
1472 req);1012 manager);
1473 }1013 }
1474}1014}
14751015
1476static void
1477shutdown_registration(GripGestureRegistration *reg)
1478{
1479 free_registration(reg);
1480 geis_finish(reg->instance);
1481 reg->instance = NULL;
1482 g_free(reg);
1483}
14841016
1485void1017void
1486grip_gesture_manager_unregister_window (GripGestureManager *manager,1018grip_gesture_manager_unregister_window (GripGestureManager *manager G_GNUC_UNUSED,
1487 GtkWidget *toplevel)1019 GtkWidget *toplevel G_GNUC_UNUSED)
1488{1020{
1489 GripGestureManagerPrivate *priv = manager->priv;
1490 struct Registrations *registrations;
1491
1492 g_return_if_fail (GRIP_IS_GESTURE_MANAGER (manager));1021 g_return_if_fail (GRIP_IS_GESTURE_MANAGER (manager));
1493 g_return_if_fail (GTK_IS_WINDOW (toplevel));1022 g_return_if_fail (GTK_IS_WINDOW (toplevel));
14941023
1495 /* Currently only allow unsubscribing after the window has been shown. */1024 window_destroyed_cb (toplevel, manager);
1496 g_return_if_fail (gtk_widget_get_mapped (GTK_WIDGET (toplevel)));
1497 registrations = g_hash_table_lookup (priv->registered_windows, toplevel);
1498 if (!registrations) {
1499 return;
1500 }
1501
1502 shutdown_registration(registrations->touchscreen);
1503 shutdown_registration(registrations->touchpad);
1504 shutdown_registration(registrations->independent);
1505 g_free(registrations);
1506 g_hash_table_remove(priv->registered_windows, toplevel);
1507
1508}1025}
15091026
1027
1510GType1028GType
1511grip_gesture_event_get_type (void)1029grip_gesture_event_get_type (void)
1512{1030{
15131031
=== modified file 'src/gripinputdevice.c'
--- src/gripinputdevice.c 2011-10-19 14:05:35 +0000
+++ src/gripinputdevice.c 2013-04-17 15:02:24 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright 2011 Canonical, Ltd.2 * Copyright 2011, 2013 Canonical Ltd.
3 *3 *
4 * This program is free software: you can redistribute it and/or modify it4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of either or both of the following licenses:5 * under the terms of either or both of the following licenses:
@@ -79,53 +79,61 @@
79 for (a = attrs; a->name; a++)79 for (a = attrs; a->name; a++)
80 {80 {
81 if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_NAME))81 if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_NAME))
82 {
83 input_device->priv->name = g_strdup (a->string_val);82 input_device->priv->name = g_strdup (a->string_val);
84 }
85 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_ID))83 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_ID))
86 {
87 input_device->priv->device_id = a->integer_val;84 input_device->priv->device_id = a->integer_val;
88 }
89 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_TOUCHES))85 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_TOUCHES))
90 {
91 input_device->priv->touches = a->integer_val;86 input_device->priv->touches = a->integer_val;
92 }
93 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH))87 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH))
94 {
95 input_device->priv->is_direct = a->boolean_val;88 input_device->priv->is_direct = a->boolean_val;
96 }
97 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH))89 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH))
98 {
99 input_device->priv->is_independent = a->boolean_val;90 input_device->priv->is_independent = a->boolean_val;
100 }
101 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_MIN_X))91 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_MIN_X))
102 {
103 input_device->priv->x_extents.minimum = a->float_val;92 input_device->priv->x_extents.minimum = a->float_val;
104 }
105 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_MAX_X))93 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_MAX_X))
106 {
107 input_device->priv->x_extents.maximum = a->float_val;94 input_device->priv->x_extents.maximum = a->float_val;
108 }
109 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_RES_X))95 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_RES_X))
110 {
111 input_device->priv->x_extents.resolution = a->float_val;96 input_device->priv->x_extents.resolution = a->float_val;
112 }
113 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_MIN_Y))97 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_MIN_Y))
114 {
115 input_device->priv->y_extents.minimum = a->float_val;98 input_device->priv->y_extents.minimum = a->float_val;
116 }
117 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_MAX_Y))99 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_MAX_Y))
118 {
119 input_device->priv->y_extents.maximum = a->float_val;100 input_device->priv->y_extents.maximum = a->float_val;
120 }
121 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_RES_Y))101 else if (0 == g_strcmp0 (a->name, GEIS_DEVICE_ATTRIBUTE_RES_Y))
122 {
123 input_device->priv->y_extents.resolution = a->float_val;102 input_device->priv->y_extents.resolution = a->float_val;
124 }
125 }103 }
126 }104 }
127 }105 }
128 }106 }
107 else
108 {
109 guint num_attrs = geis_device_attr_count(input_device->priv->geis_device);
110 for (i = 0; i < num_attrs; ++i)
111 {
112 GeisAttr attr = geis_device_attr(input_device->priv->geis_device, i);
113 if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_NAME))
114 input_device->priv->name = g_strdup (geis_attr_value_to_string(attr));
115 else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_ID))
116 input_device->priv->device_id = geis_attr_value_to_integer(attr);
117 else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_TOUCHES))
118 input_device->priv->touches = geis_attr_value_to_integer(attr);
119 else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH))
120 input_device->priv->is_direct = geis_attr_value_to_boolean(attr);
121 else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH))
122 input_device->priv->is_independent = geis_attr_value_to_boolean(attr);
123 else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_MIN_X))
124 input_device->priv->x_extents.minimum = geis_attr_value_to_float(attr);
125 else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_MAX_X))
126 input_device->priv->x_extents.maximum = geis_attr_value_to_float(attr);
127 else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_RES_X))
128 input_device->priv->x_extents.resolution = geis_attr_value_to_float(attr);
129 else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_MIN_Y))
130 input_device->priv->y_extents.minimum = geis_attr_value_to_float(attr);
131 else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_MAX_Y))
132 input_device->priv->y_extents.maximum = geis_attr_value_to_float(attr);
133 else if (0 == g_strcmp0 (geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_RES_Y))
134 input_device->priv->y_extents.resolution = geis_attr_value_to_float(attr);
135 }
136 }
129137
130 return object;138 return object;
131}139}

Subscribers

People subscribed via source and target branches