Merge lp:~dandrader/geis/lp1045785 into lp:geis

Proposed by Daniel d'Andrada
Status: Merged
Merged at revision: 283
Proposed branch: lp:~dandrader/geis/lp1045785
Merge into: lp:geis
Diff against target: 1186 lines (+617/-177)
16 files modified
libgeis/backend/dbus/geis_dbus_backend.c (+6/-0)
libgeis/backend/grail/geis_grail_backend.c (+263/-132)
libgeis/backend/grail/geis_grail_backend.h (+7/-0)
libgeis/backend/grail/geis_grail_token.c (+10/-0)
libgeis/backend/grail/geis_ugsubscription_store.c (+50/-37)
libgeis/backend/grail/geis_ugsubscription_store.h (+22/-4)
libgeis/backend/test_fixture/geis_backend_test_fixture.c (+7/-0)
libgeis/geis_backend_protected.h (+1/-0)
libgeis/geis_backend_token.c (+9/-1)
libgeis/geis_backend_token.h (+11/-0)
libgeis/geis_subscription.c (+15/-2)
testsuite/geis2/Makefile.am (+1/-0)
testsuite/geis2/gtest_gbe_configure_new_devices.cpp (+201/-0)
testsuite/geis2/gtest_grail_backend.cpp (+3/-0)
testsuite/geis2/gtest_grail_backend.h (+3/-1)
testsuite/x11_mocks/x11_mocks.c (+8/-0)
To merge this branch: bzr merge lp:~dandrader/geis/lp1045785
Reviewer Review Type Date Requested Status
Chase Douglas (community) Approve
Review via email: mp+122898@code.launchpad.net

Description of the change

Fixes bug 1045785.

Improved handling of gesture configuration options for GeisSubscriptions

- You can now call geis_subscription_set_configuration() independently of whether the subscription is active or not. Before that, setting configuration options on an inactive subscription would fail.

- configuration options remain valid for devices that become available *after* the subscription is configured.

Also a number of memory leaks were plugged along the way.

To post a comment you must log in.
Revision history for this message
Chase Douglas (chasedouglas) wrote :

* It doesn't make much sense to include the current actual outcome in the test description because it will no longer be the actual outcome after the branch is merged :). The test could also fail in other ways in the future.

* Typo in a test comment: "Set a huge threshold (in meters) so that there's no *change* a drag can be"

Everything else looks good to me! This is a great improvement over the current functionality :).

review: Approve
lp:~dandrader/geis/lp1045785 updated
289. By Daniel d'Andrada

Fix comments in tests

* Remove the "actual outcome" from the test description. It doesn't make sense
to have it there and it's also no longer the actual outcome.

