Merge lp:~dandrader/geis/lp1045785 into lp:geis
- lp1045785
- Merge into trunk
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Chase Douglas (community) | Approve | ||
Review via email: mp+122898@code.launchpad.net |
Commit message
Description of the change
Fixes bug 1045785.
Improved handling of gesture configuration options for GeisSubscriptions
- You can now call geis_subscripti
- 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.
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 | } |
* 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 :).