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

Proposed by Daniel d'Andrada
Status: Merged
Merged at revision: 258
Proposed branch: lp:~dandrader/geis/lp984069
Merge into: lp:geis
Diff against target: 1242 lines (+1068/-27)
14 files modified
.bzrignore (+1/-0)
configure.ac (+5/-0)
include/geis/geis.h (+5/-0)
libutouch-geis/backend/grail/geis_grail_backend.c (+18/-8)
m4/gtest.m4 (+51/-0)
testsuite/Makefile.am (+1/-1)
testsuite/geis2/Makefile.am (+39/-9)
testsuite/geis2/gtest_gbe_direct_touch_coords.cpp (+295/-0)
testsuite/geis2/gtest_grail_backend.cpp (+134/-0)
testsuite/geis2/gtest_grail_backend.h (+52/-0)
testsuite/gtest/Makefile.am (+14/-9)
testsuite/x11_mocks/Makefile.am (+13/-0)
testsuite/x11_mocks/x11_mocks.c (+406/-0)
testsuite/x11_mocks/x11_mocks.h (+34/-0)
To merge this branch: bzr merge lp:~dandrader/geis/lp984069
Reviewer Review Type Date Requested Status
Chase Douglas (community) Approve
Stephen M. Webb (community) Needs Fixing
Review via email: mp+102337@code.launchpad.net

Description of the change

GeisTouches from direct devices should be in window coordinates. Have this also documented in geis.h

The fix for bug #978378 in Unity depends on it.

This should be tested by someone with a touchscreen device along with the fix for bug #978378 (lp:~dandrader/unity/direct_device) to verify that those modifications indeed get bug #978378 fixed.

To post a comment you must log in.
Revision history for this message
Stephen M. Webb (bregma) wrote :

The code change looks OK. I built and tested with a touchscreen, and nothing appears to be broken, but I don't think that's really a valid test of this change. Is there a better interactive test?

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

I tested the branch and everything seems to work appropriately. In the unity branch, the unity bug #978378 seems to be fixed.

We just need tests in geis now.

review: Needs Fixing
lp:~dandrader/geis/lp984069 updated
253. By Stephen M. Webb

Added an API for setting and getting grail tuning properties.

254. By Stephen M. Webb

Added a compile-time sentinel check to variadic calls in the API.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

It now has a unit test.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

I would make it use Google Test istead of Check Framework but in utouch-geis GTest is quite entangled with xorg-gtest and integration tests (ENABLE_INTEGRATION_TESTS).

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

As far as I understand, the gtest issue is merely that we need to make the autotools stuff know about gtest for unit testing. I would prefer to fix that issue now and continue to use gtest.

Otherwise, I'm ok with this for now. I think we may want to split the mock out into a separate project in the future, maybe using a mock framework like google-mock to make things easier.

review: Needs Fixing
lp:~dandrader/geis/lp984069 updated
255. By Chase Douglas

Merge fixes for radius and position delta calculations

256. By Chase Douglas

Merge fix for GeisSubscriptionFlags usage when compiling with g++

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

Took libgtest.a out of libgtest_geis.a and made the regression test of this bug GTest based instead of Check based.

Ready for a new review.

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

* xorg-gtest.m4 shouldn't be modified. It comes from upstream xorg-gtest and may be replaced by a newer version from an updated xorg-gtest automatically by aclocal --install. IIRC, I think it may also be always replaced by our packaging since it uses aclocal --install --force.

Since _CHECK_GTEST is meant to be an internal implementation detail of xorg-gtest.m4, I suggest copying it to a new file m4/gtest.m4 and removing the leading underscore.

* libgtest_geis_a_CPPFLAGS still needs $(GTEST_CPPFLAGS). If the gtest headers are installed somewhere other than a standard location, GTEST_CPPFLAGS will have the -I<header path> option. This will be needed for building xorg-gtest too. Likewise for gtest_geis2_grail_backend_CPPFLAGS.

* libgtest_geis_a_LIBADD should add the libgtest.a file instead of an intermediate object file. I don't know if that will work, but the .o file is sort of an autotools implementation detail. This may also remove the need for libgtest_geis_a_DEPENDENCIES.

* libgtest doesn't need to be built with --std=c++0x. xorg-gtest doesn't need to built with it either. I also don't know why TEST_ROOT_DIR is defined for both gtest libs. I think it was a copy/paste error.

* PRINT_FAILURE_AND_RETURN isn't necessary. All you need is ADD_FAILURE() << [message]; The file and line will be printed automatically, and the function return automatically.

* I like the idea of MOCK_PRINT. I think it duplicates the geis logging, though. Why not use geis_debug()? I know this means you can't enable mock printouts without geis debug printouts, but I think that's ok. If you're debugging at this level you might be setting GEIS_DEBUG=3 anyway. If you have a standard format where something like "XMOCK: " is prepended to the message, it will be easy to grep or grep -v on it.

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

(1) m4/xorg-gtest.m4 is actually a convenience copy of a source file belonging to another package and will likely be overwritten at build time. I would suggest the CHECK_GTEST macro be hoisted into its own .m4 file so it doesn't get trampled: it's already renamed so there shouldn't be a conflict.

(2) Not sure why you did all the fancy wrangling in testsuite/gtest/Makefile.am to provide multiple libraries instead of just including the xorg-gtest sources conditionally on ENABLE_INTEGRATION_TESTS. Could you make your reasoning explicit?

(3) Why reorganize testsuite/geis2/Makefile.am? Traditionally all the build targets go at the top (eg. *_PROGRAMS) and the detailed rules for building them come later, rather than the other way around. Granted, that tradition started because automake required it, but following convention makes it easier from someone who sees a lot of Makefile.ams to follow unfamiliar code. Could you make your reasoning for this explicit?

(4) If you're changing testsuite libraries around anyway, would it be possible to consolidate all support libraries used in the testsuite (gtest, mocks) into a single subdirectory? It would simplify the Makefile.ams used in the various test suites. Feel free to argue this.

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

* I like the idea of MOCK_PRINT. I think it duplicates the geis logging, though. Why not use geis_debug()? I know this means you can't enable mock printouts without geis debug printouts, but I think that's ok. If you're debugging at this level you might be setting GEIS_DEBUG=3 anyway. If you have a standard format where something like "XMOCK: " is prepended to the message, it will be easy to grep or grep -v on it.

geis_debug() is not a public symbol exported from libutouch-geis.so. It is not available for any part of the testsuite except the libutouch tests (which are internal unit tests).

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

On 04/23/2012 02:17 PM, Stephen M. Webb wrote:
> * I like the idea of MOCK_PRINT. I think it duplicates the geis logging, though. Why not use geis_debug()? I know this means you can't enable mock printouts without geis debug printouts, but I think that's ok. If you're debugging at this level you might be setting GEIS_DEBUG=3 anyway. If you have a standard format where something like "XMOCK: " is prepended to the message, it will be easy to grep or grep -v on it.
>
> geis_debug() is not a public symbol exported from libutouch-geis.so. It is not available for any part of the testsuite except the libutouch tests (which are internal unit tests).

Ok. What about printing if an env var is set, like MOCK_DEBUG? I'm not a
big fan of preprocessor macros enabling optional functionality. It's not
easy to figure out whether something has been compiled with the
functionality or not.

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

> Ok. What about printing if an env var is set, like MOCK_DEBUG? I'm not a
> big fan of preprocessor macros enabling optional functionality. It's not
> easy to figure out whether something has been compiled with the
> functionality or not.

+1

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> On 04/23/2012 02:17 PM, Stephen M. Webb wrote:
> > * I like the idea of MOCK_PRINT. I think it duplicates the geis logging,
> though. Why not use geis_debug()? I know this means you can't enable mock
> printouts without geis debug printouts, but I think that's ok. If you're
> debugging at this level you might be setting GEIS_DEBUG=3 anyway. If you have
> a standard format where something like "XMOCK: " is prepended to the message,
> it will be easy to grep or grep -v on it.
> >
> > geis_debug() is not a public symbol exported from libutouch-geis.so. It is
> not available for any part of the testsuite except the libutouch tests (which
> are internal unit tests).
>
> Ok. What about printing if an env var is set, like MOCK_DEBUG? I'm not a
> big fan of preprocessor macros enabling optional functionality. It's not
> easy to figure out whether something has been compiled with the
> functionality or not.

