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

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

Commit message

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

Description of the change

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

Original description of change on trunk:

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

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

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

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

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

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

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

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

Used g_list_free_full() to free a GList

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

+1

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

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-05-14 18:50:33 +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,17 @@
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_free_full (priv->classes, g_free);
310 {291
311 g_hash_table_foreach (priv->registered_windows,292 g_ptr_array_foreach (priv->devices, (GFunc) g_object_unref, NULL);
312 free_registration_adapter,293 g_ptr_array_unref (priv->devices);
313 NULL);
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}294}
322295
296
323static GObject *297static GObject *
324grip_gesture_manager_constructor (GType type,298grip_gesture_manager_constructor (GType type,
325 guint n_params,299 guint n_params,
@@ -332,12 +306,12 @@
332 self = G_OBJECT_CLASS (grip_gesture_manager_parent_class)->306 self = G_OBJECT_CLASS (grip_gesture_manager_parent_class)->
333 constructor (type, n_params, params);307 constructor (type, n_params, params);
334 g_object_add_weak_pointer (self, (gpointer) &self);308 g_object_add_weak_pointer (self, (gpointer) &self);
335 grip_get_devices (GRIP_GESTURE_MANAGER (self));
336 }309 }
337310
338 return g_object_ref (self);311 return g_object_ref (self);
339}312}
340313
314
341static void315static void
342grip_gesture_manager_class_init (GripGestureManagerClass *class)316grip_gesture_manager_class_init (GripGestureManagerClass *class)
343{317{
@@ -386,7 +360,6 @@
386 G_TYPE_NONE,360 G_TYPE_NONE,
387 1,361 1,
388 GRIP_TYPE_INPUT_DEVICE);362 GRIP_TYPE_INPUT_DEVICE);
389
390}363}
391364
392365
@@ -420,592 +393,306 @@
420 return input_device;393 return input_device;
421}394}
422395
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
453396
454static gint397static gint
455pinch_gesture_handle_properties (GripEventGesturePinch *event,398pinch_gesture_handle_properties (GripEventGesturePinch *event,
456 GeisSize attr_count,399 GeisFrame frame)
457 GeisGestureAttr *attrs)
458{400{
459 guint i = 0;401 guint attr_count = geis_frame_attr_count (frame);
460 gint touches = 0;402 gint num_touches = 0;
461403 guint i;
462 for (i = 0; i < attr_count; ++i)404 for (i = 0; i < attr_count; ++i)
463 {405 {
464 if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0 &&406 GeisAttr attr = geis_frame_attr(frame, i);
465 attrs[i].type == GEIS_ATTR_TYPE_INTEGER)407 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 }
510408
511 return touches;409 if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0)
410 num_touches = geis_attr_value_to_integer(attr);
411 if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0)
412 event->timestamp = geis_attr_value_to_integer(attr);
413 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0)
414 event->focus_x = geis_attr_value_to_float(attr);
415 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0)
416 event->focus_y = geis_attr_value_to_float(attr);
417 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA) == 0)
418 event->radius_delta = geis_attr_value_to_float(attr);
419 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_RADIAL_VELOCITY) == 0)
420 event->radial_velocity = geis_attr_value_to_float(attr);
421 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_RADIUS) == 0)
422 event->radius = geis_attr_value_to_float(attr);
423 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0)
424 event->position_x = geis_attr_value_to_float(attr);
425 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0)
426 event->position_y = geis_attr_value_to_float(attr);
427 }
428 return num_touches;
512}429}
513430
514static gint431static gint
515drag_gesture_handle_properties (GripEventGestureDrag *event,432drag_gesture_handle_properties (GripEventGestureDrag *event,
516 GeisSize attr_count,433 GeisFrame frame)
517 GeisGestureAttr *attrs)
518{434{
435 guint attr_count = geis_frame_attr_count (frame);
436 gint num_touches = 0;
519 guint i;437 guint i;
520 gint touches = 0;
521
522 for (i = 0; i < attr_count; ++i)438 for (i = 0; i < attr_count; ++i)
523 {439 {
524 if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0 &&440 GeisAttr attr = geis_frame_attr(frame, i);
525 attrs[i].type == GEIS_ATTR_TYPE_INTEGER)441 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 }
575442
576 return touches;443 if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0)
444 num_touches = geis_attr_value_to_integer(attr);
445 if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0)
446 event->timestamp = geis_attr_value_to_integer(attr);
447 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0)
448 event->focus_x = geis_attr_value_to_float(attr);
449 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0)
450 event->focus_y = geis_attr_value_to_float(attr);
451 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_DELTA_X) == 0)
452 event->delta_x = geis_attr_value_to_float(attr);
453 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_DELTA_Y) == 0)
454 event->delta_y = geis_attr_value_to_float(attr);
455 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_X) == 0)
456 event->velocity_x = geis_attr_value_to_float(attr);
457 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y) == 0)
458 event->velocity_y = geis_attr_value_to_float(attr);
459 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0)
460 event->position_x = geis_attr_value_to_float(attr);
461 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0)
462 event->position_y = geis_attr_value_to_float(attr);
463 }
464 return num_touches;
577}465}
578466
467
579static gint468static gint
580rotate_gesture_handle_properties (GripEventGestureRotate *event,469rotate_gesture_handle_properties (GripEventGestureRotate *event,
581 GeisSize attr_count,470 GeisFrame frame)
582 GeisGestureAttr *attrs)
583{471{
472 guint attr_count = geis_frame_attr_count (frame);
473 gint num_touches = 0;
584 guint i;474 guint i;
585 gint touches = 0;
586
587 for (i = 0; i < attr_count; ++i)475 for (i = 0; i < attr_count; ++i)
588 {476 {
589 if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0 &&477 GeisAttr attr = geis_frame_attr(frame, i);
590 attrs[i].type == GEIS_ATTR_TYPE_INTEGER)478 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 }
635479
636 return touches;480 if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0)
481 num_touches = geis_attr_value_to_integer(attr);
482 if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0)
483 event->timestamp = geis_attr_value_to_integer(attr);
484 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0)
485 event->focus_x = geis_attr_value_to_float(attr);
486 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0)
487 event->focus_y = geis_attr_value_to_float(attr);
488 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA) == 0)
489 event->angle_delta = geis_attr_value_to_float(attr);
490 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_ANGULAR_VELOCITY) == 0)
491 event->angular_velocity = geis_attr_value_to_float(attr);
492 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_ANGLE) == 0)
493 event->angle = geis_attr_value_to_float(attr);
494 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0)
495 event->position_x = geis_attr_value_to_float(attr);
496 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0)
497 event->position_y = geis_attr_value_to_float(attr);
498 }
499 return num_touches;
637}500}
638501
502
639static gint503static gint
640tap_gesture_handle_properties (GripEventGestureTap *event,504tap_gesture_handle_properties (GripEventGestureTap *event,
641 GeisSize attr_count,505 GeisFrame frame)
642 GeisGestureAttr *attrs)
643{506{
507 guint attr_count = geis_frame_attr_count (frame);
508 gint num_touches = 0;
644 guint i;509 guint i;
645 gint touches = 0;
646
647 for (i = 0; i < attr_count; ++i)510 for (i = 0; i < attr_count; ++i)
648 {511 {
649 if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0 &&512 GeisAttr attr = geis_frame_attr(frame, i);
650 attrs[i].type == GEIS_ATTR_TYPE_INTEGER)513 GeisString attr_name = geis_attr_name(attr);
651 {514
652 touches = attrs[i].integer_val;515 if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TOUCHES) == 0)
653 }516 num_touches = geis_attr_value_to_integer(attr);
654 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0 &&517 if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP) == 0)
655 attrs[i].type == GEIS_ATTR_TYPE_INTEGER)518 event->timestamp = geis_attr_value_to_integer(attr);
656 {519 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) == 0)
657 event->timestamp = attrs[i].integer_val;520 event->focus_x = geis_attr_value_to_float(attr);
658 }521 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 &&522 event->focus_y = geis_attr_value_to_float(attr);
660 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)523 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0)
661 {524 event->position_x = geis_attr_value_to_float(attr);
662 event->focus_x = attrs[i].float_val;525 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0)
663 }526 event->position_y = geis_attr_value_to_float(attr);
664 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y) == 0 &&527 else if (g_strcmp0 (attr_name, GEIS_GESTURE_ATTRIBUTE_TAP_TIME) == 0)
665 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)528 event->tap_time = geis_attr_value_to_float(attr);
666 {529 }
667 event->focus_y = attrs[i].float_val;530 return num_touches;
668 }531}
669 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_X) == 0 &&532
670 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)533
671 {534static void
672 event->position_x = attrs[i].float_val;535process_gesture_events(GripGestureManager *manager, GeisEvent geis_event)
673 }536{
674 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y) == 0 &&537 GripGestureManagerPrivate *priv = manager->priv;
675 attrs[i].type == GEIS_ATTR_TYPE_FLOAT)538
676 {539 GripTimeType time_type = GRIP_TIME_UPDATE;
677 event->position_y = attrs[i].float_val;540 if (geis_event_type(geis_event) == GEIS_EVENT_GESTURE_BEGIN)
678 }541 time_type = GRIP_TIME_START;
679 else if (g_strcmp0 (attrs[i].name, GEIS_GESTURE_ATTRIBUTE_TAP_TIME) == 0 &&542 else if (geis_event_type(geis_event) == GEIS_EVENT_GESTURE_END)
680 attrs[i].type == GEIS_ATTR_TYPE_INTEGER)543 time_type = GRIP_TIME_END;
681 {544
682 event->tap_time = attrs[i].float_val;545 GeisAttr attr = geis_event_attr_by_name (geis_event, GEIS_EVENT_ATTRIBUTE_GROUPSET);
683 }546 g_return_if_fail (attr);
684 }547
685548 GeisGroupSet groupset = geis_attr_value_to_pointer (attr);
686 return touches;549 g_return_if_fail (groupset);
687}550
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;551 GeisSize i;
749552 for (i = 0; i < geis_groupset_group_count (groupset); ++i)
750 for (i = 0; i < attr_count; ++i)553 {
751 {554 GeisGroup group = geis_groupset_group (groupset, i);
752 if (0 == g_strcmp0(attrs[i].name, GEIS_GESTURE_ATTRIBUTE_DEVICE_ID))555 g_return_if_fail (group);
753 {556
754 input_device = device_id_to_input_device(manager, attrs[i].integer_val);557 GeisSize j;
755 }558 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))559 {
757 {560 GeisFrame frame = geis_group_frame(group, j);
758 GHashTableIter iter;561 g_return_if_fail (frame);
759 GtkWidget *key;562
760 struct Registrations *value;563 GeisAttr window_attr = geis_frame_attr_by_name(frame, GEIS_GESTURE_ATTRIBUTE_EVENT_WINDOW_ID);
761 guint window_id = attrs[i].integer_val;564 guint window_id = geis_attr_value_to_integer(window_attr);
762565
763 g_hash_table_iter_init (&iter, manager->priv->registered_windows);566 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)) 567 guint device_id = geis_attr_value_to_integer(device_attr);
765 {568 GripInputDevice *input_device = device_id_to_input_device (manager, device_id);
766 if (GDK_WINDOW_XID (gtk_widget_get_window (key)) == window_id)569
767 {570 GList *l;
768 gtk_window = (GtkWindow *)key;571 for (l = priv->bindings; l != NULL; l = l->next)
769 break;572 {
770 }573 GripGestureBinding *binding = (GripGestureBinding *)l->data;
771 }574 guint widget_window_id = GDK_WINDOW_XID (gtk_widget_get_window (binding->widget));
772 }575 if (widget_window_id == window_id)
773 }576 {
774 g_return_if_fail(input_device != NULL);577 GList *class_list;
775 g_return_if_fail(gtk_window != NULL);578 for (class_list = priv->classes; class_list != NULL; class_list = class_list->next)
776579 {
777 registrations = g_hash_table_lookup (manager->priv->registered_windows, gtk_window);580 GripGestureClassMap *p = (GripGestureClassMap *)class_list->data;
778 g_return_if_fail(registrations != NULL);581 if (p->grip_type == binding->type)
779 reg = registration_for_input_device (registrations, input_device);582 {
780 g_return_if_fail(reg != NULL);583 if (geis_frame_is_class(frame, p->geis_class))
781584 {
782 for (l = reg->bindings; l != NULL; l = l->next)585 GripGestureEvent *grip_event = grip_gesture_event_new (p->grip_type);
783 {586 if (p->grip_type == GRIP_GESTURE_DRAG)
784 GripGestureBinding *binding = (GripGestureBinding *)l->data;587 {
785588 GripEventGestureDrag *drag = (GripEventGestureDrag *)grip_event;
786 if (binding->type == type)589 drag->type = p->grip_type;
787 {590 drag->id = geis_frame_id(frame);
788 GripGestureEvent *event = grip_gesture_event_new (type);591 drag->input_device = input_device;
789592 drag->fingers = drag_gesture_handle_properties (drag, frame);
790 if (type == GRIP_GESTURE_DRAG)593 binding->callback (binding->widget,
791 {594 time_type,
792 GripEventGestureDrag *drag = (GripEventGestureDrag *)event;595 grip_event,
793596 binding->data);
794 drag->type = type;597 }
795 drag->id = id;598 else if (p->grip_type == GRIP_GESTURE_PINCH)
796 drag->input_device = input_device;599 {
797 drag->fingers = drag_gesture_handle_properties (drag,600 GripEventGesturePinch *pinch = (GripEventGesturePinch *)grip_event;
798 attr_count,601 pinch->type = p->grip_type;
799 attrs);602 pinch->id = geis_frame_id(frame);
800603 pinch->input_device = input_device;
801 if (drag->fingers == (gint)binding->touches)604 pinch->fingers = pinch_gesture_handle_properties (pinch, frame);
802 {605 binding->callback (binding->widget,
803 if (matches_widget (binding->widget,606 time_type,
804 gtk_widget_get_window(GTK_WIDGET (reg->window)),607 grip_event,
805 (gint)drag->focus_x,608 binding->data);
806 (gint)drag->focus_y))609 }
807 {610 else if (p->grip_type == GRIP_GESTURE_ROTATE)
808 binding->callback (binding->widget,611 {
809 time_type,612 GripEventGestureRotate *rotate = (GripEventGestureRotate *)grip_event;
810 event,613 rotate->type = p->grip_type;
811 binding->data);614 rotate->id = geis_frame_id(frame);
812 }615 rotate->input_device = input_device;
813 }616 rotate->fingers = rotate_gesture_handle_properties (rotate, frame);
814 }617 binding->callback (binding->widget,
815 else if (type == GRIP_GESTURE_PINCH)618 time_type,
816 {619 grip_event,
817 GripEventGesturePinch *pinch = (GripEventGesturePinch *)event;620 binding->data);
818621 }
819 pinch->type = type;622 else if (p->grip_type == GRIP_GESTURE_TAP)
820 pinch->id = id;623 {
821 pinch->input_device = input_device;624 GripEventGestureTap *tap = (GripEventGestureTap *)grip_event;
822 pinch->fingers = pinch_gesture_handle_properties (pinch,625 tap->type = p->grip_type;
823 attr_count,626 tap->id = geis_frame_id(frame);
824 attrs);627 tap->input_device = input_device;
825628 tap->fingers = tap_gesture_handle_properties (tap, frame);
826 if (pinch->fingers == binding->touches)629 binding->callback (binding->widget,
827 {630 time_type,
828 if (matches_widget (binding->widget,631 grip_event,
829 gtk_widget_get_window(GTK_WIDGET (reg->window)),632 binding->data);
830 (gint)pinch->focus_x,633 }
831 (gint)pinch->focus_y))634 grip_gesture_event_free (grip_event);
832 {635 }
833 binding->callback (binding->widget,636 }
834 time_type,637 }
835 event,638 }
836 binding->data);639 }
837 }640 }
838 }641 }
839 }642}
840 else if (type == GRIP_GESTURE_ROTATE)643
841 {644
842 GripEventGestureRotate *rotate = (GripEventGestureRotate *)event;645static gboolean
843646grip_geis_event_ready (GIOChannel *source G_GNUC_UNUSED,
844 rotate->type = type;647 GIOCondition condition G_GNUC_UNUSED,
845 rotate->id = id;648 gpointer context)
846 rotate->input_device = input_device;649{
847 rotate->fingers = rotate_gesture_handle_properties (rotate,650 Geis geis = (Geis)context;
848 attr_count,651 GeisStatus status G_GNUC_UNUSED = geis_dispatch_events(geis);
849 attrs);652 return TRUE;
850653}
851 if (rotate->fingers == binding->touches)654
852 {655
853 if (matches_widget (binding->widget,656static void
854 gtk_widget_get_window(GTK_WIDGET (reg->window)),657grip_gesture_manager_init (GripGestureManager *self)
855 (gint)rotate->focus_x,658{
856 (gint)rotate->focus_y))659 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 ();660 priv->devices = g_ptr_array_new ();
936}661
937662 priv->geis = geis_new (GEIS_INIT_TRACK_DEVICES, GEIS_INIT_TRACK_GESTURE_CLASSES, NULL);
938static gboolean663 g_return_if_fail (priv->geis);
939io_callback (GIOChannel *source G_GNUC_UNUSED,664
940 GIOCondition condition G_GNUC_UNUSED,665 int fd;
941 gpointer data)666 geis_get_configuration(priv->geis, GEIS_CONFIGURATION_FD, &fd);
942{667 priv->iochannel = g_io_channel_unix_new (fd);
943 GripGestureRegistration *reg = (GripGestureRegistration *)data;668 priv->iochannel_id = g_io_add_watch (priv->iochannel, G_IO_IN, grip_geis_event_ready, priv->geis);
944669 geis_register_device_callback (priv->geis, grip_geis_event_callback, self);
945 geis_event_dispatch (reg->instance);670 geis_register_class_callback (priv->geis, grip_geis_event_callback, self);
946671 geis_register_event_callback (priv->geis, grip_geis_event_callback, self);
947 return TRUE;672}
948}673
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}
980674
981static void675static void
982window_destroyed_cb (GtkWidget *object,676window_destroyed_cb (GtkWidget *object,
983 gpointer user_data)677 gpointer user_data)
984{678{
985 GripGestureManager *manager = (GripGestureManager *)user_data;679 GripGestureManager *manager = (GripGestureManager *)user_data;
986 GripGestureManagerPrivate *priv = manager->priv;680 GList *l = manager->priv->bindings;
987 struct Registrations *reg = g_hash_table_lookup (priv->registered_windows, object);681 while (l != NULL)
988682 {
989 if (!reg)683 GList *next = l->next;
990 return;684 GripGestureBinding *binding = l->data;
991685 if (gtk_widget_get_toplevel (binding->widget) == object)
992 destroy_registration(reg->touchpad);686 {
993 destroy_registration(reg->touchscreen);687 geis_subscription_delete (binding->subscription);
994 destroy_registration(reg->independent);688
995689 if (binding->destroy)
996 g_hash_table_remove (priv->registered_windows, object);690 binding->destroy (binding->data);
997 g_free (reg);691 g_free (binding);
998}692 manager->priv->bindings = g_list_delete_link (manager->priv->bindings, l);
999693 }
1000static const gchar *694 l = next;
1001grip_type_to_geis_type (GripGestureType gesture_type,695 }
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}696}
1010697
1011698
@@ -1017,232 +704,207 @@
1017}704}
1018705
1019706
707/*
708 * processed_mapped_window_request:
709 * @reg: a #GripRegistrationRequest (removed from the GripGestureManager
710 * requests listand freed).
711 *
712 * Creates a subscription for a widget mapped to a window.
713 */
1020static void714static void
1021grip_devices_for_type (GripDeviceType type, GArray *selection,715processed_mapped_window_request (GripRegistrationRequest *req)
1022 GripDevices *devices)
1023{716{
1024 guint i;717 g_return_if_fail (GRIP_IS_GESTURE_MANAGER (req->manager));
1025718 g_return_if_fail (GTK_IS_WIDGET (req->widget));
1026 for (i = 0; i < devices->len; ++i)719
720 GtkWidget *toplevel = gtk_widget_get_toplevel (req->widget);
721 g_return_if_fail (GTK_IS_WINDOW (toplevel));
722
723 GripGestureManagerPrivate *priv = req->manager->priv;
724
725 guint window_id = GDK_WINDOW_XID (gtk_widget_get_window(req->widget));
726
727 /* XXX - check for duplicates in reg->bindings first */
728 GripGestureBinding *binding = g_new0 (GripGestureBinding, 1);
729 binding->type = req->gesture_type;
730 binding->widget = req->widget;
731 binding->touches = req->touch_points;
732 binding->callback = req->callback;
733 binding->data = req->user_data;
734 binding->destroy = req->destroy;
735
736 char sub_name[48];
737 snprintf(sub_name, 48, "sub-%x-%x-%x", window_id, req->gesture_type, req->touch_points);
738 binding->subscription = geis_subscription_new (priv->geis, sub_name, GEIS_SUBSCRIPTION_CONT);
739 g_return_if_fail (binding->subscription);
740
741 char filter_id[20];
742 snprintf(filter_id, 20, "grip-%x", window_id);
743 GeisFilter window_filter = geis_filter_new(priv->geis, filter_id);
744 geis_filter_add_term(window_filter, GEIS_FILTER_REGION,
745 GEIS_REGION_ATTRIBUTE_WINDOWID, GEIS_FILTER_OP_EQ, window_id,
746 NULL);
747
748 switch (req->gesture_type)
1027 {749 {
1028 GripInputDevice *input_device = g_ptr_array_index (devices, i);750 case GRIP_GESTURE_DRAG:
1029 GeisInputDeviceId id = grip_input_device_get_id (input_device);751 geis_filter_add_term(window_filter, GEIS_FILTER_CLASS,
1030 GripDeviceType device_type= grip_get_device_type(input_device);752 GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_DRAG,
1031753 GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, req->touch_points,
1032 if ((type & GRIP_DEVICE_TOUCHSCREEN) && device_type == GRIP_DEVICE_TOUCHSCREEN)754 NULL);
1033 {755 break;
1034 g_array_append_val (selection, id);756 case GRIP_GESTURE_PINCH:
1035 }757 geis_filter_add_term(window_filter, GEIS_FILTER_CLASS,
1036 if ((type & GRIP_DEVICE_TOUCHPAD) && device_type == GRIP_DEVICE_TOUCHPAD)758 GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_PINCH,
1037 {759 GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, req->touch_points,
1038 g_array_append_val (selection, id);760 NULL);
1039 }761 break;
1040 if ((type & GRIP_DEVICE_INDEPENDENT) && device_type == GRIP_DEVICE_INDEPENDENT)762 case GRIP_GESTURE_ROTATE:
1041 {763 geis_filter_add_term(window_filter, GEIS_FILTER_CLASS,
1042 g_array_append_val (selection, id);764 GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_ROTATE,
1043 }765 GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, req->touch_points,
766 NULL);
767 break;
768 case GRIP_GESTURE_TAP:
769 geis_filter_add_term(window_filter, GEIS_FILTER_CLASS,
770 GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_TAP,
771 GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, req->touch_points,
772 NULL);
773 break;
1044 }774 }
1045}775
1046776 if (req->device_type & GRIP_DEVICE_TOUCHSCREEN)
1047/*777 {
1048 * new_window_registration:778 char filter_name[32];
1049 * @manager: a GripGestureManager779 snprintf(filter_name, 32, "%s/touchscreen", filter_id);
1050 * @toplevel: a toplevel #GtkWindow780 GeisFilter touchscreen_filter = geis_filter_clone (window_filter, filter_name);
1051 *781 geis_filter_add_term(touchscreen_filter, GEIS_FILTER_DEVICE,
1052 * Constructs a new #GripGestureRegistration for a #GtkWidget.782 GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_FILTER_OP_EQ, GEIS_TRUE,
1053 */783 NULL);
1054static GripGestureRegistration *784 GeisStatus status = geis_subscription_add_filter(binding->subscription, touchscreen_filter);
1055new_window_registration(GripGestureManager *manager,785 g_return_if_fail (status == GEIS_STATUS_SUCCESS);
1056 GtkWidget *toplevel)786 }
1057{787 if (req->device_type & GRIP_DEVICE_TOUCHPAD)
1058 GripGestureRegistration *reg;788 {
1059 GeisInstance instance;789 char filter_name[32];
1060 gint fd = -1;790 snprintf(filter_name, 32, "%s/touchpad", filter_id);
1061 GeisXcbWinInfo xcb_win_info = {791 GeisFilter touchpad_filter = geis_filter_clone (window_filter, filter_name);
1062 .display_name = NULL,792 geis_filter_add_term(touchpad_filter, GEIS_FILTER_DEVICE,
1063 .screenp = NULL,793 GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_FILTER_OP_EQ, GEIS_FALSE,
1064 .window_id = GDK_WINDOW_XID (gtk_widget_get_window(toplevel))794 NULL);
1065 };795 GeisStatus status = geis_subscription_add_filter(binding->subscription, touchpad_filter);
1066 GeisWinInfo win_info = {796 g_return_if_fail (status == GEIS_STATUS_SUCCESS);
1067 GEIS_XCB_FULL_WINDOW,797 }
1068 &xcb_win_info798 if (req->device_type & GRIP_DEVICE_INDEPENDENT)
1069 };799 {
1070800 char filter_name[32];
1071 if (geis_init (&win_info, &instance) != GEIS_STATUS_SUCCESS)801 snprintf(filter_name, 32, "%s/indep", filter_id);
1072 {802 GeisFilter indep_filter = geis_filter_clone (window_filter, filter_name);
1073 g_warning ("Failed to initialize gesture manager.");803 geis_filter_add_term(indep_filter, GEIS_FILTER_DEVICE,
1074 return NULL;804 GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH, GEIS_FILTER_OP_EQ, GEIS_TRUE,
1075 }805 NULL);
1076806 GeisStatus status = geis_subscription_add_filter(binding->subscription, indep_filter);
1077 if (geis_configuration_supported (instance,807 g_return_if_fail (status == GEIS_STATUS_SUCCESS);
1078 GEIS_CONFIG_UNIX_FD) != GEIS_STATUS_SUCCESS)808 }
1079 {809
1080 g_warning ("Gesture manager does not support UNIX fd.");810 /*
1081 return NULL;811 * If any device types were specified, the window_filter was cloned and needs
1082 }812 * to be disposed of, otehrwise it's _the_ filter.
1083813 */
1084 if (geis_configuration_get_value (instance,814 if (req->device_type)
1085 GEIS_CONFIG_UNIX_FD,815 {
1086 &fd) != GEIS_STATUS_SUCCESS)816 geis_filter_delete(window_filter);
1087 {817 }
1088 g_error ("Gesture manager failed to obtain UNIX fd.");818 else
1089 return NULL;819 {
1090 }820 GeisStatus status = geis_subscription_add_filter(binding->subscription, window_filter);
1091821 g_return_if_fail (status == GEIS_STATUS_SUCCESS);
1092 reg = g_new0 (GripGestureRegistration, 1);822 }
1093823
1094 reg->window = GTK_WINDOW (toplevel);824
1095 reg->instance = instance;825 GeisStatus status = geis_subscription_activate (binding->subscription);
826 g_return_if_fail (status == GEIS_STATUS_SUCCESS);
827
828 priv->bindings = g_list_append (priv->bindings, binding);
1096829
1097 g_signal_connect (toplevel,830 g_signal_connect (toplevel,
1098 "destroy",831 "destroy",
1099 G_CALLBACK (window_destroyed_cb),832 G_CALLBACK (window_destroyed_cb),
1100 manager);833 req->manager);
1101834
1102 reg->iochannel = g_io_channel_unix_new (fd);835 /* remove the request from the watch list */
1103 reg->iochannel_id = g_io_add_watch (reg->iochannel,836 g_free (req);
1104 G_IO_IN,837 priv->requests = g_list_remove (priv->requests, req);
1105 io_callback,838}
1106 reg);839
1107 reg->gesture_list = g_ptr_array_new ();840
1108841/*
1109 return reg;842 * register_mapped_window:
1110}843 * @manager: a Grip gesture manager object
1111844 * @toplevel: a top-level widget
1112static void845 *
1113bind_registration(GripGestureManager *manager,846 * Processes all subscriptions requests for a newly-mapped window.
1114 GripGestureRegistration *reg,847 */
1115 GtkWidget *widget,848static void
1116 GripGestureType gesture_type,849register_mapped_window (GripGestureManager *manager, GtkWidget *toplevel)
1117 GripDeviceType device_type,850{
1118 gint touch_points,851 g_return_if_fail (gtk_widget_is_toplevel (toplevel));
1119 GripGestureCallback callback,852
1120 gpointer user_data,853 GList *pending_request = manager->priv->requests;
1121 GDestroyNotify destroy)854 while (pending_request)
1122{855 {
1123 GripGestureManagerPrivate *priv;856 GList *next = pending_request->next;
1124 GripGestureBinding *binding;857 GripRegistrationRequest *req = pending_request->data;
1125 GArray *devices;858
1126859 if (gtk_widget_get_toplevel (req->widget) == toplevel)
1127 priv = manager->priv;860 {
1128861 processed_mapped_window_request (req);
1129 if (reg->gesture_list->len)862 }
1130 g_ptr_array_remove_index (reg->gesture_list,863 pending_request = next;
1131 reg->gesture_list->len - 1);864 }
1132865}
1133 devices = g_array_new (TRUE, FALSE, sizeof(GeisInputDeviceId));866
1134 grip_devices_for_type(device_type, devices, priv->devices);867
1135 if (devices->len == 0) {868/*
1136 g_array_free(devices, TRUE);869 * register_toplevel_widget:
1137 return;870 * @manager: a Grip gesture manager object
1138 }871 * @toplevel: a top-level widget
1139872 *
1140 g_ptr_array_add (reg->gesture_list,873 * 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));874 *
1142 g_ptr_array_add (reg->gesture_list,875 * If the top-level widget is mapped to a window, it;s handled right away.
1143 NULL);876 * Otherwise, a callback is queued for when it does become mapped to a window.
1144877 */
1145 geis_subscribe (reg->instance,878static void
1146 (GeisInputDeviceId *)(void *)devices->data,879register_toplevel_widget (GripGestureManager *manager, GtkWidget *toplevel)
1147 (const char**)reg->gesture_list->pdata,880{
1148 &gesture_funcs,881 g_return_if_fail (gtk_widget_is_toplevel (toplevel));
1149 manager);882
1150883 if (gtk_widget_get_mapped (GTK_WIDGET (toplevel)))
1151 g_array_unref (devices);884 {
1152885 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 }886 }
1214 else887 else
1215 {888 {
1216 if (device_type & GRIP_DEVICE_TOUCHSCREEN)889 g_signal_connect (toplevel,
1217 geis_unsubscribe (registrations->touchscreen->instance,890 "map-event",
1218 (GeisGestureType*)registrations->touchscreen->gesture_list->pdata);891 G_CALLBACK (toplevel_mapped_cb),
1219 if (device_type & GRIP_DEVICE_TOUCHPAD)892 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 }893 }
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}894}
1245895
896
897/*
898 * toplevel_notify_cb:
899 *
900 * Called when a widget property has changed.
901 *
902 * The only widget property we're interested in here is the "parent" property.
903 * We can't subscribe to gestures on a window until the widget is mapped to a
904 * window. Only top-level widgets can be mapped to a window: we just keep
905 * queueing this callback on successive parent widgets until one is a top-level
906 * widget, then process that one.
907 */
1246static void908static void
1247toplevel_notify_cb (GtkWidget *widget,909toplevel_notify_cb (GtkWidget *widget,
1248 GParamSpec *pspec,910 GParamSpec *pspec,
@@ -1251,7 +913,7 @@
1251 if (pspec->name == g_intern_static_string ("parent"))913 if (pspec->name == g_intern_static_string ("parent"))
1252 {914 {
1253 GtkWidget *toplevel = gtk_widget_get_toplevel (widget);915 GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
1254 GripRegistrationRequest *req = (GripRegistrationRequest *)user_data;916 GripGestureManager *manager = (GripGestureManager *)user_data;
1255917
1256 g_signal_handlers_disconnect_by_func (widget,918 g_signal_handlers_disconnect_by_func (widget,
1257 G_CALLBACK (toplevel_notify_cb),919 G_CALLBACK (toplevel_notify_cb),
@@ -1259,30 +921,7 @@
1259921
1260 if (gtk_widget_is_toplevel (toplevel))922 if (gtk_widget_is_toplevel (toplevel))
1261 {923 {
1262 if (gtk_widget_get_mapped (GTK_WIDGET (toplevel)))924 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 }925 }
1287 else926 else
1288 {927 {
@@ -1294,96 +933,29 @@
1294 }933 }
1295}934}
1296935
936
1297/*937/*
1298 * register_widget:938 * toplevel_mapped_cb:
1299 *939 *
1300 * Registers a specific widget for a specific gesture made by a specific input940 * A callback invoked when a toplevel widget with one or more pending gesture
1301 * device type.941 * registration requests has been mapped to a window.
1302 *942 *
1303 * If the widget's containing window is a valid window, the widget is registered943 * This callback will in fact process all pending registration requests for the
1304 * right away, otherwise the registration is deferred until the widget actually944 * newly-mapped window.
1305 * has a top-level window.
1306 */945 */
1307static void946static 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,947toplevel_mapped_cb (GtkWidget *toplevel,
1352 GdkEvent *event G_GNUC_UNUSED,948 GdkEvent *event G_GNUC_UNUSED,
1353 gpointer user_data)949 gpointer user_data)
1354{950{
1355 GripGestureManager *manager = (GripGestureManager *)user_data;951 GripGestureManager *manager = (GripGestureManager *)user_data;
1356 GripGestureManagerPrivate *priv = manager->priv;952 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,953 g_signal_handlers_disconnect_by_func (toplevel,
1383 toplevel_mapped_cb,954 toplevel_mapped_cb,
1384 user_data);955 user_data);
1385}956}
1386957
958
1387/**959/**
1388 * grip_gesture_manager_register_window:960 * grip_gesture_manager_register_window:
1389 * @manager: A #GripGestureManager instance.961 * @manager: A #GripGestureManager instance.
@@ -1411,102 +983,47 @@
1411 gpointer user_data,983 gpointer user_data,
1412 GDestroyNotify destroy)984 GDestroyNotify destroy)
1413{985{
1414 GtkWidget *toplevel;
1415
1416 g_return_if_fail (GRIP_IS_GESTURE_MANAGER (manager));986 g_return_if_fail (GRIP_IS_GESTURE_MANAGER (manager));
1417 g_return_if_fail (GTK_IS_WIDGET (widget));987 g_return_if_fail (GTK_IS_WIDGET (widget));
1418988
1419 toplevel = gtk_widget_get_toplevel (widget);989 GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
990
991 GripRegistrationRequest *req = g_new0 (GripRegistrationRequest, 1);
992 req->manager = manager;
993 req->widget = widget;
994 req->gesture_type = gesture_type;
995 req->device_type = device_type;
996 req->touch_points = touch_points;
997 req->callback = callback;
998 req->user_data = user_data;
999 req->destroy = destroy;
1000 manager->priv->requests = g_list_append (manager->priv->requests, req);
14201001
1421 if (GTK_IS_WINDOW (toplevel))1002 if (GTK_IS_WINDOW (toplevel))
1422 {1003 {
1423 if (gtk_widget_get_mapped (GTK_WIDGET (toplevel)))1004 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 }1005 }
1456 else1006 else
1457 {1007 {
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,1008 g_signal_connect (toplevel,
1470 "notify",1009 "notify",
1471 G_CALLBACK (toplevel_notify_cb),1010 G_CALLBACK (toplevel_notify_cb),
1472 req);1011 manager);
1473 }1012 }
1474}1013}
14751014
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}
14841015
1485void1016void
1486grip_gesture_manager_unregister_window (GripGestureManager *manager,1017grip_gesture_manager_unregister_window (GripGestureManager *manager G_GNUC_UNUSED,
1487 GtkWidget *toplevel)1018 GtkWidget *toplevel G_GNUC_UNUSED)
1488{1019{
1489 GripGestureManagerPrivate *priv = manager->priv;
1490 struct Registrations *registrations;
1491
1492 g_return_if_fail (GRIP_IS_GESTURE_MANAGER (manager));1020 g_return_if_fail (GRIP_IS_GESTURE_MANAGER (manager));
1493 g_return_if_fail (GTK_IS_WINDOW (toplevel));1021 g_return_if_fail (GTK_IS_WINDOW (toplevel));
14941022
1495 /* Currently only allow unsubscribing after the window has been shown. */1023 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}1024}
15091025
1026
1510GType1027GType
1511grip_gesture_event_get_type (void)1028grip_gesture_event_get_type (void)
1512{1029{
15131030
=== modified file 'src/gripinputdevice.c'
--- src/gripinputdevice.c 2011-10-19 14:05:35 +0000
+++ src/gripinputdevice.c 2013-05-14 18:50:33 +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

to all changes: