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

Proposed by Daniel d'Andrada
Status: Merged
Merged at revision: 274
Proposed branch: lp:~dandrader/geis/lp1015775
Merge into: lp:geis
Diff against target: 514 lines (+227/-139)
8 files modified
libutouch-geis/backend/grail/geis_grail_backend.c (+6/-4)
testsuite/geis2/Makefile.am (+1/-0)
testsuite/geis2/gtest_gbe_accept_ended_grail_gesture.cpp (+85/-0)
testsuite/geis2/gtest_gbe_construction_finished.cpp (+4/-4)
testsuite/geis2/gtest_gbe_direct_touch_coords.cpp (+4/-4)
testsuite/geis2/gtest_gbe_outdated_events.cpp (+2/-121)
testsuite/geis2/gtest_grail_backend.cpp (+109/-3)
testsuite/geis2/gtest_grail_backend.h (+16/-3)
To merge this branch: bzr merge lp:~dandrader/geis/lp1015775
Reviewer Review Type Date Requested Status
Chase Douglas (community) Approve
Review via email: mp+111301@code.launchpad.net

Description of the change

Fixes bug #1015775.

Includes regression test.

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

Looks right to me.

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-05-22 12:18:55 +0000
3+++ libutouch-geis/backend/grail/geis_grail_backend.c 2012-06-20 20:08:20 +0000
4@@ -1610,10 +1610,12 @@
5 }
6
7 struct _GeisSliceState *slice_state = _grail_be_slice_state_from_id(gbe, id);
8-
9- geis_remove_matching_events(gbe->geis,
10- _grail_be_match_overlapping_gesture_event,
11- slice_state);
12+ /* the corresponding grail gesture might have already ended, in which case we
13+ no longer hold information over its state. */
14+ if (slice_state)
15+ geis_remove_matching_events(gbe->geis,
16+ _grail_be_match_overlapping_gesture_event,
17+ slice_state);
18 return status;
19 }
20
21
22=== modified file 'testsuite/geis2/Makefile.am'
23--- testsuite/geis2/Makefile.am 2012-06-05 20:04:24 +0000
24+++ testsuite/geis2/Makefile.am 2012-06-20 20:08:20 +0000
25@@ -47,6 +47,7 @@
26
27 gtest_geis2_grail_backend_SOURCES = \
28 gtest_grail_backend.h gtest_grail_backend.cpp \
29+ gtest_gbe_accept_ended_grail_gesture.cpp \
30 gtest_gbe_direct_touch_coords.cpp \
31 gtest_gbe_construction_finished.cpp \
32 gtest_gbe_outdated_events.cpp
33
34=== added file 'testsuite/geis2/gtest_gbe_accept_ended_grail_gesture.cpp'
35--- testsuite/geis2/gtest_gbe_accept_ended_grail_gesture.cpp 1970-01-01 00:00:00 +0000
36+++ testsuite/geis2/gtest_gbe_accept_ended_grail_gesture.cpp 2012-06-20 20:08:20 +0000
37@@ -0,0 +1,85 @@
38+#include "gtest_grail_backend.h"
39+#include "x11_mocks.h"
40+
41+/*
42+ Regression test for bug https://bugs.launchpad.net/utouch-geis/+bug/1015775
43+
44+ Checks that the following situation doesn't lead to a crash:
45+ - Geis processed the end event of a grail gesture
46+ - Geis has a number of geis events pending delivery to application
47+ - Application accepts that ended grail gesture
48+
49+ Cause:
50+ - While checking the queue of pending events for events that should
51+ no longer be delivered due to the gesture acceptance, geis would
52+ try to use a struct with information from the ended grail gesture
53+ that also no longer exists.
54+ */
55+
56+class AcceptEndedGesture : public Geis2GrailBackendBase
57+{
58+ protected:
59+ AcceptEndedGesture() : _subscription(nullptr) {}
60+
61+ void SendXInput2Events();
62+
63+ virtual void OnEventInitComplete(GeisEvent event);
64+ virtual void OnEventGestureBegin(GeisEvent event);
65+
66+ GeisSubscription _subscription;
67+};
68+
69+void AcceptEndedGesture::SendXInput2Events()
70+{
71+ /* args: event type, touch id, X and Y */
72+ SendTouchEvent(XI_TouchBegin, 1, 10.0f, 10.0f);
73+ SendTouchEvent(XI_TouchBegin, 2, 20.0f, 10.0f);
74+
75+ xmock_server_time += 5;
76+
77+ /* args: touch id */
78+ SendTouchOwnershipEvent(1);
79+ SendTouchOwnershipEvent(2);
80+
81+ xmock_server_time += 5;
82+
83+ SendTouchEvent(XI_TouchUpdate, 1, 10.0f, 20.0f);
84+ SendTouchEvent(XI_TouchUpdate, 2, 20.0f, 20.0f);
85+
86+ xmock_server_time += 5;
87+
88+ SendTouchEvent(XI_TouchEnd, 1, 10.0f, 30.0f);
89+ SendTouchEvent(XI_TouchEnd, 2, 20.0f, 30.0f);
90+}
91+
92+void AcceptEndedGesture::OnEventInitComplete(GeisEvent event)
93+{
94+ _subscription = CreateFilteredSubscription(
95+ "My 2-touches Touch", 2, GEIS_GESTURE_TOUCH);
96+ ASSERT_NE(nullptr, _subscription);
97+
98+ SendXInput2Events();
99+}
100+
101+void AcceptEndedGesture::OnEventGestureBegin(GeisEvent event)
102+{
103+ AcceptGestureInEvent(event);
104+}
105+
106+TEST_F(AcceptEndedGesture, Test)
107+{
108+ CreateXMockTouchScreenDevice();
109+
110+ _geis = geis_new(GEIS_INIT_UTOUCH_GRAIL_BACKEND,
111+ GEIS_INIT_NO_ATOMIC_GESTURES,
112+ nullptr);
113+ ASSERT_NE(nullptr, _geis);
114+
115+ Run();
116+
117+ if (_subscription)
118+ geis_subscription_delete(_subscription);
119+ geis_delete(_geis);
120+
121+ DestroyXMockDevices();
122+}
123
124=== modified file 'testsuite/geis2/gtest_gbe_construction_finished.cpp'
125--- testsuite/geis2/gtest_gbe_construction_finished.cpp 2012-05-16 18:14:14 +0000
126+++ testsuite/geis2/gtest_gbe_construction_finished.cpp 2012-06-20 20:08:20 +0000
127@@ -307,19 +307,19 @@
128 {
129 CreateXMockTouchScreenDevice();
130
131- Geis geis = geis_new(GEIS_INIT_UTOUCH_GRAIL_BACKEND,
132+ _geis = geis_new(GEIS_INIT_UTOUCH_GRAIL_BACKEND,
133 GEIS_INIT_NO_ATOMIC_GESTURES,
134 nullptr);
135- ASSERT_NE(nullptr, geis);
136+ ASSERT_NE(nullptr, _geis);
137
138- Run(geis);
139+ Run();
140
141 /* there should have been two gesture update events from geis */
142 ASSERT_EQ(2, _gesture_update_count);
143
144 if (_subscription)
145 geis_subscription_delete(_subscription);
146- geis_delete(geis);
147+ geis_delete(_geis);
148
149 DestroyXMockDevices();
150 }
151
152=== modified file 'testsuite/geis2/gtest_gbe_direct_touch_coords.cpp'
153--- testsuite/geis2/gtest_gbe_direct_touch_coords.cpp 2012-05-16 18:13:54 +0000
154+++ testsuite/geis2/gtest_gbe_direct_touch_coords.cpp 2012-06-20 20:08:20 +0000
155@@ -226,15 +226,15 @@
156 {
157 CreateXMockTouchScreenDevice();
158
159- Geis geis = geis_new(GEIS_INIT_UTOUCH_GRAIL_BACKEND,
160+ _geis = geis_new(GEIS_INIT_UTOUCH_GRAIL_BACKEND,
161 nullptr);
162- ASSERT_NE(nullptr, geis);
163+ ASSERT_NE(nullptr, _geis);
164
165- Run(geis);
166+ Run();
167
168 if (_subscription)
169 geis_subscription_delete(_subscription);
170- geis_delete(geis);
171+ geis_delete(_geis);
172
173 DestroyXMockDevices();
174 }
175
176=== modified file 'testsuite/geis2/gtest_gbe_outdated_events.cpp'
177--- testsuite/geis2/gtest_gbe_outdated_events.cpp 2012-05-18 22:27:59 +0000
178+++ testsuite/geis2/gtest_gbe_outdated_events.cpp 2012-06-20 20:08:20 +0000
179@@ -22,30 +22,18 @@
180 class OutdatedEventsOverlappingGestures : public Geis2GrailBackendBase
181 {
182 protected:
183- OutdatedEventsOverlappingGestures() : _geis(nullptr),
184- _subscription(nullptr),
185- _xevent_serial_number(0) {}
186+ OutdatedEventsOverlappingGestures() : _subscription(nullptr) {}
187
188 void SendXInput2Events();
189- void SendTouchEvent(int event_type, int touch_id, float x, float y);
190- void SendTouchOwnershipEvent(int touch_id);
191
192 virtual void OnEventInitComplete(GeisEvent event);
193 virtual void OnEventGestureBegin(GeisEvent event);
194 virtual void OnEventGestureUpdate(GeisEvent event);
195
196- void AcceptRejectGestureInEvent(GeisEvent event, bool accept);
197- void AcceptGestureInEvent(GeisEvent event);
198- void RejectGestureInEvent(GeisEvent event);
199-
200 int GetGestureIdInEvent(GeisEvent event);
201
202- Geis _geis;
203 GeisSubscription _subscription;
204
205- /* holds the serial number to be used on the next synthetic XEvent */
206- int _xevent_serial_number;
207-
208 std::set<int> _accepted_gestures;
209 };
210
211@@ -73,71 +61,6 @@
212 SendTouchEvent(XI_TouchUpdate, 4, 40.0f, 20.0f);
213 }
214
215-void OutdatedEventsOverlappingGestures::SendTouchEvent(
216- int event_type, int touch_id, float x, float y)
217-{
218- XEvent event;
219- XGenericEventCookie *xcookie = 0;
220- XIDeviceEvent *device_event = 0;
221-
222- event.type = GenericEvent;
223- device_event = (XIDeviceEvent*)calloc(1, sizeof(XIDeviceEvent));
224- device_event->serial = _xevent_serial_number++;
225- device_event->display = xmock_display;
226- device_event->extension = xmock_xi2_opcode;
227- device_event->evtype = event_type;
228- device_event->time = xmock_server_time;
229- device_event->deviceid = 0;
230- device_event->sourceid = device_event->deviceid;
231- device_event->detail = touch_id;
232- device_event->root = DefaultRootWindow(xmock_display);
233- device_event->event = DefaultRootWindow(xmock_display);
234- device_event->child = 0;
235- device_event->root_x = x;
236- device_event->root_y = y;
237- device_event->event_x = device_event->root_x;
238- device_event->event_y = device_event->root_y;
239- device_event->valuators.mask_len = 2;
240- device_event->valuators.mask = (unsigned char*) malloc(2);
241- XISetMask(device_event->valuators.mask, 0);
242- XISetMask(device_event->valuators.mask, 1);
243- device_event->valuators.values = (double*) malloc(sizeof(double)*2);
244- device_event->valuators.values[0] = 0; /* just change the coordinate system */
245- device_event->valuators.values[1] = 0;
246- xcookie = &event.xcookie;
247- xcookie->extension = xmock_xi2_opcode;
248- xcookie->evtype = event_type;
249- xcookie->data = device_event;
250- xmock_add_to_event_queue(&event);
251-}
252-
253-void OutdatedEventsOverlappingGestures::SendTouchOwnershipEvent(int touch_id)
254-{
255- XEvent event;
256- XGenericEventCookie *xcookie = 0;
257- XITouchOwnershipEvent *ownership_event = 0;
258-
259- event.type = GenericEvent;
260- ownership_event = (XITouchOwnershipEvent*)calloc(1, sizeof(XITouchOwnershipEvent));
261- ownership_event->type = GenericEvent;
262- ownership_event->serial = _xevent_serial_number++;
263- ownership_event->display = xmock_display;
264- ownership_event->extension = xmock_xi2_opcode;
265- ownership_event->evtype = XI_TouchOwnership;
266- ownership_event->time = xmock_server_time;
267- ownership_event->deviceid = 0;
268- ownership_event->sourceid = ownership_event->deviceid;
269- ownership_event->touchid = touch_id;
270- ownership_event->root = DefaultRootWindow(xmock_display);
271- ownership_event->event = DefaultRootWindow(xmock_display);
272- ownership_event->child = 0;
273- xcookie = &event.xcookie;
274- xcookie->extension = xmock_xi2_opcode;
275- xcookie->evtype = XI_TouchOwnership;
276- xcookie->data = ownership_event;
277- xmock_add_to_event_queue(&event);
278-}
279-
280 void OutdatedEventsOverlappingGestures::OnEventInitComplete(GeisEvent event)
281 {
282 _subscription = CreateFilteredSubscription(
283@@ -147,48 +70,6 @@
284 SendXInput2Events();
285 }
286
287-void OutdatedEventsOverlappingGestures::AcceptRejectGestureInEvent(
288- GeisEvent event, bool accept)
289-{
290- /* We expect only one group with one gesture frame.
291- Multiple groups with several gesture frames is just not supported or used.
292- That is, one GeisEvent is sent for each possible gesture instead of a single
293- GeisEvent with all possible gestures (arranged in groups). */
294-
295- GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET);
296- GeisGroupSet group_set =
297- static_cast<GeisGroupSet>(geis_attr_value_to_pointer(attr));
298-
299- ASSERT_EQ(1, geis_groupset_group_count(group_set));
300-
301- GeisGroup group = geis_groupset_group(group_set, 0);
302-
303- ASSERT_EQ(1, geis_group_frame_count(group));
304-
305- GeisFrame frame = geis_group_frame(group, 0);
306-
307- GeisStatus status;
308- if (accept)
309- {
310- status = geis_gesture_accept(_geis, group, geis_frame_id(frame));
311- }
312- else
313- {
314- status = geis_gesture_reject(_geis, group, geis_frame_id(frame));
315- }
316- ASSERT_EQ(GEIS_STATUS_SUCCESS, status);
317-}
318-
319-void OutdatedEventsOverlappingGestures::AcceptGestureInEvent(GeisEvent event)
320-{
321- AcceptRejectGestureInEvent(event, true);
322-}
323-
324-void OutdatedEventsOverlappingGestures::RejectGestureInEvent(GeisEvent event)
325-{
326- AcceptRejectGestureInEvent(event, false);
327-}
328-
329 int OutdatedEventsOverlappingGestures::GetGestureIdInEvent(GeisEvent event)
330 {
331 /* We expect only one group with one gesture frame.
332@@ -256,7 +137,7 @@
333 nullptr);
334 ASSERT_NE(nullptr, _geis);
335
336- Run(_geis);
337+ Run();
338
339 ASSERT_EQ(2, _accepted_gestures.size());
340
341
342=== modified file 'testsuite/geis2/gtest_grail_backend.cpp'
343--- testsuite/geis2/gtest_grail_backend.cpp 2012-05-18 22:27:20 +0000
344+++ testsuite/geis2/gtest_grail_backend.cpp 2012-06-20 20:08:20 +0000
345@@ -187,10 +187,8 @@
346 return got_events;
347 }
348
349-void Geis2GrailBackendBase::Run(Geis geis)
350+void Geis2GrailBackendBase::Run()
351 {
352- _geis = geis;
353-
354 bool got_events;
355 do
356 {
357@@ -198,6 +196,114 @@
358 } while (got_events);
359 }
360
361+void Geis2GrailBackendBase::SendTouchEvent(
362+ int event_type, int touch_id, float x, float y)
363+{
364+ XEvent event;
365+ XGenericEventCookie *xcookie = 0;
366+ XIDeviceEvent *device_event = 0;
367+
368+ event.type = GenericEvent;
369+ device_event = (XIDeviceEvent*)calloc(1, sizeof(XIDeviceEvent));
370+ device_event->serial = _xevent_serial_number++;
371+ device_event->display = xmock_display;
372+ device_event->extension = xmock_xi2_opcode;
373+ device_event->evtype = event_type;
374+ device_event->time = xmock_server_time;
375+ device_event->deviceid = 0;
376+ device_event->sourceid = device_event->deviceid;
377+ device_event->detail = touch_id;
378+ device_event->root = DefaultRootWindow(xmock_display);
379+ device_event->event = DefaultRootWindow(xmock_display);
380+ device_event->child = 0;
381+ device_event->root_x = x;
382+ device_event->root_y = y;
383+ device_event->event_x = device_event->root_x;
384+ device_event->event_y = device_event->root_y;
385+ device_event->valuators.mask_len = 2;
386+ device_event->valuators.mask = (unsigned char*) malloc(2);
387+ XISetMask(device_event->valuators.mask, 0);
388+ XISetMask(device_event->valuators.mask, 1);
389+ device_event->valuators.values = (double*) malloc(sizeof(double)*2);
390+ device_event->valuators.values[0] = 0; /* just change the coordinate system */
391+ device_event->valuators.values[1] = 0;
392+ xcookie = &event.xcookie;
393+ xcookie->extension = xmock_xi2_opcode;
394+ xcookie->evtype = event_type;
395+ xcookie->data = device_event;
396+ xmock_add_to_event_queue(&event);
397+}
398+
399+void Geis2GrailBackendBase::SendTouchOwnershipEvent(int touch_id)
400+{
401+ XEvent event;
402+ XGenericEventCookie *xcookie = 0;
403+ XITouchOwnershipEvent *ownership_event = 0;
404+
405+ event.type = GenericEvent;
406+ ownership_event = (XITouchOwnershipEvent*)calloc(1, sizeof(XITouchOwnershipEvent));
407+ ownership_event->type = GenericEvent;
408+ ownership_event->serial = _xevent_serial_number++;
409+ ownership_event->display = xmock_display;
410+ ownership_event->extension = xmock_xi2_opcode;
411+ ownership_event->evtype = XI_TouchOwnership;
412+ ownership_event->time = xmock_server_time;
413+ ownership_event->deviceid = 0;
414+ ownership_event->sourceid = ownership_event->deviceid;
415+ ownership_event->touchid = touch_id;
416+ ownership_event->root = DefaultRootWindow(xmock_display);
417+ ownership_event->event = DefaultRootWindow(xmock_display);
418+ ownership_event->child = 0;
419+ xcookie = &event.xcookie;
420+ xcookie->extension = xmock_xi2_opcode;
421+ xcookie->evtype = XI_TouchOwnership;
422+ xcookie->data = ownership_event;
423+ xmock_add_to_event_queue(&event);
424+}
425+
426+void Geis2GrailBackendBase::AcceptRejectGestureInEvent(
427+ GeisEvent event, bool accept)
428+{
429+ /* We expect only one group with one gesture frame.
430+ Multiple groups with several gesture frames is just not supported or used.
431+ That is, one GeisEvent is sent for each possible gesture instead of a single
432+ GeisEvent with all possible gestures (arranged in groups). */
433+
434+ GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET);
435+ GeisGroupSet group_set =
436+ static_cast<GeisGroupSet>(geis_attr_value_to_pointer(attr));
437+
438+ ASSERT_EQ(1, geis_groupset_group_count(group_set));
439+
440+ GeisGroup group = geis_groupset_group(group_set, 0);
441+
442+ ASSERT_EQ(1, geis_group_frame_count(group));
443+
444+ GeisFrame frame = geis_group_frame(group, 0);
445+
446+ GeisStatus status;
447+ if (accept)
448+ {
449+ status = geis_gesture_accept(_geis, group, geis_frame_id(frame));
450+ }
451+ else
452+ {
453+ status = geis_gesture_reject(_geis, group, geis_frame_id(frame));
454+ }
455+ ASSERT_EQ(GEIS_STATUS_SUCCESS, status);
456+}
457+
458+void Geis2GrailBackendBase::AcceptGestureInEvent(GeisEvent event)
459+{
460+ AcceptRejectGestureInEvent(event, true);
461+}
462+
463+void Geis2GrailBackendBase::RejectGestureInEvent(GeisEvent event)
464+{
465+ AcceptRejectGestureInEvent(event, false);
466+}
467+
468+
469 int main(int argc, char **argv)
470 {
471 testing::InitGoogleTest(&argc, argv);
472
473=== modified file 'testsuite/geis2/gtest_grail_backend.h'
474--- testsuite/geis2/gtest_grail_backend.h 2012-05-18 22:26:00 +0000
475+++ testsuite/geis2/gtest_grail_backend.h 2012-06-20 20:08:20 +0000
476@@ -28,12 +28,13 @@
477 class Geis2GrailBackendBase : public ::testing::Test
478 {
479 protected:
480- Geis2GrailBackendBase() : _geis(nullptr) {}
481+ Geis2GrailBackendBase() : _geis(nullptr),
482+ _xevent_serial_number(0) {}
483 virtual ~Geis2GrailBackendBase() {}
484
485 /* Dispatch and process Geis events in a loop until there are no more
486 events. */
487- void Run(Geis geis);
488+ void Run();
489
490
491 /* Creates (and activates) a GeisSubscription with the given name
492@@ -50,9 +51,21 @@
493 virtual void OnEventGestureUpdate(GeisEvent event) {}
494 virtual void OnEventGestureEnd(GeisEvent event) {}
495
496+ void SendTouchEvent(int event_type, int touch_id, float x, float y);
497+ void SendTouchOwnershipEvent(int touch_id);
498+
499+ void AcceptGestureInEvent(GeisEvent event);
500+ void RejectGestureInEvent(GeisEvent event);
501+
502+ Geis _geis;
503 private:
504- Geis _geis;
505+
506+ /* holds the serial number to be used on the next synthetic XEvent */
507+ int _xevent_serial_number;
508+
509 bool DispatchAndProcessEvents();
510+
511+ void AcceptRejectGestureInEvent(GeisEvent event, bool accept);
512 };
513
514 #endif // GTEST_GRAIL_BACKEND_H

Subscribers

People subscribed via source and target branches