Me neither, but that was the easiest way and I didn't think it was worth to invest time into making a fully fledged solution.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> (3) Why reorganize testsuite/geis2/Makefile.am? Traditionally all the build
> targets go at the top (eg. *_PROGRAMS) and the detailed rules for building
> them come later, rather than the other way around. Granted, that tradition
> started because automake required it, but following convention makes it easier
> from someone who sees a lot of Makefile.ams to follow unfamiliar code. Could
> you make your reasoning for this explicit?

I like when all code regarding a library/program is together in a single block instead of intertwined with code for other libraries/programs. I find that arrangement easier to read and maintain. But as with coding style, it's mostly a matter of personal taste.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> (2) Not sure why you did all the fancy wrangling in
> testsuite/gtest/Makefile.am to provide multiple libraries instead of just
> including the xorg-gtest sources conditionally on ENABLE_INTEGRATION_TESTS.
> Could you make your reasoning explicit?

That's another way of doing it. But I prefer the separation method since "That way we can have tests that depend on gtest but not on xorg-gtest" and therefore tests can link against only what they are going to use. Tests that use xmock will use gtest but never xorg-gtest, evemu or the fixtures included in libgtest_geis.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> (4) If you're changing testsuite libraries around anyway, would it be possible
> to consolidate all support libraries used in the testsuite (gtest, mocks) into
> a single subdirectory? It would simplify the Makefile.ams used in the various
> test suites. Feel free to argue this.

I personally find it a bit messy to have the sources of several separate, independent, binaries (programs of libraries) living together in the same directory. It can easily result in a cluttered directory listing and Makefile.am.

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

On 04/24/2012 09:52 AM, Daniel d'Andrada wrote:
>> (2) Not sure why you did all the fancy wrangling in
>> testsuite/gtest/Makefile.am to provide multiple libraries instead of just
>> including the xorg-gtest sources conditionally on ENABLE_INTEGRATION_TESTS.
>> Could you make your reasoning explicit?
>
> That's another way of doing it. But I prefer the separation method since "That way we can have tests that depend on gtest but not on xorg-gtest" and therefore tests can link against only what they are going to use. Tests that use xmock will use gtest but never xorg-gtest, evemu or the fixtures included in libgtest_geis.

But you know that for the last 40 years or so linkers only pull objects out of archives if they're used, so the only
difference between using a single library and using multiple libraries is one of increased maintenance cost and
confusion about which library to use?

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> On 04/24/2012 09:52 AM, Daniel d'Andrada wrote:
> >> (2) Not sure why you did all the fancy wrangling in
> >> testsuite/gtest/Makefile.am to provide multiple libraries instead of just
> >> including the xorg-gtest sources conditionally on ENABLE_INTEGRATION_TESTS.
> >> Could you make your reasoning explicit?
> >
> > That's another way of doing it. But I prefer the separation method since
> "That way we can have tests that depend on gtest but not on xorg-gtest" and
> therefore tests can link against only what they are going to use. Tests that
> use xmock will use gtest but never xorg-gtest, evemu or the fixtures included
> in libgtest_geis.
>
> But you know that for the last 40 years or so linkers only pull objects out of
> archives if they're used, so the only
> difference between using a single library and using multiple libraries is one
> of increased maintenance cost and
> confusion about which library to use?

I can do single library approach, no problem.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

Updated according to comments.

Ready for a new review round.

lp:~dandrader/geis/lp984069 updated
257. By Daniel d'Andrada

GeisTouches from direct devices should be in window coordinates

GeisTouches provided by gesture events (GEIS_EVENT_GESTURE_BEGIN,
GEIS_EVENT_GESTURE_UPDATE and GEIS_EVENT_GESTURE_END) should be in window
coordinates if they come from a direct device (e.g. touchscreens) and in
input device coordinates when from indirect devices (e.g. touchpads/trackpads).

Have this also documented in geis.h

They were coming always in device coordinates.

258. By Daniel d'Andrada

Make it possible to have gtest without integration tests and xorg-gtest

That way we can have unit and functional tests using gtest independently
of whether integration tests will be built or whether xorg-gtest is present.

259. By Daniel d'Andrada

Adding X11 mockups

260. By Daniel d'Andrada

Organize the Makefile a bit

Bring together the code for each binary in blocks instead of having them intertwined

261. By Daniel d'Andrada

Regression test for lp984069

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

* The --std=c++0x flags are still used.

* PRINT_FAILURE_AND_RETURN is still there.

I think everything else I commented on has been addressed.

review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> * The --std=c++0x flags are still used.
>
> * PRINT_FAILURE_AND_RETURN is still there.
>
> I think everything else I commented on has been addressed.

Ah, yeah, I forgot those. Sorry for that.

lp:~dandrader/geis/lp984069 updated
262. By Daniel d'Andrada

GTest doesn't need --std=c++0x

263. By Daniel d'Andrada

ADD_FAILURE() already prints the current file name and line number

264. By Daniel d'Andrada

Stop immediately if subscription creation fails

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

Updated.

ADD_FAILURE() does print the file name and line number but it does *not* return. Therefore a wrapping macro is still needed. So I removed the printf() command and renamed the macro.

I've removed the --std=c++0x flag from gtest

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

On 04/24/2012 11:59 AM, Daniel d'Andrada wrote:
> ADD_FAILURE() does print the file name and line number but it does *not* return. Therefore a wrapping macro is still needed. So I removed the printf() command and renamed the macro.

Ahh, I remembered wrong. You want FAIL() << [message]; It's just like
ADD_FAILURE() except that it causes the function to return. It's
analogous to ASSERT_*() vs EXPECT_*().

http://code.google.com/p/googletest/wiki/AdvancedGuide#Explicit_Success_and_Failure

> I've removed the --std=c++0x flag from gtest

gtest_geis2_grail_backend_CPPFLAGS still has --std=c++0x.

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

"make distcheck" fails (there should be no nodist_ prefix on the SOURCES variable in testsuite/x11_mocks/Makefile.am).

review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> On 04/24/2012 11:59 AM, Daniel d'Andrada wrote:
> > ADD_FAILURE() does print the file name and line number but it does *not*
> return. Therefore a wrapping macro is still needed. So I removed the printf()
> command and renamed the macro.
>
> Ahh, I remembered wrong. You want FAIL() << [message]; It's just like
> ADD_FAILURE() except that it causes the function to return. It's
> analogous to ASSERT_*() vs EXPECT_*().
>
> http://code.google.com/p/googletest/wiki/AdvancedGuide#Explicit_Success_and_Failure

FAIL(), like ASSERT_*(), can only be used from within functions that return void. That's why I have to stick with ADD_FAILURE().

>
> > I've removed the --std=c++0x flag from gtest
>
> gtest_geis2_grail_backend_CPPFLAGS still has --std=c++0x.

I needs --std=c++0x because it uses c++0x stuff (like nullptr and range-based for loops)

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> "make distcheck" fails (there should be no nodist_ prefix on the SOURCES
> variable in testsuite/x11_mocks/Makefile.am).

Fixed.

lp:~dandrader/geis/lp984069 updated
265. By Daniel d'Andrada

sources of x11_mocks are distributed

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

On 04/24/2012 12:31 PM, Daniel d'Andrada wrote:
>> On 04/24/2012 11:59 AM, Daniel d'Andrada wrote:
>>> ADD_FAILURE() does print the file name and line number but it does *not*
>> return. Therefore a wrapping macro is still needed. So I removed the printf()
>> command and renamed the macro.
>>
>> Ahh, I remembered wrong. You want FAIL() << [message]; It's just like
>> ADD_FAILURE() except that it causes the function to return. It's
>> analogous to ASSERT_*() vs EXPECT_*().
>>
>> http://code.google.com/p/googletest/wiki/AdvancedGuide#Explicit_Success_and_Failure
>
> FAIL(), like ASSERT_*(), can only be used from within functions that return void. That's why I have to stick with ADD_FAILURE().

Ahh, yes, that would be an issue.

This is a bit bike-shedding, but I would prefer to unroll the macro
since it's two simple lines. I think it would make the code easier to
read. However, I'm ok with it as is.

>>
>>> I've removed the --std=c++0x flag from gtest
>>
>> gtest_geis2_grail_backend_CPPFLAGS still has --std=c++0x.
>
> I needs --std=c++0x because it uses c++0x stuff (like nullptr and range-based for loops)

Ok, I didn't realize that.

lp:~dandrader/geis/lp984069 updated
266. By Daniel d'Andrada

We don't need a macro anymore. Wrapped code is too simple

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2012-04-11 16:18:03 +0000
3+++ .bzrignore 2012-04-24 19:38:21 +0000
4@@ -48,4 +48,5 @@
5 TAGS
6 testsuite/geistest/geistest
7 testsuite/libutouch-geis/*.xml
8+testsuite/geis2/gtest_geis2_grail_backend
9 tools/geis-server/geis-server
10
11=== modified file 'configure.ac'
12--- configure.ac 2012-04-12 17:13:41 +0000
13+++ configure.ac 2012-04-24 19:38:21 +0000
14@@ -97,6 +97,10 @@
15 [enable_integration_tests=$enableval],
16 [enable_integration_tests=auto])
17
18+# Check for Google C++ Testing Framework
19+CHECK_GTEST()
20+AM_CONDITIONAL([HAVE_GTEST], [test "x$have_gtest" = xyes])
21+
22 have_xorg_gtest=no
23 AS_IF([test "x$enable_integration_tests" != xno],
24 [CHECK_XORG_GTEST(
25@@ -132,6 +136,7 @@
26 testsuite/geis2/Makefile
27 testsuite/geis1/Makefile
28 testsuite/geistest/Makefile
29+ testsuite/x11_mocks/Makefile
30 examples/Makefile
31 python/Makefile
32 tools/Makefile
33
34=== modified file 'include/geis/geis.h'
35--- include/geis/geis.h 2012-04-20 19:14:59 +0000
36+++ include/geis/geis.h 2012-04-24 19:38:21 +0000
37@@ -2061,6 +2061,11 @@
38 * is capable of reporting differing sets of touch attributes, so there is no
39 * guarantee that any or all of the defined touch attributes will bre present.
40 *
41+ * If the touch comes from a direct device (see
42+ * GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH) its position (x and y attributes) will
43+ * be in window coordinates, otherwise it will be in the input device's own
44+ * coordinate system.
45+ *
46 * @{
47 *
48 * @def GEIS_TOUCH_ATTRIBUTE_ID
49
50=== modified file 'libutouch-geis/backend/grail/geis_grail_backend.c'
51--- libutouch-geis/backend/grail/geis_grail_backend.c 2012-04-20 15:00:21 +0000
52+++ libutouch-geis/backend/grail/geis_grail_backend.c 2012-04-24 19:38:21 +0000
53@@ -635,19 +635,29 @@
54 focus_y = frame_touch_get_window_y(uftouch);
55 }
56
57- GeisFloat fval = frame_touch_get_device_x(uftouch);
58- bboxMinX = fmin(bboxMinX, fval);
59- bboxMaxX = fmax(bboxMaxX, fval);
60+ GeisFloat touch_x, touch_y;
61+ if (is_touchscreen)
62+ {
63+ touch_x = frame_touch_get_window_x(uftouch);
64+ touch_y = frame_touch_get_window_y(uftouch);
65+ }
66+ else
67+ {
68+ touch_x = frame_touch_get_device_x(uftouch);
69+ touch_y = frame_touch_get_device_y(uftouch);
70+ }
71+
72+ bboxMinX = fmin(bboxMinX, touch_x);
73+ bboxMaxX = fmax(bboxMaxX, touch_x);
74 geis_touch_add_attr(touch, geis_attr_new(GEIS_TOUCH_ATTRIBUTE_X,
75 GEIS_ATTR_TYPE_FLOAT,
76- &fval));
77+ &touch_x));
78
79- fval = frame_touch_get_device_y(uftouch);
80- bboxMinY = fmin(bboxMinY, fval);
81- bboxMaxY = fmax(bboxMaxY, fval);
82+ bboxMinY = fmin(bboxMinY, touch_y);
83+ bboxMaxY = fmax(bboxMaxY, touch_y);
84 geis_touch_add_attr(touch, geis_attr_new(GEIS_TOUCH_ATTRIBUTE_Y,
85 GEIS_ATTR_TYPE_FLOAT,
86- &fval));
87+ &touch_y));
88
89 geis_touchset_insert(touchset, touch);
90 geis_frame_add_touchid(frame, geis_touch_id(touch));
91
92=== added file 'm4/gtest.m4'
93--- m4/gtest.m4 1970-01-01 00:00:00 +0000
94+++ m4/gtest.m4 2012-04-24 19:38:21 +0000
95@@ -0,0 +1,51 @@
96+# serial 1
97+
98+# Copyright (C) 2012 Canonical, Ltd.
99+#
100+# Permission is hereby granted, free of charge, to any person obtaining a copy
101+# of this software and associated documentation files (the "Software"), to deal
102+# in the Software without restriction, including without limitation the rights
103+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
104+# copies of the Software, and to permit persons to whom the Software is
105+# furnished to do so, subject to the following conditions:
106+#
107+# The above copyright notice and this permission notice (including the next
108+# paragraph) shall be included in all copies or substantial portions of the
109+# Software.
110+#
111+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
112+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
113+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
114+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
115+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
116+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
117+# SOFTWARE.
118+
119+# Checks whether the gtest source is available on the system. Allows for
120+# adjusting the include and source path. Sets have_gtest=yes if the source is
121+# present. Sets GTEST_CPPFLAGS and GTEST_SOURCE to the preprocessor flags and
122+# source location respectively.
123+AC_DEFUN([CHECK_GTEST],
124+[
125+ AC_ARG_WITH([gtest-include-path],
126+ [AS_HELP_STRING([--with-gtest-include-path],
127+ [location of the Google test headers])],
128+ [GTEST_CPPFLAGS="-I$withval"])
129+
130+ AC_ARG_WITH([gtest-source-path],
131+ [AS_HELP_STRING([--with-gtest-source-path],
132+ [location of the Google test sources, defaults to /usr/src/gtest])],
133+ [GTEST_SOURCE="$withval"],
134+ [GTEST_SOURCE="/usr/src/gtest"])
135+
136+ GTEST_CPPFLAGS="$GTEST_CPPFLAGS -I$GTEST_SOURCE"
137+
138+ AC_CHECK_FILES([$GTEST_SOURCE/src/gtest-all.cc]
139+ [$GTEST_SOURCE/src/gtest_main.cc],
140+ [have_gtest=yes],
141+ [have_gtest=no])
142+
143+ AS_IF([test "x$have_gtest_source" = xyes],
144+ [AC_SUBST(GTEST_CPPFLAGS)]
145+ [AC_SUBST(GTEST_SOURCE)])
146+]) # CHECK_GTEST
147
148=== modified file 'testsuite/Makefile.am'
149--- testsuite/Makefile.am 2012-03-28 16:54:23 +0000
150+++ testsuite/Makefile.am 2012-04-24 19:38:21 +0000
151@@ -20,6 +20,6 @@
152 # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
153 #
154
155-SUBDIRS = gtest geis-util libutouch-geis geis2 geis1 geistest
156+SUBDIRS = gtest x11_mocks geis-util libutouch-geis geis2 geis1 geistest
157
158 EXTRA_DIST = recordings
159
160=== modified file 'testsuite/geis2/Makefile.am'
161--- testsuite/geis2/Makefile.am 2012-04-16 19:12:46 +0000
162+++ testsuite/geis2/Makefile.am 2012-04-24 19:38:21 +0000
163@@ -1,19 +1,15 @@
164 #
165-# @file testsuite/geis1/Makefile.am
166-# @brief automake recipe for the geis v1.0 testsuite unit testing directory
167+# @file testsuite/geis2/Makefile.am
168+# @brief automake recipe for the geis v2.0 testsuite testing directory
169 #
170
171 test_targets =
172+
173+##### check_geis2_api - Tests using Check C testing framework #####
174+
175 if HAVE_CHECK
176 test_targets += check_geis2_api
177 endif
178-if ENABLE_INTEGRATION_TESTS
179- test_targets += gtest_geis2_api
180-endif
181-
182-TESTS = $(test_targets)
183-
184-check_PROGRAMS = $(test_targets)
185
186 check_geis2_api_SOURCES = \
187 check_attr.c \
188@@ -42,6 +38,38 @@
189 $(top_builddir)/libutouch-geis/libutouch-geis.la \
190 $(CHECK_LIBS)
191
192+#### gtest_geis2_grail_backend - Test for the GRAIL backend of Geis v2 API #####
193+#### using gtest #####
194+
195+if HAVE_GTEST
196+ test_targets += gtest_geis2_grail_backend
197+endif
198+
199+gtest_geis2_grail_backend_SOURCES = \
200+ gtest_grail_backend.cpp \
201+ gtest_gbe_direct_touch_coords.cpp
202+
203+gtest_geis2_grail_backend_CPPFLAGS = \
204+ --std=c++0x \
205+ -I$(top_srcdir) \
206+ -I$(top_srcdir)/include \
207+ -I$(top_srcdir)/libutouch-geis \
208+ -I$(top_srcdir)/testsuite/gtest \
209+ -I$(top_srcdir)/testsuite/x11_mocks \
210+ -DTEST_ROOT_DIR=\"$(abs_top_srcdir)/testsuite/\"
211+ $(GTEST_CFLAGS)
212+
213+gtest_geis2_grail_backend_LDADD = \
214+ $(top_builddir)/testsuite/gtest/libgtest_geis.a \
215+ $(top_builddir)/testsuite/x11_mocks/libx11_mocks.a \
216+ $(top_builddir)/libutouch-geis/libutouch-geis.la
217+
218+#### gtest_geis2_api - Integration tests using xorg-gest and evemu #####
219+
220+if ENABLE_INTEGRATION_TESTS
221+ test_targets += gtest_geis2_api
222+endif
223+
224 gtest_geis2_api_SOURCES = \
225 gtest_attrs.cpp \
226 gtest_config.cpp \
227@@ -73,3 +101,5 @@
228 geis2_api.log \
229 geis2_api.xml
230
231+TESTS = $(test_targets)
232+check_PROGRAMS = $(test_targets)
233
234=== added file 'testsuite/geis2/gtest_gbe_direct_touch_coords.cpp'
235--- testsuite/geis2/gtest_gbe_direct_touch_coords.cpp 1970-01-01 00:00:00 +0000
236+++ testsuite/geis2/gtest_gbe_direct_touch_coords.cpp 2012-04-24 19:38:21 +0000
237@@ -0,0 +1,295 @@
238+#include "gtest_grail_backend.h"
239+#include "x11_mocks.h"
240+
241+/*
242+ Check that when a direct device (e.g. a touchscreen) is being used, the
243+ position of a GeisTouch will be in window coordinates instead of input
244+ device coordinates.
245+
246+ This means that the x an y values of a GeisTouch should come from
247+ XIDeviceEvent::event_x and XIDeviceEvent::event_y and not from
248+ XIDeviceEvent::valuators.values[0] and XIDeviceEvent::valuators.values[1],
249+ like it's the case for indirect devices (such as trackpads).
250+
251+ Regression test for https://bugs.launchpad.net/bugs/984069
252+ */
253+
254+class Geis2GrailBackend : public Geis2GrailBackendBase
255+{
256+ protected:
257+ Geis2GrailBackend() : _subscription(nullptr) {}
258+
259+ void CreateXMockDevices();
260+ void DestroyXMockDevices();
261+ void SendXInput2Events();
262+
263+ virtual void OnEventInitComplete(GeisEvent event);
264+ virtual void OnEventGestureBegin(GeisEvent event);
265+
266+ GeisSubscription _subscription;
267+};
268+
269+void Geis2GrailBackend::CreateXMockDevices()
270+{
271+ xmock_devices_count = 1;
272+ xmock_devices = (XIDeviceInfo*) calloc(xmock_devices_count,
273+ sizeof(XIDeviceInfo));
274+
275+ XITouchClassInfo *touch_info = (XITouchClassInfo*) malloc(sizeof(XITouchClassInfo));
276+ touch_info->type = XITouchClass;
277+ touch_info->sourceid = 0;
278+ touch_info->mode = XIDirectTouch;
279+ touch_info->num_touches = 5;
280+
281+ XIValuatorClassInfo *x_axis_info = (XIValuatorClassInfo*) malloc(sizeof(XIValuatorClassInfo));
282+ x_axis_info->type = XIValuatorClass;
283+ x_axis_info->sourceid = 0;
284+ x_axis_info->number = 0; /* identifies it as being the X axis */
285+ x_axis_info->min = -500.0;
286+ x_axis_info->max = 500.0;
287+ x_axis_info->resolution = 3000; /* counts/meter */
288+
289+ XIValuatorClassInfo *y_axis_info = (XIValuatorClassInfo*) malloc(sizeof(XIValuatorClassInfo));
290+ y_axis_info->type = XIValuatorClass;
291+ y_axis_info->sourceid = 0;
292+ y_axis_info->number = 1; /* identifies it as being the Y axis */
293+ y_axis_info->min = -500.0;
294+ y_axis_info->max = 500.0;
295+ y_axis_info->resolution = 3000;
296+
297+ XIAnyClassInfo **classes = (XIAnyClassInfo**) malloc(sizeof(XIAnyClassInfo*)*3);
298+ classes[0] = (XIAnyClassInfo*) touch_info;
299+ classes[1] = (XIAnyClassInfo*) x_axis_info;
300+ classes[2] = (XIAnyClassInfo*) y_axis_info;
301+
302+ xmock_devices[0].deviceid = 0;
303+ xmock_devices[0].name = const_cast<char *>("Fake Touch Screen");
304+ xmock_devices[0].use = XISlavePointer;
305+ xmock_devices[0].attachment = 1;
306+ xmock_devices[0].enabled = True;
307+ xmock_devices[0].num_classes = 3;
308+ xmock_devices[0].classes = classes;
309+}
310+
311+void Geis2GrailBackend::DestroyXMockDevices()
312+{
313+ for (int i = 0; i < xmock_devices_count; ++i)
314+ {
315+ for (int j = 0; j < xmock_devices[i].num_classes; ++j)
316+ free(xmock_devices[i].classes[j]);
317+ free(xmock_devices[i].classes);
318+ }
319+ free(xmock_devices);
320+}
321+
322+void Geis2GrailBackend::SendXInput2Events()
323+{
324+ XEvent event;
325+ XGenericEventCookie *xcookie = 0;
326+ XIDeviceEvent *device_event = 0;
327+ XITouchOwnershipEvent *ownership_event = 0;
328+ int serial = 0;
329+
330+ event.type = GenericEvent;
331+ device_event = (XIDeviceEvent*)calloc(1, sizeof(XIDeviceEvent));
332+ device_event->serial = serial++;
333+ device_event->display = xmock_display;
334+ device_event->extension = xmock_xi2_opcode;
335+ device_event->evtype = XI_TouchBegin;
336+ device_event->time = xmock_server_time;
337+ device_event->deviceid = 0;
338+ /* The source device that originally generated the event. */
339+ device_event->sourceid = device_event->deviceid;
340+ device_event->detail = 0; /* touch id */
341+ device_event->root = DefaultRootWindow(xmock_display);
342+ device_event->event = DefaultRootWindow(xmock_display);
343+ device_event->child = 0;
344+ device_event->root_x = 123.0f;
345+ device_event->root_y = 456.0f;
346+ device_event->event_x = device_event->root_x;
347+ device_event->event_y = device_event->root_y;
348+ device_event->valuators.mask_len = 2; /* two bytes */
349+ device_event->valuators.mask = (unsigned char*) malloc(2);
350+ XISetMask(device_event->valuators.mask, 0); /* X axis is present */
351+ XISetMask(device_event->valuators.mask, 1); /* Y axis is present */
352+ device_event->valuators.values = (double*) malloc(sizeof(double)*2);
353+ device_event->valuators.values[0] = -200.0;
354+ device_event->valuators.values[1] = -100.0;
355+ xcookie = &event.xcookie;
356+ xcookie->extension = xmock_xi2_opcode;
357+ xcookie->evtype = XI_TouchBegin;
358+ xcookie->data = device_event;
359+ xmock_add_to_event_queue(&event);
360+
361+ event.type = GenericEvent;
362+ device_event = (XIDeviceEvent*)calloc(1, sizeof(XIDeviceEvent));
363+ device_event->serial = serial++;
364+ device_event->display = xmock_display;
365+ device_event->extension = xmock_xi2_opcode;
366+ device_event->evtype = XI_TouchBegin;
367+ device_event->time = xmock_server_time;
368+ device_event->deviceid = 0;
369+ device_event->sourceid = device_event->deviceid;
370+ device_event->detail = 1; /* touch id */
371+ device_event->root = DefaultRootWindow(xmock_display);
372+ device_event->event = DefaultRootWindow(xmock_display);
373+ device_event->child = 0;
374+ device_event->root_x = 222.0f;
375+ device_event->root_y = 456.0f;
376+ device_event->event_x = device_event->root_x;
377+ device_event->event_y = device_event->root_y;
378+ device_event->valuators.mask_len = 2;
379+ device_event->valuators.mask = (unsigned char*) malloc(2);
380+ XISetMask(device_event->valuators.mask, 0);
381+ XISetMask(device_event->valuators.mask, 1);
382+ device_event->valuators.values = (double*) malloc(sizeof(double)*2);
383+ device_event->valuators.values[0] = -150.0;
384+ device_event->valuators.values[1] = -100.0;
385+ xcookie = &event.xcookie;
386+ xcookie->extension = xmock_xi2_opcode;
387+ xcookie->evtype = XI_TouchBegin;
388+ xcookie->data = device_event;
389+ xmock_add_to_event_queue(&event);
390+
391+ xmock_server_time += 5;
392+
393+ event.type = GenericEvent;
394+ ownership_event = (XITouchOwnershipEvent*)calloc(1, sizeof(XITouchOwnershipEvent));
395+ ownership_event->type = GenericEvent;
396+ ownership_event->serial = serial++;
397+ ownership_event->display = xmock_display;
398+ ownership_event->extension = xmock_xi2_opcode;
399+ ownership_event->evtype = XI_TouchOwnership;
400+ ownership_event->time = xmock_server_time;
401+ ownership_event->deviceid = 0;
402+ ownership_event->sourceid = ownership_event->deviceid;
403+ ownership_event->touchid = 0;
404+ ownership_event->root = DefaultRootWindow(xmock_display);
405+ ownership_event->event = DefaultRootWindow(xmock_display);
406+ ownership_event->child = 0;
407+ xcookie = &event.xcookie;
408+ xcookie->extension = xmock_xi2_opcode;
409+ xcookie->evtype = XI_TouchOwnership;
410+ xcookie->data = ownership_event;
411+ xmock_add_to_event_queue(&event);
412+
413+ event.type = GenericEvent;
414+ ownership_event = (XITouchOwnershipEvent*)calloc(1, sizeof(XITouchOwnershipEvent));
415+ ownership_event->type = GenericEvent;
416+ ownership_event->serial = serial++;
417+ ownership_event->display = xmock_display;
418+ ownership_event->extension = xmock_xi2_opcode;
419+ ownership_event->evtype = XI_TouchOwnership;
420+ ownership_event->time = xmock_server_time;
421+ ownership_event->deviceid = 0;
422+ ownership_event->sourceid = ownership_event->deviceid;
423+ ownership_event->touchid = 1;
424+ ownership_event->root = DefaultRootWindow(xmock_display);
425+ ownership_event->event = DefaultRootWindow(xmock_display);
426+ ownership_event->child = 0;
427+ xcookie = &event.xcookie;
428+ xcookie->extension = xmock_xi2_opcode;
429+ xcookie->evtype = XI_TouchOwnership;
430+ xcookie->data = ownership_event;
431+ xmock_add_to_event_queue(&event);
432+
433+ event.type = GenericEvent;
434+ device_event = (XIDeviceEvent*)calloc(1, sizeof(XIDeviceEvent));
435+ device_event->serial = serial++;
436+ device_event->display = xmock_display;
437+ device_event->extension = xmock_xi2_opcode;
438+ device_event->evtype = XI_TouchUpdate;
439+ device_event->time = xmock_server_time;
440+ device_event->deviceid = 0;
441+ device_event->sourceid = device_event->deviceid;
442+ device_event->detail = 0;
443+ device_event->root = DefaultRootWindow(xmock_display);
444+ device_event->event = DefaultRootWindow(xmock_display);
445+ device_event->child = 0;
446+ device_event->root_x = 123.0f;
447+ device_event->root_y = 466.0f;
448+ device_event->event_x = device_event->root_x;
449+ device_event->event_y = device_event->root_y;
450+ device_event->valuators.mask_len = 2; /* two bytes */
451+ device_event->valuators.mask = (unsigned char*) malloc(2);
452+ XISetMask(device_event->valuators.mask, 0);
453+ XISetMask(device_event->valuators.mask, 1);
454+ device_event->valuators.values = (double*) malloc(sizeof(double)*2);
455+ device_event->valuators.values[0] = -200.0;
456+ device_event->valuators.values[1] = -90.0;
457+ xcookie = &event.xcookie;
458+ xcookie->extension = xmock_xi2_opcode;
459+ xcookie->evtype = XI_TouchUpdate;
460+ xcookie->data = device_event;
461+ xmock_add_to_event_queue(&event);
462+
463+ event.type = GenericEvent;
464+ device_event = (XIDeviceEvent*)calloc(1, sizeof(XIDeviceEvent));
465+ device_event->serial = serial++;
466+ device_event->display = xmock_display;
467+ device_event->extension = xmock_xi2_opcode;
468+ device_event->evtype = XI_TouchUpdate;
469+ device_event->time = xmock_server_time;
470+ device_event->deviceid = 0;
471+ device_event->sourceid = device_event->deviceid;
472+ device_event->detail = 1; /* touch id */
473+ device_event->root = DefaultRootWindow(xmock_display);
474+ device_event->event = DefaultRootWindow(xmock_display);
475+ device_event->child = 0;
476+ device_event->root_x = 222.0f;
477+ device_event->root_y = 466.0f;
478+ device_event->event_x = device_event->root_x;
479+ device_event->event_y = device_event->root_y;
480+ device_event->valuators.mask_len = 2;
481+ device_event->valuators.mask = (unsigned char*) malloc(2);
482+ XISetMask(device_event->valuators.mask, 0);
483+ XISetMask(device_event->valuators.mask, 1);
484+ device_event->valuators.values = (double*) malloc(sizeof(double)*2);
485+ device_event->valuators.values[0] = -150.0;
486+ device_event->valuators.values[1] = -90.0;
487+ xcookie = &event.xcookie;
488+ xcookie->extension = xmock_xi2_opcode;
489+ xcookie->evtype = XI_TouchUpdate;
490+ xcookie->data = device_event;
491+ xmock_add_to_event_queue(&event);
492+}
493+
494+void Geis2GrailBackend::OnEventInitComplete(GeisEvent event)
495+{
496+ _subscription = CreateFilteredSubscription(
497+ "My 2-touches Touch", 2, GEIS_GESTURE_TOUCH);
498+ ASSERT_NE(nullptr, _subscription);
499+
500+ SendXInput2Events();
501+}
502+
503+void Geis2GrailBackend::OnEventGestureBegin(GeisEvent event)
504+{
505+ GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_TOUCHSET);
506+ GeisTouchSet geis_touch_set = (GeisTouchSet) geis_attr_value_to_pointer(attr);
507+
508+ TouchSet touch_set(geis_touch_set);
509+
510+ /* check that there are two touch points and that they are in window coordinates
511+ (instead of input device coordinates) */
512+ ASSERT_EQ(2, touch_set.size());
513+ ASSERT_TRUE(touch_set.contains(123.0f, 456.0f));
514+ ASSERT_TRUE(touch_set.contains(222.0f, 456.0f));
515+}
516+
517+TEST_F(Geis2GrailBackend, DirectDeviceTouchCoords)
518+{
519+ CreateXMockDevices();
520+
521+ Geis geis = geis_new(GEIS_INIT_UTOUCH_GRAIL_BACKEND,
522+ nullptr);
523+ ASSERT_NE(nullptr, geis);
524+
525+ Run(geis);
526+
527+ if (_subscription)
528+ geis_subscription_delete(_subscription);
529+ geis_delete(geis);
530+
531+ DestroyXMockDevices();
532+}
533
534=== added file 'testsuite/geis2/gtest_grail_backend.cpp'
535--- testsuite/geis2/gtest_grail_backend.cpp 1970-01-01 00:00:00 +0000
536+++ testsuite/geis2/gtest_grail_backend.cpp 2012-04-24 19:38:21 +0000
537@@ -0,0 +1,134 @@
538+#include "gtest_grail_backend.h"
539+#include "x11_mocks.h"
540+#include <iostream>
541+
542+#define ADD_FAILURE_AND_RETURN(ret) \
543+ {\
544+ ADD_FAILURE();\
545+ return ret;\
546+ }\
547+
548+Touch::Touch(GeisTouch geis_touch)
549+{
550+ GeisAttr attr = geis_touch_attr_by_name(geis_touch, GEIS_TOUCH_ATTRIBUTE_X);
551+ x = geis_attr_value_to_float(attr);
552+
553+ attr = geis_touch_attr_by_name(geis_touch, GEIS_TOUCH_ATTRIBUTE_Y);
554+ y = geis_attr_value_to_float(attr);
555+
556+ attr = geis_touch_attr_by_name(geis_touch, GEIS_TOUCH_ATTRIBUTE_ID);
557+ id = geis_attr_value_to_integer(attr);
558+}
559+
560+TouchSet::TouchSet(GeisTouchSet geis_touch_set)
561+{
562+ int count = geis_touchset_touch_count(geis_touch_set);
563+ for (int i = 0; i < count; ++i)
564+ push_back(Touch(geis_touchset_touch(geis_touch_set, i)));
565+}
566+
567+bool TouchSet::contains(float x, float y)
568+{
569+ for (auto touch : *this)
570+ {
571+ if (touch.x == x && touch.y == y)
572+ return true;
573+ }
574+ return false;
575+}
576+
577+GeisSubscription Geis2GrailBackendBase::CreateFilteredSubscription(
578+ GeisString name, GeisSize num_touches, GeisString gesture_class)
579+{
580+ GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
581+ GeisFilter filter = nullptr;
582+ GeisSubscription sub = nullptr;
583+
584+ sub = geis_subscription_new(_geis, name, GEIS_SUBSCRIPTION_NONE);
585+
586+ filter = geis_filter_new(_geis, "filter");
587+ if (filter == nullptr) ADD_FAILURE_AND_RETURN(nullptr);
588+
589+ status = geis_filter_add_term(filter,
590+ GEIS_FILTER_CLASS,
591+ GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, gesture_class,
592+ GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, num_touches,
593+ nullptr);
594+ if (status != GEIS_STATUS_SUCCESS) ADD_FAILURE_AND_RETURN(nullptr);
595+
596+ status = geis_filter_add_term(filter,
597+ GEIS_FILTER_REGION,
598+ GEIS_REGION_ATTRIBUTE_WINDOWID, GEIS_FILTER_OP_EQ,
599+ DefaultRootWindow(xmock_display),
600+ nullptr);
601+ if (status != GEIS_STATUS_SUCCESS) ADD_FAILURE_AND_RETURN(nullptr);
602+
603+ status = geis_subscription_add_filter(sub, filter);
604+ if (status != GEIS_STATUS_SUCCESS) ADD_FAILURE_AND_RETURN(nullptr);
605+
606+ status = geis_subscription_activate(sub);
607+ if (status != GEIS_STATUS_SUCCESS) ADD_FAILURE_AND_RETURN(nullptr);
608+
609+ return sub;
610+}
611+
612+bool Geis2GrailBackendBase::DispatchAndProcessEvents()
613+{
614+ bool got_events = false;
615+ GeisEvent event;
616+ GeisStatus status;
617+
618+ status = geis_dispatch_events(_geis);
619+ if (status != GEIS_STATUS_SUCCESS) ADD_FAILURE_AND_RETURN(false);
620+
621+ status = geis_next_event(_geis, &event);
622+ if (status != GEIS_STATUS_SUCCESS
623+ && status != GEIS_STATUS_CONTINUE
624+ && status != GEIS_STATUS_EMPTY)
625+ ADD_FAILURE_AND_RETURN(false);
626+
627+ if (status == GEIS_STATUS_SUCCESS || status == GEIS_STATUS_CONTINUE)
628+ got_events = true;
629+
630+ while (status == GEIS_STATUS_CONTINUE || status == GEIS_STATUS_SUCCESS)
631+ {
632+ switch (geis_event_type(event))
633+ {
634+ case GEIS_EVENT_INIT_COMPLETE:
635+ OnEventInitComplete(event);
636+ break;
637+ case GEIS_EVENT_GESTURE_BEGIN:
638+ OnEventGestureBegin(event);
639+ break;
640+ case GEIS_EVENT_GESTURE_UPDATE:
641+ OnEventGestureUpdate(event);
642+ break;
643+ case GEIS_EVENT_GESTURE_END:
644+ OnEventGestureEnd(event);
645+ break;
646+ default:
647+ break;
648+ }
649+ geis_event_delete(event);
650+ status = geis_next_event(_geis, &event);
651+ }
652+
653+ return got_events;
654+}
655+
656+void Geis2GrailBackendBase::Run(Geis geis)
657+{
658+ _geis = geis;
659+
660+ bool got_events;
661+ do
662+ {
663+ got_events = DispatchAndProcessEvents();
664+ } while (got_events);
665+}
666+
667+int main(int argc, char **argv)
668+{
669+ testing::InitGoogleTest(&argc, argv);
670+ return RUN_ALL_TESTS();
671+}
672
673=== added file 'testsuite/geis2/gtest_grail_backend.h'
674--- testsuite/geis2/gtest_grail_backend.h 1970-01-01 00:00:00 +0000
675+++ testsuite/geis2/gtest_grail_backend.h 2012-04-24 19:38:21 +0000
676@@ -0,0 +1,52 @@
677+#ifndef GTEST_GRAIL_BACKEND_H
678+#define GTEST_GRAIL_BACKEND_H
679+
680+#include <gtest/gtest.h>
681+#include <geis/geis.h>
682+#include <vector>
683+
684+class Touch
685+{
686+ public:
687+ Touch(GeisTouch geis_touch);
688+
689+ int id;
690+ float x;
691+ float y;
692+};
693+
694+class TouchSet : public std::vector<Touch>
695+{
696+ public:
697+ TouchSet(GeisTouchSet geis_touch_set);
698+ bool contains(float x, float y);
699+};
700+
701+class Geis2GrailBackendBase : public ::testing::Test
702+{
703+ protected:
704+ Geis2GrailBackendBase() : _geis(nullptr) {}
705+ virtual ~Geis2GrailBackendBase() {}
706+
707+ /* Dispatch and process Geis events in a loop until there are no more
708+ events. */
709+ void Run(Geis geis);
710+
711+
712+ /* Creates (and activates) a GeisSubscription with the given name
713+ and with filters for the given number of touches and gesture class. */
714+ GeisSubscription CreateFilteredSubscription(GeisString name,
715+ GeisSize num_touches,
716+ GeisString gesture_class);
717+
718+ virtual void OnEventInitComplete(GeisEvent event) {}
719+ virtual void OnEventGestureBegin(GeisEvent event) {}
720+ virtual void OnEventGestureUpdate(GeisEvent event) {}
721+ virtual void OnEventGestureEnd(GeisEvent event) {}
722+
723+ private:
724+ Geis _geis;
725+ bool DispatchAndProcessEvents();
726+};
727+
728+#endif // GTEST_GRAIL_BACKEND_H
729
730=== modified file 'testsuite/gtest/Makefile.am'
731--- testsuite/gtest/Makefile.am 2012-03-30 11:51:09 +0000
732+++ testsuite/gtest/Makefile.am 2012-04-24 19:38:21 +0000
733@@ -3,26 +3,31 @@
734 # @brief automake recipe for the geis gtest testsuite harness directory
735 #
736
737-if ENABLE_INTEGRATION_TESTS
738+if HAVE_GTEST
739 check_LIBRARIES = libgtest_geis.a
740 endif
741
742-libgtest_geis_a_SOURCES = \
743- gtest_evemu_device.h gtest_evemu_device.cpp \
744- gtest_geis_fixture.h gtest_geis_fixture.cpp \
745- gtest_geis1_fixture.h gtest_geis1_fixture.cpp
746-
747 nodist_libgtest_geis_a_SOURCES = \
748- $(XORG_GTEST_SOURCE)/src/xorg-gtest-all.cpp \
749 $(GTEST_SOURCE)/src/gtest-all.cc
750
751 libgtest_geis_a_CPPFLAGS = \
752- --std=c++0x \
753 -I$(top_srcdir) \
754 -I$(top_srcdir)/include \
755 -I$(top_srcdir)/libutouch-geis \
756 -DTEST_ROOT_DIR=\"$(abs_top_srcdir)/testsuite/\" \
757+ $(GTEST_CPPFLAGS)
758+
759+if ENABLE_INTEGRATION_TESTS
760+libgtest_geis_a_SOURCES = \
761+ gtest_evemu_device.h gtest_evemu_device.cpp \
762+ gtest_geis_fixture.h gtest_geis_fixture.cpp \
763+ gtest_geis1_fixture.h gtest_geis1_fixture.cpp
764+
765+nodist_libgtest_geis_a_SOURCES += \
766+ $(XORG_GTEST_SOURCE)/src/xorg-gtest-all.cpp
767+
768+libgtest_geis_a_CPPFLAGS += \
769 $(XORG_GTEST_CPPFLAGS) \
770- $(GTEST_CPPFLAGS) \
771 $(EVEMU_CFLAGS) \
772 $(XORG_GTEST_CFLAGS)
773+endif
774
775=== added directory 'testsuite/x11_mocks'
776=== added file 'testsuite/x11_mocks/Makefile.am'
777--- testsuite/x11_mocks/Makefile.am 1970-01-01 00:00:00 +0000
778+++ testsuite/x11_mocks/Makefile.am 2012-04-24 19:38:21 +0000
779@@ -0,0 +1,13 @@
780+#
781+# @file testsuite/x11_mocks/Makefile.am
782+# @brief automake recipe for the X11 mockups
783+#
784+
785+check_LIBRARIES = libx11_mocks.a
786+
787+libx11_mocks_a_SOURCES = \
788+ x11_mocks.c
789+
790+libx11_mocks_a_CFLAGS = \
791+ --std=c99
792+
793
794=== added file 'testsuite/x11_mocks/x11_mocks.c'
795--- testsuite/x11_mocks/x11_mocks.c 1970-01-01 00:00:00 +0000
796+++ testsuite/x11_mocks/x11_mocks.c 2012-04-24 19:38:21 +0000
797@@ -0,0 +1,406 @@
798+/* needed to break into 'Display' struct internals. */
799+#define XLIB_ILLEGAL_ACCESS
800+#include <X11/Xlib.h>
801+
802+#include <geis/geis.h>
803+
804+#include "x11_mocks.h"
805+
806+#include <sys/eventfd.h>
807+#include <stdio.h>
808+#include <unistd.h>
809+
810+int xmock_xi2_opcode = 42;
811+int xmock_xi2_event_base = 40000;
812+int xmock_xi2_error_base = 40000;
813+int xmock_xsync_event_base = 50000;
814+int xmock_xsync_error_base = 50000;
815+Display *xmock_display = NULL;
816+uint64_t xmock_server_time = 0;
817+
818+XIDeviceInfo *xmock_devices = NULL;
819+int xmock_devices_count = 0;
820+
821+/* id to be used for the next alarm that gets created */
822+XSyncAlarm _xmock_next_alarm = 1;
823+
824+struct EventQueueItem
825+{
826+ XEvent event;
827+ struct EventQueueItem *next;
828+} *xmock_event_queue = NULL;
829+
830+#define XMOCK_PRINT_FUNCTION _xmock_print_function(__func__)
831+void _xmock_print_function(const char *function)
832+{
833+ static int debug_enabled = -1;
834+ if (debug_enabled == -1)
835+ {
836+ if (getenv("XMOCK_DEBUG"))
837+ debug_enabled = 1;
838+ else
839+ debug_enabled = 0;
840+ }
841+
842+ if (debug_enabled)
843+ printf("XMOCK: %s mock called.\n", function);
844+}
845+
846+void xmock_add_to_event_queue(const XEvent *event)
847+{
848+ struct EventQueueItem *new_item = malloc(sizeof(struct EventQueueItem));
849+ new_item->event = *event;
850+ new_item->next = NULL;
851+
852+ if (!xmock_event_queue)
853+ {
854+ xmock_event_queue = new_item;
855+ }
856+ else
857+ {
858+ struct EventQueueItem *last_item = xmock_event_queue;
859+ while (last_item->next)
860+ {
861+ last_item = last_item->next;
862+ }
863+ last_item->next = new_item;
864+ }
865+
866+ static const uint64_t num = 1;
867+ if (write(xmock_display->fd, &num, sizeof(num)) != sizeof(num))
868+ {
869+ fprintf(stderr, "ERROR: failed to update eventfd instance,\n");
870+ exit(1);
871+ }
872+}
873+
874+Display *XOpenDisplay(_Xconst char *display_name)
875+{
876+ XMOCK_PRINT_FUNCTION;
877+ (void)display_name;
878+
879+ Display *display = (Display*)calloc(1, sizeof(Display));
880+ display->fd = eventfd(0, EFD_NONBLOCK);
881+ display->default_screen = 0;
882+ display->nscreens = 1;
883+ display->screens = (Screen*)calloc(1, sizeof(Screen));
884+ display->screens[0].root = 1;
885+
886+ xmock_display = display;
887+
888+ return display;
889+}
890+
891+int XCloseDisplay(Display *display)
892+{
893+ XMOCK_PRINT_FUNCTION;
894+
895+ close(display->fd);
896+ free(display->screens);
897+ free(display);
898+
899+ xmock_display = NULL;
900+
901+ return 0;
902+}
903+
904+int XSync(Display *display, Bool discard)
905+{
906+ (void)display;
907+ (void)discard;
908+ return 0;
909+}
910+
911+int XFlush(Display *display)
912+{
913+ (void)display;
914+ return 0;
915+}
916+
917+Bool XQueryExtension(Display *display, const char *name,
918+ int *major_opcode_return, int *first_event_return, int *first_error_return)
919+{
920+ XMOCK_PRINT_FUNCTION;
921+ (void)display;
922+ (void)name; /* assuming name == "XInputExtension" */
923+
924+ *major_opcode_return = xmock_xi2_opcode;
925+ *first_event_return = xmock_xi2_event_base;
926+ *first_error_return = xmock_xi2_error_base;
927+
928+ return True;
929+}
930+
931+int XPending(Display *display)
932+{
933+ XMOCK_PRINT_FUNCTION;
934+ (void)display;
935+
936+ int pending_events_count = 0;
937+ struct EventQueueItem *item = xmock_event_queue;
938+ while (item != NULL)
939+ {
940+ ++pending_events_count;
941+ item = item->next;
942+ }
943+ return pending_events_count;
944+}
945+
946+int XNextEvent(Display *display, XEvent *event_return)
947+{
948+ XMOCK_PRINT_FUNCTION;
949+ (void)display;
950+
951+
952+ if (xmock_event_queue)
953+ {
954+ uint64_t num = 1;
955+ ssize_t bytes_read = read(xmock_display->fd, &num, sizeof(num));
956+ (void)bytes_read;
957+
958+ *event_return = xmock_event_queue->event;
959+
960+ struct EventQueueItem *removed_item = xmock_event_queue;
961+ xmock_event_queue = xmock_event_queue->next;
962+ free(removed_item);
963+ }
964+ else
965+ {
966+ /* not going to block... */
967+ }
968+
969+ return 0;
970+}
971+
972+Bool XGetEventData(Display *display, XGenericEventCookie *cookie)
973+{
974+ XMOCK_PRINT_FUNCTION;
975+ (void)display;
976+ (void)cookie;
977+ return True;
978+}
979+
980+void XFreeEventData(Display *display, XGenericEventCookie *cookie)
981+{
982+ XMOCK_PRINT_FUNCTION;
983+ (void)display;
984+
985+ if (cookie->data && cookie->extension == xmock_xi2_opcode)
986+ {
987+ if (cookie->evtype == XI_TouchBegin
988+ || cookie->evtype == XI_TouchUpdate
989+ || cookie->evtype == XI_TouchEnd)
990+ {
991+ XIDeviceEvent *device_event = (XIDeviceEvent*) cookie->data;
992+ free(device_event->valuators.mask);
993+ free(device_event->valuators.values);
994+ }
995+ free(cookie->data);
996+ }
997+}
998+
999+XIDeviceInfo* XIQueryDevice(Display * display,
1000+ int deviceid,
1001+ int * ndevices_return)
1002+{
1003+ XMOCK_PRINT_FUNCTION;
1004+ (void)display;
1005+ (void)deviceid; /* assuming XIAllDevices */
1006+
1007+ XIDeviceInfo *devices;
1008+
1009+ devices = calloc(xmock_devices_count, sizeof(XIDeviceInfo));
1010+
1011+ for (int i = 0; i < xmock_devices_count; ++i) {
1012+ devices[i] = xmock_devices[i];
1013+ }
1014+
1015+ *ndevices_return = xmock_devices_count;
1016+
1017+ return devices;
1018+}
1019+
1020+void XIFreeDeviceInfo(XIDeviceInfo *info)
1021+{
1022+ XMOCK_PRINT_FUNCTION;
1023+ free(info);
1024+}
1025+
1026+Status XIQueryVersion(Display *display,
1027+ int *major_version_inout,
1028+ int *minor_version_inout)
1029+{
1030+ XMOCK_PRINT_FUNCTION;
1031+ (void)display;
1032+ *major_version_inout = 2;
1033+ *minor_version_inout = 2;
1034+ return Success;
1035+}
1036+
1037+Status XISelectEvents(Display *display,
1038+ Window win,
1039+ XIEventMask *masks,
1040+ int num_masks)
1041+{
1042+ XMOCK_PRINT_FUNCTION;
1043+ (void)display;
1044+ (void)win;
1045+ (void)masks;
1046+ (void)num_masks;
1047+ return Success;
1048+}
1049+
1050+int XIGrabTouchBegin(
1051+ Display* display,
1052+ int deviceid,
1053+ Window grab_window,
1054+ int owner_events,
1055+ XIEventMask *mask,
1056+ int num_modifiers,
1057+ XIGrabModifiers *modifiers_inout)
1058+{
1059+ XMOCK_PRINT_FUNCTION;
1060+ (void)display;
1061+ (void)deviceid;
1062+ (void)grab_window;
1063+ (void)owner_events;
1064+ (void)mask;
1065+
1066+ for (int i = 0; i < num_modifiers; ++i)
1067+ {
1068+ modifiers_inout[i].status = XIGrabSuccess;
1069+ }
1070+
1071+ return 0;
1072+}
1073+
1074+Status XIUngrabTouchBegin(
1075+ Display* display,
1076+ int deviceid,
1077+ Window grab_window,
1078+ int num_modifiers,
1079+ XIGrabModifiers *modifiers)
1080+{
1081+ XMOCK_PRINT_FUNCTION;
1082+ (void)display;
1083+ (void)deviceid;
1084+ (void)grab_window;
1085+ (void)num_modifiers;
1086+ (void)modifiers;
1087+ return Success;
1088+}
1089+
1090+Status XIAllowTouchEvents(
1091+ Display* display,
1092+ int deviceid,
1093+ unsigned int touchid,
1094+ Window grab_window,
1095+ int event_mode)
1096+{
1097+ XMOCK_PRINT_FUNCTION;
1098+ (void)display;
1099+ (void)deviceid;
1100+ (void)touchid;
1101+ (void)grab_window;
1102+ (void)event_mode;
1103+ return Success;
1104+}
1105+
1106+Status XSyncQueryExtension(
1107+ Display* dpy,
1108+ int* event_base_return,
1109+ int* error_base_return)
1110+{
1111+ XMOCK_PRINT_FUNCTION;
1112+ (void)dpy;
1113+ *event_base_return = xmock_xsync_event_base;
1114+ *error_base_return = xmock_xsync_error_base;
1115+ return True;
1116+}
1117+
1118+Status XSyncInitialize(
1119+ Display* dpy,
1120+ int* major_version_return,
1121+ int* minor_version_return)
1122+{
1123+ XMOCK_PRINT_FUNCTION;
1124+ (void)dpy;
1125+ *major_version_return = 1;
1126+ *minor_version_return = 0;
1127+ return True;
1128+}
1129+
1130+XSyncSystemCounter *XSyncListSystemCounters(
1131+ Display* dpy,
1132+ int* n_counters_return)
1133+{
1134+ XMOCK_PRINT_FUNCTION;
1135+ (void)dpy;
1136+ *n_counters_return = 1;
1137+
1138+ XSyncSystemCounter *sys_counter = malloc(sizeof(XSyncSystemCounter));
1139+ sys_counter->name = "SERVERTIME";
1140+ sys_counter->counter = 1;
1141+ sys_counter->resolution.hi = 1;
1142+ sys_counter->resolution.lo = 0;
1143+ return sys_counter;
1144+}
1145+
1146+void XSyncFreeSystemCounterList(XSyncSystemCounter* list)
1147+{
1148+ XMOCK_PRINT_FUNCTION;
1149+ free(list);
1150+}
1151+
1152+XSyncAlarm XSyncCreateAlarm(
1153+ Display* dpy,
1154+ unsigned long values_mask,
1155+ XSyncAlarmAttributes* values)
1156+{
1157+ XMOCK_PRINT_FUNCTION;
1158+ (void)dpy;
1159+
1160+ XSyncAlarmNotifyEvent alarm_notify;
1161+ alarm_notify.type = xmock_xsync_event_base + XSyncAlarmNotify;
1162+ alarm_notify.alarm = _xmock_next_alarm;
1163+ alarm_notify.counter_value = values->trigger.wait_value;
1164+ xmock_add_to_event_queue((XEvent*)&alarm_notify);
1165+
1166+ XSyncValue time = values->trigger.wait_value;
1167+ uint64_t timeout = (uint64_t)XSyncValueHigh32(time) << 32
1168+ | (uint64_t)XSyncValueLow32(time);
1169+ xmock_server_time = timeout + 1;
1170+
1171+ return _xmock_next_alarm++;
1172+}
1173+
1174+Status XSyncDestroyAlarm(
1175+ Display* dpy,
1176+ XSyncAlarm alarm)
1177+{
1178+ XMOCK_PRINT_FUNCTION;
1179+ (void)dpy;
1180+ (void)alarm;
1181+}
1182+
1183+void XSyncIntsToValue(
1184+ XSyncValue* pv,
1185+ unsigned int l,
1186+ int h)
1187+{
1188+ XMOCK_PRINT_FUNCTION;
1189+ pv->hi = h;
1190+ pv->lo = l;
1191+}
1192+
1193+int XSyncValueHigh32(XSyncValue v)
1194+{
1195+ XMOCK_PRINT_FUNCTION;
1196+ return v.hi;
1197+}
1198+
1199+unsigned int XSyncValueLow32(XSyncValue v)
1200+{
1201+ XMOCK_PRINT_FUNCTION;
1202+ return v.lo;
1203+}
1204
1205=== added file 'testsuite/x11_mocks/x11_mocks.h'
1206--- testsuite/x11_mocks/x11_mocks.h 1970-01-01 00:00:00 +0000
1207+++ testsuite/x11_mocks/x11_mocks.h 2012-04-24 19:38:21 +0000
1208@@ -0,0 +1,34 @@
1209+#ifndef X11_MOCKS_H
1210+#define X11_MOCKS_H
1211+
1212+#include <X11/Xlib.h>
1213+#include <X11/extensions/XInput2.h>
1214+#include <X11/extensions/sync.h>
1215+
1216+#ifdef __cplusplus
1217+extern "C" {
1218+#endif
1219+
1220+extern int xmock_xi2_opcode;
1221+extern int xmock_xi2_event_base;
1222+extern int xmock_xi2_error_base;
1223+extern int xmock_xsync_event_base;
1224+extern int xmock_xsync_error_base;
1225+extern Display *xmock_display;
1226+extern uint64_t xmock_server_time;
1227+
1228+/* to be filled by user. A copy of it will be returned by each
1229+ XIQueryDevice call */
1230+extern XIDeviceInfo *xmock_devices;
1231+extern int xmock_devices_count;
1232+
1233+/* Adds the given XEvent to the xmock event queue.
1234+ The Diplay connection will signal that there are
1235+ pending events */
1236+extern void xmock_add_to_event_queue(const XEvent* event);
1237+
1238+#ifdef __cplusplus
1239+}
1240+#endif
1241+
1242+#endif

Subscribers

People subscribed via source and target branches