Merge lp:~bregma/geis/lp-934207 into lp:geis

Proposed by Stephen M. Webb
Status: Merged
Merged at revision: 214
Proposed branch: lp:~bregma/geis/lp-934207
Merge into: lp:geis
Diff against target: 1227 lines (+818/-31)
22 files modified
configure.ac (+4/-4)
include/geis/geis.h (+18/-2)
libutouch-geis/backend/dbus/geis_dbus_backend.c (+23/-0)
libutouch-geis/backend/dbus/geis_dbus_client.c (+24/-0)
libutouch-geis/backend/dbus/geis_dbus_client.h (+27/-0)
libutouch-geis/backend/grail/geis_grail_backend.c (+131/-4)
libutouch-geis/backend/grail/geis_grail_window_grab.c (+13/-1)
libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c (+20/-0)
libutouch-geis/backend/xcb/geis_xcb_backend.c (+23/-1)
libutouch-geis/geis.c (+33/-0)
libutouch-geis/geis_backend.c (+22/-0)
libutouch-geis/geis_backend.h (+24/-0)
libutouch-geis/geis_backend_protected.h (+2/-0)
libutouch-geis/geis_event_queue.c (+63/-4)
libutouch-geis/geis_event_queue.h (+18/-0)
libutouch-geis/geis_frame.c (+0/-8)
libutouch-geis/geis_private.h (+19/-0)
libutouch-geis/libutouch-geis.ver (+1/-0)
testsuite/geis2/Makefile.am (+4/-1)
testsuite/geis2/gtest_subscriptions.cpp (+264/-6)
testsuite/libutouch-geis/check_event_queue.c (+37/-0)
testsuite/libutouch-geis/check_geis_private.c (+48/-0)
To merge this branch: bzr merge lp:~bregma/geis/lp-934207
Reviewer Review Type Date Requested Status
Chase Douglas (community) Approve
Review via email: mp+97019@code.launchpad.net

Description of the change

Exposes gesture accept and reject functionality if available in back end. Closes lp:934207.

Includes unit tests for both reject and accept.

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

* Typo:

geis_warning("error %d gettubg subscription window", ugstatus);

* Does geis have a queue of gesture events, or when you call geis_next_event(), does it only then go get an event from grail? If geis has a queue of grail events, reject needs to remove all matching gesture events from the geis queue.

To go along with this, I would like to see the reject test expanded so that it checks if any further gesture events are received for a rejected gesture.

* The accept test case should accept on the begin event, and check if an end event for the gesture is received. This will ensure that the gesture is actually accepted and not rejected.

* These tests don't check whether a gesture and its touches are really accepted or rejected. To do this, we need a test that has a subwindow that would receive the touch events if the gesture is rejected, and does not receive touch events if the gesture is accepted. I think this is getting into more testing than this specific functionality requires, but if we hit any bugs where geis accept/reject is not being propagated properly we will need to make these tests.

review: Needs Fixing
lp:~bregma/geis/lp-934207 updated
215. By Stephen M. Webb

Added remove_if function to GEIS event queues.

216. By Stephen M. Webb

Added geis_remove_matching_event() function.

217. By Stephen M. Webb

Updated integration test to check for rejected events.

218. By Stephen M. Webb

Added queued event removal on gesture reject.

219. By Stephen M. Webb

fixed typo in warning message

220. By Stephen M. Webb

 Added check got GESTURE_END in gesture-accept test case.

221. By Stephen M. Webb

Fixed an edge case in queued events removal.

Revision history for this message
Stephen M. Webb (bregma) wrote :

* Typo:

Fixed.

* reject needs to remove all matching gesture events from the geis queue.

Since it's impossible to guarantee at the API level that no further event for a rejected gesture will ever come through (event generation is asynchronous over possibly several processes), I figured the application needs to handle this anyway. However, since it is not a big effort to remove these events from the internal GEIS queues, I added this and extended the test case accordingly.

* The accept test case should accept on the begin event, and check if an end event for the gesture is received. This will ensure that the gesture is actually accepted and not rejected.

Sure. Done.

* These tests don't check whether a gesture and its touches are really accepted or rejected. To do this, we need a test that has a subwindow that would receive the touch events if the gesture is rejected, and does not receive touch events if the gesture is accepted. I think this is getting into more testing than this specific functionality requires, but if we hit any bugs where geis accept/reject is not being propagated properly we will need to make these tests.

Yes, I think testing how clients interact with the X server is a little beyond the scope of unit tests for the GEIS API.

Revision history for this message
Chase Douglas (chasedouglas) wrote :

> * reject needs to remove all matching gesture events from the geis queue.
>
> Since it's impossible to guarantee at the API level that no further event for
> a rejected gesture will ever come through (event generation is asynchronous
> over possibly several processes), I figured the application needs to handle
> this anyway. However, since it is not a big effort to remove these events
> from the internal GEIS queues, I added this and extended the test case
> accordingly.

Grail does guarantee this. It does the same queued event removal that you implemented for geis. This ensures that no further events may propagate up the stack after a rejection.

If we implemented things right, the application should not receive any events after a reject call.

Everything looks good to me now. Let's get this merged and released!

review: Approve
Revision history for this message
Stephen M. Webb (bregma) wrote :

GEIS is not grail. GEIS was designed to be able to wrap the native gestures on Windows and MacOS (and other targets). GEIS could be used in a client-server mode to comply with the original requirements established last year, and events could be on the wire. It's possible that a future input server could operate in an asynchronous mode.

GEIS was also designed to be extensible through client-programmable recognizers (long term) that could mutate events.

There is no way for the API to guarantee synchronous removal of asynchronous events on gesture rejection unless some sort of complex blacklisting or ongoing detection of events, at considerable cost.

Yes, this particular implementation of the grail back end can minimize outstanding events on a rejected gesture, assuming it is used in client-embedded mode.

Revision history for this message
Chase Douglas (chasedouglas) wrote :

