Merge lp:~oif-team/grail/trunk.fixes into lp:grail

Proposed by Henrik Rydberg
Status: Superseded
Proposed branch: lp:~oif-team/grail/trunk.fixes
Merge into: lp:grail
Diff against target: 562 lines (+151/-197)
11 files modified
src/evbuf.h (+1/-1)
src/gestures-drag.c (+14/-0)
src/gestures-pinch.c (+14/-0)
src/gestures-rotate.c (+14/-0)
src/gestures-tapping.c (+2/-0)
src/grail-api.c (+86/-162)
src/grail-event.c (+2/-16)
src/grail-gestures.c (+14/-7)
src/grail-gestures.h (+2/-1)
src/grail-impl.h (+2/-0)
src/grail-recognizer.h (+0/-10)
To merge this branch: bzr merge lp:~oif-team/grail/trunk.fixes
Reviewer Review Type Date Requested Status
Chase Douglas (community) Needs Fixing
Stephen M. Webb (community) Approve
Review via email: mp+51127@code.launchpad.net

This proposal has been superseded by a proposal from 2011-02-24.

Description of the change

A bunch of patches aiming to integrate the ideas of v1.0.19 more seamlessly into the grail code. This will fix the remaining tap bug and help further development. The only part not addressed by this branch is the sysflag, and a discussion around it is likely enough to see how to form a patch for it.

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

A more elegant and nuanced way of handling the various timeout issues. Compiles and runs OK.

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

In line 371 of the patch below, there's an ambiguity in the if statement "if (a || b && c)". This should be cleaned up.

I need to test this branch, but I think the changes look reasonable. However, I can't approve the request until it also handles the global flag. This is something I think we will really need in natty, since we're going to have more applications using gestures.

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

Test results:

1. Regression: If you use a physical trackpad button to click while there's no movement on the trackpad, it's held up until a movement is performed.

2. Timeouts seem ok. I was able to request all 3, 4, and 5 finger gestures and still perform two finger multitouch reasonably. I will perform more thorough testing when the regressions are resolved.

3. Regression: I often get a tap event at the end of a drag gesture sequence. The tap touch count matches the drag touch count.

review: Needs Fixing
Revision history for this message
Henrik Rydberg (rydberg) wrote :

Thank you very much for the tests! I have updated the branch with fixes for
the two problems found. I will add something for the global flag shortly.

lp:~oif-team/grail/trunk.fixes updated
115. By Henrik Rydberg

Revert "Add button passthrough"

116. By Henrik Rydberg

Revert "Add global vs local gesture handling"

117. By Henrik Rydberg

Introduce gesture timeouts

The timeout of a gesture is integral to the gesture type.
This patch introduces timeout per gesture type, potentially
enabling more control over gesture timing aspects. The timeout
logic replaces the recently added recognition state.

118. By Henrik Rydberg

Introduce activation hold time

Do not activate a drag, pinch or rotate immediately, even
if the activation threshold is met. This allows for a smoother
transition between fingers.

119. By Henrik Rydberg

Wait for the right number of fingers before gesture timeout

A client listening only for multi-finger gestures will not get
the chance to recognize unless there is a gesture timeout. This
patch waits until the drag hold time has passed before releasing
the touch.

120. By Henrik Rydberg

Skip events selectively

Buffer all events as planned, but strip the stream of all events
involved with pointer and MT, rather than bluntly removing all
events. In practise, this means button and switch events are let
through, undistorted although possibly slightly delayed.

121. By Henrik Rydberg

Adjust gesture buffer sizes and timings

Adjust timings to put drag, pinch and rotate on more equal footing,
with regard to gesture timeouts. Also make sure events are not lost
during hold, now that all MT events are buffered as well.

122. By Henrik Rydberg

Reset tap state after timeout

A touch and hold will not properly reset the tap state, such that
the next tap fails to register. Fixed with this patch.

123. By Henrik Rydberg

Remove unused tapping state

This patch removes some cruft that was left over from the
removal of the short tap time logic.

124. By Henrik Rydberg

Make reset logic of pinch and drag same as for drag

There is no direct reason for one-fingered pinch/rotate gestures
to be discarded immediately, so only reset gestures on touch down,
as for drags.

