Merge lp:~chasedouglas/grail/rework into lp:grail

Proposed by Chase Douglas
Status: Merged
Merged at revision: 174
Proposed branch: lp:~chasedouglas/grail/rework
Merge into: lp:grail
Diff against target: 15435 lines (+11164/-3707)
92 files modified
Makefile.am (+30/-0)
configure.ac (+33/-9)
include/utouch/grail.h (+685/-0)
m4/gcov.m4 (+83/-0)
m4/gtest.m4 (+24/-0)
src/Makefile.am (+48/-24)
src/evbuf.h (+0/-57)
src/gebuf.h (+0/-68)
src/gestures-drag.c (+0/-135)
src/gestures-pinch.c (+0/-131)
src/gestures-rotate.c (+0/-130)
src/gestures-tapping.c (+0/-100)
src/gestures-touch.c (+0/-98)
src/grail-api.c (+0/-328)
src/grail-bits.c (+0/-93)
src/grail-event.c (+0/-118)
src/grail-frame.c (+0/-410)
src/grail-gestures.c (+0/-219)
src/grail-gestures.h (+0/-115)
src/grail-impl.h (+0/-88)
src/grail-init.c (+0/-236)
src/grail-inserter.c (+0/-304)
src/grail-inserter.h (+0/-93)
src/grail-legacy.c (+0/-64)
src/grail-recognizer.c (+0/-58)
src/grail-recognizer.h (+0/-44)
src/grailbuf.h (+0/-59)
src/v2/evbuf.h (+57/-0)
src/v2/gebuf.h (+68/-0)
src/v2/gestures-drag.c (+135/-0)
src/v2/gestures-pinch.c (+131/-0)
src/v2/gestures-rotate.c (+130/-0)
src/v2/gestures-tapping.c (+100/-0)
src/v2/gestures-touch.c (+98/-0)
src/v2/grail-api.c (+328/-0)
src/v2/grail-bits.c (+93/-0)
src/v2/grail-event.c (+118/-0)
src/v2/grail-frame.c (+410/-0)
src/v2/grail-gestures.c (+223/-0)
src/v2/grail-gestures.h (+115/-0)
src/v2/grail-impl.h (+88/-0)
src/v2/grail-init.c (+236/-0)
src/v2/grail-inserter.c (+304/-0)
src/v2/grail-inserter.h (+93/-0)
src/v2/grail-legacy.c (+64/-0)
src/v2/grail-recognizer.c (+58/-0)
src/v2/grail-recognizer.h (+44/-0)
src/v2/grailbuf.h (+59/-0)
src/v3/event.cpp (+102/-0)
src/v3/event.h (+57/-0)
src/v3/forward.h (+57/-0)
src/v3/gesture.cpp (+350/-0)
src/v3/gesture.h (+85/-0)
src/v3/handle.cpp (+329/-0)
src/v3/handle.h (+74/-0)
src/v3/log.cpp (+63/-0)
src/v3/log.h (+59/-0)
src/v3/recognizer.cpp (+933/-0)
src/v3/recognizer.h (+95/-0)
src/v3/slice.cpp (+710/-0)
src/v3/slice.h (+99/-0)
src/v3/subscription.cpp (+271/-0)
src/v3/subscription.h (+81/-0)
test/Makefile.am (+29/-11)
test/check-grail.c (+0/-25)
test/check-mapping.cpp (+96/-124)
test/check-transform.cpp (+112/-133)
test/device.cpp (+64/-0)
test/device.h (+49/-0)
test/events.h (+57/-0)
test/grail.cpp (+65/-0)
test/recording.cpp (+41/-0)
test/recording.h (+53/-0)
test/recordings/ntrig-2-drag.event (+598/-0)
test/recordings/ntrig-dell-xt2.prop (+32/-0)
test/subscription.cpp (+257/-0)
test/x11/fixture.cpp (+191/-0)
test/x11/fixture.h (+65/-0)
test/x11/twodrag.cpp (+341/-0)
tools/Makefile.am (+37/-1)
tools/common/device.c (+188/-0)
tools/common/device.h (+28/-0)
tools/common/servertime.c (+91/-0)
tools/common/servertime.h (+30/-0)
tools/common/slice.c (+94/-0)
tools/common/slice.h (+24/-0)
tools/grail-eventprinter.c (+1/-1)
tools/grail-test-3-1.c (+348/-0)
tools/grail-test-atomic.c (+361/-0)
tools/grail-test-edge.c (+362/-0)
tools/grail-test-propagation.c (+330/-0)
tools/grail-transform.c (+0/-431)
To merge this branch: bzr merge lp:~chasedouglas/grail/rework
Reviewer Review Type Date Requested Status
Stephen M. Webb (community) Approve
Review via email: mp+90032@code.launchpad.net

Description of the change

The new grail implementation is ready! I don't feel like recapping the changes, you should be familiar with the general idea by now :). There are unit tests for the subscription object, and an integration test for a two-touch drag. Unfortunately, if you run the two-touch drag test under valgrind it is slowed down enough that timeouts occur that would not under normal operation. I'm still pondering how to handle this, but for now we must ignore failure under valgrind.

To post a comment you must log in.
lp:~chasedouglas/grail/rework updated
291. By Chase Douglas

Merge from trunk

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

I've been using this branch for geis development and testing, so I give it a general approval except for the following.

(1) The test suite gets built with a 'make all' target, which is not usual procedure. The Makefile.am in the test subdirectory should use a check_PROGRAMS target and not a noinst_PROGRAMS target.

(2) There is no way to disable building the test suite if xorg-gtest is installed on your system, and the test suite fails to build if the --with-xi argument is not given to ./configure.

(3) The TwoDrag test fails throwing a "Failed to open device file" exception. It looks like the test data is missing from the repo.

review: Needs Fixing
lp:~chasedouglas/grail/rework updated
292. By Chase Douglas

Add recordings needed for testing

293. By Chase Douglas

Build testsuite at "make check" time

294. By Chase Douglas

Fix build for HAVE_XI conditional

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

> I've been using this branch for geis development and testing, so I give it a
> general approval except for the following.
>
> (1) The test suite gets built with a 'make all' target, which is not usual
> procedure. The Makefile.am in the test subdirectory should use a
> check_PROGRAMS target and not a noinst_PROGRAMS target.

Fixed

> (2) There is no way to disable building the test suite if xorg-gtest is
> installed on your system, and the test suite fails to build if the --with-xi
> argument is not given to ./configure.

The entire build system was broken, so I fixed it all up.

> (3) The TwoDrag test fails throwing a "Failed to open device file" exception.
> It looks like the test data is missing from the repo.

Yep, I forgot to bzr add the recordings directory. It should work now.

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

