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

Proposed by Stephen M. Webb
Status: Merged
Merged at revision: 213
Proposed branch: lp:~bregma/geis/lp-937021
Merge into: lp:geis
Diff against target: 499 lines (+261/-56)
10 files modified
.bzrignore (+3/-3)
configure.ac (+3/-1)
libutouch-geis/backend/grail/geis_grail_backend.c (+15/-1)
libutouch-geis/backend/grail/geis_grail_window_grab.c (+15/-4)
libutouch-geis/backend/grail/geis_grail_window_grab.h (+4/-2)
testsuite/geis2/Makefile.am (+3/-1)
testsuite/geis2/gtest_attrs.cpp (+9/-44)
testsuite/geis2/gtest_geis_fixture.cpp (+64/-0)
testsuite/geis2/gtest_geis_fixture.h (+50/-0)
testsuite/geis2/gtest_subscriptions.cpp (+95/-0)
To merge this branch: bzr merge lp:~bregma/geis/lp-937021
Reviewer Review Type Date Requested Status
Chase Douglas (community) Approve
Review via email: mp+94837@code.launchpad.net

Description of the change

Check he success of grabbing multi-touch input on a window and propagates the result up the stack.

Fixes lp:937021.

Fix can be verified by running the geistest tool without any command-line arguments so that it attempts to grab input from the root window. This will now fail, additional error messages are show if the environment variable GEIS_DEBUG is set to an integer value greater than or equal to 1.

To post a comment you must log in.
Revision history for this message
Jussi Pakkanen (jpakkane) wrote :

Having final_exit and goto would make more sense if some resource were freed there. Personally I would replace them with an explicit "return GEIS_STATUS_UNKNOWN_ERROR;". This is not a blocker for merging, though.

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

This needs an automated test that runs at 'make check'.

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

synched with trunk

211. By Stephen M. Webb

Refactored GEIS test fixture.

212. By Stephen M. Webb

Removed warnings from configure.

213. By Stephen M. Webb

Added test case for lp:937021

214. By Stephen M. Webb

Got lp:937021 test case passing (when evemu works).

215. By Stephen M. Webb

Eliminated transient evemy device creation failures.

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

OK, test cases seem to pass every time. Ready for full review.

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

Looks good to me :). The GeisSubscriptionTests class doesn't need the SetUp or TearDown methods since they just call the superclass methods. After deleting them, feel free to merge.

review: Approve
lp:~bregma/geis/lp-937021 updated
216. By Stephen M. Webb

Removed unnecessary fixture SetUp() and TearDown() in gtest-based tests.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2012-02-21 20:31:39 +0000
3+++ .bzrignore 2012-03-07 18:15:24 +0000
4@@ -10,9 +10,9 @@
5 *Makefile.in
6 aclocal.m4
7 autom4te.cache
8-check_geis1_api
9-check_geis2_api
10-check_geis2_internals
11+check-*-compile
12+check_*_api
13+check_*_internals
14 check_geis_util
15 config.*
16 configure
17
18=== modified file 'configure.ac'
19--- configure.ac 2012-02-23 17:07:26 +0000
20+++ configure.ac 2012-03-07 18:15:24 +0000
21@@ -32,6 +32,7 @@
22
23 # Checks for programs.
24 AM_PROG_CC_C_O
25+AC_PROG_CXX
26 AM_PATH_PYTHON([2.7])
27
28 LT_PREREQ([2.2.6b])
29@@ -99,7 +100,7 @@
30 [with_integration_tests=check])
31 AC_MSG_RESULT([$with_integration_tests])
32 AS_IF([test "x$with_integration_tests" != xno],
33- [AC_PROG_CXX
34+ [AC_LANG_PUSH(C++)
35 AC_CHECK_LIB([gtest], [main], [have_gtest=yes])
36 AS_IF([test "x$have_gtest" = xyes],
37 [PKG_CHECK_MODULES([XORG_GTEST],
38@@ -109,6 +110,7 @@
39 unit testing disabled])])
40 PKG_CHECK_MODULES([EVEMU],[utouch-evemu >= 1.0.5])
41 ])
42+ AC_LANG_POP
43 XORG_GTEST_LIBS="$XORG_GTEST_LIBS -lgtest -lpthread"])
44 AM_CONDITIONAL([HAVE_XORG_GTEST],[test "x$have_xorg_gtest" = xyes])
45
46
47=== modified file 'libutouch-geis/backend/grail/geis_grail_backend.c'
48--- libutouch-geis/backend/grail/geis_grail_backend.c 2012-02-24 17:12:40 +0000
49+++ libutouch-geis/backend/grail/geis_grail_backend.c 2012-03-07 18:15:24 +0000
50@@ -1437,7 +1437,13 @@
51 (void *)ugsub,
52 grail_use_atomic_gestures);
53
54- geis_grail_window_grab_store_grab(gbe->window_grabs, window_id);
55+ status = geis_grail_window_grab_store_grab(gbe->window_grabs, window_id);
56+ if (status != GEIS_STATUS_SUCCESS)
57+ {
58+ geis_error("failed to grab input on window 0x%08x", window_id);
59+ goto final_exit;
60+ }
61+
62 ugstatus = grail_subscription_activate(gbe->grail, ugsub);
63 if (ugstatus != UGStatusSuccess)
64 {
65@@ -1486,6 +1492,10 @@
66 device,
67 window_id,
68 subscription);
69+ if (status != GEIS_STATUS_SUCCESS)
70+ {
71+ goto final_exit;
72+ }
73 }
74 else
75 {
76@@ -1506,6 +1516,8 @@
77 subscription);
78 }
79 }
80+
81+final_exit:
82 return status;
83 }
84
85@@ -1558,6 +1570,8 @@
86 status = GEIS_STATUS_SUCCESS;
87 }
88 geis_device_bag_delete(selected_devices);
89+ if (status != GEIS_STATUS_SUCCESS)
90+ break;
91 }
92
93 return status;
94
95=== modified file 'libutouch-geis/backend/grail/geis_grail_window_grab.c'
96--- libutouch-geis/backend/grail/geis_grail_window_grab.c 2012-03-02 17:54:50 +0000
97+++ libutouch-geis/backend/grail/geis_grail_window_grab.c 2012-03-07 18:15:24 +0000
98@@ -20,7 +20,6 @@
99 #include "geis_config.h"
100 #include "geis_grail_window_grab.h"
101
102-#include "geis/geis.h"
103 #include "geis_bag.h"
104 #include "geis_logging.h"
105 #include <X11/extensions/XInput2.h>
106@@ -124,9 +123,10 @@
107 /*
108 * Grabs a window through a window grab store.
109 */
110-void
111+GeisStatus
112 geis_grail_window_grab_store_grab(GeisGrailWindowGrabStore wgs, Window window_id)
113 {
114+ GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
115 GeisGrailWindowGrab grab = _window_grab_store_find(wgs, window_id);
116 if (!grab)
117 {
118@@ -147,16 +147,27 @@
119 int xstat = XIGrabTouchBegin(wgs->display, XIAllMasterDevices,
120 window_id,
121 0, &mask, 1, &mods);
122+ free(mask.mask);
123 if (xstat)
124 {
125 geis_error("error %d returned from XIGrabTouchBegin()", xstat);
126- }
127- free(mask.mask);
128+ goto final_exit;
129+ }
130+ else if (mods.status != XIGrabSuccess)
131+ {
132+ geis_error("status %d returned from XIGrabTouchBegin()", mods.status);
133+ goto final_exit;
134+ }
135+ status = GEIS_STATUS_SUCCESS;
136 }
137 else
138 {
139 ++grab->grab_count;
140+ status = GEIS_STATUS_SUCCESS;
141 }
142+
143+final_exit:
144+ return status;
145 }
146
147
148
149=== modified file 'libutouch-geis/backend/grail/geis_grail_window_grab.h'
150--- libutouch-geis/backend/grail/geis_grail_window_grab.h 2012-01-31 20:46:42 +0000
151+++ libutouch-geis/backend/grail/geis_grail_window_grab.h 2012-03-07 18:15:24 +0000
152@@ -20,6 +20,7 @@
153 #ifndef GEIS_BACKEND_GRAIL_WINDOW_GRAB_H_
154 #define GEIS_BACKEND_GRAIL_WINDOW_GRAB_H_
155
156+#include "geis/geis.h"
157 #include <X11/Xlib.h>
158
159
160@@ -56,9 +57,10 @@
161 * @param store A window grab store.
162 * @param window The window to grab.
163 *
164- * @returns a reference to the grab.
165+ * @returns GEIS_STATUS_SUCCESS if the multi-touch for the window was grabbed
166+ * successfully, GEIS_STATUS_UNKNOWN_ERROR otherwise.
167 */
168-void
169+GeisStatus
170 geis_grail_window_grab_store_grab(GeisGrailWindowGrabStore store,
171 Window window);
172
173
174=== modified file 'testsuite/geis2/Makefile.am'
175--- testsuite/geis2/Makefile.am 2012-03-05 14:22:20 +0000
176+++ testsuite/geis2/Makefile.am 2012-03-07 18:15:24 +0000
177@@ -44,7 +44,9 @@
178
179 gtest_geis2_api_SOURCES = \
180 gtest_attrs.cpp \
181- gtest_evemu_device.h gtest_evemu_device.cpp
182+ gtest_subscriptions.cpp \
183+ gtest_evemu_device.h gtest_evemu_device.cpp \
184+ gtest_geis_fixture.h gtest_geis_fixture.cpp
185
186 gtest_geis2_api_CPPFLAGS = \
187 --std=c++0x \
188
189=== modified file 'testsuite/geis2/gtest_attrs.cpp'
190--- testsuite/geis2/gtest_attrs.cpp 2012-03-05 17:22:19 +0000
191+++ testsuite/geis2/gtest_attrs.cpp 2012-03-07 18:15:24 +0000
192@@ -7,13 +7,11 @@
193 #include <functional>
194 #include "geis/geis.h"
195 #include "gtest_evemu_device.h"
196+#include "gtest_geis_fixture.h"
197 #include <gtest/gtest.h>
198-#include <memory>
199 #include <mutex>
200 #include <sys/select.h>
201 #include <sys/time.h>
202-#include <X11/extensions/XInput2.h>
203-#include <xorg/gtest/test.h>
204
205
206 namespace
207@@ -23,52 +21,19 @@
208 static const std::string TEST_DEVICE_EVENTS_FILE("touchscreen_a_rotate90.events");
209
210 /**
211- * Fixture for testing expected attributes.
212+ * Fixture for testing expected attributes. This has to be a separate class
213+ * because of the way Java reflection is used in jUnit.
214 */
215 class GeisAttributeTests
216-: public xorg::testing::Test
217+: public GTestGeisFixture
218 {
219 public:
220- void
221- SetUp()
222- {
223- // Chain up the static class heirarchy, as if the test framework was
224- // designed by a Java trainee with some exposure to glib but has never used
225- // C++.
226- ASSERT_NO_FATAL_FAILURE(xorg::testing::Test::SetUp());
227-
228- // Verify that whatever X server is in use supports the required XInput
229- // version.
230- int xi_major = 2;
231- int xi_minor = 2;
232- ASSERT_EQ(Success, XIQueryVersion(Display(), &xi_major, &xi_minor));
233- ASSERT_GE(xi_major, 2);
234- ASSERT_GE(xi_minor, 2);
235-
236- evemu_device_.reset(new Testsuite::EvemuDevice(TEST_DEVICE_PROP_FILE));
237-
238- geis_ = geis_new(GEIS_INIT_SYNCHRONOUS_START, GEIS_INIT_NO_ATOMIC_GESTURES, NULL);
239- }
240-
241- void
242- TearDown()
243- {
244- geis_delete(geis_);
245- xorg::testing::Test::TearDown(); // NVI ftw.
246- evemu_device_.reset();
247- }
248-
249- int
250- geis_fd()
251- {
252- GeisInteger fd;
253- geis_get_configuration(geis_, GEIS_CONFIGURATION_FD, &fd);
254- return fd;
255- }
256+ GeisAttributeTests()
257+ : evemu_device_(TEST_DEVICE_PROP_FILE)
258+ { }
259
260 protected:
261- std::unique_ptr<Testsuite::EvemuDevice> evemu_device_;
262- Geis geis_;
263+ Testsuite::EvemuDevice evemu_device_;
264 };
265
266
267@@ -114,7 +79,7 @@
268 {
269 if (geis_event_type(event) == GEIS_EVENT_INIT_COMPLETE)
270 {
271- evemu_device_->play(TEST_DEVICE_EVENTS_FILE);
272+ evemu_device_.play(TEST_DEVICE_EVENTS_FILE);
273 }
274 else if (geis_event_type(event) == GEIS_EVENT_GESTURE_END)
275 {
276
277=== added file 'testsuite/geis2/gtest_geis_fixture.cpp'
278--- testsuite/geis2/gtest_geis_fixture.cpp 1970-01-01 00:00:00 +0000
279+++ testsuite/geis2/gtest_geis_fixture.cpp 2012-03-07 18:15:24 +0000
280@@ -0,0 +1,64 @@
281+/**
282+ * @file gtest_geis_fixture.cpp
283+ * @brief A GTest fixture for testing the full uTouch stack through GEIS.
284+ */
285+/*
286+ * Copyright 2012 Canonical Ltd.
287+ *
288+ * This program is free software: you can redistribute it and/or modify it
289+ * under the terms of the GNU General Public License version 3, as published
290+ * by the Free Software Foundation.
291+ *
292+ * This program is distributed in the hope that it will be useful, but
293+ * WITHOUT ANY WARRANTY; without even the implied warranties of
294+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
295+ * PURPOSE. See the GNU General Public License for more details.
296+ *
297+ * You should have received a copy of the GNU General Public License along
298+ * with this program. If not, see <http://www.gnu.org/licenses/>.
299+ */
300+#include "gtest_geis_fixture.h"
301+
302+#include <unistd.h>
303+#include <X11/extensions/XInput2.h>
304+
305+
306+void GTestGeisFixture::
307+SetUp()
308+{
309+ // wait for things to settle
310+ usleep(1000000);
311+
312+ // Chain up the static class heirarchy, as if the test framework was
313+ // designed by a Java trainee with some exposure to glib but has never used
314+ // C++.
315+ ASSERT_NO_FATAL_FAILURE(xorg::testing::Test::SetUp());
316+
317+ // Verify that whatever X server is in use supports the required XInput
318+ // version.
319+ int xi_major = 2;
320+ int xi_minor = 2;
321+ ASSERT_EQ(Success, XIQueryVersion(Display(), &xi_major, &xi_minor));
322+ ASSERT_GE(xi_major, 2);
323+ ASSERT_GE(xi_minor, 2);
324+
325+ geis_ = geis_new(GEIS_INIT_SYNCHRONOUS_START, GEIS_INIT_NO_ATOMIC_GESTURES, NULL);
326+}
327+
328+void GTestGeisFixture::
329+TearDown()
330+{
331+ geis_delete(geis_);
332+ xorg::testing::Test::TearDown(); // NVI ftw.
333+ usleep(1000000);
334+}
335+
336+int GTestGeisFixture::
337+geis_fd()
338+{
339+ GeisInteger fd;
340+ geis_get_configuration(geis_, GEIS_CONFIGURATION_FD, &fd);
341+ return fd;
342+}
343+
344+
345
346=== added file 'testsuite/geis2/gtest_geis_fixture.h'
347--- testsuite/geis2/gtest_geis_fixture.h 1970-01-01 00:00:00 +0000
348+++ testsuite/geis2/gtest_geis_fixture.h 2012-03-07 18:15:24 +0000
349@@ -0,0 +1,50 @@
350+/**
351+ * @file gtest_geis_fixture.h
352+ * @brief A GTest fixture for testing the full uTouch stack through GEIS.
353+ */
354+/*
355+ * Copyright 2012 Canonical Ltd.
356+ *
357+ * This program is free software: you can redistribute it and/or modify it
358+ * under the terms of the GNU General Public License version 3, as published
359+ * by the Free Software Foundation.
360+ *
361+ * This program is distributed in the hope that it will be useful, but
362+ * WITHOUT ANY WARRANTY; without even the implied warranties of
363+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
364+ * PURPOSE. See the GNU General Public License for more details.
365+ *
366+ * You should have received a copy of the GNU General Public License along
367+ * with this program. If not, see <http://www.gnu.org/licenses/>.
368+ */
369+#ifndef GTEST_GEIS_FIXTURE_H_
370+#define GTEST_GEIS_FIXTURE_H_
371+
372+#include "geis/geis.h"
373+#include <gtest/gtest.h>
374+#include <xorg/gtest/test.h>
375+
376+
377+/**
378+ * Fixture for testing expected attributes.
379+ */
380+class GTestGeisFixture
381+: public xorg::testing::Test
382+{
383+public:
384+ void
385+ SetUp();
386+
387+ void
388+ TearDown();
389+
390+ int
391+ geis_fd();
392+
393+protected:
394+ Geis geis_;
395+};
396+
397+
398+#endif /* GTEST_GEIS_FIXTURE_H_ */
399+
400
401=== added file 'testsuite/geis2/gtest_subscriptions.cpp'
402--- testsuite/geis2/gtest_subscriptions.cpp 1970-01-01 00:00:00 +0000
403+++ testsuite/geis2/gtest_subscriptions.cpp 2012-03-07 18:15:24 +0000
404@@ -0,0 +1,95 @@
405+/**
406+ * GTest-based test suite for GEIS subscription actions.
407+ *
408+ * Copyright 2012 Canonical Ltd.
409+ */
410+
411+#include "gtest_evemu_device.h"
412+#include "gtest_geis_fixture.h"
413+
414+
415+static const std::string TEST_DEVICE_PROP_FILE("touchscreen_a.prop");
416+
417+
418+/**
419+ * Tests need to make sure at least one multi-touch device is available.
420+ */
421+class GeisSubscriptionTests
422+: public GTestGeisFixture
423+{
424+public:
425+ GeisSubscriptionTests()
426+ : evemu_device_(TEST_DEVICE_PROP_FILE)
427+ { }
428+
429+private:
430+ Testsuite::EvemuDevice evemu_device_;
431+};
432+
433+
434+/**
435+ * Regression test for lp:937021: Geis subscription touch grabs need to check
436+ * for failure.
437+ *
438+ * This test creates two subscriptions, both attached to the root window but
439+ * each on a different X client. Since multiple subscriptions for the same
440+ * window but a different client are expected to fail using the XI2.2-based
441+ * grail back end, activating the second subscription is extected to resut in
442+ * a failure.
443+ *
444+ * This behaviour is very dependent on the particular back end used and internal
445+ * implementattion details of that back end. It is not a unit test or a
446+ * reliable group or system test.
447+ */
448+TEST_F(GeisSubscriptionTests, duplicate_window_subscription)
449+{
450+ Geis geis2 = geis_new(GEIS_INIT_SYNCHRONOUS_START,
451+ GEIS_INIT_NO_ATOMIC_GESTURES,
452+ NULL);
453+ EXPECT_TRUE(geis2 != NULL) << "can not create second geis instance";
454+
455+ GeisSubscription sub1 = geis_subscription_new(geis_,
456+ "subscription 1",
457+ GEIS_SUBSCRIPTION_NONE);
458+ EXPECT_TRUE(sub1 != NULL) << "can not create first subscription";
459+
460+ GeisSubscription sub2 = geis_subscription_new(geis2,
461+ "subscription 2",
462+ GEIS_SUBSCRIPTION_NONE);
463+ EXPECT_TRUE(sub1 != NULL) << "can not create second subscription";
464+
465+ GeisFilter filter1 = geis_filter_new(geis_, "root window 1");
466+ EXPECT_TRUE(filter1 != NULL) << "can not create filter 1";
467+
468+ GeisStatus fs = geis_filter_add_term(filter1,
469+ GEIS_FILTER_CLASS,
470+ GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_ROTATE,
471+ GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_GT, 1,
472+ NULL);
473+ EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add class to filter 1";
474+
475+ GeisFilter filter2 = geis_filter_new(geis_, "root window 2");
476+ EXPECT_TRUE(filter2 != NULL) << "can not create filter 2";
477+
478+ fs = geis_filter_add_term(filter2,
479+ GEIS_FILTER_CLASS,
480+ GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_ROTATE,
481+ GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_GT, 1,
482+ NULL);
483+ EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add class to filter 2";
484+
485+ fs = geis_subscription_add_filter(sub1, filter1);
486+ EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not subscribe filter 1";
487+ fs = geis_subscription_add_filter(sub2, filter2);
488+ EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not subscribe filter 2";
489+
490+ EXPECT_EQ(GEIS_STATUS_SUCCESS, geis_subscription_activate(sub1))
491+ << "can not activate subscription 1";
492+ EXPECT_NE(GEIS_STATUS_SUCCESS, geis_subscription_activate(sub2))
493+ << "mistakenly activated subscription 2";
494+
495+ geis_subscription_delete(sub2);
496+ geis_subscription_delete(sub1);
497+ geis_delete(geis2);
498+}
499+

Subscribers

People subscribed via source and target branches