* Correct comment on the drag threshold

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'libgeis/backend/dbus/geis_dbus_backend.c'
2--- libgeis/backend/dbus/geis_dbus_backend.c 2012-07-24 16:04:12 +0000
3+++ libgeis/backend/dbus/geis_dbus_backend.c 2012-09-05 18:11:18 +0000
4@@ -156,6 +156,11 @@
5 return GEIS_STATUS_UNKNOWN_ERROR;
6 }
7
8+static void
9+_geis_dbus_token_free_subscription_pdata(GeisBackendToken token GEIS_UNUSED,
10+ GeisSubscription subscription GEIS_UNUSED)
11+{
12+}
13
14 static struct GeisBackendTokenVtable _token_vtbl = {
15 _geis_dbus_token_clone,
16@@ -163,6 +168,7 @@
17 _geis_dbus_token_compose,
18 _geis_dbus_token_activate,
19 _geis_dbus_token_deactivate,
20+ _geis_dbus_token_free_subscription_pdata
21 };
22
23
24
25=== modified file 'libgeis/backend/grail/geis_grail_backend.c'
26--- libgeis/backend/grail/geis_grail_backend.c 2012-08-27 21:58:31 +0000
27+++ libgeis/backend/grail/geis_grail_backend.c 2012-09-05 18:11:18 +0000
28@@ -106,29 +106,27 @@
29 GeisBoolean send_synchronous_events;
30 };
31
32-
33 /**
34- * A table of supported grail cofiguration properties and their GEIS
35- * equivalents.
36+ Holds backend-specific information regarding a GeisSubscription
37 */
38-static const struct GeisGrailConfigProperties
39+struct GeisGrailSubscriptionData
40 {
41- GeisString geis_config_name;
42- GeisAttrType geis_value_type;
43- UGSubscriptionProperty grail_property_name;
44-} _grail_be_config_properties[] = {
45- { GEIS_CONFIG_DRAG_TIMEOUT, GEIS_ATTR_TYPE_INTEGER, UGSubscriptionPropertyDragTimeout },
46- { GEIS_CONFIG_DRAG_THRESHOLD, GEIS_ATTR_TYPE_FLOAT, UGSubscriptionPropertyDragThreshold },
47- { GEIS_CONFIG_PINCH_TIMEOUT, GEIS_ATTR_TYPE_INTEGER, UGSubscriptionPropertyPinchTimeout },
48- { GEIS_CONFIG_PINCH_THRESHOLD, GEIS_ATTR_TYPE_FLOAT, UGSubscriptionPropertyPinchThreshold },
49- { GEIS_CONFIG_ROTATE_TIMEOUT, GEIS_ATTR_TYPE_INTEGER, UGSubscriptionPropertyRotateTimeout },
50- { GEIS_CONFIG_ROTATE_THRESHOLD, GEIS_ATTR_TYPE_FLOAT, UGSubscriptionPropertyRotateThreshold },
51- { GEIS_CONFIG_TAP_TIMEOUT, GEIS_ATTR_TYPE_INTEGER, UGSubscriptionPropertyTapTimeout },
52- { GEIS_CONFIG_TAP_THRESHOLD, GEIS_ATTR_TYPE_FLOAT, UGSubscriptionPropertyTapThreshold },
53- { NULL, 0, 0 }
54+ GeisUGSubscriptionStore ugstore;
55+
56+ /* configuration options
57+ NULL if not set by user, in which case grail defaults are used */
58+ uint64_t *drag_timeout;
59+ float *drag_threshold;
60+ uint64_t *pinch_timeout;
61+ float *pinch_threshold;
62+ uint64_t *rotate_timeout;
63+ float *rotate_threshold;
64+ uint64_t *tap_timeout;
65+ float *tap_threshold;
66 };
67
68
69+
70 static GeisStatus
71 _grail_be_activate_for_device(GeisGrailBackend gbe,
72 GeisFilter filter,
73@@ -839,7 +837,8 @@
74 it != geis_subscription_bag_end(gbe->subscription_bag);
75 it = geis_subscription_bag_iterator_next(gbe->subscription_bag, it))
76 {
77- GeisUGSubscriptionStore ugstore = geis_subscription_pdata(*it);
78+ struct GeisGrailSubscriptionData *subscription_data = geis_subscription_pdata(*it);
79+ GeisUGSubscriptionStore ugstore = subscription_data->ugstore;
80 for (GeisFilterIterator fit = geis_subscription_filter_begin(*it);
81 fit != geis_subscription_filter_end(*it);
82 fit = geis_subscription_filter_next(*it, fit))
83@@ -1702,12 +1701,11 @@
84 * subscriptions have the same property value setting.
85 */
86 static GeisStatus
87-_grail_be_get_ugsub_property(GeisSubscription geis_subscription,
88+_grail_be_get_ugsub_property(GeisUGSubscriptionStore ugstore,
89 UGSubscriptionProperty grail_property,
90 GeisPointer grail_value)
91 {
92 GeisStatus retval = GEIS_STATUS_UNKNOWN_ERROR;
93- GeisUGSubscriptionStore ugstore = geis_subscription_pdata(geis_subscription);
94 if (ugstore)
95 {
96 for (GeisSize i = 0; i < geis_ugsubscription_count(ugstore); ++i)
97@@ -1731,29 +1729,65 @@
98 * Sets a given grail property to a specified value.
99 */
100 static GeisStatus
101-_grail_be_set_ugsub_property(GeisSubscription geis_subscription,
102+_grail_be_set_ugsub_property(GeisUGSubscriptionStore ugstore,
103 UGSubscriptionProperty grail_property,
104 GeisPointer grail_value)
105 {
106- GeisStatus retval = GEIS_STATUS_UNKNOWN_ERROR;
107- GeisUGSubscriptionStore ugstore = geis_subscription_pdata(geis_subscription);
108- if (ugstore)
109+ /* OBS: it's still a success if there's no grail subscription */
110+ GeisStatus retval = GEIS_STATUS_SUCCESS;
111+ for (GeisSize i = 0; i < geis_ugsubscription_count(ugstore); ++i)
112 {
113- for (GeisSize i = 0; i < geis_ugsubscription_count(ugstore); ++i)
114- {
115- UGSubscription ugsub = geis_ugsubscription_get_ugsubscription_at(ugstore,
116- i);
117- if (UGStatusSuccess == grail_subscription_set_property(ugsub,
118- grail_property,
119- grail_value))
120- {
121- retval = GEIS_STATUS_SUCCESS;
122- }
123+ UGSubscription ugsub = geis_ugsubscription_get_ugsubscription_at(ugstore,
124+ i);
125+ if (UGStatusSuccess == grail_subscription_set_property(ugsub,
126+ grail_property,
127+ grail_value))
128+ {
129+ retval = GEIS_STATUS_SUCCESS;
130+ }
131+ else
132+ {
133+ retval = GEIS_STATUS_UNKNOWN_ERROR;
134 }
135 }
136 return retval;
137 }
138
139+static GeisStatus
140+_grail_be_get_integer_configuration(GeisUGSubscriptionStore ugstore,
141+ uint64_t *prop,
142+ UGSubscriptionProperty grail_prop,
143+ GeisPointer geis_value)
144+{
145+ if (prop)
146+ {
147+ *((GeisInteger*)geis_value) = *prop;
148+ return GEIS_STATUS_SUCCESS;
149+ }
150+ else
151+ {
152+ return _grail_be_get_ugsub_property(ugstore, grail_prop, geis_value);
153+ }
154+
155+}
156+
157+static GeisStatus
158+_grail_be_get_float_configuration(GeisUGSubscriptionStore ugstore,
159+ float *prop,
160+ UGSubscriptionProperty grail_prop,
161+ GeisPointer geis_value)
162+{
163+ if (prop)
164+ {
165+ *((GeisFloat*)geis_value) = *prop;
166+ return GEIS_STATUS_SUCCESS;
167+ }
168+ else
169+ {
170+ return _grail_be_get_ugsub_property(ugstore, grail_prop, geis_value);
171+ }
172+
173+}
174
175 /*
176 * Dispatches the get-configuration call.
177@@ -1765,42 +1799,75 @@
178 GeisPointer item_value)
179 {
180 GeisStatus retval = GEIS_STATUS_NOT_SUPPORTED;
181- for (int i = 0; _grail_be_config_properties[i].geis_config_name; ++i)
182+
183+ struct GeisGrailSubscriptionData *subscription_data =
184+ geis_subscription_pdata(subscription);
185+ if (!subscription_data)
186 {
187- if (0 == strcmp(item_name, _grail_be_config_properties[i].geis_config_name))
188- {
189- switch (_grail_be_config_properties[i].geis_value_type)
190- {
191- case GEIS_ATTR_TYPE_INTEGER:
192- {
193- uint64_t value;
194- retval = _grail_be_get_ugsub_property(subscription,
195- _grail_be_config_properties[i].grail_property_name,
196- &value);
197- *(GeisInteger*)item_value = value;
198- break;
199- }
200- case GEIS_ATTR_TYPE_FLOAT:
201- {
202- float value;
203- retval = _grail_be_get_ugsub_property(subscription,
204- _grail_be_config_properties[i].grail_property_name,
205- &value);
206- *(GeisFloat*)item_value = value;
207- break;
208- }
209- default:
210- geis_error("configuration value of unknown type requested");
211- retval = GEIS_STATUS_UNKNOWN_ERROR;
212- break;
213- }
214- break;
215- }
216- }
217+ return retval;
218+ }
219+
220+ #define GEIS_GRAIL_CHECK_GESTURE_CONFIG(gesture, Gesture, GESTURE) \
221+ if (strcmp(item_name, GEIS_CONFIG_##GESTURE##_TIMEOUT) == 0) \
222+ { \
223+ retval = _grail_be_get_integer_configuration( \
224+ subscription_data->ugstore, \
225+ subscription_data->gesture##_timeout, \
226+ UGSubscriptionProperty##Gesture##Timeout, \
227+ item_value); \
228+ } \
229+ else if (strcmp(item_name, GEIS_CONFIG_##GESTURE##_THRESHOLD) == 0) \
230+ { \
231+ retval = _grail_be_get_float_configuration( \
232+ subscription_data->ugstore, \
233+ subscription_data->gesture##_threshold, \
234+ UGSubscriptionProperty##Gesture##Threshold, \
235+ item_value); \
236+ }
237+
238+ GEIS_GRAIL_CHECK_GESTURE_CONFIG(drag, Drag, DRAG)
239+ else GEIS_GRAIL_CHECK_GESTURE_CONFIG(pinch, Pinch, PINCH)
240+ else GEIS_GRAIL_CHECK_GESTURE_CONFIG(rotate, Rotate, ROTATE)
241+ else GEIS_GRAIL_CHECK_GESTURE_CONFIG(tap, Tap, TAP)
242+
243+ #undef GEIS_GRAIL_CHECK_GESTURE_CONFIG
244
245 return retval;
246 }
247
248+static GeisStatus
249+_grail_be_set_integer_configuration(GeisUGSubscriptionStore ugstore,
250+ uint64_t **prop,
251+ UGSubscriptionProperty grail_prop,
252+ GeisPointer geis_value)
253+{
254+ if (!*prop)
255+ *prop = malloc(sizeof(uint64_t));
256+
257+ **prop = *((GeisInteger*)geis_value);
258+
259+ if (ugstore)
260+ return _grail_be_set_ugsub_property(ugstore, grail_prop, *prop);
261+ else
262+ return GEIS_STATUS_SUCCESS;
263+}
264+
265+static GeisStatus
266+_grail_be_set_float_configuration(GeisUGSubscriptionStore ugstore,
267+ float **prop,
268+ UGSubscriptionProperty grail_prop,
269+ GeisPointer geis_value)
270+{
271+ if (!*prop)
272+ *prop = malloc(sizeof(float));
273+
274+ **prop = *((GeisFloat*)geis_value);
275+
276+ if (ugstore)
277+ return _grail_be_set_ugsub_property(ugstore, grail_prop, *prop);
278+ else
279+ return GEIS_STATUS_SUCCESS;
280+}
281
282 /*
283 * Dispatches the set-configuration call.
284@@ -1813,41 +1880,42 @@
285 {
286 GeisStatus retval = GEIS_STATUS_NOT_SUPPORTED;
287
288- for (int i = 0; _grail_be_config_properties[i].geis_config_name; ++i)
289+ struct GeisGrailSubscriptionData *subscription_data =
290+ geis_subscription_pdata(subscription);
291+ if (!subscription_data)
292 {
293- if (0 == strcmp(item_name, _grail_be_config_properties[i].geis_config_name))
294- {
295- switch (_grail_be_config_properties[i].geis_value_type)
296- {
297- case GEIS_ATTR_TYPE_INTEGER:
298- {
299- uint64_t value = *(GeisInteger *)item_value;
300- retval = _grail_be_set_ugsub_property(subscription,
301- _grail_be_config_properties[i].grail_property_name,
302- &value);
303- break;
304- }
305- case GEIS_ATTR_TYPE_FLOAT:
306- {
307- float value = *(GeisFloat *)item_value;
308- retval = _grail_be_set_ugsub_property(subscription,
309- _grail_be_config_properties[i].grail_property_name,
310- &value);
311- break;
312- }
313- default:
314- geis_error("configuration value of unknown type requested");
315- retval = GEIS_STATUS_UNKNOWN_ERROR;
316- break;
317- }
318- break;
319- }
320- }
321+ subscription_data = calloc(1, sizeof(struct GeisGrailSubscriptionData));
322+ geis_subscription_set_pdata(subscription, subscription_data);
323+ }
324+
325+ #define GEIS_GRAIL_CHECK_GESTURE_CONFIG(gesture, Gesture, GESTURE) \
326+ if (strcmp(item_name, GEIS_CONFIG_##GESTURE##_TIMEOUT) == 0) \
327+ { \
328+ retval = _grail_be_set_integer_configuration( \
329+ subscription_data->ugstore, \
330+ &(subscription_data->gesture##_timeout), \
331+ UGSubscriptionProperty##Gesture##Timeout, \
332+ item_value); \
333+ } \
334+ else if (strcmp(item_name, GEIS_CONFIG_##GESTURE##_THRESHOLD) == 0) \
335+ { \
336+ retval = _grail_be_set_float_configuration( \
337+ subscription_data->ugstore, \
338+ &(subscription_data->gesture##_threshold), \
339+ UGSubscriptionProperty##Gesture##Threshold, \
340+ item_value); \
341+ }
342+
343+ GEIS_GRAIL_CHECK_GESTURE_CONFIG(drag, Drag, DRAG)
344+ else GEIS_GRAIL_CHECK_GESTURE_CONFIG(pinch, Pinch, PINCH)
345+ else GEIS_GRAIL_CHECK_GESTURE_CONFIG(rotate, Rotate, ROTATE)
346+ else GEIS_GRAIL_CHECK_GESTURE_CONFIG(tap, Tap, TAP)
347+
348+ #undef GEIS_GRAIL_CHECK_GESTURE_CONFIG
349
350 return retval;
351 }
352
353-
354 static struct GeisBackendVtable gbe_vtbl = {
355 _geis_grail_backend_construct,
356 _geis_grail_backend_finalize,
357@@ -1855,10 +1923,9 @@
358 _grail_be_accept_gesture,
359 _grail_be_reject_gesture,
360 _grail_be_get_configuration,
361- _grail_be_set_configuration,
362+ _grail_be_set_configuration
363 };
364
365-
366 static GeisStatus
367 _geis_grail_filter_gestures(GeisGrailBackend gbe,
368 GeisFilter filter,
369@@ -2029,6 +2096,45 @@
370 }
371
372
373+static void
374+_geis_grail_set_ugsubscription_properties(GeisGrailBackend gbe,
375+ UGSubscription ugsub,
376+ GeisSubscription subscription)
377+{
378+ struct GeisGrailSubscriptionData *subscription_data = geis_subscription_pdata(subscription);
379+
380+ GeisBoolean geis_use_atomic_gestures = GEIS_FALSE;
381+ geis_get_configuration(gbe->geis,
382+ GEIS_CONFIG_ATOMIC_GESTURES,
383+ &geis_use_atomic_gestures);
384+ int grail_use_atomic_gestures = (geis_use_atomic_gestures == GEIS_TRUE);
385+ grail_subscription_set_property(ugsub,
386+ UGSubscriptionPropertyAtomicGestures,
387+ &grail_use_atomic_gestures);
388+
389+
390+ #define GEIS_GRAIL_SYNC_GESTURE_PROPERTIES(gesture, Gesture) \
391+ if (subscription_data->gesture##_timeout) \
392+ { \
393+ grail_subscription_set_property(ugsub, \
394+ UGSubscriptionProperty##Gesture##Timeout, \
395+ subscription_data->gesture##_timeout); \
396+ } \
397+ if (subscription_data->gesture##_threshold) \
398+ { \
399+ grail_subscription_set_property(ugsub, \
400+ UGSubscriptionProperty##Gesture##Threshold, \
401+ subscription_data->gesture##_threshold); \
402+ }
403+
404+ GEIS_GRAIL_SYNC_GESTURE_PROPERTIES(drag, Drag);
405+ GEIS_GRAIL_SYNC_GESTURE_PROPERTIES(pinch, Pinch);
406+ GEIS_GRAIL_SYNC_GESTURE_PROPERTIES(rotate, Rotate);
407+ GEIS_GRAIL_SYNC_GESTURE_PROPERTIES(tap, Tap);
408+
409+ #undef GEIS_GRAIL_SYNC_GESTURE_PROPERTIES
410+}
411+
412 /**
413 * Activates a subscription for a (device, region).
414 */
415@@ -2042,56 +2148,45 @@
416 GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
417 GeisInteger device_id = geis_device_id(device);
418 UFDevice ufdevice = _grail_be_ufdevice_from_device_id(gbe, device_id);
419- GeisUGSubscriptionStore ugstore = geis_subscription_pdata(subscription);
420+ struct GeisGrailSubscriptionData *subscription_data = geis_subscription_pdata(subscription);
421+ GeisUGSubscriptionStore ugstore = subscription_data->ugstore;
422 UGSubscription ugsub = geis_ugsubscription_get_ugsubscription(ugstore,
423 filter,
424 ufdevice,
425 window_id);
426+
427+ if (!ugsub)
428+ {
429+ ugsub = geis_ugsubscription_create_ugsubscription(ugstore,
430+ filter,
431+ ufdevice,
432+ window_id);
433+ _geis_grail_set_ugsubscription_properties(gbe, ugsub, subscription);
434+ }
435+
436 if (!ugsub)
437 {
438 geis_error("can not retrieve UGSubscription for (device, window)");
439 goto final_exit;
440 }
441
442- UGStatus ugstatus = UGStatusErrorGeneric;
443- GeisBoolean geis_use_atomic_gestures = GEIS_FALSE;
444- geis_get_configuration(gbe->geis,
445- GEIS_CONFIG_ATOMIC_GESTURES,
446- &geis_use_atomic_gestures);
447- int grail_use_atomic_gestures = (geis_use_atomic_gestures == GEIS_TRUE);
448- ugstatus = grail_subscription_set_property(ugsub,
449- UGSubscriptionPropertyAtomicGestures,
450- &grail_use_atomic_gestures);
451-
452 status = _geis_grail_filter_gestures(gbe, filter, subscription, ugsub);
453
454- UGGestureTypeMask ugmask;
455- ugstatus = grail_subscription_get_property(ugsub,
456- UGSubscriptionPropertyMask,
457- &ugmask);
458- if (ugstatus != UGStatusSuccess)
459- {
460- geis_error("failed to get UGSubscription mask");
461- goto final_exit;
462- }
463-
464 if (filter)
465 geis_debug("subscription='%s' filter='%s' device=%d '%s' window=0x%08x "
466- "ugsub=%p atomic=%d",
467+ "ugsub=%p",
468 geis_subscription_name(subscription),
469 geis_filter_name(filter),
470 device_id, geis_device_name(device),
471 window_id,
472- (void *)ugsub,
473- grail_use_atomic_gestures);
474+ (void *)ugsub);
475 else
476 geis_debug("subscription='%s' no-filter device=%d '%s' window=0x%08x "
477- "ugsub=%p atomic=%d",
478+ "ugsub=%p",
479 geis_subscription_name(subscription),
480 device_id, geis_device_name(device),
481 window_id,
482- (void *)ugsub,
483- grail_use_atomic_gestures);
484+ (void *)ugsub);
485
486 status = geis_grail_window_grab_store_grab(gbe->window_grabs, window_id);
487 if (status != GEIS_STATUS_SUCCESS)
488@@ -2100,7 +2195,7 @@
489 goto final_exit;
490 }
491
492- ugstatus = grail_subscription_activate(gbe->grail, ugsub);
493+ UGStatus ugstatus = grail_subscription_activate(gbe->grail, ugsub);
494 if (ugstatus != UGStatusSuccess)
495 {
496 status = GEIS_STATUS_UNKNOWN_ERROR;
497@@ -2264,16 +2359,22 @@
498 goto final_exit;
499 }
500
501- GeisUGSubscriptionStore ugstore = geis_subscription_pdata(subscription);
502- if (ugstore == NULL)
503- {
504- ugstore = geis_ugsubscription_store_new();
505- if (!ugstore)
506+ struct GeisGrailSubscriptionData *subscription_data =
507+ geis_subscription_pdata(subscription);
508+ if (!subscription_data)
509+ {
510+ subscription_data = calloc(1, sizeof(struct GeisGrailSubscriptionData));
511+ geis_subscription_set_pdata(subscription, subscription_data);
512+ }
513+
514+ if (subscription_data->ugstore == NULL)
515+ {
516+ subscription_data->ugstore = geis_ugsubscription_store_new();
517+ if (!subscription_data->ugstore)
518 {
519 geis_error("error creating grail subscription store");
520 goto final_exit;
521 }
522- geis_subscription_set_pdata(subscription, ugstore);
523 }
524
525 if (geis_subscription_filter_count(subscription) > 0)
526@@ -2313,7 +2414,9 @@
527 goto final_exit;
528 }
529
530- GeisUGSubscriptionStore ugstore = geis_subscription_pdata(subscription);
531+ struct GeisGrailSubscriptionData *subscription_data =
532+ geis_subscription_pdata(subscription);
533+ GeisUGSubscriptionStore ugstore = subscription_data->ugstore;
534 if (ugstore)
535 {
536 for (GeisSize i = 0; i < geis_ugsubscription_count(ugstore); ++i)
537@@ -2347,6 +2450,34 @@
538 return status;
539 }
540
541+/*
542+ Frees the memory allocated for the GEIS subscription private data
543+ */
544+void
545+geis_grail_backend_free_subscription_pdata(GeisGrailBackend gbe GEIS_UNUSED,
546+ GeisSubscription subscription)
547+{
548+ struct GeisGrailSubscriptionData *subscription_data =
549+ geis_subscription_pdata(subscription);
550+ if (!subscription_data)
551+ return;
552+
553+ if (subscription_data->ugstore)
554+ geis_ugsubscription_delete(subscription_data->ugstore);
555+
556+ free(subscription_data->drag_timeout);
557+ free(subscription_data->drag_threshold);
558+ free(subscription_data->pinch_timeout);
559+ free(subscription_data->pinch_threshold);
560+ free(subscription_data->rotate_timeout);
561+ free(subscription_data->rotate_threshold);
562+ free(subscription_data->tap_timeout);
563+ free(subscription_data->tap_threshold);
564+
565+ free(subscription_data);
566+
567+ geis_subscription_set_pdata(subscription, NULL);
568+}
569
570 /**
571 * Registers the back end with the GEIS back end registry.
572
573=== modified file 'libgeis/backend/grail/geis_grail_backend.h'
574--- libgeis/backend/grail/geis_grail_backend.h 2012-03-31 16:15:35 +0000
575+++ libgeis/backend/grail/geis_grail_backend.h 2012-09-05 18:11:18 +0000
576@@ -40,4 +40,11 @@
577 geis_grail_backend_deactivate_subscription(GeisGrailBackend gbe,
578 GeisSubscription subscription);
579
580+/**
581+ * Frees the memory allocated for the GEIS subscription private data
582+ */
583+void
584+geis_grail_backend_free_subscription_pdata(GeisGrailBackend gbe,
585+ GeisSubscription subscription);
586+
587 #endif /* GEIS_BACKEND_GRAIL_BACKEND_H_ */
588
589=== modified file 'libgeis/backend/grail/geis_grail_token.c'
590--- libgeis/backend/grail/geis_grail_token.c 2012-03-31 16:15:35 +0000
591+++ libgeis/backend/grail/geis_grail_token.c 2012-09-05 18:11:18 +0000
592@@ -126,6 +126,15 @@
593 return status;
594 }
595
596+/**
597+ * Frees the memory allocated for the GEIS subscription private data
598+ */
599+static void
600+_geis_grail_token_free_subscription_pdata(GeisBackendToken token, GeisSubscription sub)
601+{
602+ GeisGrailToken gdt = _geis_grail_token_from_geis_token(token);
603+ geis_grail_backend_free_subscription_pdata(gdt->be, sub);
604+}
605
606 /**
607 * Creates Grail-back-end-specific back end token.
608@@ -140,6 +149,7 @@
609 _geis_grail_token_compose,
610 _geis_grail_token_activate,
611 _geis_grail_token_deactivate,
612+ _geis_grail_token_free_subscription_pdata
613 };
614
615 GeisGrailToken token = _geis_grail_token_allocate();
616
617=== modified file 'libgeis/backend/grail/geis_ugsubscription_store.c'
618--- libgeis/backend/grail/geis_ugsubscription_store.c 2012-06-21 21:17:25 +0000
619+++ libgeis/backend/grail/geis_ugsubscription_store.c 2012-09-05 18:11:18 +0000
620@@ -59,7 +59,8 @@
621 {
622 for (GeisSize i = 0; i < geis_bag_count(store); ++i)
623 {
624- grail_subscription_delete(*(UGSubscription*)geis_bag_at(store, i));
625+ struct GeisUGSubscription * s = (struct GeisUGSubscription *)geis_bag_at(store, i);
626+ grail_subscription_delete(s->ugsub);
627 }
628 geis_bag_delete(store);
629 }
630@@ -86,6 +87,53 @@
631 return ((GeisUGSubscription)geis_bag_at(store, index))->ugsub;
632 }
633
634+/*
635+ * Creates a new UGSubscription and adds it to the store.
636+ */
637+UGSubscription
638+geis_ugsubscription_create_ugsubscription(GeisUGSubscriptionStore store,
639+ GeisFilter filter,
640+ UFDevice device,
641+ GeisInteger region_id)
642+{
643+ UGSubscription ugsub = NULL;
644+
645+ UGStatus ugstatus = grail_subscription_new(&ugsub);
646+ if (ugstatus != UGStatusSuccess)
647+ {
648+ geis_error("failed to create grail subscription");
649+ goto final_exit;
650+ }
651+
652+ ugstatus = grail_subscription_set_property(ugsub,
653+ UGSubscriptionPropertyDevice,
654+ &device);
655+ if (ugstatus != UGStatusSuccess)
656+ {
657+ geis_error("failed to set UGSubscription device property");
658+ }
659+
660+ UFWindowId window_id = frame_x11_create_window_id(region_id);
661+ ugstatus = grail_subscription_set_property(ugsub,
662+ UGSubscriptionPropertyWindow,
663+ &window_id);
664+ if (ugstatus != UGStatusSuccess)
665+ {
666+ geis_error("failed to set UGSubscription window property");
667+ }
668+
669+ struct GeisUGSubscription s = {
670+ .filter = filter,
671+ .device = device,
672+ .region_id = region_id,
673+ .ugsub = ugsub
674+ };
675+ geis_bag_append(store, &s);
676+
677+ final_exit:
678+ return ugsub;
679+}
680+
681
682 /*
683 * Gets a UGSubscription from the store.
684@@ -97,6 +145,7 @@
685 GeisInteger region_id)
686 {
687 UGSubscription ugsub = NULL;
688+
689 for (GeisSize i = 0; i < geis_bag_count(store); ++i)
690 {
691 GeisUGSubscription s = (GeisUGSubscription)geis_bag_at(store, i);
692@@ -107,42 +156,6 @@
693 }
694 }
695
696- if (!ugsub)
697- {
698- UGStatus ugstatus = grail_subscription_new(&ugsub);
699- if (ugstatus != UGStatusSuccess)
700- {
701- geis_error("failed to create grail subscription");
702- goto final_exit;
703- }
704-
705- ugstatus = grail_subscription_set_property(ugsub,
706- UGSubscriptionPropertyDevice,
707- &device);
708- if (ugstatus != UGStatusSuccess)
709- {
710- geis_error("failed to set UGSubscription device property");
711- }
712-
713- UFWindowId window_id = frame_x11_create_window_id(region_id);
714- ugstatus = grail_subscription_set_property(ugsub,
715- UGSubscriptionPropertyWindow,
716- &window_id);
717- if (ugstatus != UGStatusSuccess)
718- {
719- geis_error("failed to set UGSubscription window property");
720- }
721-
722- struct GeisUGSubscription s = {
723- .filter = filter,
724- .device = device,
725- .region_id = region_id,
726- .ugsub = ugsub
727- };
728- geis_bag_append(store, &s);
729- }
730-
731-final_exit:
732 return ugsub;
733 }
734
735
736=== modified file 'libgeis/backend/grail/geis_ugsubscription_store.h'
737--- libgeis/backend/grail/geis_ugsubscription_store.h 2012-06-21 21:17:25 +0000
738+++ libgeis/backend/grail/geis_ugsubscription_store.h 2012-09-05 18:11:18 +0000
739@@ -64,8 +64,7 @@
740 * @param[in] store The grail subscription store.
741 * @param[in] index Indicates a ugsub.
742 *
743- * Gets a UGSubscription from the store for the identified device and region.
744- * If no such UGSubscription is available, it creates one first.
745+ * Gets a UGSubscription from the store at the given index.
746 *
747 * @returns a valid UGSubscription or NULL to indicate failure.
748 */
749@@ -73,6 +72,27 @@
750 geis_ugsubscription_get_ugsubscription_at(GeisUGSubscriptionStore store,
751 GeisSize index);
752
753+/*
754+ * Creates a new UGSubscription and adds it to the store.
755+ * @param[in] store The grail subscription store.
756+ * @param[in] filter Identifies a filter.
757+ * @param[in] device Identifies a device.
758+ * @param[in] region_id Identifies a region.
759+ *
760+ * Creates a new UGSubscription for the identified filter, device,
761+ * and region. It's added to the store. A separate grail subscription
762+ * is required for each (filter, device, window) because filters on a
763+ * geis subscription are ORed, meaning each filter may have a different
764+ * minimum touch requirement.
765+ *
766+ * @returns a valid UGSubscription or NULL to indicate failure.
767+ */
768+UGSubscription
769+geis_ugsubscription_create_ugsubscription(GeisUGSubscriptionStore store,
770+ GeisFilter filter,
771+ UFDevice device,
772+ GeisInteger region_id);
773+
774 /**
775 * Gets a UGSubscription from the store.
776 * @param[in] store The grail subscription store.
777@@ -85,8 +105,6 @@
778 * device, window) because filters on a geis subscription are ORed, meaning each
779 * filter may have a different minimum touch requirement.
780 *
781- * If no such UGSubscription is available, it creates one first.
782- *
783 * @returns a valid UGSubscription or NULL to indicate failure.
784 */
785 UGSubscription
786
787=== modified file 'libgeis/backend/test_fixture/geis_backend_test_fixture.c'
788--- libgeis/backend/test_fixture/geis_backend_test_fixture.c 2012-07-24 16:04:12 +0000
789+++ libgeis/backend/test_fixture/geis_backend_test_fixture.c 2012-09-05 18:11:18 +0000
790@@ -82,6 +82,7 @@
791 static void _token_compose(GeisBackendToken, GeisBackendToken);
792 static GeisStatus _token_activate(GeisBackendToken, GeisSubscription);
793 static GeisStatus _token_deactivate(GeisBackendToken, GeisSubscription);
794+static void _token_free_subscription_pdata(GeisBackendToken, GeisSubscription);
795
796 static struct GeisBackendTokenVtable _token_vtbl = {
797 _token_clone,
798@@ -89,6 +90,7 @@
799 _token_compose,
800 _token_activate,
801 _token_deactivate,
802+ _token_free_subscription_pdata
803 };
804
805 static GeisGestureClass g_poke_class = NULL;
806@@ -424,6 +426,11 @@
807 return status;
808 }
809
810+void
811+_token_free_subscription_pdata(GeisBackendToken gbtoken GEIS_UNUSED,
812+ GeisSubscription subscription GEIS_UNUSED)
813+{
814+}
815
816 __attribute__((constructor))
817 static void _register_test_fixture()
818
819=== modified file 'libgeis/geis_backend_protected.h'
820--- libgeis/geis_backend_protected.h 2012-04-17 23:43:04 +0000
821+++ libgeis/geis_backend_protected.h 2012-09-05 18:11:18 +0000
822@@ -58,6 +58,7 @@
823 void (* compose)(GeisBackendToken, GeisBackendToken);
824 GeisStatus (* activate)(GeisBackendToken, GeisSubscription);
825 GeisStatus (* deactivate)(GeisBackendToken, GeisSubscription);
826+ void (* free_subscription_pdata)(GeisBackendToken, GeisSubscription);
827 } *GeisBackendTokenVtable;
828
829
830
831=== modified file 'libgeis/geis_backend_token.c'
832--- libgeis/geis_backend_token.c 2011-10-17 16:52:22 +0000
833+++ libgeis/geis_backend_token.c 2012-09-05 18:11:18 +0000
834@@ -77,4 +77,12 @@
835 return token->vtbl->deactivate(token, subscription);
836 }
837
838-
839+/**
840+ * Frees the private data that the backend allocated for a given subscription
841+ */
842+void
843+geis_backend_token_free_subscription_pdata(GeisBackendToken token,
844+ GeisSubscription subscription)
845+{
846+ token->vtbl->free_subscription_pdata(token, subscription);
847+}
848
849=== modified file 'libgeis/geis_backend_token.h'
850--- libgeis/geis_backend_token.h 2011-10-17 16:52:22 +0000
851+++ libgeis/geis_backend_token.h 2012-09-05 18:11:18 +0000
852@@ -101,4 +101,15 @@
853 geis_backend_token_deactivate(GeisBackendToken token,
854 GeisSubscription subscription);
855
856+/**
857+ * Frees the private data that the backend allocated for a given subscription
858+ *
859+ * @param[in] token The backend token.
860+ * @param[in] subscription The subscription that will have its backend private data
861+ * freed
862+ */
863+void
864+geis_backend_token_free_subscription_pdata(GeisBackendToken token,
865+ GeisSubscription subscription);
866+
867 #endif /* GEIS_BACKEND_TOKEN_H_ */
868
869=== modified file 'libgeis/geis_subscription.c'
870--- libgeis/geis_subscription.c 2012-06-21 21:17:25 +0000
871+++ libgeis/geis_subscription.c 2012-09-05 18:11:18 +0000
872@@ -337,8 +337,6 @@
873 if (sub->sub_backend_token)
874 {
875 status = geis_backend_token_deactivate(sub->sub_backend_token, sub);
876- geis_backend_token_delete(sub->sub_backend_token);
877- sub->sub_backend_token = NULL;
878 }
879 return status;
880 }
881@@ -426,6 +424,14 @@
882 {
883 geis_debug("destroying subscription \"%s\" id %d", sub->sub_name, sub->sub_id);
884 geis_subscription_deactivate(sub);
885+
886+ if (sub->sub_backend_token)
887+ {
888+ geis_backend_token_free_subscription_pdata(sub->sub_backend_token, sub);
889+ geis_backend_token_delete(sub->sub_backend_token);
890+ sub->sub_backend_token = NULL;
891+ }
892+
893 if (sub->sub_geis != NULL)
894 {
895 geis_unref(sub->sub_geis);
896@@ -507,6 +513,13 @@
897 geis_error("error adding filter to subscription");
898 goto error_exit;
899 }
900+ else
901+ {
902+ /* since we're taking ownership of the filter, we're removing the initial
903+ reference that belonged to the API user, created in geis_filter_new().
904+ Now the only remaining reference is the one held by our geis_filter_bag */
905+ geis_filter_unref(filter);
906+ }
907
908 error_exit:
909 return status;
910
911=== modified file 'testsuite/geis2/Makefile.am'
912--- testsuite/geis2/Makefile.am 2012-07-24 22:18:36 +0000
913+++ testsuite/geis2/Makefile.am 2012-09-05 18:11:18 +0000
914@@ -48,6 +48,7 @@
915 gtest_geis2_grail_backend_SOURCES = \
916 gtest_grail_backend.h gtest_grail_backend.cpp \
917 gtest_gbe_accept_ended_grail_gesture.cpp \
918+ gtest_gbe_configure_new_devices.cpp \
919 gtest_gbe_deactivate_sub.cpp \
920 gtest_gbe_direct_touch_coords.cpp \
921 gtest_gbe_construction_finished.cpp \
922
923=== added file 'testsuite/geis2/gtest_gbe_configure_new_devices.cpp'
924--- testsuite/geis2/gtest_gbe_configure_new_devices.cpp 1970-01-01 00:00:00 +0000
925+++ testsuite/geis2/gtest_gbe_configure_new_devices.cpp 2012-09-05 18:11:18 +0000
926@@ -0,0 +1,201 @@
927+#include "gtest_grail_backend.h"
928+#include "x11_mocks.h"
929+
930+/*
931+ Regression test for bug LP#1045785
932+ https://bugs.launchpad.net/geis/+bug/1045785
933+
934+ Steps to reproduce the issue:
935+ 1 - create a subscription, set some configuration options
936+ (geis_subscription_set_configuration) and activate it.
937+ 2 - connect a new multitouch device to your computer (e.g. pair an Apple
938+ Magic Trackpad)
939+
940+ Expected outcome:
941+ Gestures from that new multitouch device follow the configurations set by
942+ the subscription.
943+ */
944+
945+class ConfigureNewDevice : public Geis2GrailBackendBase
946+{
947+ protected:
948+ ConfigureNewDevice();
949+
950+ virtual void OnEventInitComplete(GeisEvent event);
951+ virtual void OnEventClassAvailable(GeisEvent event);
952+ virtual void OnEventGestureBegin(GeisEvent event);
953+
954+ void CreateSubscription();
955+ void SendXInput2Events();
956+
957+ /* signals that a new device has been added */
958+ void SendXIDeviceAddedEvent();
959+
960+ GeisSubscription _subscription;
961+ GeisGestureClass _drag_class;
962+};
963+
964+ConfigureNewDevice::ConfigureNewDevice()
965+ : _subscription(nullptr),
966+ _drag_class(nullptr)
967+{
968+}
969+
970+void ConfigureNewDevice::OnEventInitComplete(GeisEvent event)
971+{
972+ CreateSubscription();
973+
974+ /* The new device comes only after the subscription has been created and
975+ configured */
976+ CreateXMockTouchScreenDevice();
977+ SendXIDeviceAddedEvent();
978+
979+ SendXInput2Events();
980+}
981+
982+void ConfigureNewDevice::OnEventClassAvailable(GeisEvent event)
983+{
984+ GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_CLASS);
985+ GeisGestureClass gesture_class =
986+ reinterpret_cast<GeisGestureClass>(geis_attr_value_to_pointer(attr));
987+
988+ if (strcmp(geis_gesture_class_name(gesture_class), GEIS_GESTURE_DRAG) == 0)
989+ {
990+ _drag_class = gesture_class;
991+ geis_gesture_class_ref(gesture_class);
992+ }
993+}
994+
995+void ConfigureNewDevice::OnEventGestureBegin(GeisEvent event)
996+{
997+ /* There should be no drag gesture since we set a huge drag threshold. */
998+
999+ GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET);
1000+ GeisGroupSet group_set =
1001+ reinterpret_cast<GeisGroupSet>(geis_attr_value_to_pointer(attr));
1002+ GeisGroup group = geis_groupset_group(group_set, 0);
1003+ GeisFrame frame = geis_group_frame(group, 0);
1004+
1005+ ASSERT_NE(nullptr, _drag_class);
1006+ GeisBoolean is_drag = geis_frame_is_class(frame, _drag_class);
1007+ ASSERT_FALSE(is_drag);
1008+}
1009+
1010+void ConfigureNewDevice::CreateSubscription()
1011+{
1012+ GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
1013+ GeisFilter filter = nullptr;
1014+
1015+ _subscription = geis_subscription_new(_geis, "2-fingers drag",
1016+ GEIS_SUBSCRIPTION_NONE);
1017+
1018+ filter = geis_filter_new(_geis, "filter");
1019+ ASSERT_NE(nullptr, filter);
1020+
1021+ status = geis_filter_add_term(filter,
1022+ GEIS_FILTER_CLASS,
1023+ GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_DRAG,
1024+ GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, 2,
1025+ nullptr);
1026+ ASSERT_EQ(GEIS_STATUS_SUCCESS, status);
1027+
1028+ status = geis_filter_add_term(filter,
1029+ GEIS_FILTER_REGION,
1030+ GEIS_REGION_ATTRIBUTE_WINDOWID, GEIS_FILTER_OP_EQ,
1031+ DefaultRootWindow(xmock_display),
1032+ nullptr);
1033+ ASSERT_EQ(GEIS_STATUS_SUCCESS, status);
1034+
1035+ status = geis_subscription_add_filter(_subscription, filter);
1036+ ASSERT_EQ(GEIS_STATUS_SUCCESS, status);
1037+
1038+ /* Set a huge threshold (in meters) so that no drag can be recognized */
1039+ GeisFloat drag_threshold = 1000.0f;
1040+ status = geis_subscription_set_configuration(_subscription,
1041+ GEIS_CONFIG_DRAG_THRESHOLD, &drag_threshold);
1042+ ASSERT_EQ(GEIS_STATUS_SUCCESS, status);
1043+
1044+ status = geis_subscription_activate(_subscription);
1045+ ASSERT_EQ(GEIS_STATUS_SUCCESS, status);
1046+}
1047+
1048+void ConfigureNewDevice::SendXInput2Events()
1049+{
1050+ /* Emulate a simple 2 fingers drag */
1051+
1052+ /* event type, touch id, X and Y */
1053+ SendTouchEvent(XI_TouchBegin, 1, 10.0f, 10.0f);
1054+ SendTouchEvent(XI_TouchBegin, 2, 20.0f, 10.0f);
1055+
1056+ xmock_server_time += 2;
1057+
1058+ /* touch id */
1059+ SendTouchOwnershipEvent(1);
1060+ SendTouchOwnershipEvent(2);
1061+
1062+ xmock_server_time += 20;
1063+
1064+ SendTouchEvent(XI_TouchUpdate, 1, 10.0f, 25.0f);
1065+ SendTouchEvent(XI_TouchUpdate, 2, 20.0f, 25.0f);
1066+
1067+ xmock_server_time += 20;
1068+
1069+ SendTouchEvent(XI_TouchUpdate, 1, 10.0f, 35.0f);
1070+ SendTouchEvent(XI_TouchUpdate, 2, 20.0f, 35.0f);
1071+
1072+ xmock_server_time += 20;
1073+
1074+ SendTouchEvent(XI_TouchEnd, 1, 10.0f, 50.0f);
1075+ SendTouchEvent(XI_TouchEnd, 2, 20.0f, 50.0f);
1076+}
1077+
1078+void ConfigureNewDevice::SendXIDeviceAddedEvent()
1079+{
1080+ XEvent event;
1081+ XGenericEventCookie *xcookie = 0;
1082+ XIHierarchyEvent *hierarchy_event;
1083+ XIHierarchyInfo *info;
1084+
1085+ info = (XIHierarchyInfo*)calloc(1, sizeof(XIHierarchyInfo));
1086+ info->deviceid = xmock_devices[0].deviceid;
1087+ info->enabled = True;
1088+ info->flags = XISlaveAdded;
1089+
1090+ hierarchy_event = (XIHierarchyEvent*)calloc(1, sizeof(XIHierarchyEvent));
1091+ hierarchy_event->type = GenericEvent;
1092+ hierarchy_event->serial = _xevent_serial_number++;
1093+ hierarchy_event->display = xmock_display;
1094+ hierarchy_event->extension = xmock_xi2_opcode;
1095+ hierarchy_event->evtype = XI_HierarchyChanged;
1096+ hierarchy_event->time = xmock_server_time;
1097+ hierarchy_event->flags = XISlaveAdded;
1098+ hierarchy_event->num_info = 1;
1099+ hierarchy_event->info = info;
1100+
1101+ event.type = GenericEvent;
1102+ xcookie = &event.xcookie;
1103+ xcookie->extension = xmock_xi2_opcode;
1104+ xcookie->evtype = XI_HierarchyChanged;
1105+ xcookie->data = hierarchy_event;
1106+ xmock_add_to_event_queue(&event);
1107+}
1108+
1109+TEST_F(ConfigureNewDevice, Test)
1110+{
1111+ _geis = geis_new(GEIS_INIT_GRAIL_BACKEND,
1112+ GEIS_INIT_NO_ATOMIC_GESTURES,
1113+ nullptr);
1114+ ASSERT_NE(nullptr, _geis);
1115+
1116+ Run();
1117+
1118+ if (_subscription)
1119+ geis_subscription_delete(_subscription);
1120+
1121+ if (_drag_class)
1122+ geis_gesture_class_unref(_drag_class);
1123+
1124+ geis_delete(_geis);
1125+
1126+ DestroyXMockDevices();
1127+}
1128
1129=== modified file 'testsuite/geis2/gtest_grail_backend.cpp'
1130--- testsuite/geis2/gtest_grail_backend.cpp 2012-07-05 17:13:06 +0000
1131+++ testsuite/geis2/gtest_grail_backend.cpp 2012-09-05 18:11:18 +0000
1132@@ -168,6 +168,9 @@
1133 case GEIS_EVENT_INIT_COMPLETE:
1134 OnEventInitComplete(event);
1135 break;
1136+ case GEIS_EVENT_CLASS_AVAILABLE:
1137+ OnEventClassAvailable(event);
1138+ break;
1139 case GEIS_EVENT_GESTURE_BEGIN:
1140 OnEventGestureBegin(event);
1141 break;
1142
1143=== modified file 'testsuite/geis2/gtest_grail_backend.h'
1144--- testsuite/geis2/gtest_grail_backend.h 2012-07-05 17:13:06 +0000
1145+++ testsuite/geis2/gtest_grail_backend.h 2012-09-05 18:11:18 +0000
1146@@ -47,6 +47,7 @@
1147 void DestroyXMockDevices();
1148
1149 virtual void OnEventInitComplete(GeisEvent event) {}
1150+ virtual void OnEventClassAvailable(GeisEvent event) {}
1151 virtual void OnEventGestureBegin(GeisEvent event) {}
1152 virtual void OnEventGestureUpdate(GeisEvent event) {}
1153 virtual void OnEventGestureEnd(GeisEvent event) {}
1154@@ -59,11 +60,12 @@
1155 void GetGestureTimestampInEvent(GeisInteger *timestamp, GeisEvent event);
1156
1157 Geis _geis;
1158- private:
1159
1160 /* holds the serial number to be used on the next synthetic XEvent */
1161 int _xevent_serial_number;
1162
1163+ private:
1164+
1165 bool DispatchAndProcessEvents();
1166
1167 void AcceptRejectGestureInEvent(GeisEvent event, bool accept);
1168
1169=== modified file 'testsuite/x11_mocks/x11_mocks.c'
1170--- testsuite/x11_mocks/x11_mocks.c 2012-04-25 17:23:11 +0000
1171+++ testsuite/x11_mocks/x11_mocks.c 2012-09-05 18:11:18 +0000
1172@@ -194,6 +194,14 @@
1173 free(device_event->valuators.mask);
1174 free(device_event->valuators.values);
1175 }
1176+ else if (cookie->evtype == XI_HierarchyChanged)
1177+ {
1178+ XIHierarchyEvent *hierarchy_event = (XIHierarchyEvent*) cookie->data;
1179+ for (int i = 0; i < hierarchy_event->num_info; ++i)
1180+ {
1181+ free(&(hierarchy_event->info[i]));
1182+ }
1183+ }
1184 free(cookie->data);
1185 }
1186 }

Subscribers

People subscribed via source and target branches