That's a valid point. In light of that, it's nice that we clean things up :). You're right that we might not be able to guarantee this functionality in all circumstances.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'configure.ac'
2--- configure.ac 2012-03-06 16:38:03 +0000
3+++ configure.ac 2012-03-13 20:56:18 +0000
4@@ -101,9 +101,9 @@
5 AC_MSG_RESULT([$with_integration_tests])
6 AS_IF([test "x$with_integration_tests" != xno],
7 [AC_LANG_PUSH(C++)
8- AC_CHECK_LIB([gtest], [main], [have_gtest=yes])
9- AS_IF([test "x$have_gtest" = xyes],
10- [PKG_CHECK_MODULES([XORG_GTEST],
11+ AC_CHECK_HEADER([gtest/gtest.h],
12+ [AC_SUBST([GTEST_CFLAGS], [-I/usr/src/gtest])
13+ PKG_CHECK_MODULES([XORG_GTEST],
14 [xorg-gtest],
15 [have_xorg_gtest=yes],
16 [AC_MSG_WARN([package 'xorg-gtest' not found: related
17@@ -111,7 +111,7 @@
18 PKG_CHECK_MODULES([EVEMU],[utouch-evemu >= 1.0.5])
19 ])
20 AC_LANG_POP
21- XORG_GTEST_LIBS="$XORG_GTEST_LIBS -lgtest -lpthread"])
22+ XORG_GTEST_LIBS="$XORG_GTEST_LIBS -lpthread"])
23 AM_CONDITIONAL([HAVE_XORG_GTEST],[test "x$have_xorg_gtest" = xyes])
24
25 AC_CONFIG_FILES([Makefile
26
27=== modified file 'include/geis/geis.h'
28--- include/geis/geis.h 2012-02-28 15:15:42 +0000
29+++ include/geis/geis.h 2012-03-13 20:56:18 +0000
30@@ -2086,16 +2086,32 @@
31 GEIS_API GeisTouchId geis_frame_touchid(GeisFrame frame, GeisSize index);
32
33 /**
34+ * Marks a gesture as accepted.
35+ *
36+ * @param[in] geis The GEIS instance.
37+ * @param[in] group The gesture group containing the accepted gesture.
38+ * @param[in] gesture_id Identifies the gesture.
39+ *
40+ * @sa geis_frame_id
41+ */
42+GEIS_API GeisStatus geis_gesture_accept(Geis geis,
43+ GeisGroup group,
44+ GeisGestureId gesture_id);
45+
46+/**
47 * Marks a gesture as rejected.
48- * @memberof GeisFrame
49 *
50+ * @param[in] geis The GEIS instance.
51+ * @param[in] group The gesture group containing the rejected gesture.
52 * @param[in] gesture_id Identifies the gesture.
53 *
54 * After you reject a gesture you no longer get its frames.
55 *
56 * @sa geis_frame_id
57 */
58-GEIS_API void geis_gesture_reject(GeisGestureId gesture_id);
59+GEIS_API GeisStatus geis_gesture_reject(Geis geis,
60+ GeisGroup group,
61+ GeisGestureId gesture_id);
62
63 /* @} */
64
65
66=== modified file 'libutouch-geis/backend/dbus/geis_dbus_backend.c'
67--- libutouch-geis/backend/dbus/geis_dbus_backend.c 2011-10-18 19:30:57 +0000
68+++ libutouch-geis/backend/dbus/geis_dbus_backend.c 2012-03-13 20:56:18 +0000
69@@ -221,10 +221,33 @@
70 }
71
72
73+static GeisStatus
74+_geis_dbus_accept_gesture(GeisBackend be,
75+ GeisGroup group,
76+ GeisGestureId gesture_id)
77+{
78+ GeisDBusBackend gdb = (GeisDBusBackend)be;
79+ return geis_dbus_client_accept_gesture(gdb->dbus_client, group, gesture_id);
80+}
81+
82+
83+static GeisStatus
84+_geis_dbus_reject_gesture(GeisBackend be,
85+ GeisGroup group,
86+ GeisGestureId gesture_id)
87+{
88+ GeisDBusBackend gdb = (GeisDBusBackend)be;
89+ return geis_dbus_client_reject_gesture(gdb->dbus_client, group, gesture_id);
90+}
91+
92+
93+
94 static struct GeisBackendVtable gdb_vtbl = {
95 _geis_dbus_backend_construct,
96 _geis_dbus_backend_finalize,
97 _geis_dbus_backend_create_token,
98+ _geis_dbus_accept_gesture,
99+ _geis_dbus_reject_gesture,
100 };
101
102
103
104=== modified file 'libutouch-geis/backend/dbus/geis_dbus_client.c'
105--- libutouch-geis/backend/dbus/geis_dbus_client.c 2011-10-18 18:41:30 +0000
106+++ libutouch-geis/backend/dbus/geis_dbus_client.c 2012-03-13 20:56:18 +0000
107@@ -681,5 +681,29 @@
108 }
109
110
111+/*
112+ * Asks the remote server to accept a gesture.
113+ */
114+GeisStatus
115+geis_dbus_client_accept_gesture(GeisDBusClient client GEIS_UNUSED,
116+ GeisGroup group GEIS_UNUSED,
117+ GeisGestureId gesture_id GEIS_UNUSED)
118+{
119+ return GEIS_STATUS_SUCCESS;
120+}
121+
122+
123+/*
124+ * Asks the remote server to reject a gesture.
125+ */
126+GeisStatus
127+geis_dbus_client_reject_gesture(GeisDBusClient client GEIS_UNUSED,
128+ GeisGroup group GEIS_UNUSED,
129+ GeisGestureId gesture_id GEIS_UNUSED)
130+{
131+ return GEIS_STATUS_SUCCESS;
132+}
133+
134+
135
136
137
138=== modified file 'libutouch-geis/backend/dbus/geis_dbus_client.h'
139--- libutouch-geis/backend/dbus/geis_dbus_client.h 2011-09-08 17:54:35 +0000
140+++ libutouch-geis/backend/dbus/geis_dbus_client.h 2012-03-13 20:56:18 +0000
141@@ -93,5 +93,32 @@
142 geis_dbus_client_unsubscribe(GeisDBusClient client,
143 GeisSubscription subscription);
144
145+/**
146+ * Asks the remote server to accept a gesture.
147+ *
148+ * @param[in] client The client side of the DBus connection.
149+ * @param[in] group The gesture group to which the gesture belongs.
150+ * @param[in] gesture_id The gesture to accept.
151+ *
152+ * @returns GEIS_STATUS_SUCCESS on success, some other value otherwise.
153+ */
154+GeisStatus
155+geis_dbus_client_accept_gesture(GeisDBusClient client,
156+ GeisGroup group,
157+ GeisGestureId gesture_id);
158+
159+/**
160+ * Asks the remote server to reject a gesture.
161+ *
162+ * @param[in] client The client side of the DBus connection.
163+ * @param[in] group The gesture group to which the gesture belongs.
164+ * @param[in] gesture_id The gesture to reject.
165+ *
166+ * @returns GEIS_STATUS_SUCCESS on success, some other value otherwise.
167+ */
168+GeisStatus
169+geis_dbus_client_reject_gesture(GeisDBusClient client,
170+ GeisGroup group,
171+ GeisGestureId gesture_id);
172
173 #endif /* GEIS_DBUS_CLIENT_H_ */
174
175=== modified file 'libutouch-geis/backend/grail/geis_grail_backend.c'
176--- libutouch-geis/backend/grail/geis_grail_backend.c 2012-02-27 19:35:04 +0000
177+++ libutouch-geis/backend/grail/geis_grail_backend.c 2012-03-13 20:56:18 +0000
178@@ -1188,6 +1188,15 @@
179 }
180
181
182+static int
183+_grail_be_x_error_handler(Display* display GEIS_UNUSED,
184+ XErrorEvent* event GEIS_UNUSED)
185+{
186+ geis_error("error in X detected");
187+ return 0;
188+}
189+
190+
191 /**
192 * Deconstructs a Grail back end.
193 *
194@@ -1205,14 +1214,117 @@
195 geis_demultiplex_fd(gbe->geis, frame_get_fd(gbe->frame));
196 frame_x11_delete(gbe->frame);
197 geis_demultiplex_fd(gbe->geis, ConnectionNumber(gbe->display));
198+
199+ XErrorHandler old_x_handler = XSetErrorHandler(_grail_be_x_error_handler);
200 XCloseDisplay(gbe->display);
201-}
202-
203+ XSetErrorHandler(old_x_handler);
204+}
205+
206+
207+/*
208+ * Asks grail to accept an identified gesture.
209+ */
210+GeisStatus
211+_grail_be_accept_gesture(GeisBackend be,
212+ GeisGroup group GEIS_UNUSED,
213+ GeisGestureId gesture_id)
214+{
215+ GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
216+ GeisGrailBackend gbe = (GeisGrailBackend)be;
217+ unsigned id = gesture_id;
218+ UGStatus ugstatus = grail_accept_gesture(gbe->grail, id);
219+ if (ugstatus != UGStatusSuccess)
220+ {
221+ geis_error("accept failed for gesture %u", id);
222+ }
223+ else
224+ {
225+ geis_debug("gesture %u accepted", id);
226+ status = GEIS_STATUS_SUCCESS;
227+ }
228+ return status;
229+}
230+
231+
232+/*
233+ * Predicate to identify events to remove on rejection.
234+ */
235+static GeisBoolean
236+_grail_be_match_gesture_event(GeisEvent event, void *context)
237+{
238+ GeisGestureId gesture_id = *(GeisGestureId *)context;
239+ GeisEventType event_type = geis_event_type(event);
240+ if (event_type == GEIS_EVENT_GESTURE_BEGIN
241+ || event_type == GEIS_EVENT_GESTURE_UPDATE
242+ || event_type == GEIS_EVENT_GESTURE_END)
243+ {
244+ GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET);
245+ if (!attr)
246+ {
247+ geis_error("can not get groupset from event");
248+ return GEIS_FALSE;
249+ }
250+ GeisGroupSet groupset = (GeisGroupSet)geis_attr_value_to_pointer(attr);
251+ for (GeisSize i = 0; i < geis_groupset_group_count(groupset); ++i)
252+ {
253+ GeisGroup group = geis_groupset_group(groupset, i);
254+ if (!group)
255+ {
256+ geis_error("can not get group %zu in groupset of event", i);
257+ return GEIS_FALSE;
258+ }
259+
260+ for (GeisSize j = 0; j < geis_group_frame_count(group); ++j)
261+ {
262+ GeisFrame frame = geis_group_frame(group, j);
263+ if (!frame)
264+ {
265+ geis_error("can not get frame %zu in group %zu of event", j, i);
266+ return GEIS_FALSE;
267+ }
268+
269+ return gesture_id == geis_frame_id(frame);
270+ }
271+ }
272+ }
273+ return GEIS_FALSE;
274+}
275+
276+
277+/*
278+ * Asks grail to reject an identified gesture.
279+ */
280+GeisStatus
281+_grail_be_reject_gesture(GeisBackend be,
282+ GeisGroup group GEIS_UNUSED,
283+ GeisGestureId gesture_id)
284+{
285+ GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
286+ GeisGrailBackend gbe = (GeisGrailBackend)be;
287+ unsigned id = gesture_id;
288+ UGStatus ugstatus = grail_reject_gesture(gbe->grail, id);
289+ if (ugstatus != UGStatusSuccess)
290+ {
291+ geis_error("rejection failed for gesture %u", id);
292+ }
293+ else
294+ {
295+ geis_debug("gesture %u rejected", id);
296+ status = GEIS_STATUS_SUCCESS;
297+ }
298+
299+ geis_remove_matching_events(gbe->geis,
300+ _grail_be_match_gesture_event,
301+ &gesture_id);
302+ return status;
303+}
304
305 static struct GeisBackendVtable gbe_vtbl = {
306 _geis_grail_backend_construct,
307 _geis_grail_backend_finalize,
308- geis_grail_token_new
309+ geis_grail_token_new,
310+ _grail_be_accept_gesture,
311+ _grail_be_reject_gesture,
312 };
313
314
315@@ -1397,7 +1509,6 @@
316 }
317
318 UGStatus ugstatus = UGStatusErrorGeneric;
319-
320 GeisBoolean geis_use_atomic_gestures = GEIS_FALSE;
321 geis_get_configuration(gbe->geis,
322 GEIS_CONFIG_ATOMIC_GESTURES,
323@@ -1633,6 +1744,22 @@
324 {
325 UGSubscription ugsub = geis_ugsubscription_get_ugsubscription_at(ugstore,
326 i);
327+
328+ UFWindowId ufwindow;
329+ UGStatus ugstatus;
330+ ugstatus = grail_subscription_get_property(ugsub,
331+ UGSubscriptionPropertyWindow,
332+ &ufwindow);
333+ if (ugstatus != UGStatusSuccess)
334+ {
335+ geis_warning("error %d getting subscription window", ugstatus);
336+ }
337+ else
338+ {
339+ Window window_id = frame_x11_get_window_id(ufwindow);
340+ geis_grail_window_grab_store_ungrab(gbe->window_grabs, window_id);
341+ }
342+
343 grail_subscription_deactivate(gbe->grail, ugsub);
344 }
345 }
346
347=== modified file 'libutouch-geis/backend/grail/geis_grail_window_grab.c'
348--- libutouch-geis/backend/grail/geis_grail_window_grab.c 2012-03-06 15:27:17 +0000
349+++ libutouch-geis/backend/grail/geis_grail_window_grab.c 2012-03-13 20:56:18 +0000
350@@ -185,7 +185,19 @@
351 --grab->grab_count;
352 if (0 == grab->grab_count)
353 {
354- /* @todo: ungrab */
355+ XIGrabModifiers mods = { XIAnyModifier, 0 };
356+ Status xstat = XIUngrabTouchBegin(wgs->display,
357+ XIAllMasterDevices,
358+ window_id,
359+ 1, &mods);
360+ if (xstat)
361+ {
362+ geis_error("error %d returned from XIUngrabTouchBegin()", xstat);
363+ }
364+ else if (mods.status != XIGrabSuccess)
365+ {
366+ geis_error("status %d returned from XIUnrabTouchBegin()", mods.status);
367+ }
368 }
369 }
370 }
371
372=== modified file 'libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c'
373--- libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c 2011-11-20 13:40:43 +0000
374+++ libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c 2012-03-13 20:56:18 +0000
375@@ -228,10 +228,30 @@
376 }
377
378
379+GeisStatus
380+_gmock_accept_gesture(GeisBackend be GEIS_UNUSED,
381+ GeisGroup group GEIS_UNUSED,
382+ GeisGestureId gesture_ID GEIS_UNUSED)
383+{
384+ return GEIS_STATUS_SUCCESS;
385+}
386+
387+
388+GeisStatus
389+_gmock_reject_gesture(GeisBackend be GEIS_UNUSED,
390+ GeisGroup group GEIS_UNUSED,
391+ GeisGestureId gesture_ID GEIS_UNUSED)
392+{
393+ return GEIS_STATUS_SUCCESS;
394+}
395+
396+
397 static struct GeisBackendVtable tf_vtbl = {
398 _construct,
399 _finalize,
400 _create_token,
401+ _gmock_accept_gesture,
402+ _gmock_reject_gesture
403 };
404
405
406
407=== modified file 'libutouch-geis/backend/xcb/geis_xcb_backend.c'
408--- libutouch-geis/backend/xcb/geis_xcb_backend.c 2012-01-13 10:06:14 +0000
409+++ libutouch-geis/backend/xcb/geis_xcb_backend.c 2012-03-13 20:56:18 +0000
410@@ -105,13 +105,17 @@
411 static void _construct(void *mem, Geis geis);
412 static void _finalize(GeisBackend g);
413 static GeisBackendToken _create_token(GeisBackend be, GeisBackendTokenInitState);
414+static GeisStatus _gxcb_accept_gesture(GeisBackend, GeisGroup, GeisGestureId);
415+static GeisStatus _gxcb_reject_gesture(GeisBackend, GeisGroup, GeisGestureId);
416 static void _fd_callback(int fd, GeisBackendMultiplexorActivity ev, void *ctx);
417
418
419 static struct GeisBackendVtable be_vtbl = {
420 _construct,
421 _finalize,
422- _create_token
423+ _create_token,
424+ _gxcb_accept_gesture,
425+ _gxcb_reject_gesture
426 };
427
428
429@@ -1040,3 +1044,21 @@
430 {
431 }
432
433+
434+GeisStatus
435+_gxcb_accept_gesture(GeisBackend be GEIS_UNUSED,
436+ GeisGroup group GEIS_UNUSED,
437+ GeisGestureId gesture_id GEIS_UNUSED)
438+{
439+ return GEIS_STATUS_UNKNOWN_ERROR;
440+}
441+
442+
443+GeisStatus
444+_gxcb_reject_gesture(GeisBackend be GEIS_UNUSED,
445+ GeisGroup group GEIS_UNUSED,
446+ GeisGestureId gesture_id GEIS_UNUSED)
447+{
448+ return GEIS_STATUS_UNKNOWN_ERROR;
449+}
450+
451
452=== modified file 'libutouch-geis/geis.c'
453--- libutouch-geis/geis.c 2012-02-23 19:42:24 +0000
454+++ libutouch-geis/geis.c 2012-03-13 20:56:18 +0000
455@@ -950,6 +950,19 @@
456
457
458 /*
459+ * Removes all matching events from all event queues.
460+ */
461+void
462+geis_remove_matching_events(Geis geis,
463+ GeisEventMatch matching,
464+ void *context)
465+{
466+ geis_event_queue_remove_if(geis->input_event_queue, matching, context);
467+ geis_event_queue_remove_if(geis->output_event_queue, matching, context);
468+}
469+
470+
471+/*
472 * Registers an application-supplied event callback.
473 */
474 void
475@@ -1512,3 +1525,23 @@
476 return device;
477 }
478
479+
480+/*
481+ * Marks a gesture as accepted.
482+ */
483+GeisStatus
484+geis_gesture_accept(Geis geis, GeisGroup group, GeisGestureId gesture_id)
485+{
486+ return geis_backend_gesture_accept(geis->backend, group, gesture_id);
487+}
488+
489+
490+/*
491+ * Marks a gesture as rejected.
492+ */
493+GeisStatus
494+geis_gesture_reject(Geis geis, GeisGroup group, GeisGestureId gesture_id)
495+{
496+ return geis_backend_gesture_reject(geis->backend, group, gesture_id);
497+}
498+
499
500=== modified file 'libutouch-geis/geis_backend.c'
501--- libutouch-geis/geis_backend.c 2011-12-19 22:14:48 +0000
502+++ libutouch-geis/geis_backend.c 2012-03-13 20:56:18 +0000
503@@ -177,3 +177,25 @@
504 }
505
506
507+GeisStatus
508+geis_backend_gesture_accept(GeisBackend be,
509+ GeisGroup group,
510+ GeisGestureId gesture_id)
511+{
512+ GeisStatus status = be->be_class->vtbl->accept_gesture(_data_from_be(be),
513+ group,
514+ gesture_id);
515+ return status;
516+}
517+
518+
519+GeisStatus
520+geis_backend_gesture_reject(GeisBackend be,
521+ GeisGroup group,
522+ GeisGestureId gesture_id)
523+{
524+ GeisStatus status = be->be_class->vtbl->reject_gesture(_data_from_be(be),
525+ group,
526+ gesture_id);
527+ return status;
528+}
529
530=== modified file 'libutouch-geis/geis_backend.h'
531--- libutouch-geis/geis_backend.h 2011-06-29 14:40:25 +0000
532+++ libutouch-geis/geis_backend.h 2012-03-13 20:56:18 +0000
533@@ -66,4 +66,28 @@
534 GeisBackendToken geis_backend_create_token(GeisBackend be,
535 GeisBackendTokenInitState);
536
537+/**
538+ * Marks a gesture as accepted by the back end.
539+ *
540+ * @param[in] be The GEIS back end.
541+ * @param[in] group The gesture group containing the accepted gesture.
542+ * @param[in] gesture_id Identifies the gesture.
543+ */
544+GeisStatus
545+geis_backend_gesture_accept(GeisBackend be,
546+ GeisGroup group,
547+ GeisGestureId gesture_id);
548+
549+/**
550+ * Marks a gesture as rejected by the back end.
551+ *
552+ * @param[in] be The GEIS back end.
553+ * @param[in] group The gesture group containing the rejected gesture.
554+ * @param[in] gesture_id Identifies the gesture.
555+ */
556+GeisStatus
557+geis_backend_gesture_reject(GeisBackend be,
558+ GeisGroup group,
559+ GeisGestureId gesture_id);
560+
561 #endif /* GEIS_BACKEND_H_ */
562
563=== modified file 'libutouch-geis/geis_backend_protected.h'
564--- libutouch-geis/geis_backend_protected.h 2011-10-17 16:52:22 +0000
565+++ libutouch-geis/geis_backend_protected.h 2012-03-13 20:56:18 +0000
566@@ -38,6 +38,8 @@
567 void (* construct)(void *mem, Geis geis);
568 void (* finalize)(GeisBackend);
569 GeisBackendToken (* create_token)(GeisBackend, GeisBackendTokenInitState);
570+ GeisStatus (* accept_gesture)(GeisBackend, GeisGroup, GeisGestureId);
571+ GeisStatus (* reject_gesture)(GeisBackend, GeisGroup, GeisGestureId);
572 } *GeisBackendVtable;
573
574
575
576=== modified file 'libutouch-geis/geis_event_queue.c'
577--- libutouch-geis/geis_event_queue.c 2011-02-05 13:49:54 +0000
578+++ libutouch-geis/geis_event_queue.c 2012-03-13 20:56:18 +0000
579@@ -1,8 +1,8 @@
580 /**
581 * @file geis_event_queue.c
582 * @brief internal uTouch Geis event queue implementation
583- *
584- * Copyright 2010 Canonical Ltd.
585+ */
586+/* Copyright 2010, 2012 Canonical Ltd.
587 *
588 * This library is free software; you can redistribute it and/or modify it under
589 * the terms of the GNU Lesser General Public License as published by the Free
590@@ -26,12 +26,19 @@
591
592 typedef struct _GeisEventQueueNode *GeisEventQueueNode;
593
594+/**
595+ * A node in a GEIS event queue. The event queue is a singly-linked list.
596+ */
597 struct _GeisEventQueueNode
598 {
599 GeisEventQueueNode eq_next;
600 GeisEvent eq_event;
601 };
602
603+/**
604+ * A GEIS event queue. The event queue is a singly linked list with a pool of
605+ * free nodes.
606+ */
607 struct _GeisEventQueue
608 {
609 GeisEventQueueNode eq_front;
610@@ -135,6 +142,18 @@
611
612
613 /*
614+ * Pushes a node into the front of the free pool for a queue.
615+ */
616+static void
617+_geis_event_queue_add_node_to_pool(GeisEventQueue queue,
618+ GeisEventQueueNode node)
619+{
620+ node->eq_next = queue->eq_pool;
621+ queue->eq_pool = node;
622+}
623+
624+
625+/*
626 * Pops the event off the front of the event queue.
627 */
628 GeisEvent
629@@ -147,11 +166,51 @@
630
631 GeisEventQueueNode node = queue->eq_front;
632 queue->eq_front = node->eq_next;
633- node->eq_next = queue->eq_pool;
634- queue->eq_pool = node;
635+ _geis_event_queue_add_node_to_pool(queue, node);
636 if (!queue->eq_front)
637 queue->eq_back = NULL;
638 }
639 return event;
640 }
641
642+
643+/*
644+ * Removes events from a queue of they match a condition.
645+ */
646+void
647+geis_event_queue_remove_if(GeisEventQueue queue,
648+ GeisEventMatch matching,
649+ void *context)
650+{
651+ GeisEventQueueNode prev = NULL;
652+ GeisEventQueueNode node = queue->eq_front;
653+ while (node)
654+ {
655+ if (matching(node->eq_event, context))
656+ {
657+ GeisEventQueueNode matching_node = node;
658+ node = node->eq_next;
659+
660+ if (matching_node == queue->eq_front)
661+ {
662+ queue->eq_front = matching_node->eq_next;
663+ }
664+ else
665+ {
666+ prev->eq_next = matching_node->eq_next;
667+ }
668+ if (matching_node == queue->eq_back)
669+ {
670+ queue->eq_back = prev;
671+ }
672+ geis_event_delete(matching_node->eq_event);
673+ _geis_event_queue_add_node_to_pool(queue, matching_node);
674+ }
675+ else
676+ {
677+ prev = node;
678+ node = node->eq_next;
679+ }
680+ }
681+}
682+
683
684=== modified file 'libutouch-geis/geis_event_queue.h'
685--- libutouch-geis/geis_event_queue.h 2010-12-14 17:11:24 +0000
686+++ libutouch-geis/geis_event_queue.h 2012-03-13 20:56:18 +0000
687@@ -83,4 +83,22 @@
688 */
689 GeisEvent geis_event_queue_dequeue(GeisEventQueue queue);
690
691+/**
692+ * Prototype for GEIS event matching predicate functions.
693+ */
694+typedef GeisBoolean (*GeisEventMatch)(GeisEvent event, void *context);
695+
696+/**
697+ * Removes events from a queue of they match a condition.
698+ *
699+ * @param[in] queue The event queue.
700+ * @param[in] matching A unary predicate function to indicate the events to be
701+ * removed.
702+ * @param[in] context An application-specific context value to be passed to
703+ * the matching function.
704+ */
705+void geis_event_queue_remove_if(GeisEventQueue queue,
706+ GeisEventMatch matching,
707+ void *context);
708+
709 #endif /* GEIS_EVENT_QUEUE_H_ */
710
711=== modified file 'libutouch-geis/geis_frame.c'
712--- libutouch-geis/geis_frame.c 2012-02-09 18:13:15 +0000
713+++ libutouch-geis/geis_frame.c 2012-03-13 20:56:18 +0000
714@@ -381,11 +381,3 @@
715 }
716
717
718-/*
719- * Marks a gesture as rejected.
720- */
721-void
722-geis_gesture_reject(GeisGestureId gesture_id GEIS_UNUSED)
723-{
724-}
725-
726
727=== modified file 'libutouch-geis/geis_private.h'
728--- libutouch-geis/geis_private.h 2012-02-11 00:30:17 +0000
729+++ libutouch-geis/geis_private.h 2012-03-13 20:56:18 +0000
730@@ -34,6 +34,7 @@
731 #include "geis_backend_multiplexor.h"
732 #include "geis_class.h"
733 #include "geis_device.h"
734+#include "geis_event_queue.h"
735 #include "geis_filterable.h"
736 #include "geis_region.h"
737 #include "geis_subscription.h"
738@@ -146,6 +147,24 @@
739 void *context);
740
741 /**
742+ * Removes all matching events from all event queues.
743+ *
744+ * @param[in] geis The API instance.
745+ * @param[in] matching A unary predicate function to indicate the events to be
746+ * removed.
747+ * @param[in] context An application-specific context value to be passed to
748+ * the matching function.
749+ *
750+ * Removes any and all queued events that are indicated by the passed matching
751+ * function.
752+ */
753+void geis_remove_matching_events(Geis geis,
754+ GeisEventMatch matching,
755+ void *context);
756+
757+
758+
759+/**
760 * @defgroup geis_v2_plugin Plugin Interfaces
761 * @ingroup geis_v2
762 * Interfaces for plugin implementors.
763
764=== modified file 'libutouch-geis/libutouch-geis.ver'
765--- libutouch-geis/libutouch-geis.ver 2011-11-23 15:17:53 +0000
766+++ libutouch-geis/libutouch-geis.ver 2012-03-13 20:56:18 +0000
767@@ -49,6 +49,7 @@
768 geis_frame_matrix;
769 geis_frame_touchid;
770 geis_frame_touchid_count;
771+ geis_gesture_accept;
772 geis_gesture_class_attr;
773 geis_gesture_class_attr_count;
774 geis_gesture_class_id;
775
776=== modified file 'testsuite/geis2/Makefile.am'
777--- testsuite/geis2/Makefile.am 2012-03-06 17:30:02 +0000
778+++ testsuite/geis2/Makefile.am 2012-03-13 20:56:18 +0000
779@@ -46,12 +46,15 @@
780 gtest_attrs.cpp \
781 gtest_subscriptions.cpp \
782 gtest_evemu_device.h gtest_evemu_device.cpp \
783- gtest_geis_fixture.h gtest_geis_fixture.cpp
784+ gtest_geis_fixture.h gtest_geis_fixture.cpp
785+
786+nodist_gtest_geis2_api_SOURCES = /usr/src/gtest/src/gtest-all.cc
787
788 gtest_geis2_api_CPPFLAGS = \
789 --std=c++0x \
790 -I$(top_srcdir) \
791 -I$(top_srcdir)/include \
792+ $(GTEST_CFLAGS) \
793 $(EVEMU_CFLAGS) \
794 $(XORG_GTEST_CFLAGS)
795
796
797=== modified file 'testsuite/geis2/gtest_subscriptions.cpp'
798--- testsuite/geis2/gtest_subscriptions.cpp 2012-03-07 18:12:01 +0000
799+++ testsuite/geis2/gtest_subscriptions.cpp 2012-03-13 20:56:18 +0000
800@@ -6,10 +6,12 @@
801
802 #include "gtest_evemu_device.h"
803 #include "gtest_geis_fixture.h"
804+#include <sys/select.h>
805+#include <sys/time.h>
806
807
808 static const std::string TEST_DEVICE_PROP_FILE("touchscreen_a.prop");
809-
810+static const std::string TEST_DEVICE_EVENTS_FILE("touchscreen_a_rotate90.events");
811
812 /**
813 * Tests need to make sure at least one multi-touch device is available.
814@@ -22,7 +24,7 @@
815 : evemu_device_(TEST_DEVICE_PROP_FILE)
816 { }
817
818-private:
819+protected:
820 Testsuite::EvemuDevice evemu_device_;
821 };
822
823@@ -67,8 +69,11 @@
824 GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_GT, 1,
825 NULL);
826 EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add class to filter 1";
827+ fs = geis_subscription_add_filter(sub1, filter1);
828+ EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not subscribe filter 1";
829+ geis_filter_delete(filter1);
830
831- GeisFilter filter2 = geis_filter_new(geis_, "root window 2");
832+ GeisFilter filter2 = geis_filter_new(geis2, "root window 2");
833 EXPECT_TRUE(filter2 != NULL) << "can not create filter 2";
834
835 fs = geis_filter_add_term(filter2,
836@@ -77,11 +82,9 @@
837 GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_GT, 1,
838 NULL);
839 EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add class to filter 2";
840-
841- fs = geis_subscription_add_filter(sub1, filter1);
842- EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not subscribe filter 1";
843 fs = geis_subscription_add_filter(sub2, filter2);
844 EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not subscribe filter 2";
845+ geis_filter_delete(filter2);
846
847 EXPECT_EQ(GEIS_STATUS_SUCCESS, geis_subscription_activate(sub1))
848 << "can not activate subscription 1";
849@@ -93,3 +96,258 @@
850 geis_delete(geis2);
851 }
852
853+/**
854+ * Regression test 1 for lp:934207: gesture rejection
855+ */
856+TEST_F(GeisSubscriptionTests, reject_gesture)
857+{
858+ GeisGestureClass rotate_class = NULL;
859+ GeisGestureId rejected_gesture_id = 0;
860+ bool gesture_rejected = false;
861+ GeisSubscription sub = geis_subscription_new(geis_,
862+ "subscription",
863+ GEIS_SUBSCRIPTION_NONE);
864+ EXPECT_TRUE(sub != NULL) << "can not create subscription";
865+ GeisFilter filter = geis_filter_new(geis_, "root window");
866+ EXPECT_TRUE(filter != NULL) << "can not create filter";
867+ GeisStatus fs = geis_filter_add_term(filter,
868+ GEIS_FILTER_CLASS,
869+ GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_ROTATE,
870+ GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_GT, 1,
871+ NULL);
872+ EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add class to filter";
873+ fs = geis_subscription_add_filter(sub, filter);
874+ EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not subscribe filter";
875+ geis_filter_delete(filter);
876+ EXPECT_EQ(GEIS_STATUS_SUCCESS, geis_subscription_activate(sub))
877+ << "can not activate subscription";
878+
879+ GeisStatus dispatch_status= geis_dispatch_events(geis_);
880+ while (dispatch_status == GEIS_STATUS_CONTINUE
881+ || dispatch_status == GEIS_STATUS_SUCCESS)
882+ {
883+ GeisEvent event;
884+ GeisStatus event_status = geis_next_event(geis_, &event);
885+ while (event_status == GEIS_STATUS_CONTINUE
886+ || event_status == GEIS_STATUS_SUCCESS)
887+ {
888+ switch (geis_event_type(event))
889+ {
890+ case GEIS_EVENT_INIT_COMPLETE:
891+ evemu_device_.play(TEST_DEVICE_EVENTS_FILE);
892+ break;
893+
894+ case GEIS_EVENT_CLASS_AVAILABLE:
895+ {
896+ GeisAttr attr = geis_event_attr_by_name(event,
897+ GEIS_EVENT_ATTRIBUTE_CLASS);
898+ EXPECT_TRUE(attr != NULL) << "event is missing class attr";
899+ GeisGestureClass gesture_class = (GeisGestureClass)geis_attr_value_to_pointer(attr);
900+ for (GeisSize i = 0; i < geis_gesture_class_attr_count(gesture_class); ++i)
901+ {
902+ GeisAttr attr2 = geis_gesture_class_attr(gesture_class, i);
903+ if (0 == strcmp(geis_attr_name(attr2), GEIS_CLASS_ATTRIBUTE_NAME))
904+ {
905+ if (0 == strcmp(geis_attr_value_to_string(attr2),
906+ GEIS_GESTURE_ROTATE))
907+ {
908+ rotate_class = gesture_class;
909+ }
910+ }
911+ }
912+ break;
913+ }
914+
915+ case GEIS_EVENT_GESTURE_BEGIN:
916+ case GEIS_EVENT_GESTURE_UPDATE:
917+ {
918+ GeisAttr attr = geis_event_attr_by_name(event,
919+ GEIS_EVENT_ATTRIBUTE_GROUPSET);
920+ EXPECT_TRUE(attr != NULL) << "event is missing groupset attr";
921+ GeisGroupSet groupset = (GeisGroupSet)geis_attr_value_to_pointer(attr);
922+ EXPECT_TRUE(groupset != NULL) << "event is missing groupset";
923+ for (GeisSize i = 0; i < geis_groupset_group_count(groupset); ++i)
924+ {
925+ GeisGroup group = geis_groupset_group(groupset, i);
926+ EXPECT_TRUE(group != NULL) << "group " << i
927+ << " not found in groupset";
928+
929+ for (GeisSize j = 0; j < geis_group_frame_count(group); ++j)
930+ {
931+ GeisFrame frame = geis_group_frame(group, j);
932+ EXPECT_TRUE(frame != NULL) << "frame " << j
933+ << " not found in group";
934+
935+ if (geis_frame_is_class(frame, rotate_class))
936+ {
937+ if (!gesture_rejected)
938+ {
939+ rejected_gesture_id = geis_frame_id(frame);
940+ GeisStatus gs = geis_gesture_reject(geis_,
941+ group,
942+ rejected_gesture_id);
943+ EXPECT_EQ(gs, GEIS_STATUS_SUCCESS) << "rejection failed";
944+ gesture_rejected = true;
945+ }
946+ else
947+ {
948+ EXPECT_NE(geis_frame_id(frame), rejected_gesture_id)
949+ << "gesture events after gesture rejected";
950+ }
951+ }
952+ }
953+ }
954+ break;
955+ }
956+
957+ default:
958+ break;
959+ }
960+
961+ geis_event_delete(event);
962+
963+ event_status = geis_next_event(geis_, &event);
964+ }
965+
966+ fd_set read_fds;
967+ FD_ZERO(&read_fds);
968+ FD_SET(geis_fd(), &read_fds);
969+ timeval tmo = { 5, 0 };
970+ int sstat = select(geis_fd() + 1, &read_fds, NULL, NULL, &tmo);
971+ EXPECT_GT(sstat, -1) << "error in select";
972+ if (sstat == 0)
973+ break;
974+ dispatch_status = geis_dispatch_events(geis_);
975+ }
976+
977+ EXPECT_EQ(gesture_rejected, true) << "gesture was never rejected";
978+ geis_subscription_delete(sub);
979+}
980+
981+
982+/**
983+ * Regression test 2 for lp:934207: gesture acceptance
984+ */
985+TEST_F(GeisSubscriptionTests, accept_gesture)
986+{
987+ GeisGestureClass rotate_class = NULL;
988+ bool gesture_accepted = false;
989+ bool gesture_ended = false;
990+ GeisSubscription sub = geis_subscription_new(geis_,
991+ "subscription",
992+ GEIS_SUBSCRIPTION_NONE);
993+ EXPECT_TRUE(sub != NULL) << "can not create subscription";
994+ GeisFilter filter = geis_filter_new(geis_, "root window");
995+ EXPECT_TRUE(filter != NULL) << "can not create filter";
996+ GeisStatus fs = geis_filter_add_term(filter,
997+ GEIS_FILTER_CLASS,
998+ GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_ROTATE,
999+ GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_GT, 1,
1000+ NULL);
1001+ EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add class to filter";
1002+ fs = geis_subscription_add_filter(sub, filter);
1003+ EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not subscribe filter";
1004+ geis_filter_delete(filter);
1005+ EXPECT_EQ(GEIS_STATUS_SUCCESS, geis_subscription_activate(sub))
1006+ << "can not activate subscription";
1007+
1008+ GeisStatus dispatch_status= geis_dispatch_events(geis_);
1009+ while (dispatch_status == GEIS_STATUS_CONTINUE
1010+ || dispatch_status == GEIS_STATUS_SUCCESS)
1011+ {
1012+ GeisEvent event;
1013+ GeisStatus event_status = geis_next_event(geis_, &event);
1014+ while (event_status == GEIS_STATUS_CONTINUE
1015+ || event_status == GEIS_STATUS_SUCCESS)
1016+ {
1017+ switch (geis_event_type(event))
1018+ {
1019+ case GEIS_EVENT_INIT_COMPLETE:
1020+ evemu_device_.play(TEST_DEVICE_EVENTS_FILE);
1021+ break;
1022+
1023+ case GEIS_EVENT_CLASS_AVAILABLE:
1024+ {
1025+ GeisAttr attr = geis_event_attr_by_name(event,
1026+ GEIS_EVENT_ATTRIBUTE_CLASS);
1027+ EXPECT_TRUE(attr != NULL) << "event is missing class attr";
1028+ GeisGestureClass gesture_class = (GeisGestureClass)geis_attr_value_to_pointer(attr);
1029+ for (GeisSize i = 0; i < geis_gesture_class_attr_count(gesture_class); ++i)
1030+ {
1031+ GeisAttr attr2 = geis_gesture_class_attr(gesture_class, i);
1032+ if (0 == strcmp(geis_attr_name(attr2), GEIS_CLASS_ATTRIBUTE_NAME))
1033+ {
1034+ if (0 == strcmp(geis_attr_value_to_string(attr2),
1035+ GEIS_GESTURE_ROTATE))
1036+ {
1037+ rotate_class = gesture_class;
1038+ }
1039+ }
1040+ }
1041+ break;
1042+ }
1043+
1044+ case GEIS_EVENT_GESTURE_BEGIN:
1045+ case GEIS_EVENT_GESTURE_UPDATE:
1046+ {
1047+ GeisAttr attr = geis_event_attr_by_name(event,
1048+ GEIS_EVENT_ATTRIBUTE_GROUPSET);
1049+ EXPECT_TRUE(attr != NULL) << "event is missing groupset attr";
1050+ GeisGroupSet groupset = (GeisGroupSet)geis_attr_value_to_pointer(attr);
1051+ EXPECT_TRUE(groupset != NULL) << "event is missing groupset";
1052+ for (GeisSize i = 0; i < geis_groupset_group_count(groupset); ++i)
1053+ {
1054+ GeisGroup group = geis_groupset_group(groupset, i);
1055+ EXPECT_TRUE(group != NULL) << "group " << i
1056+ << " not found in groupset";
1057+
1058+ for (GeisSize j = 0; j < geis_group_frame_count(group); ++j)
1059+ {
1060+ GeisFrame frame = geis_group_frame(group, j);
1061+ EXPECT_TRUE(frame != NULL) << "frame " << j
1062+ << " not found in group";
1063+
1064+ if (!gesture_accepted && geis_frame_is_class(frame, rotate_class))
1065+ {
1066+ GeisStatus gs = geis_gesture_accept(geis_,
1067+ group,
1068+ geis_frame_id(frame));
1069+ EXPECT_EQ(gs, GEIS_STATUS_SUCCESS) << "aceptance failed";
1070+ gesture_accepted = true;
1071+ }
1072+ }
1073+ }
1074+ break;
1075+ }
1076+
1077+ case GEIS_EVENT_GESTURE_END:
1078+ gesture_ended = true;
1079+ goto end_of_outer_loop;
1080+ break;
1081+
1082+ default:
1083+ break;
1084+ }
1085+
1086+ geis_event_delete(event);
1087+
1088+ event_status = geis_next_event(geis_, &event);
1089+ }
1090+
1091+ fd_set read_fds;
1092+ FD_ZERO(&read_fds);
1093+ FD_SET(geis_fd(), &read_fds);
1094+ timeval tmo = { 5, 0 };
1095+ int sstat = select(geis_fd() + 1, &read_fds, NULL, NULL, &tmo);
1096+ EXPECT_GT(sstat, -1) << "error in select";
1097+ if (sstat == 0)
1098+ break;
1099+ dispatch_status = geis_dispatch_events(geis_);
1100+ }
1101+end_of_outer_loop:
1102+
1103+ EXPECT_EQ(gesture_accepted, true) << "gesture was never accepted";
1104+ EXPECT_EQ(gesture_ended, true) << "gesture did not end";
1105+ geis_subscription_delete(sub);
1106+}
1107+
1108
1109=== modified file 'testsuite/libutouch-geis/check_event_queue.c'
1110--- testsuite/libutouch-geis/check_event_queue.c 2010-12-20 18:06:36 +0000
1111+++ testsuite/libutouch-geis/check_event_queue.c 2012-03-13 20:56:18 +0000
1112@@ -68,6 +68,42 @@
1113 }
1114 END_TEST
1115
1116+/* verify event_queue remove_if */
1117+static GeisBoolean
1118+_is_event_type(GeisEvent event, void* context)
1119+{
1120+ GeisEventType event_type = *(GeisEventType*)context;
1121+ return geis_event_type(event) == event_type;
1122+}
1123+
1124+START_TEST(remove_if)
1125+{
1126+ GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
1127+ GeisEvent event1 = geis_event_new(GEIS_EVENT_GESTURE_BEGIN);
1128+ status = geis_event_queue_enqueue(g_queue, event1);
1129+ fail_unless(status == GEIS_STATUS_SUCCESS, "failure at enqueue(event1)");
1130+
1131+ GeisEvent event2 = geis_event_new(GEIS_EVENT_USER_DEFINED);
1132+ status = geis_event_queue_enqueue(g_queue, event2);
1133+ fail_unless(status == GEIS_STATUS_SUCCESS, "failure at enqueue(event2)");
1134+
1135+ GeisEvent event3 = geis_event_new(GEIS_EVENT_GESTURE_END);
1136+ status = geis_event_queue_enqueue(g_queue, event3);
1137+ fail_unless(status == GEIS_STATUS_SUCCESS, "failure at enqueue(event3)");
1138+
1139+ GeisEventType event_type = GEIS_EVENT_USER_DEFINED;
1140+ geis_event_queue_remove_if(g_queue, _is_event_type, &event_type);
1141+
1142+ event_type = GEIS_EVENT_GESTURE_BEGIN;
1143+ geis_event_queue_remove_if(g_queue, _is_event_type, &event_type);
1144+
1145+ event_type = GEIS_EVENT_GESTURE_END;
1146+ geis_event_queue_remove_if(g_queue, _is_event_type, &event_type);
1147+
1148+ fail_unless(geis_event_queue_is_empty(g_queue), "queue is not empty");
1149+}
1150+END_TEST
1151+
1152 /* boilerplate */
1153 Suite *
1154 make_event_queue_suite()
1155@@ -81,6 +117,7 @@
1156 TCase *usage = tcase_create("event-queue-operation");
1157 tcase_add_checked_fixture(usage, construct_event_queue, destroy_event_queue);
1158 tcase_add_test(usage, enqueue_dequeue);
1159+ tcase_add_test(usage, remove_if);
1160 suite_add_tcase(s, usage);
1161
1162 return s;
1163
1164=== modified file 'testsuite/libutouch-geis/check_geis_private.c'
1165--- testsuite/libutouch-geis/check_geis_private.c 2011-09-02 02:04:05 +0000
1166+++ testsuite/libutouch-geis/check_geis_private.c 2012-03-13 20:56:18 +0000
1167@@ -79,6 +79,53 @@
1168 }
1169 END_TEST
1170
1171+/* Check selective queue removal. */
1172+static GeisBoolean
1173+_is_event_type(GeisEvent event, void* context)
1174+{
1175+ GeisEventType event_type = *(GeisEventType*)context;
1176+ return geis_event_type(event) == event_type;
1177+}
1178+
1179+START_TEST(remove_matching)
1180+{
1181+ GeisStatus status;
1182+
1183+ /* empty the event queue */
1184+ while (GEIS_STATUS_CONTINUE == geis_dispatch_events(g_geis))
1185+ ;
1186+ GeisEvent event_out;
1187+ while (GEIS_STATUS_CONTINUE == geis_next_event(g_geis, &event_out))
1188+ geis_event_delete(event_out);
1189+
1190+ /* push 3 controlled events into the queue */
1191+ GeisEvent event_in_1 = geis_event_new(GEIS_EVENT_GESTURE_BEGIN);
1192+ geis_post_event(g_geis, event_in_1);
1193+ GeisEvent event_in_2 = geis_event_new(GEIS_EVENT_USER_DEFINED);
1194+ geis_post_event(g_geis, event_in_2);
1195+ GeisEvent event_in_3 = geis_event_new(GEIS_EVENT_GESTURE_END);
1196+ geis_post_event(g_geis, event_in_3);
1197+
1198+ /* remove the middle event */
1199+ GeisEventType event_type = GEIS_EVENT_USER_DEFINED;
1200+ geis_remove_matching_events(g_geis, _is_event_type, &event_type);
1201+
1202+ /* verify it's no longer in the queue */
1203+ status = geis_dispatch_events(g_geis);
1204+ fail_unless(status == GEIS_STATUS_SUCCESS,
1205+ "unexpected status from geis_dispatch_events");
1206+ for (status = geis_next_event(g_geis, &event_out);
1207+ status != GEIS_STATUS_EMPTY;
1208+ status = geis_next_event(g_geis, &event_out))
1209+ {
1210+ fail_if(GEIS_EVENT_USER_DEFINED == geis_event_type(event_out),
1211+ "event was not successfully removed");
1212+ geis_event_delete(event_out);
1213+ }
1214+
1215+}
1216+END_TEST
1217+
1218 START_TEST(multiplex_fd)
1219 {
1220 int pfd[2];
1221@@ -151,6 +198,7 @@
1222 TCase *usage = tcase_create("backend-event-posting");
1223 tcase_add_checked_fixture(usage, construct_geis, destroy_geis);
1224 tcase_add_test(usage, backend_post);
1225+ tcase_add_test(usage, remove_matching);
1226 tcase_add_test(usage, multiplex_fd);
1227 suite_add_tcase(s, usage);
1228

Subscribers

People subscribed via source and target branches