Yep. Good to go.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Makefile.am'
--- Makefile.am 2011-01-02 12:06:04 +0000
+++ Makefile.am 2012-01-25 15:53:29 +0000
@@ -5,6 +5,36 @@
55
6INCLUDES = $(top_srcdir)/include/6INCLUDES = $(top_srcdir)/include/
77
8if HAVE_GCOV
9 .PHONY: coverage-html generate-coverage-html coverage-html-clean
10 coverage-html:
11 -$(MAKE) $(AM_MAKEFLAGS) -k check
12 $(MAKE) $(AM_MAKEFLAGS) generate-coverage-html
13
14 generate-coverage-html:
15 @echo Collecting coverage data
16 $(LCOV) --directory $(top_builddir) --base-directory src --capture --output-file coverage.info --no-checksum --compat-libtool
17 LANG=C $(GENHTML) --prefix $(top_builddir) --output-directory coveragereport --title "Code Coverage" --legend --show-details coverage.info
18
19 clean-coverage-html:
20 -$(LCOV) --directory $(top_builddir) -z
21 -rm -rf coverage.info coveragereport
22 -find $(top_builddir) -name '*.gcda' -print | xargs rm
23
24 .PHONY: coverage-xml generate-coverage-xml coverage-xml-clean
25 coverage-xml:
26 -$(MAKE) $(AM_MAKEFLAGS) -k check
27 $(MAKE) $(AM_MAKEFLAGS) generate-coverage-xml
28
29 generate-coverage-xml:
30 @echo Generating coverage XML report
31 $(MAKE) $(AM_MAKEFLAGS) clean-coverage-xml
32 $(GCOVR) -x -r $(top_builddir) -o $(top_builddir)/coverage.xml --object-directory=$(abs_builddir)/.libs
33
34 clean-coverage-xml:
35 -rm -rf $(top_builddir)/coverage.xml
36endif # HAVE_GCOV
37
8.PHONY: ChangeLog INSTALL38.PHONY: ChangeLog INSTALL
9INSTALL:39INSTALL:
10 $(INSTALL_CMD)40 $(INSTALL_CMD)
1141
=== modified file 'configure.ac'
--- configure.ac 2011-08-31 17:20:48 +0000
+++ configure.ac 2012-01-25 15:53:29 +0000
@@ -1,16 +1,21 @@
1# Initialize Autoconf1# Initialize Autoconf
2AC_PREREQ([2.60])2AC_PREREQ([2.60])
3AC_INIT([Gesture Recognition And Instantiation Library],3AC_INIT([Gesture Recognition And Instantiation Library],
4 [2.1.0],4 [2.99.1],
5 [],5 [],
6 [utouch-grail])6 [utouch-grail])
7AC_CONFIG_SRCDIR([Makefile.am])7AC_CONFIG_SRCDIR([Makefile.am])
8AC_CONFIG_HEADERS([config.h])8AC_CONFIG_HEADERS([config.h])
9AC_CONFIG_AUX_DIR([config-aux])9AC_CONFIG_AUX_DIR([config-aux])
10AC_CONFIG_MACRO_DIR([m4])
11
12m4_include([m4/gcov.m4])
13m4_include([m4/gtest.m4])
1014
11# Initialize Automake15# Initialize Automake
12AM_INIT_AUTOMAKE([foreign dist-bzip2])16AM_INIT_AUTOMAKE([foreign dist-bzip2])
13AM_MAINTAINER_MODE17AM_SILENT_RULES([yes])
18AM_MAINTAINER_MODE([enable])
1419
15LIB_VERSION=3:0:220LIB_VERSION=3:0:2
16AC_SUBST([LIB_VERSION])21AC_SUBST([LIB_VERSION])
@@ -20,11 +25,12 @@
2025
21# Checks for programs.26# Checks for programs.
22AC_PROG_CC27AC_PROG_CC
28AC_PROG_CXX
23AC_PROG_INSTALL29AC_PROG_INSTALL
2430
25PKG_CHECK_MODULES([MTDEV], [mtdev >= 1.1])31PKG_CHECK_MODULES([MTDEV], [mtdev >= 1.1])
26PKG_CHECK_MODULES([EVEMU], [utouch-evemu >= 1.0.5])32PKG_CHECK_MODULES([EVEMU], [utouch-evemu >= 1.0.5])
27PKG_CHECK_MODULES([FRAME], [utouch-frame >= 1.2])33PKG_CHECK_MODULES([FRAME], [utouch-frame >= 1.9.0])
2834
29AC_ARG_WITH([xi], AS_HELP_STRING([--with-xi], [Build with XI2.1 support]))35AC_ARG_WITH([xi], AS_HELP_STRING([--with-xi], [Build with XI2.1 support]))
30AM_CONDITIONAL([HAVE_XI], [test "x$with_xi" != "x"])36AM_CONDITIONAL([HAVE_XI], [test "x$with_xi" != "x"])
@@ -33,19 +39,37 @@
33 PKG_CHECK_MODULES(XINPUT, x11 xext [xi >= 1.4.1.99.1] [inputproto >= 2.0.99.1])39 PKG_CHECK_MODULES(XINPUT, x11 xext [xi >= 1.4.1.99.1] [inputproto >= 2.0.99.1])
34 AC_DEFINE([HAVE_XI], [1], [XI2.1 support])40 AC_DEFINE([HAVE_XI], [1], [XI2.1 support])
35])41])
42
36# Check for TDD tools43# Check for TDD tools
37PKG_CHECK_MODULES([CHECK], [check >= 0.9.8],44AC_CHECK_GTEST
38 [have_check=yes],45
39 AC_MSG_WARN([package 'check' not found: tests disabled]))46AS_IF([test "x$have_gtest" = xyes],
40AM_CONDITIONAL([HAVE_CHECK],[test "x$have_check" = xyes])47 [PKG_CHECK_MODULES(XORG_GTEST, xorg-gtest,
4148 [have_xorg_gtest="yes"],
49 [AC_MSG_WARN([xorg-gtest not installed, tests will not be built])])],
50 [AC_MSG_WARN([gtest not installed, tests will not be build])]
51)
52
53AM_CONDITIONAL([HAVE_GTEST], [test "x$have_xorg_gtest" = xyes])
54
55AC_SUBST([GTEST_LDFLAGS])
56AC_SUBST([GTEST_CXXFLAGS])
57
58# Enable coverage reports using gcov
59AC_TDD_GCOV
60
61AM_CONDITIONAL([HAVE_GCOV],[test "x$ac_cv_check_gcov" = xyes])
62
42AC_CONFIG_FILES([Makefile63AC_CONFIG_FILES([Makefile
43 src/Makefile64 src/Makefile
44 tools/Makefile65 tools/Makefile
45 test/Makefile66 test/Makefile
46 utouch-grail.pc])67 utouch-grail.pc])
4768
48AC_SUBST(AM_CPPFLAGS, "-Wall -Werror")69AC_SUBST(AM_CPPFLAGS, "-DBUILDING_GRAIL $GTEST_CPPFLAGS")
70AC_SUBST(AM_CFLAGS, "-fvisibility=hidden -Wall -Werror $COVERAGE_CFLAGS")
71AC_SUBST(AM_CXXFLAGS, "-std=c++0x $COVERAGE_CXXFLAGS $GTEST_CXXFLAGS")
72AC_SUBST(AM_LDFLAGS, "$COVERAGE_LDFLAGS $GTEST_LDFLAGS")
4973
50AC_OUTPUT74AC_OUTPUT
5175
5276
=== added directory 'include/utouch'
=== added file 'include/utouch/grail.h'
--- include/utouch/grail.h 1970-01-01 00:00:00 +0000
+++ include/utouch/grail.h 2012-01-25 15:53:29 +0000
@@ -0,0 +1,685 @@
1/*****************************************************************************
2 *
3 * utouch-grail - Multitouch Gesture Recognition Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22/**
23 * @file utouch/grail.h
24 * Definitions of the main and platform-generic API
25 */
26
27#ifndef UTOUCH_GRAIL_UTOUCH_GRAIL_H_
28#define UTOUCH_GRAIL_UTOUCH_GRAIL_H_
29
30#include <stdint.h>
31
32#include <utouch/frame.h>
33
34#ifdef __cplusplus
35extern "C" {
36#endif
37
38/**
39 * @defgroup v3 uTouch-Grail 3.x
40 * @{
41 */
42
43/** An object for the context of the uTouch Frame instance */
44typedef struct UGHandle_* UGHandle;
45/** An object for a gesture subscription */
46typedef struct UGSubscription_* UGSubscription;
47/** An object for an event */
48typedef struct UGEvent_* UGEvent;
49/** An object for a gesture state in time */
50typedef const struct UGSlice_* UGSlice;
51
52/** The status code denoting the result of a function call */
53typedef enum UGStatus {
54 UGStatusSuccess = 0, /**< The call was successful */
55 UGStatusErrorGeneric, /**< A platform-dependent error occurred */
56 UGStatusErrorResources, /**< An error occurred due to insufficient resources */
57 UGStatusErrorNoEvent, /**< No events were available to get */
58 UGStatusErrorUnknownProperty, /**< The requested property value was not set */
59 UGStatusErrorInvalidValue, /**< The property value passed in is invalid */
60 UGStatusErrorInvalidDevice, /**< The requested device does not exist */
61 UGStatusErrorInvalidSubscription, /**< The subscription is invalid */
62 UGStatusErrorInvalidGesture, /**< The requested gesture does not exist */
63 UGStatusErrorInvalidIndex, /**< The requested touch index is invalid */
64 UGStatusErrorAtomicity, /**< The subscription has a different value for
65 UGSubscriptionPropertyAtomicGestures than other
66 subscriptions active on the window */
67} UGStatus;
68
69/** Subscription properties */
70typedef enum UGSubscriptionProperty {
71 /**
72 * Device to subscribe to gesture events for
73 *
74 * Value type: UFDevice
75 */
76 UGSubscriptionPropertyDevice,
77 /**
78 * Window to subscribe to gesture events for
79 *
80 * Value type: UFWindowId
81 */
82 UGSubscriptionPropertyWindow,
83 /**
84 * Gesture types to subscribe for
85 *
86 * Value type: UGGestureTypeMask
87 */
88 UGSubscriptionPropertyMask,
89 /**
90 * Number of touches required to begin gesture
91 *
92 * Value type: unsigned int
93 */
94 UGSubscriptionPropertyTouchesStart,
95 /**
96 * Minimum number of touches for gesture
97 *
98 * Value type: unsigned int
99 */
100 UGSubscriptionPropertyTouchesMinimum,
101 /**
102 * Maximum number of touches for gesture
103 *
104 * Value type: unsigned int
105 */
106 UGSubscriptionPropertyTouchesMaximum,
107 /**
108 * Timeout for recognizing a drag gesture
109 *
110 * Value type: 64-bit unsigned integer
111 */
112 UGSubscriptionPropertyDragTimeout,
113 /**
114 * Threshold value for recognizing a drag gesture
115 *
116 * Value type: float
117 */
118 UGSubscriptionPropertyDragThreshold,
119 /**
120 * Timeout for recognizing a pinch gesture
121 *
122 * Value type: 64-bit unsigned integer
123 */
124 UGSubscriptionPropertyPinchTimeout,
125 /**
126 * Threshold value for recognizing a pinch gesture
127 *
128 * Value type: float
129 */
130 UGSubscriptionPropertyPinchThreshold,
131 /**
132 * Timeout for recognizing a rotate gesture
133 *
134 * Value type: 64-bit unsigned integer
135 */
136 UGSubscriptionPropertyRotateTimeout,
137 /**
138 * Threshold value for recognizing a rotate gesture
139 *
140 * Value type: float
141 */
142 UGSubscriptionPropertyRotateThreshold,
143 /**
144 * Timeout for recognizing a tap gesture
145 *
146 * Value type: 64-bit unsigned integer
147 */
148 UGSubscriptionPropertyTapTimeout,
149 /**
150 * Threshold value for recognizing a tap gesture
151 *
152 * Value type: float
153 */
154 UGSubscriptionPropertyTapThreshold,
155 /**
156 * Only support one gesture at a time
157 *
158 * Value type: int with boolean semantics
159 *
160 * The first version of uTouch-Grail supported only one gesture at a time.
161 * When this property is true, uTouch-Grail will mimic this behavior. This
162 * results in the following:
163 *
164 * - The uTouch-Grail client must not attempt to accept or reject a gesture
165 * - If a gesture is active for a maximum of N touches, the addition of
166 * another touch will end the gesture. A new gesture is begun if another
167 * subscription's TouchesStart property equals the new number of touches.
168 * - All subscriptions for a window must have the same value for this
169 * property. If a client attempts to activate a subscription with a
170 * different value for this property than the already activated
171 * subscriptions for the window, UGStatusErrorAtomicity will be returned.
172 *
173 * There is one key difference between uTouch-Grail v1 behavior and the use of
174 * this option. The v1 behavior only supported one gesture per device. The use
175 * of this option only supports one gesture per device per window. The
176 * beginning of a gesture in a window does not inhibit gestures in other
177 * windows. It also does not guarantee that there are no active touches
178 * outside the window.
179 */
180 UGSubscriptionPropertyAtomicGestures,
181} UGSubscriptionProperty;
182
183/** Event type */
184typedef enum UGEventType {
185 UGEventTypeSlice = 0, /**< A new gesture slice */
186} UGEventType;
187
188/** Event properties */
189typedef enum UGEventProperty {
190 /**
191 * Type of event
192 *
193 * Value type: UGEventType
194 */
195 UGEventPropertyType = 0,
196 /**
197 * Slice of a gesture
198 *
199 * Value type: UGSlice
200 */
201 UGEventPropertySlice,
202 /**
203 * Event time
204 *
205 * Value type: 64-bit unsigned int
206 *
207 * This property holds the time the event occurred in display server
208 * timespace. The time is provided in milliseconds (ms).
209 */
210 UGEventPropertyTime,
211} UGEventProperty;
212
213/** Gesture type bit indices */
214typedef enum UGGestureType {
215 UGGestureTypeDrag = 0x1, /**< Drag gesture */
216 UGGestureTypePinch = 0x2, /**< Pinch gesture */
217 UGGestureTypeRotate = 0x4, /**< Rotate gesture */
218 UGGestureTypeTap = 0x8, /**< Tap gesture */
219 UGGestureTypeTouch = 0x10, /**< Touch gesture */
220} UGGestureType;
221
222/** Bit-mask of gesture types */
223typedef uint32_t UGGestureTypeMask;
224
225/** 2D affine transformation */
226typedef const float UGTransform[3][3];
227
228/** Gesture slice state */
229typedef enum UGGestureState {
230 UGGestureStateBegin = 0, /**< Gesture slice begin */
231 UGGestureStateUpdate, /**< Gesture slice update */
232 UGGestureStateEnd, /**< Gesture slice end */
233} UGGestureState;
234
235/** Gesture slice properties */
236typedef enum UGSliceProperty {
237 /**
238 * Gesture ID
239 *
240 * Value type: unsigned int
241 */
242 UGSlicePropertyId = 0,
243 /**
244 * Gesture set state
245 *
246 * Value type: UGGestureState
247 */
248 UGSlicePropertyState,
249 /**
250 * Gesture subscription
251 *
252 * Value type: UGSubscription
253 */
254 UGSlicePropertySubscription,
255 /**
256 * Recognized gestures
257 *
258 * Value type: UGGestureTypeMask
259 */
260 UGSlicePropertyRecognized,
261 /**
262 * Number of touches
263 *
264 * Value type: unsigned int
265 */
266 UGSlicePropertyNumTouches,
267 /**
268 * Touch frame
269 *
270 * Value type: UFFrame
271 */
272 UGSlicePropertyFrame,
273 /**
274 * Original gesture center along the X axis
275 *
276 * Value type: float
277 *
278 * This value represents the original geometric center of the touches.
279 */
280 UGSlicePropertyOriginalCenterX,
281 /**
282 * Original gesture center along the Y axis
283 *
284 * Value type: float
285 *
286 * This value represents the original geometric center of the touches.
287 */
288 UGSlicePropertyOriginalCenterY,
289 /**
290 * Original radius of touches
291 *
292 * Value type: float
293 *
294 * This value represents the average of the square of the euclidean distance
295 * from the geometric center of the original touches to each touch.
296 */
297 UGSlicePropertyOriginalRadius,
298 /**
299 * Best-fit 2D affine transformation of previous to current touch locations
300 *
301 * Value type: pointer to UGTransform
302 *
303 * The transformation is relative to the previous geometric center of the
304 * touches.
305 */
306 UGSlicePropertyTransform,
307 /**
308 * Best-fit 2D affine transformation of original to current touch locations
309 *
310 * Value type: pointer to UGTransform
311 *
312 * The transformation is relative to the original geometric center of the
313 * touches.
314 */
315 UGSlicePropertyCumulativeTransform,
316 /**
317 * Best-fit instant center of rotation along the X axis
318 *
319 * Value type: float
320 */
321 UGSlicePropertyCenterOfRotationX,
322 /**
323 * Best-fit instant center of rotation along the Y axis
324 *
325 * Value type: float
326 */
327 UGSlicePropertyCenterOfRotationY,
328 /**
329 * Whether the construction of all gestures containing the same touches is
330 * finished
331 *
332 * Value type: int with boolean semantics
333 *
334 * Grail events are serial. This property allows the client to determine if
335 * all the possible gestures from the set of touches in this gesture have been
336 * sent. When this value is true, the client will have received all the
337 * information needed to make a gesture accept and reject decision based on
338 * potentially overlapping gestures. An example is when both one and two touch
339 * gestures are subscribed on the same window with the same gesture types and
340 * thresholds. When this property is true for one touch gesture events, the
341 * client can be sure there are no other touches unless a two touch gesture
342 * event has already been sent.
343 */
344 UGSlicePropertyConstructionFinished,
345} UGSliceProperty;
346
347/**
348 * Create a new grail context
349 *
350 * @param [in] frame_handle The uTouch frame context object
351 * @param [out] handle The new uTouch grail context object
352 * @return UGStatusSuccess or UGStatusErrorResources
353 */
354UGStatus grail_new(UFHandle frame_handle, UGHandle *handle);
355
356/**
357 * Delete a grail context
358 *
359 * @param [in] handle The uTouch Grail context object
360 */
361void grail_delete_v3(UGHandle handle);
362
363/**
364 * Get the event file descriptor for the uTouch Frame context
365 *
366 * @param [in] handle The uTouch Grail context object
367 * @return A file descriptor for the context
368 *
369 * When events are available for processing, the file descriptor will be
370 * readable. Perform an 8-byte read from the file descriptor to clear the state.
371 * Refer to the EVENTFD(2) man page for more details.
372 */
373int grail_get_fd(UGHandle handle);
374
375/**
376 * Create a new subscription object
377 *
378 * @param [out] subscription The new subscription object
379 * @return UGStatusSuccess or UGStatusErrorResources
380 */
381UGStatus grail_subscription_new(UGSubscription* subscription);
382
383/**
384 * Delete a subscription object
385 *
386 * @param [in] subscription The subscription object
387 */
388void grail_subscription_delete(UGSubscription subscription);
389
390/**
391 * Set a subscription property
392 *
393 * @param [in] subscription The subscription object
394 * @param [in] property The subscription property
395 * @param [in] value The new value of the property
396 * @return UGStatusSuccess or UGStatusInvalidProperty
397 */
398UGStatus grail_subscription_set_property(UGSubscription subscription,
399 UGSubscriptionProperty property,
400 const void* value);
401
402/**
403 * Get a subscription property
404 *
405 * @param [in] subscription The subscription object
406 * @param [in] property The subscription property
407 * @param [out] value The value of the property
408 * @return UGStatusSuccess or UGStatusInvalidProperty
409 */
410UGStatus grail_subscription_get_property(UGSubscription subscription,
411 UGSubscriptionProperty property,
412 void* value);
413
414/**
415 * Activate a subscription
416 *
417 * @param [in] handle The context object
418 * @param [in] subscription The subscription object
419 * @return UGStatusSuccess or UGStatusErrorInvalidDevice
420 */
421UGStatus grail_subscription_activate(UGHandle handle, UGSubscription subscription);
422
423/**
424 * Deactivate a subscription
425 *
426 * @param [in] handle The context object
427 * @param [in] subscription The subscription object
428 */
429void grail_subscription_deactivate(UGHandle handle,
430 UGSubscription subscription);
431
432/**
433 * Process a uTouch Frame event
434 *
435 * @param [in] handle The context object
436 * @param [in] event The uTouch Frame event
437 */
438void grail_process_frame_event(UGHandle handle, const UFEvent event);
439
440/**
441 * Get an event from the uTouch Grail context
442 *
443 * @param [in] handle The context object
444 * @param [out] event The retrieved event
445 * @return UGStatusSuccess or UGStatusErrorNoEvent
446 */
447UGStatus grail_get_event(UGHandle handle, UGEvent *event);
448
449/**
450 * Update the grail state for the given server time
451 *
452 * @param [in] handle The context object
453 * @param [in] time The current server time
454 *
455 * The recognizer uses timeouts for deciding whether to accept or reject
456 * touches. Calling this function will perform any pending decisions based on
457 * the current server time.
458 */
459void grail_update_time(UGHandle handle, uint64_t time);
460
461/**
462 * Get the next timeout at which to update the grail state
463 *
464 * @param [in] handle The context object
465 * @return The next server time at which the grail state should be updated
466 *
467 * To update the grail state, call grail_update_time().
468 */
469uint64_t grail_next_timeout(UGHandle handle);
470
471/**
472 * Increment the reference count of an event
473 *
474 * @param [in] event The event object
475 */
476void grail_event_ref(UGEvent event);
477
478/**
479 * Decrement the reference count of an event
480 *
481 * @param [in] event The event object
482 *
483 * When the reference count reaches zero, the event is freed.
484 */
485void grail_event_unref(UGEvent event);
486
487/**
488 * Get the value of a property of an event
489 *
490 * @param [in] event The event object
491 * @param [in] property The property to retrieve a value for
492 * @param [out] value The value retrieved
493 * @return UGStatusSuccess or UGStatusErrorUnknownProperty
494 */
495UGStatus grail_event_get_property(const UGEvent event, UGEventProperty property,
496 void *value);
497
498/**
499 * Get the touch ID of a touch in a slice
500 *
501 * @param [in] slice The gesture slcie object
502 * @param [in] index The index of the touch in the slice
503 * @param [out] touch_id The touch ID of the touch
504 */
505UGStatus grail_slice_get_touch_id(const UGSlice slice, unsigned int index,
506 UFTouchId *touch_id);
507
508/**
509 * Get the value of a property of a gesture slice
510 *
511 * @param [in] slice The gesture slice object
512 * @param [in] property The property to retrieve a value for
513 * @param [out] value The value retrieved
514 * @return UGStatusSuccess or UGStatusErrorUnknownProperty
515 */
516UGStatus grail_slice_get_property(const UGSlice slice, UGSliceProperty property,
517 void *value);
518
519/**
520 * Accept gesture associated with gesture slice
521 *
522 * @param [in] handle The context object
523 * @param [in] id The ID of the gesture to accept
524 * @return UGStatusSuccess or UGStatusErrorInvalidGesture
525 */
526UGStatus grail_accept_gesture(UGHandle handle, unsigned int id);
527
528/**
529 * Reject gesture associated with gesture slice
530 *
531 * @param [in] handle The context object
532 * @param [in] id The ID of the gesture to reject
533 * @return UGStatusSuccess or UGStatusErrorInvalidGesture
534 */
535UGStatus grail_reject_gesture(UGHandle handle, unsigned int id);
536
537/**
538 * @defgroup v3-helpers Helper Functions
539 * These helper functions may be used in place of the generic property getters.
540 * They are limited to properties that are guaranteed to exist in all instances
541 * of the objects.
542 * @{
543 */
544
545/**
546 * Get the type of an event
547 *
548 * @param [in] event The event object
549 * @return The type of the event
550 */
551UGEventType grail_event_get_type(const UGEvent event);
552
553/**
554 * Get the time of an event
555 *
556 * @param [in] event The event object
557 * @return The time of the event
558 */
559uint64_t grail_event_get_time(const UGEvent event);
560
561/**
562 * Get the ID of a gesture from a slice
563 *
564 * @param [in] slice The gesture slice object
565 * @return The ID of the gesture
566 */
567unsigned int grail_slice_get_id(const UGSlice slice);
568
569/**
570 * Get the state of a gesture in a slice
571 *
572 * @param [in] slice The gesture slice object
573 * @return The state of the gesture in the slice
574 */
575UGGestureState grail_slice_get_state(const UGSlice slice);
576
577/**
578 * Get the subscription for the gesture from the slice
579 *
580 * @param [in] slice The gesture slice object
581 * @return The subscription
582 */
583UGSubscription grail_slice_get_subscription(const UGSlice slice);
584
585/**
586 * Get the gestures recognized through the slice
587 *
588 * @param [in] slice The gesture slice object
589 * @return The recognized gestures
590 */
591UGGestureTypeMask grail_slice_get_recognized(const UGSlice slice);
592
593/**
594 * Get the current number of touches in the slice
595 *
596 * @param [in] slice The gesture slice object
597 * @return The number of touches
598 */
599unsigned int grail_slice_get_num_touches(const UGSlice slice);
600
601/**
602 * Get the original centroid position of the gesture along the X axis
603 *
604 * @param [in] slice The gesture slice object
605 * @return The position
606 */
607float grail_slice_get_original_center_x(const UGSlice slice);
608
609/**
610 * Get the original centroid position of the gesture along the Y axis
611 *
612 * @param [in] slice The gesture slice object
613 * @return The position
614 */
615float grail_slice_get_original_center_y(const UGSlice slice);
616
617/**
618 * Get the original radius of the gesture
619 *
620 * @param [in] slice The gesture slice object
621 * @return The position
622 */
623float grail_slice_get_original_radius(const UGSlice slice);
624
625/**
626 * Get the instantaneous center of rotation of the gesture along the X axis
627 *
628 * @param [in] slice The gesture slice object
629 * @return The position
630 */
631float grail_slice_get_center_of_rotation_x(const UGSlice slice);
632
633/**
634 * Get the instantaneous center of rotation of the gesture along the Y axis
635 *
636 * @param [in] slice The gesture slice object
637 * @return The position
638 */
639float grail_slice_get_center_of_rotation_y(const UGSlice slice);
640
641/**
642 * Get the best-fit instantaneous 2D affine transformation for the gesture slice
643 *
644 * @param [in] slice The gesture slice object
645 * @return the transformation
646 *
647 * The returned transformation is owned by the gesture slice.
648 */
649const UGTransform *grail_slice_get_transform(const UGSlice slice);
650
651/**
652 * Get the best-fit cumulative 2D affine transformation for the gesture slice
653 *
654 * @param [in] slice The gesture slice object
655 * @return the transformation
656 *
657 * The returned transformation is owned by the gesture slice.
658 */
659const UGTransform *grail_slice_get_cumulative_transform(const UGSlice slice);
660
661/**
662 * Get the uTouch-Frame frame for the slice
663 *
664 * @param [in] slice The gesture slice object
665 * @return the frame
666 */
667const UFFrame grail_slice_get_frame(const UGSlice slice);
668
669/**
670 * Get whether construction has finished for all touches in the gesture
671 *
672 * @param [in] slice The gesture slice object
673 * @return whether construction has finished
674 */
675int grail_slice_get_construction_finished(const UGSlice slice);
676
677/** @} */
678
679/** @} */
680
681#ifdef __cplusplus
682}
683#endif
684
685#endif // UTOUCH_GRAIL_UTOUCH_GRAIL_H_
0686
=== added directory 'm4'
=== added file 'm4/gcov.m4'
--- m4/gcov.m4 1970-01-01 00:00:00 +0000
+++ m4/gcov.m4 2012-01-25 15:53:29 +0000
@@ -0,0 +1,83 @@
1# Checks for existence of coverage tools:
2# * gcov
3# * lcov
4# * genhtml
5# * gcovr
6#
7# Sets ac_cv_check_gcov to yes if tooling is present
8# and reports the executables to the variables LCOV, GCOVR and GENHTML.
9AC_DEFUN([AC_TDD_GCOV],
10[
11 AC_ARG_ENABLE(gcov,
12 AS_HELP_STRING([--enable-gcov],
13 [enable coverage testing with gcov]),
14 [use_gcov=$enableval], [use_gcov=no])
15
16 if test "x$use_gcov" = "xyes"; then
17 # we need gcc:
18 if test "$GCC" != "yes"; then
19 AC_MSG_ERROR([GCC is required for --enable-gcov])
20 fi
21
22 # Check if ccache is being used
23 AC_CHECK_PROG(SHTOOL, shtool, shtool)
24 case `$SHTOOL path $CC` in
25 *ccache*[)] gcc_ccache=yes;;
26 *[)] gcc_ccache=no;;
27 esac
28
29 if test "$gcc_ccache" = "yes" && (test -z "$CCACHE_DISABLE" || test "$CCACHE_DISABLE" != "1"); then
30 AC_MSG_ERROR([ccache must be disabled when --enable-gcov option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.])
31 fi
32
33 lcov_version_list="1.6 1.7 1.8 1.9"
34 AC_CHECK_PROG(LCOV, lcov, lcov)
35 AC_CHECK_PROG(GENHTML, genhtml, genhtml)
36 AC_CHECK_PROG(GCOVR, gcovr, gcovr)
37
38 if test "$LCOV"; then
39 AC_CACHE_CHECK([for lcov version], glib_cv_lcov_version, [
40 glib_cv_lcov_version=invalid
41 lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'`
42 for lcov_check_version in $lcov_version_list; do
43 if test "$lcov_version" = "$lcov_check_version"; then
44 glib_cv_lcov_version="$lcov_check_version (ok)"
45 fi
46 done
47 ])
48 else
49 lcov_msg="To enable code coverage reporting you must have one of the following lcov versions installed: $lcov_version_list"
50 AC_MSG_ERROR([$lcov_msg])
51 fi
52
53 case $glib_cv_lcov_version in
54 ""|invalid[)]
55 lcov_msg="You must have one of the following versions of lcov: $lcov_version_list (found: $lcov_version)."
56 AC_MSG_ERROR([$lcov_msg])
57 LCOV="exit 0;"
58 ;;
59 esac
60
61 if test -z "$GENHTML"; then
62 AC_MSG_ERROR([Could not find genhtml from the lcov package])
63 fi
64
65 if test -z "$GCOVR"; then
66 AC_MSG_ERROR([Could not find gcovr; easy_install (or pip) gcovr])
67 fi
68
69 ac_cv_check_gcov=yes
70
71 # Remove all optimization flags from CFLAGS
72 changequote({,})
73 CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'`
74 changequote([,])
75
76 # Add the special gcc flags
77 COVERAGE_CFLAGS="-O0 -fprofile-arcs -ftest-coverage"
78 COVERAGE_CXXFLAGS="-O0 -fprofile-arcs -ftest-coverage"
79 COVERAGE_LDFLAGS="-lgcov"
80
81fi
82]) # AC_TDD_GCOV
83
084
=== added file 'm4/gtest.m4'
--- m4/gtest.m4 1970-01-01 00:00:00 +0000
+++ m4/gtest.m4 2012-01-25 15:53:29 +0000
@@ -0,0 +1,24 @@
1# Checks whether the gtest library is available on the system
2# Allows for adjusting the include and library path.
3# Sets have_gtest=yes if the library is present and
4# reports the compiler and linker flags in
5# GTEST_CXXFLAGS AND GTEST_LDFLAGS, respectively.
6AC_DEFUN([AC_CHECK_GTEST],
7[
8 AC_ARG_WITH([gtest-include-path],
9 [AS_HELP_STRING([--with-gtest-include-path],
10 [location of the Google test headers, defaults to /usr/include])],
11 [GTEST_CXXFLAGS="-I$withval"],
12 [GTEST_CXXFLAGS='-I/usr/include'])
13
14 AC_ARG_WITH([gtest-lib-path],
15 [AS_HELP_STRING([--with-gtest-lib-path], [location of the Google test libraries])],
16 [GTEST_LDFLAGS="-L$withval -lpthread"],
17 [GTEST_LDFLAGS='-lgtest -lpthread'])
18
19 AC_HAVE_LIBRARY( [gtest],
20 [have_gtest=yes],
21 AC_MSG_WARN([package 'gtest' not found: tests disabled]))
22
23]) # AC_CHECK_GTEST
24
025
=== modified file 'src/Makefile.am'
--- src/Makefile.am 2011-04-28 16:53:41 +0000
+++ src/Makefile.am 2012-01-25 15:53:29 +0000
@@ -1,3 +1,5 @@
1AUTOMAKE_OPTIONS = subdir-objects
2
1lib_LTLIBRARIES = libutouch-grail.la3lib_LTLIBRARIES = libutouch-grail.la
24
3libutouch_grail_la_LDFLAGS = \5libutouch_grail_la_LDFLAGS = \
@@ -7,32 +9,48 @@
7 $(EVEMU_LIBS) \9 $(EVEMU_LIBS) \
8 $(FRAME_LIBS)10 $(FRAME_LIBS)
911
12v2dir = v2
10libutouch_grail_la_SOURCES = \13libutouch_grail_la_SOURCES = \
11 evbuf.h \14 v2/evbuf.h \
12 gebuf.h \15 v2/gebuf.h \
13 grailbuf.h \16 v2/grailbuf.h \
14 grail-bits.c \17 v2/grail-bits.c \
15 grail-inserter.c \18 v2/grail-inserter.c \
16 grail-inserter.h \19 v2/grail-inserter.h \
17 grail-gestures.c \20 v2/grail-gestures.c \
18 grail-gestures.h \21 v2/grail-gestures.h \
19 gestures-touch.c \22 v2/gestures-touch.c \
20 gestures-drag.c \23 v2/gestures-drag.c \
21 gestures-pinch.c \24 v2/gestures-pinch.c \
22 gestures-rotate.c \25 v2/gestures-rotate.c \
23 gestures-tapping.c \26 v2/gestures-tapping.c \
24 grail-recognizer.c \27 v2/grail-recognizer.c \
25 grail-recognizer.h \28 v2/grail-recognizer.h \
26 grail-event.c \29 v2/grail-event.c \
27 grail-impl.h \30 v2/grail-impl.h \
28 grail-api.c \31 v2/grail-api.c \
29 grail-legacy.c \32 v2/grail-legacy.c \
30 grail-init.c \33 v2/grail-init.c \
31 grail-frame.c34 v2/grail-frame.c
3235
33# These are flags required to properly set up36if HAVE_XI
34# the build. -fvisibility requires GCC > 4 (or clang)37v3dir = v3
35AM_CFLAGS = $(CWARNFLAGS) -DBUILDING_GRAIL -fvisibility=hidden38libutouch_grail_la_SOURCES += \
39 v3/event.cpp \
40 v3/event.h \
41 v3/gesture.cpp \
42 v3/gesture.h \
43 v3/handle.cpp \
44 v3/handle.h \
45 v3/log.cpp \
46 v3/log.h \
47 v3/recognizer.cpp \
48 v3/recognizer.h \
49 v3/slice.cpp \
50 v3/slice.h \
51 v3/subscription.cpp \
52 v3/subscription.h
53endif
3654
37INCLUDES = -I$(top_srcdir)/include/55INCLUDES = -I$(top_srcdir)/include/
3856
@@ -41,3 +59,9 @@
41 $(top_srcdir)/include/grail-bits.h \59 $(top_srcdir)/include/grail-bits.h \
42 $(top_srcdir)/include/grail-types.h \60 $(top_srcdir)/include/grail-types.h \
43 $(top_srcdir)/include/grail.h61 $(top_srcdir)/include/grail.h
62
63if HAVE_XI
64libutouch_grail_v3includedir = $(includedir)/utouch
65libutouch_grail_v3include_HEADERS = \
66 $(top_srcdir)/include/utouch/grail.h
67endif
4468
=== removed file 'src/evbuf.h'
--- src/evbuf.h 2011-04-28 16:53:57 +0000
+++ src/evbuf.h 1970-01-01 00:00:00 +0000
@@ -1,57 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#ifndef GRAIL_EVBUF_H
23#define GRAIL_EVBUF_H
24
25#define DIM_EVENTS 4096
26
27struct evbuf {
28 int head;
29 int tail;
30 struct input_event buffer[DIM_EVENTS];
31};
32
33static inline void evbuf_clear(struct evbuf *evbuf)
34{
35 evbuf->head = evbuf->tail = 0;
36}
37
38static inline int evbuf_empty(const struct evbuf *evbuf)
39{
40 return evbuf->head == evbuf->tail;
41}
42
43static inline void evbuf_put(struct evbuf *evbuf,
44 const struct input_event *ev)
45{
46 evbuf->buffer[evbuf->head++] = *ev;
47 evbuf->head &= DIM_EVENTS - 1;
48}
49
50static inline void evbuf_get(struct evbuf *evbuf,
51 struct input_event *ev)
52{
53 *ev = evbuf->buffer[evbuf->tail++];
54 evbuf->tail &= DIM_EVENTS - 1;
55}
56
57#endif
580
=== removed file 'src/gebuf.h'
--- src/gebuf.h 2011-05-17 14:15:22 +0000
+++ src/gebuf.h 1970-01-01 00:00:00 +0000
@@ -1,68 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#ifndef GRAIL_GESTURE_BUFFER_H
23#define GRAIL_GESTURE_BUFFER_H
24
25#include "grail-impl.h"
26
27#define DIM_GESTURE_EVENTS 512
28
29struct gesture_event {
30 int status;
31 int ntouch;
32 int nprop;
33 utouch_frame_time_t time;
34 struct grail_coord pos;
35 grail_prop_t prop[DIM_GRAIL_PROP];
36};
37
38struct gebuf {
39 int head;
40 int tail;
41 struct gesture_event buffer[DIM_GESTURE_EVENTS];
42};
43
44static inline void gebuf_clear(struct gebuf *gebuf)
45{
46 gebuf->head = gebuf->tail = 0;
47}
48
49static inline int gebuf_empty(const struct gebuf *gebuf)
50{
51 return gebuf->head == gebuf->tail;
52}
53
54static inline void gebuf_put(struct gebuf *gebuf,
55 const struct gesture_event *ev)
56{
57 gebuf->buffer[gebuf->head++] = *ev;
58 gebuf->head &= DIM_GESTURE_EVENTS - 1;
59}
60
61static inline void gebuf_get(struct gebuf *gebuf,
62 struct gesture_event *ev)
63{
64 *ev = gebuf->buffer[gebuf->tail++];
65 gebuf->tail &= DIM_GESTURE_EVENTS - 1;
66}
67
68#endif
690
=== removed file 'src/gestures-drag.c'
--- src/gestures-drag.c 2011-04-28 16:53:57 +0000
+++ src/gestures-drag.c 1970-01-01 00:00:00 +0000
@@ -1,135 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#include "grail-recognizer.h"
23#include <math.h>
24#include <stdio.h>
25
26static const int getype[DIM_TOUCH + 1] = {
27 -1,
28 GRAIL_TYPE_DRAG1,
29 GRAIL_TYPE_DRAG2,
30 GRAIL_TYPE_DRAG3,
31 GRAIL_TYPE_DRAG4,
32 GRAIL_TYPE_DRAG5,
33};
34
35static void set_props(const struct gesture_inserter *gin,
36 struct combo_model *s, const struct move_model *m,
37 const struct utouch_frame *frame)
38{
39 if (m->single) {
40 s->prop[GRAIL_PROP_DRAG_DX] = m->fm[FM_X].raw_delta;
41 s->prop[GRAIL_PROP_DRAG_DY] = m->fm[FM_Y].raw_delta;
42 } else {
43 s->prop[GRAIL_PROP_DRAG_DX] = m->fm[FM_X].action_delta;
44 s->prop[GRAIL_PROP_DRAG_DY] = m->fm[FM_Y].action_delta;
45 }
46 s->prop[GRAIL_PROP_DRAG_VX] = m->fm[FM_X].velocity;
47 s->prop[GRAIL_PROP_DRAG_VY] = m->fm[FM_Y].velocity;
48 s->prop[GRAIL_PROP_DRAG_X] = m->fm[FM_X].value;
49 s->prop[GRAIL_PROP_DRAG_Y] = m->fm[FM_Y].value;
50 s->nprop = 6;
51 s->nprop += gin_add_contact_props(gin, s->prop + s->nprop, frame);
52}
53
54static const int fm_mask = 0x03;
55
56int gru_drag(struct grail *ge,
57 const struct utouch_frame *frame)
58{
59 struct gesture_recognizer *gru = ge->gru;
60 struct combo_model *state = &gru->drag;
61 struct move_model *move = &gru->move;
62 int mask = state->active ? (move->active & fm_mask) : fm_mask;
63 if (!move->multi && !move->single) {
64 if (state->active) {
65 gru_end(ge, state->gid, move,
66 state->prop, state->nprop);
67 state->active = 0;
68 }
69 }
70 if ((move->timeout & fm_mask) == fm_mask) {
71 if (state->active) {
72 gin_gid_timeout(ge, state->gid);
73 }
74 }
75 if (!state->active) {
76 int type = getype[move->ntouch];
77 if (type < 0)
78 return 0;
79 state->gid = gin_gid_begin(ge, type, PRIO_GESTURE, frame);
80 state->active = 1;
81 }
82 if (!(move->tickle & mask))
83 return 0;
84 if (!(move->active & fm_mask))
85 return 0;
86 set_props(ge->gin, state, move, frame);
87 gru_event(ge, state->gid, move, state->prop, state->nprop);
88 return 1;
89}
90
91int gru_windrag(struct grail *ge,
92 const struct utouch_frame *frame)
93{
94 struct gesture_recognizer *gru = ge->gru;
95 struct combo_model *state = &gru->windrag;
96 struct move_model *move = &gru->move;
97 int mask = state->active ? (move->active & fm_mask) : fm_mask;
98 if (!move->multi && !move->single) {
99 if (state->active && out_of_bounds(state, move)) {
100 gru_end(ge, state->gid, move,
101 state->prop, state->nprop);
102 state->active = 0;
103 }
104 }
105 if ((move->timeout & fm_mask) == fm_mask) {
106 if (state->active) {
107 gin_gid_timeout(ge, state->gid);
108 }
109 }
110 if (!state->active) {
111 if (move->ntouch == 4) {
112 state->gid = gin_gid_begin(ge, GRAIL_TYPE_MDRAG,
113 PRIO_META, frame);
114 state->mintouch = 1;
115 state->maxtouch = 4;
116 state->active = 1;
117 } else if (move->ntouch == 3) {
118 state->gid = gin_gid_begin(ge, GRAIL_TYPE_EDRAG,
119 PRIO_ENV, frame);
120 state->mintouch = 1;
121 state->maxtouch = 3;
122 state->active = 1;
123 } else {
124 return 0;
125 }
126 }
127 if (!(move->tickle & mask))
128 return 0;
129 if (!(move->active & fm_mask))
130 return 0;
131 set_props(ge->gin, state, move, frame);
132 gru_event(ge, state->gid, move, state->prop, state->nprop);
133 return 1;
134}
135
1360
=== removed file 'src/gestures-pinch.c'
--- src/gestures-pinch.c 2011-06-06 14:42:39 +0000
+++ src/gestures-pinch.c 1970-01-01 00:00:00 +0000
@@ -1,131 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#include "grail-recognizer.h"
23#include <math.h>
24#include <stdio.h>
25
26static const int getype[DIM_TOUCH + 1] = {
27 0,
28 0,
29 GRAIL_TYPE_PINCH2,
30 GRAIL_TYPE_PINCH3,
31 GRAIL_TYPE_PINCH4,
32 GRAIL_TYPE_PINCH5,
33};
34
35static const int fm_mask = 0x04;
36
37static void set_props(const struct gesture_inserter *gin,
38 struct combo_model *s,
39 const struct move_model *m,
40 const struct utouch_frame *frame)
41{
42 s->prop[GRAIL_PROP_PINCH_DR] = m->fm[FM_R].action_delta;
43 s->prop[GRAIL_PROP_PINCH_VR] = m->fm[FM_R].velocity;
44 s->prop[GRAIL_PROP_PINCH_R] = m->fm[FM_R].value;
45 s->prop[GRAIL_PROP_PINCH_X] = m->fm[FM_X].value;
46 s->prop[GRAIL_PROP_PINCH_Y] = m->fm[FM_Y].value;
47 s->nprop = 5;
48 s->nprop += gin_add_contact_props(gin, s->prop + s->nprop, frame);
49}
50
51int gru_pinch(struct grail *ge,
52 const struct utouch_frame *frame)
53{
54 struct gesture_recognizer *gru = ge->gru;
55 struct combo_model *state = &gru->pinch;
56 struct move_model *move = &gru->move;
57 int mask = state->active ? (move->active & fm_mask) : fm_mask;
58 if (!move->multi && !move->single) {
59 if (state->active) {
60 gru_end(ge, state->gid, move,
61 state->prop, state->nprop);
62 state->active = 0;
63 }
64 return 0;
65 }
66 if ((move->timeout & fm_mask) == fm_mask) {
67 if (state->active) {
68 gin_gid_timeout(ge, state->gid);
69 }
70 }
71 if (!(move->tickle & mask))
72 return 0;
73 if (!state->active) {
74 int type = getype[move->ntouch];
75 if (!type)
76 return 0;
77 state->gid = gin_gid_begin(ge, type, PRIO_GESTURE, frame);
78 state->active = 1;
79 }
80 if (!(move->active & fm_mask))
81 return 0;
82 set_props(ge->gin, state, move, frame);
83 gru_event(ge, state->gid, move, state->prop, state->nprop);
84 return 1;
85}
86
87int gru_winpinch(struct grail *ge,
88 const struct utouch_frame *frame)
89{
90 struct gesture_recognizer *gru = ge->gru;
91 struct combo_model *state = &gru->winpinch;
92 struct move_model *move = &gru->move;
93 int mask = state->active ? (move->active & fm_mask) : fm_mask;
94 if (!move->multi) {
95 if (state->active && out_of_bounds(state, move)) {
96 gru_end(ge, state->gid, move,
97 state->prop, state->nprop);
98 state->active = 0;
99 }
100 return 0;
101 }
102 if ((move->timeout & fm_mask) == fm_mask) {
103 if (state->active) {
104 gin_gid_timeout(ge, state->gid);
105 }
106 }
107 if (!(move->tickle & mask))
108 return 0;
109 if (!state->active) {
110 if (move->ntouch == 4) {
111 state->gid = gin_gid_begin(ge, GRAIL_TYPE_MPINCH,
112 PRIO_META, frame);
113 state->mintouch = 2;
114 state->maxtouch = 4;
115 state->active = 1;
116 } else if (move->ntouch == 3) {
117 state->gid = gin_gid_begin(ge, GRAIL_TYPE_EPINCH,
118 PRIO_ENV, frame);
119 state->mintouch = 2;
120 state->maxtouch = 3;
121 state->active = 1;
122 } else {
123 return 0;
124 }
125 }
126 if (!(move->active & fm_mask))
127 return 0;
128 set_props(ge->gin, state, move, frame);
129 gru_event(ge, state->gid, move, state->prop, state->nprop);
130 return 1;
131}
1320
=== removed file 'src/gestures-rotate.c'
--- src/gestures-rotate.c 2011-06-03 12:54:23 +0000
+++ src/gestures-rotate.c 1970-01-01 00:00:00 +0000
@@ -1,130 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#include "grail-recognizer.h"
23#include <math.h>
24#include <stdio.h>
25
26static const int getype[DIM_TOUCH + 1] = {
27 0,
28 0,
29 GRAIL_TYPE_ROTATE2,
30 GRAIL_TYPE_ROTATE3,
31 GRAIL_TYPE_ROTATE4,
32 GRAIL_TYPE_ROTATE5,
33};
34
35static const int fm_mask = 0x08;
36
37static void set_props(const struct gesture_inserter *gin,
38 struct combo_model *s, const struct move_model *m,
39 const struct utouch_frame *frame)
40{
41 s->prop[GRAIL_PROP_ROTATE_DA] = m->fm[FM_A].action_delta;
42 s->prop[GRAIL_PROP_ROTATE_VA] = m->fm[FM_A].velocity;
43 s->prop[GRAIL_PROP_ROTATE_A] = m->fm[FM_A].value;
44 s->prop[GRAIL_PROP_ROTATE_X] = m->fm[FM_X].value;
45 s->prop[GRAIL_PROP_ROTATE_Y] = m->fm[FM_Y].value;
46 s->nprop = 5;
47 s->nprop += gin_add_contact_props(gin, s->prop + s->nprop, frame);
48}
49
50int gru_rotate(struct grail *ge,
51 const struct utouch_frame *frame)
52{
53 struct gesture_recognizer *gru = ge->gru;
54 struct combo_model *state = &gru->rotate;
55 struct move_model *move = &gru->move;
56 int mask = state->active ? (move->active & fm_mask) : fm_mask;
57 if (!move->multi && !move->single) {
58 if (state->active) {
59 gru_end(ge, state->gid, move,
60 state->prop, state->nprop);
61 state->active = 0;
62 }
63 return 0;
64 }
65 if ((move->timeout & fm_mask) == fm_mask) {
66 if (state->active) {
67 gin_gid_timeout(ge, state->gid);
68 }
69 }
70 if (!(move->tickle & mask))
71 return 0;
72 if (!state->active) {
73 int type = getype[move->ntouch];
74 if (!type)
75 return 0;
76 state->gid = gin_gid_begin(ge, type, PRIO_GESTURE, frame);
77 state->active = 1;
78 }
79 if (!(move->active & fm_mask))
80 return 0;
81 set_props(ge->gin, state, move, frame);
82 gru_event(ge, state->gid, move, state->prop, state->nprop);
83 return 1;
84}
85
86int gru_winrotate(struct grail *ge,
87 const struct utouch_frame *frame)
88{
89 struct gesture_recognizer *gru = ge->gru;
90 struct combo_model *state = &gru->winrotate;
91 struct move_model *move = &gru->move;
92 int mask = state->active ? (move->active & fm_mask) : fm_mask;
93 if (!move->multi) {
94 if (state->active && out_of_bounds(state, move)) {
95 gru_end(ge, state->gid, move,
96 state->prop, state->nprop);
97 state->active = 0;
98 }
99 return 0;
100 }
101 if ((move->timeout & fm_mask) == fm_mask) {
102 if (state->active) {
103 gin_gid_timeout(ge, state->gid);
104 }
105 }
106 if (!(move->tickle & mask))
107 return 0;
108 if (!state->active) {
109 if (move->ntouch == 4) {
110 state->gid = gin_gid_begin(ge, GRAIL_TYPE_MROTATE,
111 PRIO_META, frame);
112 state->mintouch = 2;
113 state->maxtouch = 4;
114 state->active = 1;
115 } else if (move->ntouch == 3) {
116 state->gid = gin_gid_begin(ge, GRAIL_TYPE_EROTATE,
117 PRIO_ENV, frame);
118 state->mintouch = 2;
119 state->maxtouch = 3;
120 state->active = 1;
121 } else {
122 return 0;
123 }
124 }
125 if (!(move->active & fm_mask))
126 return 0;
127 set_props(ge->gin, state, move, frame);
128 gru_event(ge, state->gid, move, state->prop, state->nprop);
129 return 1;
130}
1310
=== removed file 'src/gestures-tapping.c'
--- src/gestures-tapping.c 2011-04-28 16:53:57 +0000
+++ src/gestures-tapping.c 1970-01-01 00:00:00 +0000
@@ -1,100 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#include "grail-recognizer.h"
23#include <math.h>
24
25static const int fm_mask = 0x07;
26
27static void set_props(const struct gesture_inserter *gin,
28 struct tapping_model *s, const struct move_model *m,
29 const struct utouch_frame *frame)
30{
31 s->prop[GRAIL_PROP_TAP_DT] = m->time - s->start;
32 s->prop[GRAIL_PROP_TAP_X] = m->fm[FM_X].value;
33 s->prop[GRAIL_PROP_TAP_Y] = m->fm[FM_Y].value;
34 s->nprop = 3;
35 s->nprop += gin_add_contact_props(gin, s->prop + s->nprop, frame);
36}
37
38int gru_tapping(struct grail *ge,
39 const struct utouch_frame *frame)
40{
41 struct gesture_recognizer *gru = ge->gru;
42 struct tapping_model *state = &gru->tapping;
43 struct move_model *move = &gru->move;
44 state->tap = 0;
45 if (frame->num_active && !frame->prev->num_active) {
46 state->mintouch = 0;
47 state->maxtouch = 0;
48 }
49 if (move->ntouch > state->maxtouch) {
50 if (state->active) {
51 gin_gid_discard(ge, state->gid);
52 state->active = 0;
53 }
54 state->start = move->time;
55 state->maxtouch = move->ntouch;
56 set_props(ge->gin, state, move, frame);
57 if (state->maxtouch <= 5) {
58 int type = GRAIL_TYPE_TAP1 + state->maxtouch - 1;
59 state->gid = gin_gid_begin(ge, type, PRIO_TAP, frame);
60 state->active = 1;
61 }
62 return 0;
63 }
64 if (!state->active) {
65 state->mintouch = move->ntouch;
66 state->maxtouch = move->ntouch;
67 return 0;
68 }
69 if (move->ntouch <= state->mintouch) {
70 int x = state->prop[GRAIL_PROP_TAP_X];
71 int y = state->prop[GRAIL_PROP_TAP_Y];
72 int t = move->time - state->start;
73 if (t > move->fm[FM_X].bar_ms) {
74 gin_gid_discard(ge, state->gid);
75 state->mintouch = move->ntouch;
76 state->maxtouch = move->ntouch;
77 state->active = 0;
78 return 0;
79 }
80 state->tap = state->maxtouch;
81 state->prop[GRAIL_PROP_TAP_DT] = t;
82 gin_gid_event(ge, state->gid, x, y, state->maxtouch,
83 state->prop, state->nprop, 1);
84 state->mintouch = move->ntouch;
85 state->maxtouch = move->ntouch;
86 state->active = 0;
87 return 1;
88 }
89 if (!move->ntouch)
90 return 0;
91 state->prop[GRAIL_PROP_TAP_DT] = move->time - state->start;
92 if ((move->active & fm_mask) ||
93 move->time - state->start > move->fm[FM_X].bar_ms) {
94 gin_gid_discard(ge, state->gid);
95 state->mintouch = move->ntouch;
96 state->maxtouch = move->ntouch;
97 state->active = 0;
98 }
99 return 0;
100}
1010
=== removed file 'src/gestures-touch.c'
--- src/gestures-touch.c 2011-04-04 17:27:38 +0000
+++ src/gestures-touch.c 1970-01-01 00:00:00 +0000
@@ -1,98 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 * Copyright (C) 2010 Henrik Rydberg <rydberg@bitmath.org>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 ****************************************************************************/
22
23#include "grail-recognizer.h"
24#include <math.h>
25#include <stdio.h>
26
27static const int getype[DIM_TOUCH + 1] = {
28 -1,
29 GRAIL_TYPE_TOUCH1,
30 GRAIL_TYPE_TOUCH2,
31 GRAIL_TYPE_TOUCH3,
32 GRAIL_TYPE_TOUCH4,
33 GRAIL_TYPE_TOUCH5,
34};
35
36int gru_touch(struct grail *ge,
37 const struct utouch_frame *frame)
38{
39 struct gesture_recognizer *gru = ge->gru;
40 struct combo_model *state = &gru->touch;
41 struct move_model *move = &gru->move;
42 if (frame->slot_revision != frame->prev->slot_revision) {
43 if (state->active) {
44 gru_end(ge, state->gid, move,
45 state->prop, state->nprop);
46 state->active = 0;
47 }
48 }
49 if (!state->active) {
50 int type = getype[move->ntouch];
51 if (type <= 0)
52 return 0;
53 state->gid = gin_gid_begin(ge, type, -PRIO_GESTURE, frame);
54 state->active = 1;
55 }
56 if (move->time - move->fm[FM_X].original_ms <= move->fm[FM_X].hold_ms)
57 return 0;
58 state->nprop = gin_add_contact_props(ge->gin, state->prop, frame);
59 gru_event(ge, state->gid, move, state->prop, state->nprop);
60 return 1;
61}
62
63int gru_wintouch(struct grail *ge,
64 const struct utouch_frame *frame)
65{
66 struct gesture_recognizer *gru = ge->gru;
67 struct combo_model *state = &gru->wintouch;
68 struct move_model *move = &gru->move;
69 if (frame->slot_revision != frame->prev->slot_revision) {
70 if (state->active && out_of_bounds(state, move)) {
71 gru_end(ge, state->gid, move,
72 state->prop, state->nprop);
73 state->active = 0;
74 }
75 }
76 if (!state->active) {
77 if (move->ntouch == 4) {
78 state->gid = gin_gid_begin(ge, GRAIL_TYPE_MTOUCH,
79 -PRIO_META, frame);
80 state->mintouch = 1;
81 state->maxtouch = 4;
82 state->active = 1;
83 } else if (move->ntouch == 3) {
84 state->gid = gin_gid_begin(ge, GRAIL_TYPE_ETOUCH,
85 -PRIO_ENV, frame);
86 state->mintouch = 1;
87 state->maxtouch = 3;
88 state->active = 1;
89 } else {
90 return 0;
91 }
92 }
93 if (move->time - move->fm[FM_X].original_ms <= move->fm[FM_X].hold_ms)
94 return 0;
95 state->nprop = gin_add_contact_props(ge->gin, state->prop, frame);
96 gru_event(ge, state->gid, move, state->prop, state->nprop);
97 return 1;
98}
990
=== removed file 'src/grail-api.c'
--- src/grail-api.c 2011-08-31 17:20:48 +0000
+++ src/grail-api.c 1970-01-01 00:00:00 +0000
@@ -1,328 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#include "grail-impl.h"
23#include "grail-inserter.h"
24#include "grail-recognizer.h"
25#include <string.h>
26#include <stdio.h>
27#include <unistd.h>
28#include <fcntl.h>
29#include <malloc.h>
30#include <errno.h>
31#include <stdlib.h>
32#include <sys/stat.h>
33
34#define DIM_FRAMES 100
35#define FRAME_RATE 100
36
37unsigned int GRAIL_PUBLIC grail_get_version(void)
38{
39 return GRAIL_VERSION;
40}
41
42int GRAIL_PUBLIC grail_open(struct grail *ge, int fd)
43{
44 struct grail_impl *x;
45 struct stat fs;
46 int ret;
47
48 ret = fstat(fd, &fs);
49 if (ret)
50 return ret;
51
52 x = calloc(1, sizeof(*x));
53 if (!x)
54 return -ENOMEM;
55
56 if (!fs.st_rdev)
57 x->fptest = fdopen(fd, "r");
58
59 x->evemu = evemu_new(x->fptest ? "fptest" : 0);
60 if (!x->evemu) {
61 ret = -ENOMEM;
62 goto freemem;
63 }
64 if (x->fptest)
65 ret = evemu_read(x->evemu, x->fptest) <= 0;
66 else
67 ret = evemu_extract(x->evemu, fd);
68 if (ret)
69 goto freemem;
70 if (!utouch_frame_is_supported_mtdev(x->evemu)) {
71 ret = -ENODEV;
72 goto freemem;
73 }
74
75 if (!x->fptest) {
76 x->mtdev = mtdev_new_open(fd);
77 if (!x->mtdev) {
78 ret = -ENOMEM;
79 goto freemem;
80 }
81 }
82 x->fh = utouch_frame_new_engine(DIM_FRAMES, DIM_TOUCH, FRAME_RATE);
83 if (!x->fh) {
84 ret = -ENOMEM;
85 goto freedev;
86 }
87 ret = utouch_frame_init_mtdev(x->fh, x->evemu);
88 if (ret)
89 goto freeframe;
90
91 ge->impl = x;
92
93 ret = gin_init(ge);
94 if (ret)
95 goto freeframe;
96
97 ret = gru_init(ge);
98 if (ret)
99 goto freegin;
100
101 return 0;
102 freegin:
103 gin_destroy(ge);
104 freeframe:
105 utouch_frame_delete_engine(x->fh);
106 freedev:
107 if (x->mtdev)
108 mtdev_close_delete(x->mtdev);
109 freemem:
110 evemu_delete(x->evemu);
111 if (x->fptest)
112 fclose(x->fptest);
113 free(x);
114 ge->impl = 0;
115 return ret;
116}
117
118void GRAIL_PUBLIC grail_close(struct grail *ge, int fd)
119{
120 struct grail_impl *x = ge->impl;
121 gru_destroy(ge);
122 gin_destroy(ge);
123 utouch_frame_delete_engine(x->fh);
124 if (x->mtdev)
125 mtdev_close_delete(x->mtdev);
126 evemu_delete(x->evemu);
127 if (x->fptest)
128 fclose(x->fptest);
129 free(x);
130 ge->impl = 0;
131}
132
133int GRAIL_PUBLIC grail_idle(struct grail *ge, int fd, int ms)
134{
135 struct grail_impl *x = ge->impl;
136 if (x->fptest)
137 return 0;
138 if (x->mtdev)
139 return mtdev_idle(x->mtdev, fd, ms);
140 return 1;
141}
142
143void GRAIL_PUBLIC grail_get_units(const struct grail *ge,
144 struct grail_coord *min, struct grail_coord *max)
145{
146 struct utouch_surface *s = utouch_frame_get_surface(ge->impl->fh);
147 min->x = s->min_x;
148 min->y = s->min_y;
149 max->x = s->max_x;
150 max->y = s->max_y;
151}
152
153const struct utouch_frame GRAIL_PUBLIC *
154grail_get_contact_frame(const struct grail *ge)
155{
156 return ge->impl->touch;
157}
158
159static void flush_events(struct grail *ge)
160{
161 struct grail_impl *impl = ge->impl;
162 struct input_event iev;
163
164 grailbuf_clear(&impl->gbuf);
165 while (!evbuf_empty(&impl->evbuf)) {
166 evbuf_get(&impl->evbuf, &iev);
167 if (ge->event)
168 ge->event(ge, &iev);
169 }
170}
171
172static int skip_event(const struct input_event *ev, int count)
173{
174 switch (ev->type) {
175 case EV_ABS:
176 return 1;
177 case EV_KEY:
178 return ev->code >= BTN_DIGI && ev->code < BTN_WHEEL;
179 case EV_SYN:
180 switch (ev->code) {
181 case SYN_MT_REPORT:
182 return 1;
183 case SYN_REPORT:
184 return count == 0;
185 default:
186 return 0;
187 }
188 default:
189 return 0;
190 }
191}
192
193static void flush_gestures(struct grail *ge)
194{
195 struct grail_impl *impl = ge->impl;
196 struct input_event iev;
197 struct grail_event gev;
198 int count = 0;
199
200 while (!evbuf_empty(&impl->evbuf)) {
201 evbuf_get(&impl->evbuf, &iev);
202 if (skip_event(&iev, count))
203 continue;
204 if (ge->event)
205 ge->event(ge, &iev);
206 if (iev.type == EV_SYN && iev.code == SYN_REPORT)
207 count = 0;
208 else
209 count++;
210 }
211 while (!grailbuf_empty(&impl->gbuf)) {
212 grailbuf_get(&impl->gbuf, &gev);
213 if (ge->gesture)
214 ge->gesture(ge, &gev);
215 }
216}
217
218static int gesture_timeout(struct grail *ge, const struct utouch_frame *frame)
219{
220 struct gesture_recognizer *gru = ge->gru;
221 struct gesture_inserter *gin = ge->gin;
222
223 return grail_mask_count(gin->used, sizeof(gin->used)) == 0 &&
224 frame->time - frame->mod_time > gru->move.fm[FM_X].hold_ms;
225}
226
227static void report_frame(struct grail *ge,
228 const struct utouch_frame *touch,
229 const struct input_event *syn)
230{
231 struct grail_impl *impl = ge->impl;
232
233 impl->touch = touch;
234
235 if (touch->num_active && !touch->prev->num_active) {
236 impl->ongoing = 1;
237 impl->gesture = 0;
238 }
239
240 if (!impl->ongoing)
241 return;
242
243 gin_frame_begin(ge, touch);
244 gru_recognize(ge, touch);
245 gin_frame_end(ge, touch);
246
247 if (!grailbuf_empty(&impl->gbuf))
248 impl->gesture = 1;
249
250 if (touch->num_active == 0 || gesture_timeout(ge, touch))
251 impl->ongoing &= impl->gesture;
252}
253
254static void grail_pump_mtdev(struct grail *ge, const struct input_event *ev)
255{
256 struct grail_impl *impl = ge->impl;
257 const struct utouch_frame *frame;
258
259 evbuf_put(&impl->evbuf, ev);
260
261 if (ev->type == EV_SYN || ev->type == EV_ABS || ev->type == EV_KEY) {
262 frame = utouch_frame_pump_mtdev(impl->fh, ev);
263 if (frame)
264 report_frame(ge, frame, ev);
265 }
266
267 if (ev->type == EV_SYN) {
268 if (!impl->ongoing)
269 flush_events(ge);
270 if (impl->gesture)
271 flush_gestures(ge);
272 }
273}
274
275/**
276 * Read an event from the given file. If fast_fileread is true,
277 * return immediately. If it is false, delay between events
278 * so it looks like they are coming in real time.
279 */
280static int grail_read_evemu_event(FILE *fp, struct input_event *ev,
281 struct timeval *evtime, int fast_fileread) {
282 if (fast_fileread)
283 return evemu_read_event(fp, ev);
284 return evemu_read_event_realtime(fp, ev, evtime);
285}
286
287
288static int grail_pull_fstest(struct grail *ge, int fd)
289{
290 struct grail_impl *impl = ge->impl;
291 struct input_event ev;
292 struct timeval evtime;
293 int count = 0;
294
295 memset(&evtime, 0, sizeof(evtime));
296 while (grail_read_evemu_event(impl->fptest, &ev, &evtime, impl->fast_fileread) > 0) {
297 grail_pump_mtdev(ge, &ev);
298 count++;
299 }
300
301 fclose(impl->fptest);
302 impl->fptest = 0;
303
304 return count > 0 ? count : -1;
305}
306
307int GRAIL_PUBLIC grail_pull(struct grail *ge, int fd)
308{
309 struct grail_impl *impl = ge->impl;
310 struct input_event ev;
311 int ret, count = 0;
312
313 if (impl->fptest)
314 return grail_pull_fstest(ge, fd);
315
316 while ((ret = mtdev_get(impl->mtdev, fd, &ev, 1)) > 0) {
317 grail_pump_mtdev(ge, &ev);
318 count++;
319 }
320
321 return count > 0 ? count : ret;
322}
323
324void GRAIL_PUBLIC grail_set_coordinate_transform_callback(struct grail *ge,
325 utouch_coordinate_transform_cb callback,
326 void *user_data) {
327 utouch_frame_set_coordinate_transform_callback(ge->impl->fh, callback, user_data);
328}
3290
=== removed file 'src/grail-bits.c'
--- src/grail-bits.c 2011-04-28 16:53:57 +0000
+++ src/grail-bits.c 1970-01-01 00:00:00 +0000
@@ -1,93 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#include "grail-bits.h"
23
24static const int grail_bits_in_byte[256] =
25{
26 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
27 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
28 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
29 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
30 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
31 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
32 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
33 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
34};
35
36static const int grail_first_set_bit[256] =
37{
38 -1,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
39 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
40 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
41 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
42 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
43 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
44 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
45 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
46};
47
48void GRAIL_PUBLIC grail_mask_set_mask(grail_mask_t *a, const grail_mask_t *b,
49 int bytes)
50{
51 while (bytes--)
52 *a++ |= *b++;
53}
54
55void GRAIL_PUBLIC grail_mask_clear_mask(grail_mask_t *a, const grail_mask_t *b,
56 int bytes)
57{
58 while (bytes--)
59 *a++ &= ~*b++;
60}
61
62int GRAIL_PUBLIC grail_mask_count(const grail_mask_t *mask, int bytes)
63{
64 int count = 0;
65 while (bytes--)
66 count += grail_bits_in_byte[*mask++];
67 return count;
68}
69
70int GRAIL_PUBLIC grail_mask_get_first(const grail_mask_t *mask, int bytes)
71{
72 int k;
73 for (k = 0; k < bytes; k++)
74 if (mask[k])
75 return (k << 3) | grail_first_set_bit[mask[k]];
76 return -1;
77}
78
79int GRAIL_PUBLIC grail_mask_get_next(int i, const grail_mask_t *mask, int bytes)
80{
81 int k = ++i >> 3;
82 if (k < bytes) {
83 i = grail_first_set_bit[mask[k] & (~0 << (i & 7))];
84 if (i >= 0)
85 return (k << 3) | i;
86 while (++k < bytes) {
87 i = grail_first_set_bit[mask[k]];
88 if (i >= 0)
89 return (k << 3) | i;
90 }
91 }
92 return -1;
93}
940
=== removed file 'src/grail-event.c'
--- src/grail-event.c 2011-08-31 17:45:31 +0000
+++ src/grail-event.c 1970-01-01 00:00:00 +0000
@@ -1,118 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#include "grail-inserter.h"
23#include "grail-impl.h"
24#include <malloc.h>
25#include <string.h>
26#include <errno.h>
27#include <math.h>
28
29static void compute_bbox(struct grail_coord *min, struct grail_coord *max,
30 const struct utouch_frame *frame)
31{
32 float x, y;
33 int i;
34 if (frame->num_active < 1)
35 return;
36 x = frame->active[0]->x;
37 y = frame->active[0]->y;
38 min->x = max->x = x;
39 min->y = max->y = y;
40 for (i = 1; i < frame->num_active; i++) {
41 x = frame->active[i]->x;
42 y = frame->active[i]->y;
43 if (x < min->x)
44 min->x = x;
45 if (y < min->y)
46 min->y = y;
47 if (x > max->x)
48 max->x = x;
49 if (y > max->y)
50 max->y = y;
51 }
52}
53
54int gin_add_contact_props(const struct gesture_inserter *gin,
55 grail_prop_t *prop, const struct utouch_frame *frame)
56{
57 struct grail_coord min = { 0, 0 };
58 struct grail_coord max = { 0, 0 };
59 int i, n = 0, ntouch = frame->num_active;
60 if (!ntouch)
61 return n;
62 if (ntouch > 5)
63 ntouch = 5;
64 compute_bbox(&min, &max, frame);
65 prop[n++] = min.x;
66 prop[n++] = min.y;
67 prop[n++] = max.x;
68 prop[n++] = max.y;
69 for (i = 0; i < ntouch; i++) {
70 const struct utouch_contact *ct = frame->active[i];
71 prop[n++] = ct->id;
72 prop[n++] = ct->x;
73 prop[n++] = ct->y;
74 }
75 return n;
76}
77
78int gin_get_clients(struct grail *ge,
79 struct grail_client_info *info, int maxinfo,
80 const grail_mask_t* types, int btypes,
81 const grail_mask_t* span, int bspan,
82 const struct utouch_frame *frame)
83{
84 struct grail_coord pos[DIM_TOUCH];
85 int i, npos = 0;
86 if (!ge->get_clients)
87 return 0;
88 grail_mask_foreach(i, span, bspan) {
89 pos[npos].x = frame->slots[i]->x;
90 pos[npos].y = frame->slots[i]->y;
91 npos++;
92 }
93 return ge->get_clients(ge, info, maxinfo, pos, npos, types, btypes);
94}
95
96void gin_send_event(struct grail *ge, struct slot_state *s,
97 const struct gesture_event *ev,
98 const struct utouch_frame *frame)
99{
100 struct grail_impl *impl = ge->impl;
101 struct grail_event gev;
102 int i;
103 if (!ge->gesture)
104 return;
105 gev.type = s->type;
106 gev.id = s->id;
107 gev.status = ev->status;
108 gev.ntouch = ev->ntouch;
109 gev.nprop = ev->nprop;
110 gev.time = ev->time;
111 gev.pos.x = ev->pos.x;
112 gev.pos.y = ev->pos.y;
113 memcpy(gev.prop, ev->prop, ev->nprop * sizeof(grail_prop_t));
114 for (i = 0; i < s->nclient; i++) {
115 gev.client_id = s->client_id[i];
116 grailbuf_put(&impl->gbuf, &gev);
117 }
118}
1190
=== removed file 'src/grail-frame.c'
--- src/grail-frame.c 2011-08-31 17:20:48 +0000
+++ src/grail-frame.c 1970-01-01 00:00:00 +0000
@@ -1,410 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#include "grail-impl.h"
23#include <stdlib.h>
24#include <string.h>
25#include <math.h>
26
27static void set_center_velocity_and_radius(struct grail_impl *impl,
28 struct grail_element *slot)
29{
30 const struct utouch_contact **tc = slot->touches;
31 double x, y, vx, vy, r2, dx, dy;
32 int i;
33
34 switch (slot->num_touches) {
35 case 1:
36 x = tc[0]->x;
37 y = tc[0]->y;
38 vx = tc[0]->vx;
39 vy = tc[0]->vy;
40 r2 = 0;
41 break;
42 case 2:
43 dx = 0.5 * (tc[1]->x - tc[0]->x);
44 dy = 0.5 * (tc[1]->y - tc[0]->y);
45 x = tc[0]->x + dx;
46 y = tc[0]->y + dy;
47 vx = 0.5 * (tc[0]->vx + tc[1]->vx);
48 vy = 0.5 * (tc[0]->vy + tc[1]->vy);
49 r2 = dx * dx + dy * dy;
50 break;
51 default:
52 x = y = vx = vy = r2 = 0;
53 for (i = 0; i < slot->num_touches; i++) {
54 x += tc[i]->x;
55 y += tc[i]->y;
56 vx += tc[i]->vx;
57 vy += tc[i]->vy;
58 }
59 x /= slot->num_touches;
60 y /= slot->num_touches;
61 vx /= slot->num_touches;
62 vy /= slot->num_touches;
63 for (i = 0; i < slot->num_touches; i++) {
64 dx = tc[i]->x - x;
65 dy = tc[i]->y - y;
66 r2 += dx * dx + dy * dy;
67 }
68 r2 /= slot->num_touches;
69 break;
70 }
71
72 slot->center.x = x;
73 slot->center.y = y;
74 slot->velocity.x = 1000 * vx;
75 slot->velocity.y = 1000 * vy;
76 slot->radius2 = r2;
77}
78
79static void set_transform(struct grail_impl *impl, struct grail_element *slot,
80 double ds, double dc)
81{
82 const struct grail_element *pslot = slot->prev;
83 double dx = slot->center.x - pslot->center.x;
84 double dy = slot->center.y - pslot->center.y;
85 float *T = slot->transform;
86
87 T[0] = dc;
88 T[1] = ds;
89 T[2] = dx;
90 T[3] = -ds;
91 T[4] = dc;
92 T[5] = dy;
93
94 slot->drag.x = pslot->drag.x + dx;
95 slot->drag.y = pslot->drag.y + dy;
96}
97
98static void start_slot(struct grail_impl *impl,
99 struct grail_element *slot,
100 const struct utouch_frame *touch)
101{
102 float *T = slot->transform;
103
104 slot->id = impl->seqid++ & GRAIL_ID_MAX;
105 slot->expect_mask = GRAIL_EXPECT_MASK;
106 slot->active_mask = 0;
107 slot->start_time = touch->time;
108 set_center_velocity_and_radius(impl, slot);
109 T[0] = T[4] = 1;
110 T[1] = T[2] = T[3] = T[5] = 0;
111 slot->drag.x = 0;
112 slot->drag.y = 0;
113 slot->scale2 = 1;
114 slot->angle = 0;
115}
116
117static void update_slot(struct grail_impl *impl,
118 struct grail_element *slot,
119 double ds, double dc)
120{
121 const struct grail_element *pslot = slot->prev;
122
123 slot->id = pslot->id;
124 slot->start_time = pslot->start_time;
125 slot->expect_mask = pslot->expect_mask;
126 slot->active_mask = pslot->active_mask;
127
128 set_center_velocity_and_radius(impl, slot);
129 set_transform(impl, slot, ds, dc);
130
131 slot->scale2 = pslot->scale2 * (ds * ds + dc * dc);
132 slot->angle = pslot->angle + ds / dc; /* atan2(ds, dc) */
133}
134
135static void stop_slot(struct grail_impl *impl,
136 struct grail_element *slot)
137{
138 const struct grail_element *pslot = slot->prev;
139 float *T = slot->transform;
140
141 slot->id = -1;
142 slot->num_touches = 0;
143 slot->start_time = pslot->start_time;
144 slot->expect_mask = 0;
145 slot->active_mask = pslot->active_mask;
146 slot->center = pslot->center;
147 slot->velocity = pslot->velocity;
148 slot->radius2 = pslot->radius2;
149 T[0] = T[4] = 1;
150 T[1] = T[2] = T[3] = T[5] = 0;
151 slot->drag = pslot->drag;
152 slot->scale2 = pslot->scale2;
153 slot->angle = pslot->angle;
154}
155
156static void set_slot_one(struct grail_impl *impl,
157 struct grail_element *slot,
158 const struct utouch_frame *touch,
159 const struct utouch_contact *t1)
160{
161 const struct grail_element *pslot = slot->prev;
162 const struct utouch_contact *p1 = pslot->touches[0];
163
164 if (!t1->active) {
165 stop_slot(impl, slot);
166 return;
167 }
168
169 slot->touches[0] = t1;
170 slot->num_touches = 1;
171
172 if (pslot->num_touches != slot->num_touches || t1->id != p1->id) {
173 start_slot(impl, slot, touch);
174 return;
175 }
176
177 update_slot(impl, slot, 0, 1);
178}
179
180static void set_slot_two(struct grail_impl *impl,
181 struct grail_element *slot,
182 const struct utouch_frame *touch,
183 const struct utouch_contact *t1,
184 const struct utouch_contact *t2)
185{
186 const struct grail_element *pslot = slot->prev;
187 const struct utouch_contact *p1 = pslot->touches[0];
188 const struct utouch_contact *p2 = pslot->touches[1];
189 double tx, ty, px, py, d2;
190
191 if (!t1->active || !t2->active) {
192 stop_slot(impl, slot);
193 return;
194 }
195
196 slot->touches[0] = t1;
197 slot->touches[1] = t2;
198 slot->num_touches = 2;
199
200 if (pslot->num_touches != slot->num_touches ||
201 t1->id != p1->id || t2->id != p2->id) {
202 start_slot(impl, slot, touch);
203 return;
204 }
205
206 tx = t2->x - t1->x;
207 ty = t2->y - t1->y;
208 px = p2->x - p1->x;
209 py = p2->y - p1->y;
210
211 d2 = px * px + py * py;
212 if (d2 > 0) {
213 px /= d2;
214 py /= d2;
215 }
216
217 update_slot(impl, slot, tx * py - ty * px, tx * px + ty * py);
218}
219
220static void set_slot_multi(struct grail_impl *impl,
221 struct grail_element *slot,
222 struct grail_frame *frame,
223 const struct utouch_frame *touch)
224{
225 const struct grail_element *pslot = slot->prev;
226 struct grail_element **slots = frame->slots;
227 int i, j, n = impl->num_touches;
228 struct grail_element *best = 0;
229
230 if (touch->num_active < 3) {
231 stop_slot(impl, slot);
232 return;
233 }
234
235 memcpy(slot->touches, touch->active,
236 touch->num_active * sizeof(slot->touches[0]));
237 slot->num_touches = touch->num_active;
238
239 if (pslot->num_touches != slot->num_touches) {
240 start_slot(impl, slot, touch);
241 return;
242 }
243
244 for (i = 0; i < slot->num_touches; i++) {
245 if (slot->touches[i]->id != pslot->touches[i]->id) {
246 start_slot(impl, slot, touch);
247 return;
248 }
249 }
250
251 for (i = 0; i < impl->num_touches; i++) {
252 for (j = i + 1; j < impl->num_touches; j++) {
253 struct grail_element *s = slots[n++];
254 if (!s->num_touches)
255 continue;
256 if (!best || s->radius2 > best->radius2)
257 best = s;
258 }
259 }
260
261 update_slot(impl, slot, best->transform[1], best->transform[0]);
262}
263
264/**
265 * Determine the center of rotation point.
266 *
267 * For any given point q that is transformed by a 2D affine transformation
268 * matrix T about anchor point P the new point q' may be determined by the
269 * following equation:
270 *
271 * q' = T * (q - P) + P
272 *
273 * T and P are dependent, so we can modify one and find a new value for the
274 * other. We will label the original T and P as T0 and P0, and the new values
275 * will be labeled T1 and P1. We can find new values by solving the following
276 * equation:
277 *
278 * q' = T0 * (q - P0) + P0 = T1 * (q - P1) + P1
279 *
280 * In the calculations below, we use variables for the scalar values
281 * that make up T0, P0, T1, and P1:
282 *
283 * T0: [ a -b c ] P0: [ x0 ] T1: [ a -b 0 ] P1: [ x1 ]
284 * [ b a d ] [ y0 ] [ b a 0 ] [ y1 ]
285 * [ 0 0 1 ] [ 0 ] [ 0 0 1 ] [ 0 ]
286 *
287 * Note that rotation and scaling are independent of the anchor point, so a and
288 * b are equivalent between the transformation matrices.
289 *
290 * Since we know all the values of T0, P0, and T1, we can calculate the values
291 * x1 and y1 in P1.
292 */
293static inline int set_center_of_rotation(struct grail_element *e)
294{
295 float a = e->transform[0];
296 float b = e->transform[3];
297 float c = e->transform[2];
298 float d = e->transform[5];
299 float x0 = e->center.x;
300 float y0 = e->center.y;
301 float x1;
302 float y1;
303
304 float div = a*a - 2*a + b*b + 1;
305
306 if (fabsf(div) < 1e-5)
307 return 0;
308
309 x1 = (a*a*x0 - a*(2*x0+c) + b*b*x0 - b*d + c + x0) / div;
310 y1 = (a*a*y0 - a*(2*y0+d) + b*b*y0 + b*c + d + y0) / div;
311
312 e->rotation_center.x = x1;
313 e->rotation_center.y = y1;
314
315 return 1;
316}
317
318static void set_slots(struct grail_impl *impl,
319 struct grail_frame *frame,
320 const struct utouch_frame *touch)
321{
322 struct grail_element **slots = frame->slots;
323 struct utouch_contact *const *tc = touch->slots;
324 int i, j, n = 0;
325
326 for (i = 0; i < impl->num_touches; i++)
327 set_slot_one(impl, slots[n++], touch, tc[i]);
328
329 for (i = 0; i < impl->num_touches; i++)
330 for (j = i + 1; j < impl->num_touches; j++)
331 set_slot_two(impl, slots[n++], touch, tc[i], tc[j]);
332
333 set_slot_multi(impl, slots[n++], frame, touch);
334}
335
336static void collect_transforms(struct grail_impl *impl,
337 struct grail_frame *frame,
338 const struct utouch_frame *touch)
339{
340 const struct utouch_surface *s = utouch_frame_get_surface(impl->fh);
341 const struct grail_control *ctl = impl->ctl;
342 float d_x = ctl->bar_drag_x * (s->mapped_max_x - s->mapped_min_x);
343 float d_y = ctl->bar_drag_y * (s->mapped_max_y - s->mapped_min_y);
344 float ds2 = ctl->bar_scale * ctl->bar_scale;
345 float dt;
346 int i;
347
348 for (i = 0; i < impl->num_slots; i++) {
349 struct grail_element *s = frame->slots[i];
350
351 if (!s->num_touches)
352 continue;
353
354 set_center_of_rotation(s);
355
356 dt = touch->time - s->start_time;
357 if (dt > ctl->glue_ms) {
358 unsigned int mask = s->active_mask;
359
360 if (fabs(s->drag.x) > d_x)
361 mask |= GRAIL_EXPECT_DRAG_X;
362 if (fabs(s->drag.y) > d_y)
363 mask |= GRAIL_EXPECT_DRAG_Y;
364 if (fabs(s->scale2 - 1) > ds2)
365 mask |= GRAIL_EXPECT_SCALE;
366 if (fabs(s->angle) > ctl->bar_angle)
367 mask |= GRAIL_EXPECT_ANGLE;
368
369 s->active_mask = mask;
370
371 if (dt < ctl->drop_x_ms)
372 mask |= GRAIL_EXPECT_DRAG_X;
373 if (dt < ctl->drop_y_ms)
374 mask |= GRAIL_EXPECT_DRAG_Y;
375 if (dt < ctl->drop_scale_ms)
376 mask |= GRAIL_EXPECT_SCALE;
377 if (dt < ctl->drop_angle_ms)
378 mask |= GRAIL_EXPECT_ANGLE;
379
380 s->expect_mask &= mask;
381 }
382
383 frame->ongoing[frame->num_ongoing++] = s;
384 }
385}
386
387const struct grail_frame GRAIL_PUBLIC *
388grail_pump_frame(grail_handle ge, const struct utouch_frame *touch)
389{
390 struct grail_impl *impl = ge->impl;
391 struct grail_frame *frame = impl->frames[impl->nextframe];
392 const struct grail_frame *prev = frame->prev;
393 int i;
394
395 if (touch->slot_revision == touch->prev->slot_revision &&
396 !prev->num_ongoing)
397 return 0;
398
399 frame->touch = touch;
400 frame->num_ongoing = 0;
401 for (i = 0; i < impl->num_slots; i++)
402 frame->slots[i]->prev = prev->slots[i];
403
404 set_slots(impl, frame, touch);
405 collect_transforms(impl, frame, touch);
406
407 impl->nextframe = (impl->nextframe + 1) % impl->num_frames;
408
409 return frame;
410}
4110
=== removed file 'src/grail-gestures.c'
--- src/grail-gestures.c 2011-10-03 11:14:32 +0000
+++ src/grail-gestures.c 1970-01-01 00:00:00 +0000
@@ -1,219 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#include "grail-recognizer.h"
23#include "grail-impl.h"
24#include <math.h>
25
26/* Units of mm or radians */
27static const float FM_SN[DIM_FM] = { 0.13, 0.13, 0.26, 2 * M_PI / 1000 };
28static const float FM_BAR[DIM_FM] = { 2.6, 2.6, 5.2, 2 * M_PI / 50 };
29
30/* Units of ms */
31static const grail_time_t FM_HOLD_MS[DIM_FM] = { 60, 60, 60, 60 };
32static const grail_time_t FM_BAR_MS[DIM_FM] = { 300, 300, 500, 500 };
33static const grail_time_t SAMPLE_MS = 10;
34
35static const float EPS = 1e-3;
36
37static void compute_position(float *x, float *y,
38 const struct utouch_frame *frame)
39{
40 int i, n = frame->num_active;
41 *x = 0;
42 *y = 0;
43 if (n < 1)
44 return;
45 for (i = 0; i < n; i++) {
46 const struct utouch_contact *t = frame->active[i];
47 *x += t->x;
48 *y += t->y;
49 }
50 *x /= n;
51 *y /= n;
52}
53
54static float compute_radius(float x, float y,
55 const struct utouch_frame *frame)
56{
57 int i, n = frame->num_active;
58 float r = 0, r2 = 0;
59 if (n < 2)
60 return r;
61 for (i = 0; i < n; i++) {
62 const struct utouch_contact *t = frame->active[i];
63 float dx = t->x - x;
64 float dy = t->y - y;
65 r2 += dx * dx + dy * dy;
66 }
67 r2 /= n;
68 r = sqrt(r2);
69 return r;
70}
71
72static float compute_rotation(float x, float y, float r,
73 const struct utouch_frame *frame)
74{
75 int i, n = frame->num_active;
76 float da = 0, darc2 = 0;
77 if (n < 2)
78 return da;
79 for (i = 0; i < n; i++) {
80 const struct utouch_contact *t = frame->active[i];
81 const struct utouch_contact *ot = t->prev;
82 float dx = t->x - x;
83 float dy = t->y - y;
84 float mx = t->x - ot->x;
85 float my = t->y - ot->y;
86 darc2 += dx * my - dy * mx;
87 }
88 darc2 /= n;
89 da = darc2 / (r * r);
90 return da;
91}
92
93static void move_reset(struct move_model *m, int i, float x, grail_time_t t)
94{
95 struct filter_model *fm = &m->fm[i];
96 fm->raw_delta = 0;
97 fm->action_delta = 0;
98 fm->velocity = 0;
99 fm->value = x;
100 fm->original = x;
101 fm->original_ms = t;
102 fm->sample = x;
103 fm->sample_ms = t;
104 m->tickle &= ~(1 << i);
105 m->active &= ~(1 << i);
106 m->timeout &= ~(1 << i);
107}
108
109static void move_update(struct move_model *m, int i, float x, grail_time_t t)
110{
111 struct filter_model *fm = &m->fm[i];
112 float dt = t - fm->sample_ms;
113 fm->raw_delta = x - fm->value;
114 fm->action_delta = fm->raw_delta;
115 fm->value = x;
116 if (dt > SAMPLE_MS) {
117 fm->velocity = (x - fm->sample) / dt;
118 fm->sample = x;
119 fm->sample_ms = t;
120 }
121 if (fabs(fm->raw_delta) > EPS)
122 m->tickle |= (1 << i);
123 else
124 m->tickle &= ~(1 << i);
125 if (m->active & (1 << i))
126 return;
127 fm->action_delta = 0;
128 if (fabs(x - fm->original) > fm->bar) {
129 if (t - fm->original_ms > fm->hold_ms) {
130 m->active |= (1 << i);
131 fm->action_delta = x - fm->original;
132 }
133 } else if (t - fm->original_ms > fm->bar_ms) {
134 m->timeout |= (1 << i);
135 }
136}
137
138void gru_init_motion(struct grail *ge)
139{
140 struct utouch_surface *s = utouch_frame_get_surface(ge->impl->fh);
141 struct gesture_recognizer *gru = ge->gru;
142 struct move_model *m = &gru->move;
143 float U[DIM_FM]; /* Device unit dimensions */
144 float P[DIM_FM]; /* Device physical dimensions */
145 int i;
146 U[FM_X] = s->mapped_max_x - s->mapped_min_x;
147 U[FM_Y] = s->mapped_max_y - s->mapped_min_y;
148 U[FM_R] = sqrt(U[FM_X] * U[FM_X] + U[FM_Y] * U[FM_Y]);
149 U[FM_A] = 2 * M_PI;
150 P[FM_X] = s->phys_width;
151 P[FM_Y] = s->phys_height;
152 P[FM_R] = sqrt(P[FM_X] * P[FM_X] + P[FM_Y] * P[FM_Y]);
153 P[FM_A] = 2 * M_PI;
154 for (i = 0; i < DIM_FM; i++) {
155 m->fm[i].fuzz = U[i] * FM_SN[i] / P[i];
156 m->fm[i].bar = U[i] * FM_BAR[i] / P[i];
157 m->fm[i].hold_ms = FM_HOLD_MS[i];
158 m->fm[i].bar_ms = FM_BAR_MS[i];
159 }
160}
161
162void gru_motion(struct grail *ge,
163 const struct utouch_frame *frame)
164{
165 const struct utouch_surface *s = utouch_frame_get_surface(ge->impl->fh);
166 struct gesture_recognizer *gru = ge->gru;
167 struct move_model *m = &gru->move;
168 grail_time_t t = frame->time;
169 float x, y, r, a;
170
171 compute_position(&x, &y, frame);
172 if (frame->prev->revision != frame->revision) {
173 r = compute_radius(x, y, frame);
174 a = 0;
175 move_reset(m, FM_X, x, t);
176 move_reset(m, FM_Y, y, t);
177 move_reset(m, FM_R, r, t);
178 move_reset(m, FM_A, a, t);
179 m->single = 0;
180 m->multi = 0;
181 } else if (frame->num_active < 2) {
182 r = 0;
183 a = 0;
184 move_update(m, FM_X, x, t);
185 move_update(m, FM_Y, y, t);
186 move_reset(m, FM_R, r, t);
187 move_reset(m, FM_A, a, t);
188 m->single = 1;
189 m->multi = 0;
190 } else {
191 r = compute_radius(x, y, frame);
192 a = m->fm[FM_A].value;
193 if (!s->is_semi_mt)
194 a += compute_rotation(x, y, r, frame);
195 move_update(m, FM_X, x, t);
196 move_update(m, FM_Y, y, t);
197 move_update(m, FM_R, r, t);
198 move_update(m, FM_A, a, t);
199 m->single = 0;
200 m->multi = 1;
201 }
202 m->ntouch = frame->num_active;
203 m->time = t;
204}
205
206void gru_event(struct grail *ge, int gid,
207 const struct move_model *m,
208 const grail_prop_t *prop, int nprop)
209{
210 gin_gid_event(ge, gid, m->fm[FM_X].value, m->fm[FM_Y].value, m->ntouch,
211 prop, nprop, 0);
212}
213
214void gru_end(struct grail *ge, int gid, const struct move_model *m,
215 const grail_prop_t *prop, int nprop)
216{
217 gin_gid_end(ge, gid, m->fm[FM_X].value, m->fm[FM_Y].value, m->ntouch,
218 prop, nprop);
219}
2200
=== removed file 'src/grail-gestures.h'
--- src/grail-gestures.h 2011-05-17 14:15:22 +0000
+++ src/grail-gestures.h 1970-01-01 00:00:00 +0000
@@ -1,115 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#ifndef GRAIL_GESTURES_H
23#define GRAIL_GESTURES_H
24
25#include "grail-inserter.h"
26
27#define PRIO_POINTER 1
28#define PRIO_GESTURE 2
29#define PRIO_ENV 3
30#define PRIO_META 4
31#define PRIO_TAP 5
32
33#define DIM_FM 4
34
35#define FM_X 0
36#define FM_Y 1
37#define FM_R 2
38#define FM_A 3
39
40struct filter_model {
41 float raw_delta;
42 float action_delta;
43 float velocity;
44 float value;
45 float original;
46 float sample;
47 float fuzz;
48 float bar;
49 grail_time_t original_ms;
50 grail_time_t sample_ms;
51 grail_time_t hold_ms;
52 grail_time_t bar_ms;
53};
54
55struct move_model {
56 struct filter_model fm[DIM_FM];
57 int tickle, active, timeout;
58 int single, multi, ntouch;
59 grail_time_t time;
60};
61
62void gru_init_motion(struct grail *ge);
63void gru_motion(struct grail *ge,
64 const struct utouch_frame *frame);
65void gru_event(struct grail *ge, int gid,
66 const struct move_model *move,
67 const grail_prop_t *prop, int nprop);
68void gru_end(struct grail *ge, int gid,
69 const struct move_model *move,
70 const grail_prop_t *prop, int nprop);
71
72struct combo_model {
73 int active, gid;
74 int mintouch, maxtouch;
75 int nprop;
76 grail_prop_t prop[DIM_GRAIL_PROP];
77};
78
79int gru_touch(struct grail *ge,
80 const struct utouch_frame *frame);
81int gru_drag(struct grail *ge,
82 const struct utouch_frame *frame);
83int gru_pinch(struct grail *ge,
84 const struct utouch_frame *frame);
85int gru_rotate(struct grail *ge,
86 const struct utouch_frame *frame);
87
88static inline int out_of_bounds(const struct combo_model *s,
89 const struct move_model *m)
90{
91 return m->ntouch < s->mintouch || m->ntouch > s->maxtouch;
92}
93
94int gru_wintouch(struct grail *ge,
95 const struct utouch_frame *frame);
96int gru_windrag(struct grail *ge,
97 const struct utouch_frame *frame);
98int gru_winpinch(struct grail *ge,
99 const struct utouch_frame *frame);
100int gru_winrotate(struct grail *ge,
101 const struct utouch_frame *frame);
102
103struct tapping_model {
104 grail_time_t start;
105 int mintouch, maxtouch;
106 int active, gid, tap;
107 int nprop;
108 grail_prop_t prop[DIM_GRAIL_PROP];
109};
110
111int gru_tapping(struct grail *ge,
112 const struct utouch_frame *frame);
113
114#endif
115
1160
=== removed file 'src/grail-impl.h'
--- src/grail-impl.h 2011-08-30 15:10:16 +0000
+++ src/grail-impl.h 1970-01-01 00:00:00 +0000
@@ -1,88 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#ifndef GRAIL_IMPL_H
23#define GRAIL_IMPL_H
24
25#define MTDEV_NO_LEGACY_API
26#define GRAIL_NO_LEGACY_API
27
28#include <grail.h>
29#include <utouch/frame-mtdev.h>
30#include "evbuf.h"
31#include "grailbuf.h"
32
33#define DIM_TOUCH 32
34#define DIM_TOUCH_BYTES ((DIM_TOUCH + 7) >> 3)
35#define GRAIL_ID_MAX 0xffff
36
37#define MIN(a, b) ((a) < (b) ? (a) : (b))
38#define MAX(a, b) ((a) > (b) ? (a) : (b))
39
40typedef void *grail_select_callback;
41
42/*
43 * In this implementation, there can be N one-gestures, N (N - 1) / 2
44 * two-gestures, and one global gesture.
45 */
46static inline int get_slot_count(int n)
47{
48 return n + n * (n - 1) / 2 + 1;
49}
50
51int create_grail2(struct grail_impl *x,
52 utouch_frame_handle fh,
53 unsigned int num_frames,
54 void *select,
55 unsigned int version,
56 unsigned int control_size,
57 unsigned int frame_size,
58 unsigned int slot_size);
59
60void destroy_grail2(struct grail_impl *x);
61
62struct grail_impl {
63 struct evemu_device *evemu;
64 struct mtdev *mtdev;
65 utouch_frame_handle fh;
66 const struct utouch_frame *touch;
67 struct evbuf evbuf;
68 struct grailbuf gbuf;
69 int filter_abs;
70 int ongoing;
71 int gesture;
72 FILE *fptest;
73 int fast_fileread;
74 /* new stuff below */
75 struct grail_control *ctl;
76 grail_select_callback select;
77 int num_frames;
78 int num_slots;
79 int num_touches;
80 int nextframe;
81 int seqid;
82 unsigned int control_size;
83 unsigned int frame_size;
84 unsigned int slot_size;
85 struct grail_frame **frames;
86};
87
88#endif
890
=== removed file 'src/grail-init.c'
--- src/grail-init.c 2011-08-31 17:20:48 +0000
+++ src/grail-init.c 1970-01-01 00:00:00 +0000
@@ -1,236 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#include "grail-impl.h"
23#include <stdlib.h>
24#include <string.h>
25#include <math.h>
26
27static struct grail_control *create_control(int size)
28{
29 struct grail_control *c = calloc(1, size);
30
31 if (!c)
32 return 0;
33
34 c->glue_ms = 60;
35 c->bar_drag_x = 0.03;
36 c->bar_drag_y = 0.03;
37 c->bar_scale = 0.3;
38 c->bar_angle = 0.1;
39 c->drop_x_ms = 300;
40 c->drop_y_ms = 300;
41 c->drop_scale_ms = 300;
42 c->drop_angle_ms = 300;
43
44 return c;
45}
46
47static void destroy_slots(struct grail_element **slots, int nslot)
48{
49 int i;
50
51 if (slots) {
52 for (i = nslot - 1; i >= 0; i--)
53 free(slots[i]);
54 free(slots);
55 }
56}
57
58static void destroy_frame(struct grail_frame *frame, int nslot)
59{
60 if (frame) {
61 destroy_slots(frame->slots, nslot);
62 free(frame->ongoing);
63 free(frame);
64 }
65}
66
67static void destroy_frames(struct grail_frame **frames, int nframe, int nslot)
68{
69 int i;
70
71 if (frames) {
72 for (i = nframe - 1; i >= 0; i--)
73 destroy_frame(frames[i], nslot);
74 free(frames);
75 }
76}
77
78static struct grail_element **create_slots(int nslot, int ntouch, int size)
79{
80 struct grail_element **slots;
81 struct grail_element *s;
82 int i;
83
84 slots = calloc(nslot, sizeof(slots[0]));
85 if (!slots)
86 return 0;
87
88 for (i = 0; i < nslot; i++) {
89 s = calloc(1, size + ntouch * sizeof(void *));
90 if (!s)
91 goto out;
92 s->slot = i;
93 s->id = -1;
94 s->touches = (void *)((char *)s + size);
95 slots[i] = s;
96 }
97
98 return slots;
99 out:
100 destroy_slots(slots, nslot);
101 return 0;
102}
103
104static struct grail_frame *create_frame(int nslot, int ntouch,
105 int frame_size, int slot_size)
106{
107 struct grail_frame *frame;
108
109 frame = calloc(1, frame_size);
110 if (!frame)
111 return 0;
112
113 frame->ongoing = calloc(nslot, sizeof(frame->ongoing[0]));
114 frame->slots = create_slots(nslot, ntouch, slot_size);
115 if (!frame->ongoing || !frame->slots)
116 goto out;
117
118 return frame;
119 out:
120 destroy_frame(frame, nslot);
121 return 0;
122}
123
124static struct grail_frame **create_frames(int nframe, int nslot, int ntouch,
125 int frame_size, int slot_size)
126{
127 struct grail_frame **frames;
128 struct grail_frame *f;
129 int i;
130
131 frames = calloc(nframe, sizeof(frames[0]));
132 if (!frames)
133 return 0;
134
135 for (i = 0; i < nframe; i++) {
136 f = create_frame(nslot, ntouch, frame_size, slot_size);
137 if (!f)
138 goto out;
139 frames[i] = f;
140 }
141
142 return frames;
143 out:
144 destroy_frames(frames, nframe, nslot);
145 return 0;
146}
147
148int create_grail2(struct grail_impl *x,
149 utouch_frame_handle fh,
150 unsigned int num_frames,
151 grail_select_callback select,
152 unsigned int version,
153 unsigned int control_size,
154 unsigned int frame_size,
155 unsigned int slot_size)
156{
157 unsigned int ntouch = utouch_frame_get_num_slots(fh);
158 unsigned int nslot = get_slot_count(ntouch);
159 int i;
160
161 x->select = select;
162 x->control_size = MAX(control_size, sizeof(struct grail_control));
163 x->frame_size = MAX(frame_size, sizeof(struct grail_frame));
164 x->slot_size = MAX(slot_size, sizeof(struct grail_element));
165
166 x->num_frames = num_frames;
167 x->num_slots = nslot;
168 x->num_touches = ntouch;
169
170 x->ctl = create_control(x->control_size);
171 if (!x->ctl)
172 goto freemem;
173
174 x->frames = create_frames(num_frames, nslot, ntouch,
175 x->frame_size, x->slot_size);
176 if (!x->frames)
177 goto freemem;
178
179 for (i = 0; i < num_frames; i++)
180 x->frames[(i + 1) % num_frames]->prev = x->frames[i];
181
182 return 0;
183
184 freemem:
185 destroy_grail2(x);
186 return -ENOMEM;
187}
188
189void destroy_grail2(struct grail_impl *x)
190{
191 destroy_frames(x->frames, x->num_frames, x->num_slots);
192 free(x->ctl);
193}
194
195grail_handle GRAIL_PUBLIC grail_new_raw(utouch_frame_handle fh,
196 unsigned int num_frames,
197 grail_select_callback select,
198 unsigned int version,
199 unsigned int control_size,
200 unsigned int frame_size,
201 unsigned int slot_size)
202{
203 struct grail *ge;
204 struct grail_impl *x;
205
206 ge = calloc(1, sizeof(*ge));
207 if (!ge)
208 return 0;
209 x = calloc(1, sizeof(*x));
210 if (!x)
211 goto out;
212 x->fh = fh;
213 if (create_grail2(x, fh, num_frames, select,
214 version, control_size, frame_size, slot_size))
215 goto out;
216
217 ge->impl = x;
218 return ge;
219
220 out:
221 free(x);
222 free(ge);
223 return 0;
224}
225
226void GRAIL_PUBLIC grail_delete(grail_handle ge)
227{
228 destroy_grail2(ge->impl);
229 free(ge->impl);
230 free(ge);
231}
232
233struct grail_control GRAIL_PUBLIC *grail_get_control(grail_handle ge)
234{
235 return ge->impl->ctl;
236}
2370
=== removed file 'src/grail-inserter.c'
--- src/grail-inserter.c 2011-08-31 17:20:48 +0000
+++ src/grail-inserter.c 1970-01-01 00:00:00 +0000
@@ -1,304 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#include "grail-gestures.h"
23#include "grail-inserter.h"
24#include "grail-impl.h"
25#include <malloc.h>
26#include <string.h>
27#include <errno.h>
28#include <math.h>
29
30static const int MAX_GESTURE_ID = 0xfff;
31
32static int find_gslot(const struct gesture_inserter *gin, int gid)
33{
34 int i;
35 grail_mask_foreach(i, gin->used, sizeof(gin->used))
36 if (gin->state[i].id == gid)
37 return i;
38 return -1;
39}
40
41static int mask_overlap(const grail_mask_t *a, const grail_mask_t *b,
42 int bytes)
43{
44 int i;
45
46 for (i = 0; i < bytes; i++)
47 if (a[i] & b[i])
48 return 1;
49
50 return 0;
51}
52
53// todo: spanning tree for multi-user case
54static void setup_new_gestures(struct grail *ge,
55 const struct utouch_frame *frame)
56{
57 struct gesture_inserter *gin = ge->gin;
58 grail_mask_t types[DIM_GRAIL_TYPE_BYTES];
59 grail_mask_t span[DIM_TOUCH_BYTES];
60 struct grail_client_info info[DIM_CLIENT];
61 int i, j, nclient = 0;
62 int nfresh = grail_mask_count(gin->fresh, sizeof(gin->fresh));
63 if (!nfresh)
64 return;
65
66 memset(types, 0, sizeof(types));
67 memset(span, 0, sizeof(span));
68
69 grail_mask_foreach(i, gin->fresh, sizeof(gin->fresh)) {
70 struct slot_state *s = &gin->state[i];
71 grail_mask_set(types, s->type);
72 grail_mask_set_mask(span, s->span, sizeof(span));
73 }
74
75 nclient = gin_get_clients(ge, info, DIM_CLIENT, types, sizeof(types),
76 span, sizeof(span), frame);
77
78 grail_mask_foreach(i, gin->fresh, sizeof(gin->fresh)) {
79 struct slot_state *s = &gin->state[i];
80 s->nclient = 0;
81 for (j = 0; j < nclient; j++) {
82 if (!grail_mask_get(info[j].mask, s->type))
83 continue;
84 if (gin->grab_active &&
85 info[j].id.client != gin->grab_client)
86 continue;
87 if (grail_mask_get(info[j].mask, GRAIL_TYPE_SYSFLAG1)) {
88 gin->grab_active = 1;
89 gin->grab_client = info[j].id.client;
90 }
91 s->client_id[s->nclient++] = info[j].id;
92 }
93 }
94
95 memset(gin->fresh, 0, sizeof(gin->fresh));
96}
97
98int gin_init(struct grail *ge)
99{
100 struct gesture_inserter *gin;
101 int i;
102 gin = calloc(1, sizeof(*gin));
103 if (!gin)
104 return -ENOMEM;
105 for (i = 0; i < DIM_INSTANCE; i++)
106 grail_mask_set(gin->unused, i);
107 ge->gin = gin;
108 return 0;
109}
110
111void gin_destroy(struct grail *ge)
112{
113 free(ge->gin);
114 ge->gin = NULL;
115}
116
117void gin_frame_begin(struct grail *ge, const struct utouch_frame *frame)
118{
119 struct gesture_inserter *gin = ge->gin;
120 memset(gin->types, 0, sizeof(gin->types));
121 gin->time = frame->time;
122 if (frame->num_active && !frame->prev->num_active)
123 gin->grab_active = 0;
124}
125
126void gin_frame_end(struct grail *ge, const struct utouch_frame *frame)
127{
128 struct gesture_inserter *gin = ge->gin;
129 grail_mask_t keep[DIM_TOUCH_BYTES];
130 int i, hold[2] = { 0, 0 }, discard[2] = { 0, 0 };
131
132 memset(keep, 0, sizeof(keep));
133 setup_new_gestures(ge, frame);
134
135 grail_mask_foreach(i, gin->used, sizeof(gin->used)) {
136 struct slot_state *s = &gin->state[i];
137 if (!s->nclient)
138 continue;
139 if (s->priority > hold[s->slice])
140 hold[s->slice] = s->priority;
141 if (s->status != GRAIL_STATUS_UPDATE)
142 continue;
143 if (s->priority > discard[s->slice])
144 discard[s->slice] = s->priority;
145 }
146
147 grail_mask_foreach(i, gin->used, sizeof(gin->used)) {
148 struct slot_state *s = &gin->state[i];
149 if (!s->nclient || (s->priority < discard[s->slice] && !s->sent))
150 gin_gid_discard(ge, s->id);
151 }
152
153 grail_mask_foreach(i, gin->used, sizeof(gin->used)) {
154 struct slot_state *s = &gin->state[i];
155 if (s->slice == 1)
156 grail_mask_set_mask(keep, s->span, sizeof(keep));
157 }
158
159 grail_mask_foreach(i, gin->used, sizeof(gin->used)) {
160 struct slot_state *s = &gin->state[i];
161 if (!s->timeout)
162 continue;
163 if (mask_overlap(keep, s->span, sizeof(keep)))
164 continue;
165 gin_gid_discard(ge, s->id);
166 }
167
168 grail_mask_foreach(i, gin->used, sizeof(gin->used)) {
169 struct slot_state *s = &gin->state[i];
170 struct gesture_event ev;
171 grail_mask_set(gin->types, s->type);
172 if (s->priority < hold[s->slice] && !s->sent)
173 continue;
174 while (!gebuf_empty(&s->buf)) {
175 gebuf_get(&s->buf, &ev);
176 gin_send_event(ge, s, &ev, frame);
177 }
178 s->sent = 1;
179 }
180
181 grail_mask_foreach(i, gin->used, sizeof(gin->used)) {
182 struct slot_state *s = &gin->state[i];
183 if (s->status == GRAIL_STATUS_END)
184 gin_gid_discard(ge, s->id);
185 }
186}
187
188int gin_gid_begin(struct grail *ge, int type, int priority,
189 const struct utouch_frame *frame)
190{
191 struct gesture_inserter *gin = ge->gin;
192 struct slot_state *s;
193 int slot;
194 int i = grail_mask_get_first(gin->unused, sizeof(gin->unused));
195 if (i < 0)
196 return -1;
197 s = &gin->state[i];
198 s->type = type;
199 if (priority < 0) {
200 s->priority = -priority;
201 s->slice = 1;
202 } else {
203 s->priority = priority;
204 s->slice = 0;
205 }
206 s->timeout = 0;
207 s->sent = 0;
208 s->id = gin->gestureid++ & MAX_GESTURE_ID;
209 s->status = GRAIL_STATUS_BEGIN;
210 s->nclient = 0;
211 for (slot = 0; slot < DIM_TOUCH; slot++)
212 grail_mask_modify(s->span, slot, frame->slots[slot]->active);
213 gebuf_clear(&s->buf);
214 grail_mask_clear(gin->unused, i);
215 grail_mask_set(gin->fresh, i);
216 grail_mask_set(gin->used, i);
217 return s->id;
218}
219
220void gin_gid_discard(struct grail *ge, int gid)
221{
222 struct gesture_inserter *gin = ge->gin;
223 struct slot_state *s;
224 int i = find_gslot(gin, gid);
225 if (i < 0)
226 return;
227 s = &gin->state[i];
228 gebuf_clear(&s->buf);
229 s->status = GRAIL_STATUS_END;
230 grail_mask_clear(gin->used, i);
231 grail_mask_set(gin->unused, i);
232}
233
234void gin_gid_timeout(struct grail *ge, int gid)
235{
236 int i = find_gslot(ge->gin, gid);
237 if (i >= 0)
238 ge->gin->state[i].timeout = 1;
239}
240
241void gin_gid_event(struct grail *ge, int gid,
242 float x, float y, int ntouch,
243 const grail_prop_t *prop, int nprop,
244 int transient)
245{
246 struct gesture_inserter *gin = ge->gin;
247 struct gesture_event ev;
248 struct slot_state *s;
249 int i = find_gslot(gin, gid);
250 if (i < 0)
251 return;
252 s = &gin->state[i];
253 ev.status = transient ? GRAIL_STATUS_UPDATE : s->status;
254 ev.ntouch = ntouch;
255 ev.nprop = nprop;
256 ev.time = gin->time;
257 ev.pos.x = x;
258 ev.pos.y = y;
259 memcpy(ev.prop, prop, nprop * sizeof(grail_prop_t));
260 gebuf_put(&s->buf, &ev);
261 if (transient)
262 s->status = GRAIL_STATUS_END;
263 else if (s->status == GRAIL_STATUS_BEGIN)
264 s->status = GRAIL_STATUS_UPDATE;
265}
266
267void gin_gid_end(struct grail *ge, int gid,
268 float x, float y, int ntouch,
269 const grail_prop_t *prop, int nprop)
270{
271 struct gesture_inserter *gin = ge->gin;
272 struct gesture_event ev;
273 struct slot_state *s;
274 int i = find_gslot(gin, gid);
275 if (i < 0)
276 return;
277 s = &gin->state[i];
278 if (s->status != GRAIL_STATUS_BEGIN) {
279 ev.status = GRAIL_STATUS_END;
280 ev.ntouch = ntouch;
281 ev.nprop = nprop;
282 ev.time = gin->time;
283 ev.pos.x = x;
284 ev.pos.y = y;
285 memcpy(ev.prop, prop, nprop * sizeof(grail_prop_t));
286 gebuf_put(&s->buf, &ev);
287 }
288 s->status = GRAIL_STATUS_END;
289}
290
291void GRAIL_PUBLIC grail_set_bbox(struct grail *ge,
292 const struct grail_coord *tmin,
293 const struct grail_coord *tmax)
294{
295 struct utouch_surface *s = utouch_frame_get_surface(ge->impl->fh);
296
297 s->mapped_min_x = tmin->x;
298 s->mapped_min_y = tmin->y;
299 s->mapped_max_x = tmax->x;
300 s->mapped_max_y = tmax->y;
301
302 if (ge->gru)
303 gru_init_motion(ge);
304}
3050
=== removed file 'src/grail-inserter.h'
--- src/grail-inserter.h 2011-05-17 14:15:22 +0000
+++ src/grail-inserter.h 1970-01-01 00:00:00 +0000
@@ -1,93 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#ifndef GRAIL_INSERTER_H
23#define GRAIL_INSERTER_H
24
25#include "grail-impl.h"
26#include "gebuf.h"
27
28#define DIM_EV_TYPE EV_CNT
29#define DIM_EV_TYPE_BYTES ((DIM_EV_TYPE + 7) >> 3)
30
31#define DIM_INSTANCE 32
32#define DIM_INSTANCE_BYTES ((DIM_INSTANCE + 7) >> 3)
33
34#define DIM_CLIENT 32
35
36struct slot_state {
37 int type;
38 int priority;
39 int slice;
40 int timeout;
41 int sent;
42 int id;
43 int status;
44 int nclient;
45 struct grail_client_id client_id[DIM_CLIENT];
46 grail_mask_t span[DIM_TOUCH_BYTES];
47 struct gebuf buf;
48};
49
50struct gesture_inserter {
51 struct slot_state state[DIM_INSTANCE];
52 grail_mask_t types[DIM_GRAIL_TYPE_BYTES];
53 grail_mask_t unused[DIM_INSTANCE_BYTES];
54 grail_mask_t fresh[DIM_INSTANCE_BYTES];
55 grail_mask_t used[DIM_INSTANCE_BYTES];
56 grail_time_t time;
57 int gestureid;
58 int grab_active;
59 int grab_client;
60};
61
62int gin_add_contact_props(const struct gesture_inserter *gin,
63 grail_prop_t *prop, const struct utouch_frame *frame);
64
65int gin_get_clients(struct grail *ge,
66 struct grail_client_info *info, int maxinfo,
67 const grail_mask_t* types, int btypes,
68 const grail_mask_t* span, int bspan,
69 const struct utouch_frame *frame);
70void gin_send_event(struct grail *ge, struct slot_state *s,
71 const struct gesture_event *ev,
72 const struct utouch_frame *frame);
73
74int gin_init(struct grail *ge);
75void gin_destroy(struct grail *ge);
76
77void gin_frame_begin(struct grail *ge, const struct utouch_frame *frame);
78void gin_frame_end(struct grail *ge, const struct utouch_frame *frame);
79
80int gin_gid_begin(struct grail *ge, int type, int priority,
81 const struct utouch_frame *frame);
82void gin_gid_discard(struct grail *ge, int gid);
83void gin_gid_timeout(struct grail *ge, int gid);
84
85void gin_gid_event(struct grail *ge, int gid,
86 float x, float y, int ntouch,
87 const grail_prop_t *prop, int nprop,
88 int transient);
89void gin_gid_end(struct grail *ge, int gid,
90 float x, float y, int ntouch,
91 const grail_prop_t *prop, int nprop);
92
93#endif
940
=== removed file 'src/grail-legacy.c'
--- src/grail-legacy.c 2011-08-31 17:20:48 +0000
+++ src/grail-legacy.c 1970-01-01 00:00:00 +0000
@@ -1,64 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#include <grail.h>
23#include "grail-inserter.h"
24#include <string.h>
25#include <stdio.h>
26#include <unistd.h>
27#include <fcntl.h>
28#include <malloc.h>
29#include <errno.h>
30#include <stdlib.h>
31
32#ifndef GRAIL_NO_LEGACY_ABI
33
34void GRAIL_PUBLIC grail_filter_abs_events(struct grail *ge, int usage)
35{
36 struct grail_impl *x = ge->impl;
37 x->filter_abs = usage;
38}
39
40int GRAIL_PUBLIC grail_get_contacts(const struct grail *ge,
41 struct grail_contact *touch, int max_touch)
42{
43 const struct utouch_frame *frame = ge->impl->touch;
44 int i;
45 if (frame->num_active < max_touch)
46 max_touch = frame->num_active;
47 for (i = 0; i < max_touch; i++) {
48 struct grail_contact *t = &touch[i];
49 const struct utouch_contact *ct = frame->active[i];
50 t->id = ct->id;
51 t->tool_type = ct->tool_type;
52 t->pos.x = ct->x;
53 t->pos.y = ct->y;
54 t->touch_major = ct->touch_major;
55 t->touch_minor = ct->touch_minor;
56 t->width_major = ct->width_major;
57 t->width_minor = ct->width_minor;
58 t->angle = ct->orientation;
59 t->pressure = ct->pressure;
60 }
61 return max_touch;
62}
63
64#endif
650
=== removed file 'src/grail-recognizer.c'
--- src/grail-recognizer.c 2011-04-28 16:53:57 +0000
+++ src/grail-recognizer.c 1970-01-01 00:00:00 +0000
@@ -1,58 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#include "grail-recognizer.h"
23#include <string.h>
24#include <malloc.h>
25#include <errno.h>
26
27int gru_init(struct grail *ge)
28{
29 struct gesture_recognizer *gru;
30 gru = calloc(1, sizeof(struct gesture_recognizer));
31 if (!gru)
32 return -ENOMEM;
33 ge->gru = gru;
34 gru_init_motion(ge);
35 return 0;
36}
37
38void gru_destroy(struct grail *ge)
39{
40 free(ge->gru);
41 ge->gru = NULL;
42}
43
44void gru_recognize(struct grail *ge, const struct utouch_frame *frame)
45{
46 if (!ge->gin || !ge->gru)
47 return;
48 gru_motion(ge, frame);
49 gru_touch(ge, frame);
50 gru_drag(ge, frame);
51 gru_pinch(ge, frame);
52 gru_rotate(ge, frame);
53 gru_wintouch(ge, frame);
54 gru_windrag(ge, frame);
55 gru_winpinch(ge, frame);
56 gru_winrotate(ge, frame);
57 gru_tapping(ge, frame);
58}
590
=== removed file 'src/grail-recognizer.h'
--- src/grail-recognizer.h 2011-05-17 14:15:22 +0000
+++ src/grail-recognizer.h 1970-01-01 00:00:00 +0000
@@ -1,44 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#ifndef GRAIL_RECOGNIZER_H
23#define GRAIL_RECOGNIZER_H
24
25#include "grail-gestures.h"
26
27struct gesture_recognizer {
28 struct move_model move;
29 struct combo_model touch;
30 struct combo_model drag;
31 struct combo_model pinch;
32 struct combo_model rotate;
33 struct combo_model wintouch;
34 struct combo_model windrag;
35 struct combo_model winpinch;
36 struct combo_model winrotate;
37 struct tapping_model tapping;
38};
39
40int gru_init(struct grail *ge);
41void gru_recognize(struct grail *ge, const struct utouch_frame *frame);
42void gru_destroy(struct grail *ge);
43
44#endif
450
=== removed file 'src/grailbuf.h'
--- src/grailbuf.h 2011-05-17 14:15:22 +0000
+++ src/grailbuf.h 1970-01-01 00:00:00 +0000
@@ -1,59 +0,0 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#ifndef GRAIL_BUFFER_H
23#define GRAIL_BUFFER_H
24
25#include <grail.h>
26
27#define DIM_GRAIL_EVENTS 512
28
29struct grailbuf {
30 int head;
31 int tail;
32 struct grail_event buffer[DIM_GRAIL_EVENTS];
33};
34
35static inline void grailbuf_clear(struct grailbuf *buf)
36{
37 buf->head = buf->tail = 0;
38}
39
40static inline int grailbuf_empty(const struct grailbuf *buf)
41{
42 return buf->head == buf->tail;
43}
44
45static inline void grailbuf_put(struct grailbuf *buf,
46 const struct grail_event *ev)
47{
48 buf->buffer[buf->head++] = *ev;
49 buf->head &= DIM_GRAIL_EVENTS - 1;
50}
51
52static inline void grailbuf_get(struct grailbuf *buf,
53 struct grail_event *ev)
54{
55 *ev = buf->buffer[buf->tail++];
56 buf->tail &= DIM_GRAIL_EVENTS - 1;
57}
58
59#endif
600
=== added directory 'src/v2'
=== added file 'src/v2/evbuf.h'
--- src/v2/evbuf.h 1970-01-01 00:00:00 +0000
+++ src/v2/evbuf.h 2012-01-25 15:53:29 +0000
@@ -0,0 +1,57 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#ifndef GRAIL_EVBUF_H
23#define GRAIL_EVBUF_H
24
25#define DIM_EVENTS 4096
26
27struct evbuf {
28 int head;
29 int tail;
30 struct input_event buffer[DIM_EVENTS];
31};
32
33static inline void evbuf_clear(struct evbuf *evbuf)
34{
35 evbuf->head = evbuf->tail = 0;
36}
37
38static inline int evbuf_empty(const struct evbuf *evbuf)
39{
40 return evbuf->head == evbuf->tail;
41}
42
43static inline void evbuf_put(struct evbuf *evbuf,
44 const struct input_event *ev)
45{
46 evbuf->buffer[evbuf->head++] = *ev;
47 evbuf->head &= DIM_EVENTS - 1;
48}
49
50static inline void evbuf_get(struct evbuf *evbuf,
51 struct input_event *ev)
52{
53 *ev = evbuf->buffer[evbuf->tail++];
54 evbuf->tail &= DIM_EVENTS - 1;
55}
56
57#endif
058
=== added file 'src/v2/gebuf.h'
--- src/v2/gebuf.h 1970-01-01 00:00:00 +0000
+++ src/v2/gebuf.h 2012-01-25 15:53:29 +0000
@@ -0,0 +1,68 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#ifndef GRAIL_GESTURE_BUFFER_H
23#define GRAIL_GESTURE_BUFFER_H
24
25#include "grail-impl.h"
26
27#define DIM_GESTURE_EVENTS 512
28
29struct gesture_event {
30 int status;
31 int ntouch;
32 int nprop;
33 utouch_frame_time_t time;
34 struct grail_coord pos;
35 grail_prop_t prop[DIM_GRAIL_PROP];
36};
37
38struct gebuf {
39 int head;
40 int tail;
41 struct gesture_event buffer[DIM_GESTURE_EVENTS];
42};
43
44static inline void gebuf_clear(struct gebuf *gebuf)
45{
46 gebuf->head = gebuf->tail = 0;
47}
48
49static inline int gebuf_empty(const struct gebuf *gebuf)
50{
51 return gebuf->head == gebuf->tail;
52}
53
54static inline void gebuf_put(struct gebuf *gebuf,
55 const struct gesture_event *ev)
56{
57 gebuf->buffer[gebuf->head++] = *ev;
58 gebuf->head &= DIM_GESTURE_EVENTS - 1;
59}
60
61static inline void gebuf_get(struct gebuf *gebuf,
62 struct gesture_event *ev)
63{
64 *ev = gebuf->buffer[gebuf->tail++];
65 gebuf->tail &= DIM_GESTURE_EVENTS - 1;
66}
67
68#endif
069
=== added file 'src/v2/gestures-drag.c'
--- src/v2/gestures-drag.c 1970-01-01 00:00:00 +0000
+++ src/v2/gestures-drag.c 2012-01-25 15:53:29 +0000
@@ -0,0 +1,135 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#include "grail-recognizer.h"
23#include <math.h>
24#include <stdio.h>
25
26static const int getype[DIM_TOUCH + 1] = {
27 -1,
28 GRAIL_TYPE_DRAG1,
29 GRAIL_TYPE_DRAG2,
30 GRAIL_TYPE_DRAG3,
31 GRAIL_TYPE_DRAG4,
32 GRAIL_TYPE_DRAG5,
33};
34
35static void set_props(const struct gesture_inserter *gin,
36 struct combo_model *s, const struct move_model *m,
37 const struct utouch_frame *frame)
38{
39 if (m->single) {
40 s->prop[GRAIL_PROP_DRAG_DX] = m->fm[FM_X].raw_delta;
41 s->prop[GRAIL_PROP_DRAG_DY] = m->fm[FM_Y].raw_delta;
42 } else {
43 s->prop[GRAIL_PROP_DRAG_DX] = m->fm[FM_X].action_delta;
44 s->prop[GRAIL_PROP_DRAG_DY] = m->fm[FM_Y].action_delta;
45 }
46 s->prop[GRAIL_PROP_DRAG_VX] = m->fm[FM_X].velocity;
47 s->prop[GRAIL_PROP_DRAG_VY] = m->fm[FM_Y].velocity;
48 s->prop[GRAIL_PROP_DRAG_X] = m->fm[FM_X].value;
49 s->prop[GRAIL_PROP_DRAG_Y] = m->fm[FM_Y].value;
50 s->nprop = 6;
51 s->nprop += gin_add_contact_props(gin, s->prop + s->nprop, frame);
52}
53
54static const int fm_mask = 0x03;
55
56int gru_drag(struct grail *ge,
57 const struct utouch_frame *frame)
58{
59 struct gesture_recognizer *gru = ge->gru;
60 struct combo_model *state = &gru->drag;
61 struct move_model *move = &gru->move;
62 int mask = state->active ? (move->active & fm_mask) : fm_mask;
63 if (!move->multi && !move->single) {
64 if (state->active) {
65 gru_end(ge, state->gid, move,
66 state->prop, state->nprop);
67 state->active = 0;
68 }
69 }
70 if ((move->timeout & fm_mask) == fm_mask) {
71 if (state->active) {
72 gin_gid_timeout(ge, state->gid);
73 }
74 }
75 if (!state->active) {
76 int type = getype[move->ntouch];
77 if (type < 0)
78 return 0;
79 state->gid = gin_gid_begin(ge, type, PRIO_GESTURE, frame);
80 state->active = 1;
81 }
82 if (!(move->tickle & mask))
83 return 0;
84 if (!(move->active & fm_mask))
85 return 0;
86 set_props(ge->gin, state, move, frame);
87 gru_event(ge, state->gid, move, state->prop, state->nprop);
88 return 1;
89}
90
91int gru_windrag(struct grail *ge,
92 const struct utouch_frame *frame)
93{
94 struct gesture_recognizer *gru = ge->gru;
95 struct combo_model *state = &gru->windrag;
96 struct move_model *move = &gru->move;
97 int mask = state->active ? (move->active & fm_mask) : fm_mask;
98 if (!move->multi && !move->single) {
99 if (state->active && out_of_bounds(state, move)) {
100 gru_end(ge, state->gid, move,
101 state->prop, state->nprop);
102 state->active = 0;
103 }
104 }
105 if ((move->timeout & fm_mask) == fm_mask) {
106 if (state->active) {
107 gin_gid_timeout(ge, state->gid);
108 }
109 }
110 if (!state->active) {
111 if (move->ntouch == 4) {
112 state->gid = gin_gid_begin(ge, GRAIL_TYPE_MDRAG,
113 PRIO_META, frame);
114 state->mintouch = 1;
115 state->maxtouch = 4;
116 state->active = 1;
117 } else if (move->ntouch == 3) {
118 state->gid = gin_gid_begin(ge, GRAIL_TYPE_EDRAG,
119 PRIO_ENV, frame);
120 state->mintouch = 1;
121 state->maxtouch = 3;
122 state->active = 1;
123 } else {
124 return 0;
125 }
126 }
127 if (!(move->tickle & mask))
128 return 0;
129 if (!(move->active & fm_mask))
130 return 0;
131 set_props(ge->gin, state, move, frame);
132 gru_event(ge, state->gid, move, state->prop, state->nprop);
133 return 1;
134}
135
0136
=== added file 'src/v2/gestures-pinch.c'
--- src/v2/gestures-pinch.c 1970-01-01 00:00:00 +0000
+++ src/v2/gestures-pinch.c 2012-01-25 15:53:29 +0000
@@ -0,0 +1,131 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#include "grail-recognizer.h"
23#include <math.h>
24#include <stdio.h>
25
26static const int getype[DIM_TOUCH + 1] = {
27 0,
28 0,
29 GRAIL_TYPE_PINCH2,
30 GRAIL_TYPE_PINCH3,
31 GRAIL_TYPE_PINCH4,
32 GRAIL_TYPE_PINCH5,
33};
34
35static const int fm_mask = 0x04;
36
37static void set_props(const struct gesture_inserter *gin,
38 struct combo_model *s,
39 const struct move_model *m,
40 const struct utouch_frame *frame)
41{
42 s->prop[GRAIL_PROP_PINCH_DR] = m->fm[FM_R].action_delta;
43 s->prop[GRAIL_PROP_PINCH_VR] = m->fm[FM_R].velocity;
44 s->prop[GRAIL_PROP_PINCH_R] = m->fm[FM_R].value;
45 s->prop[GRAIL_PROP_PINCH_X] = m->fm[FM_X].value;
46 s->prop[GRAIL_PROP_PINCH_Y] = m->fm[FM_Y].value;
47 s->nprop = 5;
48 s->nprop += gin_add_contact_props(gin, s->prop + s->nprop, frame);
49}
50
51int gru_pinch(struct grail *ge,
52 const struct utouch_frame *frame)
53{
54 struct gesture_recognizer *gru = ge->gru;
55 struct combo_model *state = &gru->pinch;
56 struct move_model *move = &gru->move;
57 int mask = state->active ? (move->active & fm_mask) : fm_mask;
58 if (!move->multi && !move->single) {
59 if (state->active) {
60 gru_end(ge, state->gid, move,
61 state->prop, state->nprop);
62 state->active = 0;
63 }
64 return 0;
65 }
66 if ((move->timeout & fm_mask) == fm_mask) {
67 if (state->active) {
68 gin_gid_timeout(ge, state->gid);
69 }
70 }
71 if (!(move->tickle & mask))
72 return 0;
73 if (!state->active) {
74 int type = getype[move->ntouch];
75 if (!type)
76 return 0;
77 state->gid = gin_gid_begin(ge, type, PRIO_GESTURE, frame);
78 state->active = 1;
79 }
80 if (!(move->active & fm_mask))
81 return 0;
82 set_props(ge->gin, state, move, frame);
83 gru_event(ge, state->gid, move, state->prop, state->nprop);
84 return 1;
85}
86
87int gru_winpinch(struct grail *ge,
88 const struct utouch_frame *frame)
89{
90 struct gesture_recognizer *gru = ge->gru;
91 struct combo_model *state = &gru->winpinch;
92 struct move_model *move = &gru->move;
93 int mask = state->active ? (move->active & fm_mask) : fm_mask;
94 if (!move->multi) {
95 if (state->active && out_of_bounds(state, move)) {
96 gru_end(ge, state->gid, move,
97 state->prop, state->nprop);
98 state->active = 0;
99 }
100 return 0;
101 }
102 if ((move->timeout & fm_mask) == fm_mask) {
103 if (state->active) {
104 gin_gid_timeout(ge, state->gid);
105 }
106 }
107 if (!(move->tickle & mask))
108 return 0;
109 if (!state->active) {
110 if (move->ntouch == 4) {
111 state->gid = gin_gid_begin(ge, GRAIL_TYPE_MPINCH,
112 PRIO_META, frame);
113 state->mintouch = 2;
114 state->maxtouch = 4;
115 state->active = 1;
116 } else if (move->ntouch == 3) {
117 state->gid = gin_gid_begin(ge, GRAIL_TYPE_EPINCH,
118 PRIO_ENV, frame);
119 state->mintouch = 2;
120 state->maxtouch = 3;
121 state->active = 1;
122 } else {
123 return 0;
124 }
125 }
126 if (!(move->active & fm_mask))
127 return 0;
128 set_props(ge->gin, state, move, frame);
129 gru_event(ge, state->gid, move, state->prop, state->nprop);
130 return 1;
131}
0132
=== added file 'src/v2/gestures-rotate.c'
--- src/v2/gestures-rotate.c 1970-01-01 00:00:00 +0000
+++ src/v2/gestures-rotate.c 2012-01-25 15:53:29 +0000
@@ -0,0 +1,130 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#include "grail-recognizer.h"
23#include <math.h>
24#include <stdio.h>
25
26static const int getype[DIM_TOUCH + 1] = {
27 0,
28 0,
29 GRAIL_TYPE_ROTATE2,
30 GRAIL_TYPE_ROTATE3,
31 GRAIL_TYPE_ROTATE4,
32 GRAIL_TYPE_ROTATE5,
33};
34
35static const int fm_mask = 0x08;
36
37static void set_props(const struct gesture_inserter *gin,
38 struct combo_model *s, const struct move_model *m,
39 const struct utouch_frame *frame)
40{
41 s->prop[GRAIL_PROP_ROTATE_DA] = m->fm[FM_A].action_delta;
42 s->prop[GRAIL_PROP_ROTATE_VA] = m->fm[FM_A].velocity;
43 s->prop[GRAIL_PROP_ROTATE_A] = m->fm[FM_A].value;
44 s->prop[GRAIL_PROP_ROTATE_X] = m->fm[FM_X].value;
45 s->prop[GRAIL_PROP_ROTATE_Y] = m->fm[FM_Y].value;
46 s->nprop = 5;
47 s->nprop += gin_add_contact_props(gin, s->prop + s->nprop, frame);
48}
49
50int gru_rotate(struct grail *ge,
51 const struct utouch_frame *frame)
52{
53 struct gesture_recognizer *gru = ge->gru;
54 struct combo_model *state = &gru->rotate;
55 struct move_model *move = &gru->move;
56 int mask = state->active ? (move->active & fm_mask) : fm_mask;
57 if (!move->multi && !move->single) {
58 if (state->active) {
59 gru_end(ge, state->gid, move,
60 state->prop, state->nprop);
61 state->active = 0;
62 }
63 return 0;
64 }
65 if ((move->timeout & fm_mask) == fm_mask) {
66 if (state->active) {
67 gin_gid_timeout(ge, state->gid);
68 }
69 }
70 if (!(move->tickle & mask))
71 return 0;
72 if (!state->active) {
73 int type = getype[move->ntouch];
74 if (!type)
75 return 0;
76 state->gid = gin_gid_begin(ge, type, PRIO_GESTURE, frame);
77 state->active = 1;
78 }
79 if (!(move->active & fm_mask))
80 return 0;
81 set_props(ge->gin, state, move, frame);
82 gru_event(ge, state->gid, move, state->prop, state->nprop);
83 return 1;
84}
85
86int gru_winrotate(struct grail *ge,
87 const struct utouch_frame *frame)
88{
89 struct gesture_recognizer *gru = ge->gru;
90 struct combo_model *state = &gru->winrotate;
91 struct move_model *move = &gru->move;
92 int mask = state->active ? (move->active & fm_mask) : fm_mask;
93 if (!move->multi) {
94 if (state->active && out_of_bounds(state, move)) {
95 gru_end(ge, state->gid, move,
96 state->prop, state->nprop);
97 state->active = 0;
98 }
99 return 0;
100 }
101 if ((move->timeout & fm_mask) == fm_mask) {
102 if (state->active) {
103 gin_gid_timeout(ge, state->gid);
104 }
105 }
106 if (!(move->tickle & mask))
107 return 0;
108 if (!state->active) {
109 if (move->ntouch == 4) {
110 state->gid = gin_gid_begin(ge, GRAIL_TYPE_MROTATE,
111 PRIO_META, frame);
112 state->mintouch = 2;
113 state->maxtouch = 4;
114 state->active = 1;
115 } else if (move->ntouch == 3) {
116 state->gid = gin_gid_begin(ge, GRAIL_TYPE_EROTATE,
117 PRIO_ENV, frame);
118 state->mintouch = 2;
119 state->maxtouch = 3;
120 state->active = 1;
121 } else {
122 return 0;
123 }
124 }
125 if (!(move->active & fm_mask))
126 return 0;
127 set_props(ge->gin, state, move, frame);
128 gru_event(ge, state->gid, move, state->prop, state->nprop);
129 return 1;
130}
0131
=== added file 'src/v2/gestures-tapping.c'
--- src/v2/gestures-tapping.c 1970-01-01 00:00:00 +0000
+++ src/v2/gestures-tapping.c 2012-01-25 15:53:29 +0000
@@ -0,0 +1,100 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#include "grail-recognizer.h"
23#include <math.h>
24
25static const int fm_mask = 0x07;
26
27static void set_props(const struct gesture_inserter *gin,
28 struct tapping_model *s, const struct move_model *m,
29 const struct utouch_frame *frame)
30{
31 s->prop[GRAIL_PROP_TAP_DT] = m->time - s->start;
32 s->prop[GRAIL_PROP_TAP_X] = m->fm[FM_X].value;
33 s->prop[GRAIL_PROP_TAP_Y] = m->fm[FM_Y].value;
34 s->nprop = 3;
35 s->nprop += gin_add_contact_props(gin, s->prop + s->nprop, frame);
36}
37
38int gru_tapping(struct grail *ge,
39 const struct utouch_frame *frame)
40{
41 struct gesture_recognizer *gru = ge->gru;
42 struct tapping_model *state = &gru->tapping;
43 struct move_model *move = &gru->move;
44 state->tap = 0;
45 if (frame->num_active && !frame->prev->num_active) {
46 state->mintouch = 0;
47 state->maxtouch = 0;
48 }
49 if (move->ntouch > state->maxtouch) {
50 if (state->active) {
51 gin_gid_discard(ge, state->gid);
52 state->active = 0;
53 }
54 state->start = move->time;
55 state->maxtouch = move->ntouch;
56 set_props(ge->gin, state, move, frame);
57 if (state->maxtouch <= 5) {
58 int type = GRAIL_TYPE_TAP1 + state->maxtouch - 1;
59 state->gid = gin_gid_begin(ge, type, PRIO_TAP, frame);
60 state->active = 1;
61 }
62 return 0;
63 }
64 if (!state->active) {
65 state->mintouch = move->ntouch;
66 state->maxtouch = move->ntouch;
67 return 0;
68 }
69 if (move->ntouch <= state->mintouch) {
70 int x = state->prop[GRAIL_PROP_TAP_X];
71 int y = state->prop[GRAIL_PROP_TAP_Y];
72 int t = move->time - state->start;
73 if (t > move->fm[FM_X].bar_ms) {
74 gin_gid_discard(ge, state->gid);
75 state->mintouch = move->ntouch;
76 state->maxtouch = move->ntouch;
77 state->active = 0;
78 return 0;
79 }
80 state->tap = state->maxtouch;
81 state->prop[GRAIL_PROP_TAP_DT] = t;
82 gin_gid_event(ge, state->gid, x, y, state->maxtouch,
83 state->prop, state->nprop, 1);
84 state->mintouch = move->ntouch;
85 state->maxtouch = move->ntouch;
86 state->active = 0;
87 return 1;
88 }
89 if (!move->ntouch)
90 return 0;
91 state->prop[GRAIL_PROP_TAP_DT] = move->time - state->start;
92 if ((move->active & fm_mask) ||
93 move->time - state->start > move->fm[FM_X].bar_ms) {
94 gin_gid_discard(ge, state->gid);
95 state->mintouch = move->ntouch;
96 state->maxtouch = move->ntouch;
97 state->active = 0;
98 }
99 return 0;
100}
0101
=== added file 'src/v2/gestures-touch.c'
--- src/v2/gestures-touch.c 1970-01-01 00:00:00 +0000
+++ src/v2/gestures-touch.c 2012-01-25 15:53:29 +0000
@@ -0,0 +1,98 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 * Copyright (C) 2010 Henrik Rydberg <rydberg@bitmath.org>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 ****************************************************************************/
22
23#include "grail-recognizer.h"
24#include <math.h>
25#include <stdio.h>
26
27static const int getype[DIM_TOUCH + 1] = {
28 -1,
29 GRAIL_TYPE_TOUCH1,
30 GRAIL_TYPE_TOUCH2,
31 GRAIL_TYPE_TOUCH3,
32 GRAIL_TYPE_TOUCH4,
33 GRAIL_TYPE_TOUCH5,
34};
35
36int gru_touch(struct grail *ge,
37 const struct utouch_frame *frame)
38{
39 struct gesture_recognizer *gru = ge->gru;
40 struct combo_model *state = &gru->touch;
41 struct move_model *move = &gru->move;
42 if (frame->slot_revision != frame->prev->slot_revision) {
43 if (state->active) {
44 gru_end(ge, state->gid, move,
45 state->prop, state->nprop);
46 state->active = 0;
47 }
48 }
49 if (!state->active) {
50 int type = getype[move->ntouch];
51 if (type <= 0)
52 return 0;
53 state->gid = gin_gid_begin(ge, type, -PRIO_GESTURE, frame);
54 state->active = 1;
55 }
56 if (move->time - move->fm[FM_X].original_ms <= move->fm[FM_X].hold_ms)
57 return 0;
58 state->nprop = gin_add_contact_props(ge->gin, state->prop, frame);
59 gru_event(ge, state->gid, move, state->prop, state->nprop);
60 return 1;
61}
62
63int gru_wintouch(struct grail *ge,
64 const struct utouch_frame *frame)
65{
66 struct gesture_recognizer *gru = ge->gru;
67 struct combo_model *state = &gru->wintouch;
68 struct move_model *move = &gru->move;
69 if (frame->slot_revision != frame->prev->slot_revision) {
70 if (state->active && out_of_bounds(state, move)) {
71 gru_end(ge, state->gid, move,
72 state->prop, state->nprop);
73 state->active = 0;
74 }
75 }
76 if (!state->active) {
77 if (move->ntouch == 4) {
78 state->gid = gin_gid_begin(ge, GRAIL_TYPE_MTOUCH,
79 -PRIO_META, frame);
80 state->mintouch = 1;
81 state->maxtouch = 4;
82 state->active = 1;
83 } else if (move->ntouch == 3) {
84 state->gid = gin_gid_begin(ge, GRAIL_TYPE_ETOUCH,
85 -PRIO_ENV, frame);
86 state->mintouch = 1;
87 state->maxtouch = 3;
88 state->active = 1;
89 } else {
90 return 0;
91 }
92 }
93 if (move->time - move->fm[FM_X].original_ms <= move->fm[FM_X].hold_ms)
94 return 0;
95 state->nprop = gin_add_contact_props(ge->gin, state->prop, frame);
96 gru_event(ge, state->gid, move, state->prop, state->nprop);
97 return 1;
98}
099
=== added file 'src/v2/grail-api.c'
--- src/v2/grail-api.c 1970-01-01 00:00:00 +0000
+++ src/v2/grail-api.c 2012-01-25 15:53:29 +0000
@@ -0,0 +1,328 @@
1/*****************************************************************************
2 *
3 * grail - Gesture Recognition And Instantiation Library
4 *
5 * Copyright (C) 2010-2011 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22#include "grail-impl.h"
23#include "grail-inserter.h"
24#include "grail-recognizer.h"
25#include <string.h>
26#include <stdio.h>
27#include <unistd.h>
28#include <fcntl.h>
29#include <malloc.h>
30#include <errno.h>
31#include <stdlib.h>
32#include <sys/stat.h>
33
34#define DIM_FRAMES 100
35#define FRAME_RATE 100
36
37unsigned int GRAIL_PUBLIC grail_get_version(void)
38{
39 return GRAIL_VERSION;
40}
41
42int GRAIL_PUBLIC grail_open(struct grail *ge, int fd)
43{
44 struct grail_impl *x;
45 struct stat fs;
46 int ret;
47
48 ret = fstat(fd, &fs);
49 if (ret)
50 return ret;
51
52 x = calloc(1, sizeof(*x));
53 if (!x)
54 return -ENOMEM;
55
56 if (!fs.st_rdev)
57 x->fptest = fdopen(fd, "r");
58
59 x->evemu = evemu_new(x->fptest ? "fptest" : 0);
60 if (!x->evemu) {
61 ret = -ENOMEM;
62 goto freemem;
63 }
64 if (x->fptest)
65 ret = evemu_read(x->evemu, x->fptest) <= 0;
66 else
67 ret = evemu_extract(x->evemu, fd);
68 if (ret)
69 goto freemem;
70 if (!utouch_frame_is_supported_mtdev(x->evemu)) {
71 ret = -ENODEV;
72 goto freemem;
73 }
74
75 if (!x->fptest) {
76 x->mtdev = mtdev_new_open(fd);
77 if (!x->mtdev) {
78 ret = -ENOMEM;
79 goto freemem;
80 }
81 }
82 x->fh = utouch_frame_new_engine(DIM_FRAMES, DIM_TOUCH, FRAME_RATE);
83 if (!x->fh) {
84 ret = -ENOMEM;
85 goto freedev;
86 }
87 ret = utouch_frame_init_mtdev(x->fh, x->evemu);
88 if (ret)
89 goto freeframe;
90
91 ge->impl = x;
92
93 ret = gin_init(ge);
94 if (ret)
95 goto freeframe;
96
97 ret = gru_init(ge);
98 if (ret)
99 goto freegin;
100
101 return 0;
102 freegin:
103 gin_destroy(ge);
104 freeframe:
105 utouch_frame_delete_engine(x->fh);
106 freedev:
107 if (x->mtdev)
108 mtdev_close_delete(x->mtdev);
109 freemem:
110 evemu_delete(x->evemu);
111 if (x->fptest)
112 fclose(x->fptest);
113 free(x);
114 ge->impl = 0;
115 return ret;
116}
117
118void GRAIL_PUBLIC grail_close(struct grail *ge, int fd)
119{
120 struct grail_impl *x = ge->impl;
121 gru_destroy(ge);
122 gin_destroy(ge);
123 utouch_frame_delete_engine(x->fh);
124 if (x->mtdev)
125 mtdev_close_delete(x->mtdev);
126 evemu_delete(x->evemu);
127 if (x->fptest)
128 fclose(x->fptest);
129 free(x);
130 ge->impl = 0;
131}
132
133int GRAIL_PUBLIC grail_idle(struct grail *ge, int fd, int ms)
134{
135 struct grail_impl *x = ge->impl;
136 if (x->fptest)
137 return 0;
138 if (x->mtdev)
139 return mtdev_idle(x->mtdev, fd, ms);
140 return 1;
141}
142
143void GRAIL_PUBLIC grail_get_units(const struct grail *ge,
144 struct grail_coord *min, struct grail_coord *max)
145{
146 struct utouch_surface *s = utouch_frame_get_surface(ge->impl->fh);
147 min->x = s->min_x;
148 min->y = s->min_y;
149 max->x = s->max_x;
150 max->y = s->max_y;
151}
152
153const struct utouch_frame GRAIL_PUBLIC *
154grail_get_contact_frame(const struct grail *ge)
155{
156 return ge->impl->touch;
157}
158
159static void flush_events(struct grail *ge)
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches