Status: | Merged |
---|---|
Merged at revision: | 234 |
Proposed branch: | lp:~bregma/geis/lp-944822 |
Merge into: | lp:geis |
Diff against target: |
919 lines (+630/-45) 9 files modified
libutouch-geis/backend/grail/geis_grail_backend.c (+151/-42) libutouch-geis/backend/grail/geis_ugsubscription_store.c (+39/-1) libutouch-geis/backend/grail/geis_ugsubscription_store.h (+14/-0) libutouch-geis/geis_filter_term.c (+123/-0) libutouch-geis/geis_filter_term.h (+11/-0) testsuite/geis2/gtest_devices.cpp (+182/-2) testsuite/libutouch-geis/Makefile.am (+1/-0) testsuite/libutouch-geis/check_filter_term.c (+107/-0) testsuite/libutouch-geis/check_geis2_internals.c (+2/-0) |
To merge this branch: | bzr merge lp:~bregma/geis/lp-944822 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Chase Douglas (community) | Approve | ||
Review via email: mp+99851@code.launchpad.net |
Commit message
Description of the change
Adds handling of device additon and removal after subscriptions have been activated (lp: #944822).
To post a comment you must log in.
lp:~bregma/geis/lp-944822
updated
- 230. By Stephen M. Webb
-
Fixed test case names and conditions.
- 231. By Stephen M. Webb
-
Fixed problems with integration tests failing after GeisDeviceTests
.removeDeviceSu bscription was run.
Revision history for this message
Stephen M. Webb (bregma) wrote : | # |
Test condition fixed, names changed, and test failures remedied.
Revision history for this message
Chase Douglas (chasedouglas) wrote : | # |
Looks good.
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'libutouch-geis/backend/grail/geis_grail_backend.c' |
2 | --- libutouch-geis/backend/grail/geis_grail_backend.c 2012-03-28 21:31:54 +0000 |
3 | +++ libutouch-geis/backend/grail/geis_grail_backend.c 2012-03-29 18:37:22 +0000 |
4 | @@ -32,6 +32,7 @@ |
5 | #include "geis_group.h" |
6 | #include "geis_logging.h" |
7 | #include "geis_private.h" |
8 | +#include "geis_subscription.h" |
9 | #include "geis_test_api.h" |
10 | #include "geis_touch.h" |
11 | #include "geis_ugsubscription_store.h" |
12 | @@ -89,6 +90,7 @@ |
13 | GeisBag devices; /**< The list of known devices. */ |
14 | GeisGrailWindowGrabStore window_grabs; /**< A collection of window inputs */ |
15 | GeisBag slice_states; /**< Gesture slice states */ |
16 | + GeisSubBag subscription_bag; |
17 | |
18 | GeisGestureClass drag_class; |
19 | GeisGestureClass pinch_class; |
20 | @@ -101,6 +103,12 @@ |
21 | }; |
22 | |
23 | |
24 | +static GeisStatus |
25 | +_grail_be_activate_for_device(GeisGrailBackend gbe, |
26 | + GeisFilter filter, |
27 | + GeisDevice device, |
28 | + GeisSubscription subscription); |
29 | + |
30 | /** |
31 | * Hashes an ID from a UFDevice. |
32 | * |
33 | @@ -640,6 +648,61 @@ |
34 | |
35 | |
36 | /** |
37 | + * Activates active subscriptions for a newly-seen device. |
38 | + */ |
39 | +static void |
40 | +_grail_be_subscribe_new_device(GeisGrailBackend gbe, GeisDevice device) |
41 | +{ |
42 | + for (GeisSubBagIterator it = geis_subscription_bag_begin(gbe->subscription_bag); |
43 | + it != geis_subscription_bag_end(gbe->subscription_bag); |
44 | + it = geis_subscription_bag_iterator_next(gbe->subscription_bag, it)) |
45 | + { |
46 | + for (GeisFilterIterator fit = geis_subscription_filter_begin(*it); |
47 | + fit != geis_subscription_filter_end(*it); |
48 | + fit = geis_subscription_filter_next(*it, fit)) |
49 | + { |
50 | + GeisBoolean device_applies = GEIS_TRUE; |
51 | + for (GeisSize tindex = 0; tindex < geis_filter_term_count(*fit); ++tindex) |
52 | + { |
53 | + if (!geis_filter_term_match_device(geis_filter_term(*fit, tindex), |
54 | + device)) |
55 | + { |
56 | + device_applies = GEIS_FALSE; |
57 | + break; |
58 | + } |
59 | + } |
60 | + |
61 | + if (device_applies) |
62 | + { |
63 | + _grail_be_activate_for_device(gbe, *fit, device, *it); |
64 | + } |
65 | + } |
66 | + } |
67 | +} |
68 | + |
69 | + |
70 | +/** |
71 | + * Removes active subscriptions for recently-removed devices. |
72 | + */ |
73 | +static void |
74 | +_grail_be_unsubscribe_removed_device(GeisGrailBackend gbe, UFDevice device) |
75 | +{ |
76 | + for (GeisSubBagIterator it = geis_subscription_bag_begin(gbe->subscription_bag); |
77 | + it != geis_subscription_bag_end(gbe->subscription_bag); |
78 | + it = geis_subscription_bag_iterator_next(gbe->subscription_bag, it)) |
79 | + { |
80 | + GeisUGSubscriptionStore ugstore = geis_subscription_pdata(*it); |
81 | + for (GeisFilterIterator fit = geis_subscription_filter_begin(*it); |
82 | + fit != geis_subscription_filter_end(*it); |
83 | + fit = geis_subscription_filter_next(*it, fit)) |
84 | + { |
85 | + geis_ugsubscription_release_for_device(ugstore, *fit, device, gbe->window_grabs); |
86 | + } |
87 | + } |
88 | +} |
89 | + |
90 | + |
91 | +/** |
92 | * Reports an X11 device to the front end as a GEIS device. |
93 | */ |
94 | static void |
95 | @@ -738,7 +801,7 @@ |
96 | / sizeof(struct GeisFilterableAttribute); |
97 | |
98 | geis_register_device(gbe->geis, geis_device, attr_count, attrs); |
99 | - goto final_exit; |
100 | + _grail_be_subscribe_new_device(gbe, geis_device); |
101 | |
102 | final_exit: |
103 | return; |
104 | @@ -758,6 +821,8 @@ |
105 | return; |
106 | } |
107 | |
108 | + _grail_be_unsubscribe_removed_device(gbe, frame_device); |
109 | + |
110 | for (GeisSize i = 0; i < geis_bag_count(gbe->devices); ++i) |
111 | { |
112 | UFDevice *device = geis_bag_at(gbe->devices, i); |
113 | @@ -1204,6 +1269,12 @@ |
114 | goto unwind_grabs; |
115 | } |
116 | |
117 | + gbe->subscription_bag = geis_subscription_bag_new(1); |
118 | + if (!gbe->subscription_bag) |
119 | + { |
120 | + goto unwind_slice_states; |
121 | + } |
122 | + |
123 | geis_get_configuration(gbe->geis, |
124 | GEIS_CONFIG_SEND_TENTATIVE_EVENTS, |
125 | &gbe->send_tentative_events); |
126 | @@ -1217,6 +1288,8 @@ |
127 | _geis_grail_report_init_complete(gbe); |
128 | goto final_exit; |
129 | |
130 | +unwind_slice_states: |
131 | + geis_bag_delete(gbe->slice_states); |
132 | unwind_grabs: |
133 | geis_grail_window_grab_store_delete(gbe->window_grabs); |
134 | unwind_devices: |
135 | @@ -1238,10 +1311,12 @@ |
136 | |
137 | |
138 | static int |
139 | -_grail_be_x_error_handler(Display* display GEIS_UNUSED, |
140 | - XErrorEvent* event GEIS_UNUSED) |
141 | +_grail_be_x_error_handler(Display* display, |
142 | + XErrorEvent* event) |
143 | { |
144 | - geis_error("error in X detected"); |
145 | + char buffer[512]; |
146 | + XGetErrorText(display, (int)event->error_code, buffer, 511); |
147 | + geis_error("error %u in X detected: %s", (unsigned)event->error_code, buffer); |
148 | return 0; |
149 | } |
150 | |
151 | @@ -1255,6 +1330,7 @@ |
152 | _geis_grail_backend_finalize(GeisBackend be) |
153 | { |
154 | GeisGrailBackend gbe = (GeisGrailBackend)be; |
155 | + geis_subscription_bag_delete(gbe->subscription_bag); |
156 | geis_bag_delete(gbe->slice_states); |
157 | geis_grail_window_grab_store_delete(gbe->window_grabs); |
158 | geis_bag_delete(gbe->devices); |
159 | @@ -1630,51 +1706,44 @@ |
160 | } |
161 | |
162 | |
163 | -/** |
164 | - * Activates a subscription for a list of devices. |
165 | - */ |
166 | static GeisStatus |
167 | -_geis_grail_activate_for_devices(GeisGrailBackend gbe, |
168 | - GeisFilter filter, |
169 | - GeisDeviceBag device_bag, |
170 | - GeisSubscription subscription) |
171 | +_grail_be_activate_for_device(GeisGrailBackend gbe, |
172 | + GeisFilter filter, |
173 | + GeisDevice device, |
174 | + GeisSubscription subscription) |
175 | { |
176 | GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; |
177 | - for (GeisSize d = 0; d < geis_device_bag_count(device_bag); ++d) |
178 | + GeisBoolean has_region_term = GEIS_FALSE; |
179 | + if (filter) |
180 | { |
181 | - GeisDevice device = geis_device_bag_device(device_bag, d); |
182 | - GeisBoolean has_region_term = GEIS_FALSE; |
183 | - if (filter) |
184 | + for (GeisSize i = 0; i < geis_filter_term_count(filter); ++i) |
185 | { |
186 | - for (GeisSize i = 0; i < geis_filter_term_count(filter); ++i) |
187 | + GeisFilterTerm term = geis_filter_term(filter, i); |
188 | + if (GEIS_FILTER_REGION == geis_filter_term_facility(term)) |
189 | { |
190 | - GeisFilterTerm term = geis_filter_term(filter, i); |
191 | - if (GEIS_FILTER_REGION == geis_filter_term_facility(term)) |
192 | - { |
193 | - GeisInteger window_id = 0; |
194 | - GeisAttr attr = geis_filter_term_attr(term); |
195 | - GeisString name = geis_attr_name(attr); |
196 | - GeisFilterOperation operation = geis_filter_term_operation(term); |
197 | + GeisInteger window_id = 0; |
198 | + GeisAttr attr = geis_filter_term_attr(term); |
199 | + GeisString name = geis_attr_name(attr); |
200 | + GeisFilterOperation operation = geis_filter_term_operation(term); |
201 | |
202 | - if (0 == strcmp(name, GEIS_REGION_ATTRIBUTE_WINDOWID) |
203 | - && operation == GEIS_FILTER_OP_EQ) |
204 | - { |
205 | - window_id = geis_attr_value_to_integer(attr); |
206 | - has_region_term = GEIS_TRUE; |
207 | - status = _geis_grail_activate_for_device_region(gbe, |
208 | - filter, |
209 | - device, |
210 | - window_id, |
211 | - subscription); |
212 | - if (status != GEIS_STATUS_SUCCESS) |
213 | - { |
214 | - goto final_exit; |
215 | - } |
216 | - } |
217 | - else |
218 | - { |
219 | - geis_warning("unhandled region filter term"); |
220 | - } |
221 | + if (0 == strcmp(name, GEIS_REGION_ATTRIBUTE_WINDOWID) |
222 | + && operation == GEIS_FILTER_OP_EQ) |
223 | + { |
224 | + window_id = geis_attr_value_to_integer(attr); |
225 | + has_region_term = GEIS_TRUE; |
226 | + status = _geis_grail_activate_for_device_region(gbe, |
227 | + filter, |
228 | + device, |
229 | + window_id, |
230 | + subscription); |
231 | + if (status != GEIS_STATUS_SUCCESS) |
232 | + { |
233 | + goto final_exit; |
234 | + } |
235 | + } |
236 | + else |
237 | + { |
238 | + geis_warning("unhandled region filter term"); |
239 | } |
240 | } |
241 | } |
242 | @@ -1695,6 +1764,28 @@ |
243 | return status; |
244 | } |
245 | |
246 | + |
247 | +/** |
248 | + * Activates a subscription for a list of devices. |
249 | + */ |
250 | +static GeisStatus |
251 | +_geis_grail_activate_for_devices(GeisGrailBackend gbe, |
252 | + GeisFilter filter, |
253 | + GeisDeviceBag device_bag, |
254 | + GeisSubscription subscription) |
255 | +{ |
256 | + GeisStatus status = GEIS_STATUS_SUCCESS; |
257 | + for (GeisSize d = 0; d < geis_device_bag_count(device_bag); ++d) |
258 | + { |
259 | + GeisDevice device = geis_device_bag_device(device_bag, d); |
260 | + status = _grail_be_activate_for_device(gbe, filter, device, subscription); |
261 | + if (status != GEIS_STATUS_SUCCESS) |
262 | + break; |
263 | + } |
264 | + |
265 | + return status; |
266 | +} |
267 | + |
268 | static GeisStatus |
269 | _geis_grail_activate_with_filters(GeisGrailBackend gbe, |
270 | GeisSubscription subscription) |
271 | @@ -1760,6 +1851,13 @@ |
272 | { |
273 | GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; |
274 | |
275 | + if (geis_subscription_bag_find(gbe->subscription_bag, |
276 | + geis_subscription_id(subscription))) |
277 | + { |
278 | + geis_warning("subscription is already activated"); |
279 | + goto final_exit; |
280 | + } |
281 | + |
282 | GeisUGSubscriptionStore ugstore = geis_subscription_pdata(subscription); |
283 | if (ugstore == NULL) |
284 | { |
285 | @@ -1784,6 +1882,8 @@ |
286 | subscription); |
287 | } |
288 | |
289 | + geis_subscription_bag_insert(gbe->subscription_bag, subscription); |
290 | + |
291 | final_exit: |
292 | return status; |
293 | } |
294 | @@ -1800,6 +1900,13 @@ |
295 | { |
296 | GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; |
297 | |
298 | + if (!geis_subscription_bag_find(gbe->subscription_bag, |
299 | + geis_subscription_id(subscription))) |
300 | + { |
301 | + geis_warning("deactivating a subscription that is not active"); |
302 | + goto final_exit; |
303 | + } |
304 | + |
305 | GeisUGSubscriptionStore ugstore = geis_subscription_pdata(subscription); |
306 | if (ugstore) |
307 | { |
308 | @@ -1824,9 +1931,11 @@ |
309 | } |
310 | |
311 | grail_subscription_deactivate(gbe->grail, ugsub); |
312 | + geis_subscription_bag_remove(gbe->subscription_bag, subscription); |
313 | } |
314 | } |
315 | |
316 | +final_exit: |
317 | return status; |
318 | } |
319 | |
320 | |
321 | === modified file 'libutouch-geis/backend/grail/geis_ugsubscription_store.c' |
322 | --- libutouch-geis/backend/grail/geis_ugsubscription_store.c 2012-02-13 17:23:34 +0000 |
323 | +++ libutouch-geis/backend/grail/geis_ugsubscription_store.c 2012-03-29 18:37:22 +0000 |
324 | @@ -83,7 +83,7 @@ |
325 | GeisSize index) |
326 | { |
327 | assert(index < geis_bag_count(store)); |
328 | - return *(UGSubscription*)geis_bag_at(store, index); |
329 | + return ((GeisUGSubscription)geis_bag_at(store, index))->ugsub; |
330 | } |
331 | |
332 | |
333 | @@ -147,6 +147,44 @@ |
334 | } |
335 | |
336 | |
337 | +void |
338 | +geis_ugsubscription_release_for_device(GeisUGSubscriptionStore store, |
339 | + GeisFilter filter, |
340 | + UFDevice device, |
341 | + GeisGrailWindowGrabStore window_grabs) |
342 | +{ |
343 | + GeisSize i = 0; |
344 | + while (i < geis_bag_count(store)) |
345 | + { |
346 | + GeisUGSubscription s = (GeisUGSubscription)geis_bag_at(store, i); |
347 | + if (s->filter == filter && s->device == device) |
348 | + { |
349 | + UFWindowId ufwindow; |
350 | + UGStatus ugstatus; |
351 | + ugstatus = grail_subscription_get_property(s->ugsub, |
352 | + UGSubscriptionPropertyWindow, |
353 | + &ufwindow); |
354 | + if (ugstatus != UGStatusSuccess) |
355 | + { |
356 | + geis_warning("error %d getting subscription window", ugstatus); |
357 | + } |
358 | + else |
359 | + { |
360 | + Window window_id = frame_x11_get_window_id(ufwindow); |
361 | + geis_grail_window_grab_store_ungrab(window_grabs, window_id); |
362 | + } |
363 | + |
364 | + grail_subscription_delete(s->ugsub); |
365 | + geis_bag_remove(store, i); |
366 | + } |
367 | + else |
368 | + { |
369 | + ++i; |
370 | + } |
371 | + } |
372 | +} |
373 | + |
374 | + |
375 | /* |
376 | * Releses a UGSubscription from the store. |
377 | */ |
378 | |
379 | === modified file 'libutouch-geis/backend/grail/geis_ugsubscription_store.h' |
380 | --- libutouch-geis/backend/grail/geis_ugsubscription_store.h 2012-02-10 04:26:23 +0000 |
381 | +++ libutouch-geis/backend/grail/geis_ugsubscription_store.h 2012-03-29 18:37:22 +0000 |
382 | @@ -22,6 +22,7 @@ |
383 | |
384 | #include "geis/geis.h" |
385 | #include "geis_bag.h" |
386 | +#include "geis_grail_window_grab.h" |
387 | #include <utouch/grail.h> |
388 | |
389 | |
390 | @@ -95,6 +96,19 @@ |
391 | GeisInteger region_id); |
392 | |
393 | /** |
394 | + * Releases all UGSubscriptions for a (filter, device). |
395 | + * @param[in] store The grail subscription store. |
396 | + * @param[in] filter Identifies a filter. |
397 | + * @param[in] device Identifies a device. |
398 | + * @param[in] window_grabs A window grab collection. |
399 | + */ |
400 | +void |
401 | +geis_ugsubscription_release_for_device(GeisUGSubscriptionStore store, |
402 | + GeisFilter filter, |
403 | + UFDevice device, |
404 | + GeisGrailWindowGrabStore window_grabs); |
405 | + |
406 | +/** |
407 | * Releses a UGSubscription from the store. |
408 | * @param[in] store The grail subscription store. |
409 | * @param[in] ugsub The UGSubscription to release. |
410 | |
411 | === modified file 'libutouch-geis/geis_filter_term.c' |
412 | --- libutouch-geis/geis_filter_term.c 2011-10-18 18:41:30 +0000 |
413 | +++ libutouch-geis/geis_filter_term.c 2012-03-29 18:37:22 +0000 |
414 | @@ -369,3 +369,126 @@ |
415 | } |
416 | |
417 | |
418 | +/** |
419 | + * Indicates if an attr string value matches a given string and condition. |
420 | + * |
421 | + * @param[in] attr The attr with a string value. |
422 | + * @param[in] op A match condition. |
423 | + * @param[in] svalue A target string value to match. |
424 | + * |
425 | + * @returns GEIS_TRUE if the attr string value matches the target string and |
426 | + * condition, GEIS_FALSE otherwise. |
427 | + */ |
428 | +static GeisBoolean |
429 | +_filter_matches_attr_string(GeisAttr attr, |
430 | + GeisFilterOperation op, |
431 | + GeisString svalue) |
432 | +{ |
433 | + GeisBoolean strings_match = GEIS_FALSE; |
434 | + GeisString attr_value = geis_attr_value_to_string(attr); |
435 | + if (attr_value) |
436 | + { |
437 | + strings_match = (0 == strcmp(attr_value, svalue)); |
438 | + } |
439 | + return (op == GEIS_FILTER_OP_EQ && strings_match) |
440 | + || (op == GEIS_FILTER_OP_NE && !strings_match); |
441 | +} |
442 | + |
443 | + |
444 | +/** |
445 | + * Indicates if an attr boolean value matches a given value and condition. |
446 | + * |
447 | + * @param[in] attr The attr with a string value. |
448 | + * @param[in] op A match condition. |
449 | + * @param[in] bvalue A target boolean value to match. |
450 | + * |
451 | + * @returns GEIS_TRUE if the attr boolean value matches the target value and |
452 | + * condition, GEIS_FALSE otherwise. |
453 | + */ |
454 | +static GeisBoolean |
455 | +_filter_matches_attr_boolean(GeisAttr attr, |
456 | + GeisFilterOperation op, |
457 | + GeisBoolean bvalue) |
458 | +{ |
459 | + GeisBoolean attr_value = geis_attr_value_to_boolean(attr); |
460 | + return (op == GEIS_FILTER_OP_EQ && attr_value == bvalue) |
461 | + || (op == GEIS_FILTER_OP_NE && attr_value != bvalue); |
462 | +} |
463 | + |
464 | + |
465 | +/** |
466 | + * Indicates if an attr integer value matches a given value and condition. |
467 | + * |
468 | + * @param[in] attr The attr with a string value. |
469 | + * @param[in] op A match condition. |
470 | + * @param[in] ivalue A target integer value to match. |
471 | + * |
472 | + * @returns GEIS_TRUE if the attr integer value matches the target value and |
473 | + * condition, GEIS_FALSE otherwise. |
474 | + */ |
475 | +static GeisBoolean |
476 | +_filter_matches_attr_integer(GeisAttr attr, |
477 | + GeisFilterOperation op, |
478 | + GeisInteger ivalue) |
479 | +{ |
480 | + GeisInteger attr_value = geis_attr_value_to_integer(attr); |
481 | + return (op == GEIS_FILTER_OP_EQ && attr_value == ivalue) |
482 | + || (op == GEIS_FILTER_OP_NE && attr_value != ivalue) |
483 | + || (op == GEIS_FILTER_OP_GT && attr_value > ivalue) |
484 | + || (op == GEIS_FILTER_OP_GE && attr_value >= ivalue) |
485 | + || (op == GEIS_FILTER_OP_LE && attr_value <= ivalue) |
486 | + || (op == GEIS_FILTER_OP_LT && attr_value < ivalue); |
487 | +} |
488 | + |
489 | + |
490 | +/* |
491 | + * Indicates a filter passes a device. |
492 | + */ |
493 | +GeisBoolean |
494 | +geis_filter_term_match_device(GeisFilterTerm term, GeisDevice device) |
495 | +{ |
496 | + if (geis_filter_term_facility(term) != GEIS_FILTER_DEVICE) |
497 | + { |
498 | + return GEIS_TRUE; |
499 | + } |
500 | + |
501 | + GeisAttr filter_attr = geis_filter_term_attr(term); |
502 | + GeisString attr_name = geis_attr_name(filter_attr); |
503 | + GeisFilterOperation op = geis_filter_term_operation(term); |
504 | + |
505 | + if (0 == strcmp(attr_name, GEIS_DEVICE_ATTRIBUTE_NAME)) |
506 | + { |
507 | + GeisString device_name = geis_device_name(device); |
508 | + if (device_name) |
509 | + { |
510 | + return _filter_matches_attr_string(filter_attr, op, device_name); |
511 | + } |
512 | + } |
513 | + else if (0 == strcmp(attr_name, GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH) |
514 | + || 0 == strcmp(attr_name, GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH)) |
515 | + { |
516 | + GeisAttr device_attr = geis_device_attr_by_name(device, attr_name); |
517 | + if (device_attr) |
518 | + { |
519 | + GeisBoolean device_value = geis_attr_value_to_boolean(device_attr); |
520 | + return _filter_matches_attr_boolean(filter_attr, op, device_value); |
521 | + } |
522 | + } |
523 | + else if (0 == strcmp(attr_name, GEIS_DEVICE_ATTRIBUTE_ID) |
524 | + || 0 == strcmp(attr_name, GEIS_DEVICE_ATTRIBUTE_TOUCHES)) |
525 | + { |
526 | + GeisAttr device_attr = geis_device_attr_by_name(device, attr_name); |
527 | + if (device_attr) |
528 | + { |
529 | + GeisInteger device_value = geis_attr_value_to_integer(device_attr); |
530 | + /* legacy special case for device ID == 0: means ALL devices in v1 */ |
531 | + if (device_value == 0) |
532 | + { |
533 | + return GEIS_TRUE; |
534 | + } |
535 | + return _filter_matches_attr_integer(filter_attr, op, device_value); |
536 | + } |
537 | + } |
538 | + return GEIS_FALSE; |
539 | +} |
540 | + |
541 | |
542 | === modified file 'libutouch-geis/geis_filter_term.h' |
543 | --- libutouch-geis/geis_filter_term.h 2011-10-13 17:49:59 +0000 |
544 | +++ libutouch-geis/geis_filter_term.h 2012-03-29 18:37:22 +0000 |
545 | @@ -93,6 +93,17 @@ |
546 | */ |
547 | GeisBoolean geis_filter_term_match_event(GeisFilterTerm term, GeisEvent event); |
548 | |
549 | +/** |
550 | + * Indicates a filter passes a device. |
551 | + * |
552 | + * @param[in] term The filter term. |
553 | + * @param[in] device A GEIS device. |
554 | + * |
555 | + * @returns GEIS_TRUE if the device is passed by the filter, GEIS_FALSE |
556 | + * otherwise. |
557 | + */ |
558 | +GeisBoolean geis_filter_term_match_device(GeisFilterTerm term, GeisDevice device); |
559 | + |
560 | /** @} */ |
561 | |
562 | /** |
563 | |
564 | === modified file 'testsuite/geis2/gtest_devices.cpp' |
565 | --- testsuite/geis2/gtest_devices.cpp 2012-03-22 18:44:56 +0000 |
566 | +++ testsuite/geis2/gtest_devices.cpp 2012-03-29 18:37:22 +0000 |
567 | @@ -4,13 +4,20 @@ |
568 | * Copyright 2012 Canonical Ltd. |
569 | */ |
570 | #include "geis/geis.h" |
571 | +#include "gtest_evemu_device.h" |
572 | +#include "gtest_geis_fixture.h" |
573 | #include "libutouch-geis/geis_test_api.h" |
574 | -#include "gtest_geis_fixture.h" |
575 | +#include <memory> |
576 | +#include <sys/select.h> |
577 | +#include <sys/time.h> |
578 | |
579 | |
580 | namespace |
581 | { |
582 | |
583 | +static const std::string TEST_DEVICE_PROP_FILE("touchscreen_a.prop"); |
584 | +static const std::string TEST_DEVICE_EVENTS_FILE("touchscreen_a_rotate90.events"); |
585 | + |
586 | /** |
587 | * Fixture for testing device handling. |
588 | * This is a separate class because gtest uses Java reflection. |
589 | @@ -29,7 +36,7 @@ |
590 | }; |
591 | |
592 | |
593 | -TEST_F(GeisDeviceTests, filter_with_no_devices) |
594 | +TEST_F(GeisDeviceTests, filterWithNoDevices) |
595 | { |
596 | GeisSubscription sub = geis_subscription_new(geis_, |
597 | "no devices", |
598 | @@ -48,4 +55,177 @@ |
599 | geis_subscription_delete(sub); |
600 | } |
601 | |
602 | + |
603 | +/* |
604 | + * Test case 1 for lp:944822 -- device added after subscription activated. |
605 | + * |
606 | + * Creates a subscriptions with a device filter (there are no devices present in |
607 | + * the system). When initializatiom signalled as complete, device events are |
608 | + * reenabled in the geis instance and a new device is added. When the |
609 | + * device-added event is received, a recording is run through the device. |
610 | + * Gesture events should be detected. |
611 | + */ |
612 | +TEST_F(GeisDeviceTests, addDeviceSubscription) |
613 | +{ |
614 | + std::unique_ptr<Testsuite::EvemuDevice> new_device; |
615 | + GeisBoolean device_has_been_created = GEIS_FALSE; |
616 | + GeisBoolean gesture_events_received = GEIS_FALSE; |
617 | + |
618 | + GeisSubscription sub = geis_subscription_new(geis_, |
619 | + "no devices", |
620 | + GEIS_SUBSCRIPTION_NONE); |
621 | + EXPECT_TRUE(sub != NULL) << "can not create subscription"; |
622 | + GeisFilter filter = geis_filter_new(geis_, "rotate"); |
623 | + EXPECT_TRUE(filter != NULL) << "can not create filter"; |
624 | + GeisStatus fs = geis_filter_add_term(filter, |
625 | + GEIS_FILTER_DEVICE, |
626 | + GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_FILTER_OP_EQ, GEIS_TRUE, |
627 | + NULL); |
628 | + EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add device term"; |
629 | + fs = geis_subscription_add_filter(sub, filter); |
630 | + EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add device term"; |
631 | + |
632 | + GeisStatus dispatch_status= geis_dispatch_events(geis_); |
633 | + while (dispatch_status == GEIS_STATUS_CONTINUE |
634 | + || dispatch_status == GEIS_STATUS_SUCCESS) |
635 | + { |
636 | + GeisEvent event; |
637 | + GeisStatus event_status = geis_next_event(geis_, &event); |
638 | + while (event_status == GEIS_STATUS_CONTINUE |
639 | + || event_status == GEIS_STATUS_SUCCESS) |
640 | + { |
641 | + switch (geis_event_type(event)) |
642 | + { |
643 | + case GEIS_EVENT_INIT_COMPLETE: |
644 | + { |
645 | + EXPECT_EQ(GEIS_STATUS_SUCCESS, geis_subscription_activate(sub)) |
646 | + << "can not activate subscription"; |
647 | + |
648 | + GeisBoolean off = GEIS_FALSE; |
649 | + geis_set_configuration(geis_, |
650 | + GEIS_CONFIG_DISCARD_DEVICE_MESSAGES, |
651 | + &off); |
652 | + new_device.reset(new Testsuite::EvemuDevice(TEST_DEVICE_PROP_FILE)); |
653 | + device_has_been_created = GEIS_TRUE; |
654 | + break; |
655 | + } |
656 | + |
657 | + case GEIS_EVENT_DEVICE_AVAILABLE: |
658 | + new_device->play(TEST_DEVICE_EVENTS_FILE); |
659 | + break; |
660 | + |
661 | + case GEIS_EVENT_GESTURE_BEGIN: |
662 | + case GEIS_EVENT_GESTURE_UPDATE: |
663 | + { |
664 | + EXPECT_EQ(device_has_been_created, GEIS_TRUE) |
665 | + << "gesture events without device"; |
666 | + gesture_events_received = device_has_been_created; |
667 | + } |
668 | + |
669 | + default: |
670 | + break; |
671 | + } |
672 | + |
673 | + geis_event_delete(event); |
674 | + event_status = geis_next_event(geis_, &event); |
675 | + } |
676 | + |
677 | + fd_set read_fds; |
678 | + FD_ZERO(&read_fds); |
679 | + FD_SET(geis_fd(), &read_fds); |
680 | + timeval tmo = { 5, 0 }; |
681 | + int sstat = select(geis_fd() + 1, &read_fds, NULL, NULL, &tmo); |
682 | + EXPECT_GT(sstat, -1) << "error in select"; |
683 | + if (sstat == 0) |
684 | + break; |
685 | + dispatch_status = geis_dispatch_events(geis_); |
686 | + } |
687 | + |
688 | + EXPECT_TRUE(gesture_events_received) << "no gesture events received"; |
689 | + EXPECT_TRUE(device_has_been_created) << "no device created"; |
690 | + geis_filter_delete(filter); |
691 | + geis_subscription_delete(sub); |
692 | +} |
693 | + |
694 | + |
695 | +/* |
696 | + * Test case 2 for lp:944822 -- device removed after subscription activated. |
697 | + * |
698 | + * This test really just makes sure nothing segfaults on device removal. |
699 | + */ |
700 | +TEST_F(GeisDeviceTests, removeDeviceSubscription) |
701 | +{ |
702 | + std::unique_ptr<Testsuite::EvemuDevice> new_device; |
703 | + |
704 | + GeisSubscription sub = geis_subscription_new(geis_, |
705 | + "remove devices", |
706 | + GEIS_SUBSCRIPTION_NONE); |
707 | + EXPECT_TRUE(sub != NULL) << "can not create subscription"; |
708 | + GeisFilter filter = geis_filter_new(geis_, "rotate"); |
709 | + EXPECT_TRUE(filter != NULL) << "can not create filter"; |
710 | + GeisStatus fs = geis_filter_add_term(filter, |
711 | + GEIS_FILTER_DEVICE, |
712 | + GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_FILTER_OP_EQ, GEIS_TRUE, |
713 | + NULL); |
714 | + EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add device term"; |
715 | + fs = geis_subscription_add_filter(sub, filter); |
716 | + EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add device term"; |
717 | + |
718 | + GeisStatus dispatch_status= geis_dispatch_events(geis_); |
719 | + while (dispatch_status == GEIS_STATUS_CONTINUE |
720 | + || dispatch_status == GEIS_STATUS_SUCCESS) |
721 | + { |
722 | + GeisEvent event; |
723 | + GeisStatus event_status = geis_next_event(geis_, &event); |
724 | + while (event_status == GEIS_STATUS_CONTINUE |
725 | + || event_status == GEIS_STATUS_SUCCESS) |
726 | + { |
727 | + switch (geis_event_type(event)) |
728 | + { |
729 | + case GEIS_EVENT_INIT_COMPLETE: |
730 | + { |
731 | + GeisBoolean off = GEIS_FALSE; |
732 | + geis_set_configuration(geis_, |
733 | + GEIS_CONFIG_DISCARD_DEVICE_MESSAGES, |
734 | + &off); |
735 | + new_device.reset(new Testsuite::EvemuDevice(TEST_DEVICE_PROP_FILE)); |
736 | + break; |
737 | + } |
738 | + |
739 | + case GEIS_EVENT_DEVICE_AVAILABLE: |
740 | + { |
741 | + EXPECT_EQ(GEIS_STATUS_SUCCESS, geis_subscription_activate(sub)) |
742 | + << "can not activate subscription"; |
743 | + new_device.reset(); |
744 | + break; |
745 | + } |
746 | + |
747 | + case GEIS_EVENT_GESTURE_BEGIN: |
748 | + case GEIS_EVENT_GESTURE_UPDATE: |
749 | + { |
750 | + } |
751 | + |
752 | + default: |
753 | + break; |
754 | + } |
755 | + |
756 | + geis_event_delete(event); |
757 | + event_status = geis_next_event(geis_, &event); |
758 | + } |
759 | + |
760 | + fd_set read_fds; |
761 | + FD_ZERO(&read_fds); |
762 | + FD_SET(geis_fd(), &read_fds); |
763 | + timeval tmo = { 5, 0 }; |
764 | + int sstat = select(geis_fd() + 1, &read_fds, NULL, NULL, &tmo); |
765 | + EXPECT_GT(sstat, -1) << "error in select"; |
766 | + if (sstat == 0) |
767 | + break; |
768 | + dispatch_status = geis_dispatch_events(geis_); |
769 | + } |
770 | + geis_filter_delete(filter); |
771 | + geis_subscription_delete(sub); |
772 | +} |
773 | + |
774 | + |
775 | } // anonymous namespace |
776 | |
777 | === modified file 'testsuite/libutouch-geis/Makefile.am' |
778 | --- testsuite/libutouch-geis/Makefile.am 2012-03-07 03:44:00 +0000 |
779 | +++ testsuite/libutouch-geis/Makefile.am 2012-03-29 18:37:22 +0000 |
780 | @@ -53,6 +53,7 @@ |
781 | check_error_reporting.c \ |
782 | check_event_queue.c \ |
783 | check_filter.c \ |
784 | + check_filter_term.c \ |
785 | check_geis_private.c \ |
786 | check_region.c \ |
787 | check_subscription.c \ |
788 | |
789 | === added file 'testsuite/libutouch-geis/check_filter_term.c' |
790 | --- testsuite/libutouch-geis/check_filter_term.c 1970-01-01 00:00:00 +0000 |
791 | +++ testsuite/libutouch-geis/check_filter_term.c 2012-03-29 18:37:22 +0000 |
792 | @@ -0,0 +1,107 @@ |
793 | +/** |
794 | + * @file check_filter_term.c |
795 | + * @brief unit tests for GEIS filter terms |
796 | + * |
797 | + * Copyright 2012 Canonical Ltd. |
798 | + */ |
799 | +#include <check.h> |
800 | +#include "libutouch-geis/geis_attr.h" |
801 | +#include "libutouch-geis/geis_device.h" |
802 | +#include "libutouch-geis/geis_filter_term.h" |
803 | + |
804 | +/* verify filter term construction/destruction */ |
805 | +START_TEST(construct) |
806 | +{ |
807 | + GeisInteger ival = 0; |
808 | + GeisAttr attr = geis_attr_new("dummy", GEIS_ATTR_TYPE_INTEGER, &ival); |
809 | + fail_unless(attr != NULL, "failed to create filter term attr"); |
810 | + |
811 | + GeisFilterTerm term = geis_filter_term_new(GEIS_FILTER_SPECIAL, |
812 | + GEIS_FILTER_OP_NE, |
813 | + attr); |
814 | + fail_unless(term != NULL, "failed to create filter term"); |
815 | + |
816 | + geis_filter_term_unref(term); |
817 | +} |
818 | +END_TEST |
819 | + |
820 | + |
821 | +/* verify device filtering capability */ |
822 | +START_TEST(device_filter) |
823 | +{ |
824 | + GeisString device_name = "direct"; |
825 | + GeisAttr name_attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_NAME, |
826 | + GEIS_ATTR_TYPE_STRING, |
827 | + (void *)device_name); |
828 | + fail_unless(name_attr != NULL, "failed to create name filter term attr"); |
829 | + GeisFilterTerm name_term = geis_filter_term_new(GEIS_FILTER_DEVICE, |
830 | + GEIS_FILTER_OP_NE, |
831 | + name_attr); |
832 | + fail_unless(name_term != NULL, "failed to create id filter term"); |
833 | + |
834 | + GeisBoolean is_direct = GEIS_TRUE; |
835 | + GeisAttr direct_attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, |
836 | + GEIS_ATTR_TYPE_BOOLEAN, |
837 | + &is_direct); |
838 | + fail_unless(direct_attr != NULL, "failed to create direct filter term attr"); |
839 | + GeisFilterTerm direct_term = geis_filter_term_new(GEIS_FILTER_DEVICE, |
840 | + GEIS_FILTER_OP_EQ, |
841 | + direct_attr); |
842 | + fail_unless(direct_term != NULL, "failed to create direct filter term"); |
843 | + |
844 | + GeisInteger id = 1; |
845 | + GeisAttr id_attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_ID, |
846 | + GEIS_ATTR_TYPE_INTEGER, |
847 | + &id); |
848 | + fail_unless(id_attr != NULL, "failed to create id filter term attr"); |
849 | + GeisFilterTerm id_term = geis_filter_term_new(GEIS_FILTER_DEVICE, |
850 | + GEIS_FILTER_OP_EQ, |
851 | + id_attr); |
852 | + fail_unless(id_term != NULL, "failed to create id filter term"); |
853 | + |
854 | + GeisDevice direct_device = geis_device_new(device_name, id); |
855 | + GeisAttr device_attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, |
856 | + GEIS_ATTR_TYPE_BOOLEAN, |
857 | + &is_direct); |
858 | + fail_unless(device_attr != NULL, "failed to create direct filter term attr"); |
859 | + geis_device_add_attr(direct_device, device_attr); |
860 | + GeisDevice indirect_device = geis_device_new("indirect", id + 1); |
861 | + |
862 | + GeisBoolean passed = GEIS_FALSE; |
863 | + passed = geis_filter_term_match_device(name_term, direct_device); |
864 | + fail_unless(passed != GEIS_TRUE, "direct device was passed by name term"); |
865 | + passed = geis_filter_term_match_device(name_term, indirect_device); |
866 | + fail_unless(passed == GEIS_TRUE, "indirect device was not passed by name term"); |
867 | + passed = geis_filter_term_match_device(direct_term, direct_device); |
868 | + fail_unless(passed == GEIS_TRUE, "direct device was not passed by direct term"); |
869 | + passed = geis_filter_term_match_device(direct_term, indirect_device); |
870 | + fail_unless(passed != GEIS_TRUE, "indirect device was passed by direct term"); |
871 | + passed = geis_filter_term_match_device(id_term, direct_device); |
872 | + fail_unless(passed == GEIS_TRUE, "direct device was not passed by id term"); |
873 | + passed = geis_filter_term_match_device(id_term, indirect_device); |
874 | + fail_unless(passed != GEIS_TRUE, "indirect device was passed by id term"); |
875 | + |
876 | + geis_device_unref(direct_device); |
877 | + geis_device_unref(indirect_device); |
878 | + geis_filter_term_unref(name_term); |
879 | + geis_filter_term_unref(direct_term); |
880 | + geis_filter_term_unref(id_term); |
881 | +} |
882 | +END_TEST |
883 | + |
884 | +/* boilerplate */ |
885 | +Suite * |
886 | +make_filter_term_suite() |
887 | +{ |
888 | + Suite *s = suite_create("utouch-geis2-filter-term"); |
889 | + |
890 | + TCase *create = tcase_create("filter-term-creation"); |
891 | + tcase_add_test(create, construct); |
892 | + suite_add_tcase(s, create); |
893 | + |
894 | + TCase *usage = tcase_create("filter-term-usage"); |
895 | + tcase_add_test(usage, device_filter); |
896 | + suite_add_tcase(s, usage); |
897 | + |
898 | + return s; |
899 | +} |
900 | |
901 | === modified file 'testsuite/libutouch-geis/check_geis2_internals.c' |
902 | --- testsuite/libutouch-geis/check_geis2_internals.c 2011-12-21 04:14:05 +0000 |
903 | +++ testsuite/libutouch-geis/check_geis2_internals.c 2012-03-29 18:37:22 +0000 |
904 | @@ -13,6 +13,7 @@ |
905 | extern Suite *make_error_reporting_suite(); |
906 | extern Suite *make_event_queue_suite(); |
907 | extern Suite *make_filter_suite(); |
908 | +extern Suite *make_filter_term_suite(); |
909 | extern Suite *make_gesture_class_suite(); |
910 | extern Suite *make_region_suite(); |
911 | extern Suite *make_select_devices_suite(); |
912 | @@ -38,6 +39,7 @@ |
913 | srunner_add_suite(sr, make_gesture_class_suite()); |
914 | srunner_add_suite(sr, make_region_suite()); |
915 | srunner_add_suite(sr, make_filter_suite()); |
916 | + srunner_add_suite(sr, make_filter_term_suite()); |
917 | srunner_add_suite(sr, make_select_devices_suite()); |
918 | srunner_add_suite(sr, make_subscription_suite()); |
919 | srunner_add_suite(sr, make_timer_suite()); |
* In the integration test, you have "EXPECT_ EQ(gesture_ events_ received, device_ has_been_ created) ;". If the device hasn't been created and no events are received we have failed, but this will pass. We need to be using EXPECT_TRUE on each individually.
* GTest test names shouldn't include underscores, according to: http:// code.google. com/p/googletes t/wiki/ FAQ#Why_ should_ not_test_ case_names_ and_test_ names_contain_ underscore
Everything else looks good to me.