125. By Henrik Rydberg

Make grabbing client exclusive

When a possible gesture is started for a global client (sysflag set),
it is desirable that gestures to other clients are disregarded until
all contacts have left the surface. In principle this could be refined
further, such that if gesture are not detected, they are passed on to
other clients, but that also affects how touches are passed onto lower
layers like XI2.1, so simply making sure a global system client gets
all events potentially leading to gestures is good enough for now.

Also note that in the current combination of synaptics/evdev X servers
and grail, there can be no overlapping potential gestures between two
global clients, or the resulting event recipient is not correct.

126. By Henrik Rydberg

Bump to v1.0.20

127. By Henrik Rydberg

Disable rotation gestures for semi-mt devices

To avoid poor user experience with semi-mt devices, disable
rotation detection, such that only drag and scale is emitted.

Signed-off-by: Chase Douglas <email address hidden>
Signed-off-by: Henrik Rydberg <email address hidden>

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/evbuf.h'
--- src/evbuf.h 2010-08-06 20:30:20 +0000
+++ src/evbuf.h 2011-02-24 13:47:05 +0000
@@ -29,7 +29,7 @@
29#ifndef GRAIL_EVBUF_H29#ifndef GRAIL_EVBUF_H
30#define GRAIL_EVBUF_H30#define GRAIL_EVBUF_H
3131
32#define DIM_EVENTS 51232#define DIM_EVENTS 4096
3333
34struct evbuf {34struct evbuf {
35 int head;35 int head;
3636
=== modified file 'src/gestures-drag.c'
--- src/gestures-drag.c 2011-01-02 12:08:08 +0000
+++ src/gestures-drag.c 2011-02-24 13:47:05 +0000
@@ -72,6 +72,13 @@
72 state->active = 0;72 state->active = 0;
73 }73 }
74 }74 }
75 if ((move->timeout & fm_mask) == fm_mask) {
76 if (state->active) {
77 gin_gid_discard(ge, state->gid);
78 state->active = 0;
79 }
80 return 0;
81 }
75 if (!state->active) {82 if (!state->active) {
76 int type = getype[move->ntouch];83 int type = getype[move->ntouch];
77 if (type < 0)84 if (type < 0)
@@ -102,6 +109,13 @@
102 state->active = 0;109 state->active = 0;
103 }110 }
104 }111 }
112 if ((move->timeout & fm_mask) == fm_mask) {
113 if (state->active) {
114 gin_gid_discard(ge, state->gid);
115 state->active = 0;
116 }
117 return 0;
118 }
105 if (!state->active) {119 if (!state->active) {
106 if (move->ntouch == 4) {120 if (move->ntouch == 4) {
107 state->gid = gin_gid_begin(ge, GRAIL_TYPE_MDRAG,121 state->gid = gin_gid_begin(ge, GRAIL_TYPE_MDRAG,
108122
=== modified file 'src/gestures-pinch.c'
--- src/gestures-pinch.c 2011-01-02 12:08:08 +0000
+++ src/gestures-pinch.c 2011-02-24 13:47:05 +0000
@@ -62,6 +62,13 @@
62 }62 }
63 return 0;63 return 0;
64 }64 }
65 if ((move->timeout & fm_mask) == fm_mask) {
66 if (state->active) {
67 gin_gid_discard(ge, state->gid);
68 state->active = 0;
69 }
70 return 0;
71 }
65 if (!(move->tickle & mask))72 if (!(move->tickle & mask))
66 return 0;73 return 0;
67 if (!state->active) {74 if (!state->active) {
@@ -93,6 +100,13 @@
93 }100 }
94 return 0;101 return 0;
95 }102 }
103 if ((move->timeout & fm_mask) == fm_mask) {
104 if (state->active) {
105 gin_gid_discard(ge, state->gid);
106 state->active = 0;
107 }
108 return 0;
109 }
96 if (!(move->tickle & mask))110 if (!(move->tickle & mask))
97 return 0;111 return 0;
98 if (!state->active) {112 if (!state->active) {
99113
=== modified file 'src/gestures-rotate.c'
--- src/gestures-rotate.c 2011-01-02 12:08:08 +0000
+++ src/gestures-rotate.c 2011-02-24 13:47:05 +0000
@@ -61,6 +61,13 @@
61 }61 }
62 return 0;62 return 0;
63 }63 }
64 if ((move->timeout & fm_mask) == fm_mask) {
65 if (state->active) {
66 gin_gid_discard(ge, state->gid);
67 state->active = 0;
68 }
69 return 0;
70 }
64 if (!(move->tickle & mask))71 if (!(move->tickle & mask))
65 return 0;72 return 0;
66 if (!state->active) {73 if (!state->active) {
@@ -92,6 +99,13 @@
92 }99 }
93 return 0;100 return 0;
94 }101 }
102 if ((move->timeout & fm_mask) == fm_mask) {
103 if (state->active) {
104 gin_gid_discard(ge, state->gid);
105 state->active = 0;
106 }
107 return 0;
108 }
95 if (!(move->tickle & mask))109 if (!(move->tickle & mask))
96 return 0;110 return 0;
97 if (!state->active) {111 if (!state->active) {
98112
=== modified file 'src/gestures-tapping.c'
--- src/gestures-tapping.c 2011-02-09 15:17:50 +0000
+++ src/gestures-tapping.c 2011-02-24 13:47:05 +0000
@@ -91,6 +91,8 @@
91 if ((move->active & fm_mask) ||91 if ((move->active & fm_mask) ||
92 move->time - state->start > move->fm[FM_X].bar_ms) {92 move->time - state->start > move->fm[FM_X].bar_ms) {
93 gin_gid_discard(ge, state->gid);93 gin_gid_discard(ge, state->gid);
94 state->mintouch = 0;
95 state->maxtouch = 0;
94 state->active = 0;96 state->active = 0;
95 }97 }
96 return 0;98 return 0;
9799
=== modified file 'src/grail-api.c'
--- src/grail-api.c 2011-02-21 01:22:08 +0000
+++ src/grail-api.c 2011-02-24 13:47:05 +0000
@@ -34,11 +34,6 @@
34#define DIM_FRAMES 10034#define DIM_FRAMES 100
35#define FRAME_RATE 10035#define FRAME_RATE 100
3636
37/* Wait time (ms) for number of touches to stabilize. */
38static const unsigned int stable_time = 50;
39/* Maximum time (ms) for gesture to be recognized. */
40static const unsigned int recognition_time = 300;
41
42void grail_filter_abs_events(struct grail *ge, int usage)37void grail_filter_abs_events(struct grail *ge, int usage)
43{38{
44 struct grail_impl *x = ge->impl;39 struct grail_impl *x = ge->impl;
@@ -132,159 +127,103 @@
132 max->y = s->max_y;127 max->y = s->max_y;
133}128}
134129
135/* Check for any potential gestures given the number of touch points and where130static void flush_events(struct grail *ge)
136 * they occur on screen. */131{
137static int check_potential_gestures(struct grail *ge,132 struct grail_impl *impl = ge->impl;
138 const struct utouch_frame *frame)133 struct input_event iev;
139{134
140 grail_mask_t types[DIM_GRAIL_TYPE_BYTES] = {0};135 grailbuf_clear(&impl->gbuf);
141 struct grail_client_info client;136 while (!evbuf_empty(&impl->evbuf)) {
142 struct grail_coord pos[frame->num_active];137 evbuf_get(&impl->evbuf, &iev);
143 int i;138 if (ge->event)
144139 ge->event(ge, &iev);
145 switch (frame->num_active) {140 }
146 case 1:141}
147 grail_mask_set(types, GRAIL_TYPE_DRAG1);142
148 grail_mask_set(types, GRAIL_TYPE_PINCH1);143static int skip_event(const struct input_event *ev, int count)
149 grail_mask_set(types, GRAIL_TYPE_ROTATE1);144{
150 grail_mask_set(types, GRAIL_TYPE_TAP1);145 switch (ev->type) {
151 break;146 case EV_ABS:
152 case 2:147 return 1;
153 grail_mask_set(types, GRAIL_TYPE_DRAG2);148 case EV_KEY:
154 grail_mask_set(types, GRAIL_TYPE_PINCH2);149 return ev->code >= BTN_DIGI && ev->code < BTN_WHEEL;
155 grail_mask_set(types, GRAIL_TYPE_ROTATE2);150 case EV_SYN:
156 grail_mask_set(types, GRAIL_TYPE_TAP2);151 switch (ev->code) {
157 break;152 case SYN_MT_REPORT:
158 case 3:153 return 1;
159 grail_mask_set(types, GRAIL_TYPE_DRAG3);154 case SYN_REPORT:
160 grail_mask_set(types, GRAIL_TYPE_PINCH3);155 return count == 0;
161 grail_mask_set(types, GRAIL_TYPE_ROTATE3);156 default:
162 grail_mask_set(types, GRAIL_TYPE_TAP3);157 return 0;
163 grail_mask_set(types, GRAIL_TYPE_EDRAG);158 }
164 grail_mask_set(types, GRAIL_TYPE_EPINCH);159 default:
165 grail_mask_set(types, GRAIL_TYPE_EROTATE);160 return 0;
166 break;161 }
167 case 4:162}
168 grail_mask_set(types, GRAIL_TYPE_DRAG4);163
169 grail_mask_set(types, GRAIL_TYPE_PINCH4);164static void flush_gestures(struct grail *ge)
170 grail_mask_set(types, GRAIL_TYPE_ROTATE4);165{
171 grail_mask_set(types, GRAIL_TYPE_TAP4);166 struct grail_impl *impl = ge->impl;
172 grail_mask_set(types, GRAIL_TYPE_MDRAG);167 struct input_event iev;
173 grail_mask_set(types, GRAIL_TYPE_MPINCH);168 struct grail_event gev;
174 grail_mask_set(types, GRAIL_TYPE_MROTATE);169 int count = 0;
175 break;170
176 case 5:171 while (!evbuf_empty(&impl->evbuf)) {
177 grail_mask_set(types, GRAIL_TYPE_DRAG5);172 evbuf_get(&impl->evbuf, &iev);
178 grail_mask_set(types, GRAIL_TYPE_PINCH5);173 if (skip_event(&iev, count))
179 grail_mask_set(types, GRAIL_TYPE_ROTATE5);174 continue;
180 grail_mask_set(types, GRAIL_TYPE_TAP5);175 if (ge->event)
181 break;176 ge->event(ge, &iev);
182 }177 if (iev.type == EV_SYN && iev.code == SYN_REPORT)
183178 count = 0;
184 for (i = 0; i < frame->num_active; i++) {179 else
185 pos[i].x = gin_prop_x(ge->gin, frame->active[i]->x);180 count++;
186 pos[i].y = gin_prop_y(ge->gin, frame->active[i]->y);181 }
187 }182 while (!grailbuf_empty(&impl->gbuf)) {
188183 grailbuf_get(&impl->gbuf, &gev);
189 return ge->get_clients(ge, &client, 1, pos, frame->num_active,184 if (ge->gesture)
190 types, DIM_GRAIL_TYPE_BYTES);185 ge->gesture(ge, &gev);
186 }
191}187}
192188
193static void report_frame(struct grail *ge,189static void report_frame(struct grail *ge,
194 const struct utouch_frame *frame,190 const struct utouch_frame *frame,
195 const struct input_event *syn)191 const struct input_event *syn)
196{192{
197 struct grail_impl *impl = ge->impl;
198 struct gesture_recognizer *gru = ge->gru;193 struct gesture_recognizer *gru = ge->gru;
199 struct input_event iev;194 struct gesture_inserter *gin = ge->gin;
195 struct grail_impl *impl = ge->impl;
200 struct grail_event gev;196 struct grail_event gev;
201197
202 ge->impl->frame = frame;198 ge->impl->frame = frame;
203199
204 /* Reset timer when number of touches changes. */200 if (frame->num_active && !frame->prev->num_active) {
205 if (frame->prev->revision != frame->revision && frame->num_active) {201 impl->timeout = 0;
206 gru->start_time = frame->time;202 impl->gesture = 0;
207 }203 }
208204
209 /* Once touches have stabilized, check if there are any potential205 if (impl->timeout) {
210 * gestures registered for the number of touches. */206 flush_events(ge);
211 if (gru->state == RECOGNIZING &&207 return;
212 frame->time > gru->start_time + stable_time &&208 }
213 check_potential_gestures(ge, frame) == 0)209
214 gru->state = UNRECOGNIZED;210 gin_frame_begin(ge, frame);
215211 gru_recognize(ge, frame);
216 /* Process the frame for gestures unless we're sure there are none. */212 gin_frame_end(ge, frame);
217 if (gru->state != UNRECOGNIZED) {213
218 gin_frame_begin(ge, frame);214 if (!grailbuf_empty(&impl->gbuf))
219 gru_recognize(ge, frame);215 impl->gesture = 1;
220 gin_frame_end(ge, frame);216
221 }217 if (!frame->num_active ||
222218 !grail_mask_count(gin->used, sizeof(gin->used)) &&
223 if (gru->state == RECOGNIZING) {219 frame->time - frame->mod_time > gru->move.fm[FM_X].hold_ms)
224 /* If a gesture is recognized and either all touches lifted or220 impl->timeout = !impl->gesture;
225 * we are within the recognition interval, set state to221
226 * recognized. Note that taps do not stay in the used array, so222 if (impl->timeout)
227 * we must check if any gesture events are buffered. */223 flush_events(ge);
228 if ((grail_mask_count(ge->gin->used, DIM_INSTANCE_BYTES) ||224
229 !grailbuf_empty(&impl->gbuf)) &&225 if (impl->gesture)
230 (frame->num_active == 0 ||226 flush_gestures(ge);
231 (frame->time > gru->start_time + stable_time &&
232 frame->time <= gru->start_time + recognition_time))) {
233 if (gru->global_client)
234 gru->state = GLOBAL;
235 else
236 gru->state = LOCAL;
237 }
238 /* If there is no gesture and all touches lifted, set state to
239 * unrecognized. */
240 else if (frame->num_active == 0)
241 gru->state = UNRECOGNIZED;
242 }
243
244 /* Now we have the state set, process events. */
245 switch (gru->state) {
246 case LOCAL:
247 case GLOBAL:
248 while (!grailbuf_empty(&impl->gbuf)) {
249 grailbuf_get(&impl->gbuf, &gev);
250 if (ge->gesture &&
251 ((gru->state == GLOBAL &&
252 gev.client_id.client == gru->global_client) ||
253 (gru->state == LOCAL &&
254 gev.client_id.client != gru->global_client)))
255 ge->gesture(ge, &gev);
256 }
257 evbuf_clear(&impl->evbuf);
258
259 /* Once all touches are lifted and no gestures are
260 * active, reset recognition state. */
261 if (grail_mask_count(ge->gin->used, DIM_INSTANCE_BYTES) == 0 &&
262 frame->num_active == 0) {
263 gru->state = RECOGNIZING;
264 gru->global_client = 0;
265 }
266 break;
267
268 case RECOGNIZING:
269 /* If we're still actively recognizing, stop here. */
270 if (frame->time <= gru->start_time + recognition_time)
271 break;
272 gru->state = UNRECOGNIZED;
273
274 case UNRECOGNIZED:
275 while (!evbuf_empty(&impl->evbuf)) {
276 evbuf_get(&impl->evbuf, &iev);
277 if (ge->event)
278 ge->event(ge, &iev);
279 }
280 grailbuf_clear(&impl->gbuf);
281
282 if (frame->num_active == 0) {
283 gru->state = RECOGNIZING;
284 gru->global_client = 0;
285 }
286 break;
287 }
288}227}
289228
290static void grail_pump_mtdev(struct grail *ge, const struct input_event *ev)229static void grail_pump_mtdev(struct grail *ge, const struct input_event *ev)
@@ -292,21 +231,6 @@
292 struct grail_impl *impl = ge->impl;231 struct grail_impl *impl = ge->impl;
293 const struct utouch_frame *frame;232 const struct utouch_frame *frame;
294233
295 if (ev->type == EV_KEY && (ev->code < BTN_DIGI ||
296 ev->code > BTN_TOOL_QUADTAP)) {
297 struct input_event sync_ev;
298
299 ge->event(ge, ev);
300
301 sync_ev.type = EV_SYN;
302 sync_ev.code = SYN_REPORT;
303 sync_ev.value = 1;
304 sync_ev.time = ev->time;
305 ge->event(ge, &sync_ev);
306
307 return;
308 }
309
310 evbuf_put(&impl->evbuf, ev);234 evbuf_put(&impl->evbuf, ev);
311235
312 if (ev->type == EV_SYN || ev->type == EV_ABS) {236 if (ev->type == EV_SYN || ev->type == EV_ABS) {
313237
=== modified file 'src/grail-event.c'
--- src/grail-event.c 2011-02-09 15:12:13 +0000
+++ src/grail-event.c 2011-02-24 13:47:05 +0000
@@ -22,7 +22,6 @@
2222
23#include "grail-inserter.h"23#include "grail-inserter.h"
24#include "grail-impl.h"24#include "grail-impl.h"
25#include "grail-recognizer.h"
26#include <malloc.h>25#include <malloc.h>
27#include <string.h>26#include <string.h>
28#include <errno.h>27#include <errno.h>
@@ -83,7 +82,7 @@
83 const struct utouch_frame *frame)82 const struct utouch_frame *frame)
84{83{
85 struct grail_coord pos[DIM_TOUCH];84 struct grail_coord pos[DIM_TOUCH];
86 int i, npos = 0, num_clients;85 int i, npos = 0;
87 if (!ge->get_clients)86 if (!ge->get_clients)
88 return 0;87 return 0;
89 grail_mask_foreach(i, span, bspan) {88 grail_mask_foreach(i, span, bspan) {
@@ -91,20 +90,7 @@
91 pos[npos].y = gin_prop_y(ge->gin, frame->slots[i]->y);90 pos[npos].y = gin_prop_y(ge->gin, frame->slots[i]->y);
92 npos++;91 npos++;
93 }92 }
9493 return ge->get_clients(ge, info, maxinfo, pos, npos, types, btypes);
95 num_clients = ge->get_clients(ge, info, maxinfo, pos, npos, types,
96 btypes);
97
98 /* Check if client is handling global gestures, using SYSFLAG1. */
99 if (num_clients > 0 && grail_mask_get(info[0].mask,
100 GRAIL_TYPE_SYSFLAG1)) {
101 /* Save client id, and clear SYSFLAG1 as it isn't a real
102 * gesture type. */
103 ge->gru->global_client = info[0].id.client;
104 grail_mask_clear(info[0].mask, GRAIL_TYPE_SYSFLAG1);
105 }
106
107 return num_clients;
108}94}
10995
110void gin_send_event(struct grail *ge, struct slot_state *s,96void gin_send_event(struct grail *ge, struct slot_state *s,
11197
=== modified file 'src/grail-gestures.c'
--- src/grail-gestures.c 2011-01-02 12:08:08 +0000
+++ src/grail-gestures.c 2011-02-24 13:47:05 +0000
@@ -24,9 +24,10 @@
24#include "grail-impl.h"24#include "grail-impl.h"
25#include <math.h>25#include <math.h>
2626
27static const float FM_SN[DIM_FM] = { 1000, 1000, 200, 1000 };27static const float FM_SN[DIM_FM] = { 1000, 1000, 1000, 1000 };
28static const float FM_BAR[DIM_FM] = { 50, 50, 30, 50 };28static const float FM_BAR[DIM_FM] = { 50, 50, 50, 50 };
29static const grail_time_t FM_BAR_MS[DIM_FM] = { 300, 300, 10000, 10000 };29static const grail_time_t FM_HOLD_MS[DIM_FM] = { 60, 60, 60, 60 };
30static const grail_time_t FM_BAR_MS[DIM_FM] = { 300, 300, 500, 500 };
30static const grail_time_t SAMPLE_MS = 10;31static const grail_time_t SAMPLE_MS = 10;
31static const float EPS = 1e-3;32static const float EPS = 1e-3;
3233
@@ -111,6 +112,7 @@
111 fm->sample_ms = t;112 fm->sample_ms = t;
112 m->tickle &= ~(1 << i);113 m->tickle &= ~(1 << i);
113 m->active &= ~(1 << i);114 m->active &= ~(1 << i);
115 m->timeout &= ~(1 << i);
114}116}
115117
116static void move_update(struct move_model *m, int i, float x, grail_time_t t)118static void move_update(struct move_model *m, int i, float x, grail_time_t t)
@@ -132,11 +134,15 @@
132 if (m->active & (1 << i))134 if (m->active & (1 << i))
133 return;135 return;
134 fm->action_delta = x - fm->original;136 fm->action_delta = x - fm->original;
135 if (fabs(fm->action_delta) > fm->bar ||137 if (t - fm->original_ms > fm->hold_ms &&
136 t - fm->original_ms > fm->bar_ms)138 fabs(fm->action_delta) > fm->bar) {
137 m->active |= (1 << i);139 m->active |= (1 << i);
138 else140 } else if (t - fm->original_ms > fm->bar_ms) {
141 m->active |= (1 << i);
142 m->timeout |= (1 << i);
143 } else {
139 fm->action_delta = 0;144 fm->action_delta = 0;
145 }
140}146}
141147
142void gru_init_motion(struct grail *ge)148void gru_init_motion(struct grail *ge)
@@ -153,6 +159,7 @@
153 for (i = 0; i < DIM_FM; i++) {159 for (i = 0; i < DIM_FM; i++) {
154 m->fm[i].fuzz = D[i] / FM_SN[i];160 m->fm[i].fuzz = D[i] / FM_SN[i];
155 m->fm[i].bar = D[i] / FM_BAR[i];161 m->fm[i].bar = D[i] / FM_BAR[i];
162 m->fm[i].hold_ms = FM_HOLD_MS[i];
156 m->fm[i].bar_ms = FM_BAR_MS[i];163 m->fm[i].bar_ms = FM_BAR_MS[i];
157 }164 }
158}165}
159166
=== modified file 'src/grail-gestures.h'
--- src/grail-gestures.h 2011-01-02 12:08:08 +0000
+++ src/grail-gestures.h 2011-02-24 13:47:05 +0000
@@ -49,12 +49,13 @@
49 float bar;49 float bar;
50 grail_time_t original_ms;50 grail_time_t original_ms;
51 grail_time_t sample_ms;51 grail_time_t sample_ms;
52 grail_time_t hold_ms;
52 grail_time_t bar_ms;53 grail_time_t bar_ms;
53};54};
5455
55struct move_model {56struct move_model {
56 struct filter_model fm[DIM_FM];57 struct filter_model fm[DIM_FM];
57 int tickle, active;58 int tickle, active, timeout;
58 int single, multi, ntouch;59 int single, multi, ntouch;
59 grail_time_t time;60 grail_time_t time;
60};61};
6162
=== modified file 'src/grail-impl.h'
--- src/grail-impl.h 2011-02-02 22:16:20 +0000
+++ src/grail-impl.h 2011-02-24 13:47:05 +0000
@@ -42,6 +42,8 @@
42 struct evbuf evbuf;42 struct evbuf evbuf;
43 struct grailbuf gbuf;43 struct grailbuf gbuf;
44 int filter_abs;44 int filter_abs;
45 int timeout;
46 int gesture;
45};47};
4648
47#endif49#endif
4850
=== modified file 'src/grail-recognizer.h'
--- src/grail-recognizer.h 2011-02-09 15:12:13 +0000
+++ src/grail-recognizer.h 2011-02-24 13:47:05 +0000
@@ -25,13 +25,6 @@
2525
26#include "grail-gestures.h"26#include "grail-gestures.h"
2727
28enum recognition_state {
29 RECOGNIZING,
30 LOCAL,
31 GLOBAL,
32 UNRECOGNIZED
33};
34
35struct gesture_recognizer {28struct gesture_recognizer {
36 struct move_model move;29 struct move_model move;
37 struct combo_model drag;30 struct combo_model drag;
@@ -41,9 +34,6 @@
41 struct combo_model winpinch;34 struct combo_model winpinch;
42 struct combo_model winrotate;35 struct combo_model winrotate;
43 struct tapping_model tapping;36 struct tapping_model tapping;
44 utouch_frame_time_t start_time;
45 enum recognition_state state;
46 int global_client;
47};37};
4838
49int gru_init(struct grail *ge);39int gru_init(struct grail *ge);

Subscribers

People subscribed via source and target branches

to all changes: