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: 667 lines (+175/-203)
14 files modified
configure.ac (+1/-1)
src/evbuf.h (+1/-1)
src/gestures-drag.c (+14/-0)
src/gestures-pinch.c (+15/-1)
src/gestures-rotate.c (+15/-1)
src/gestures-tapping.c (+6/-2)
src/grail-api.c (+90/-162)
src/grail-event.c (+2/-16)
src/grail-gestures.c (+14/-7)
src/grail-gestures.h (+3/-2)
src/grail-impl.h (+2/-0)
src/grail-inserter.c (+10/-0)
src/grail-inserter.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
Stephen M. Webb Pending
Chase Douglas Pending
Review via email: mp+51225@code.launchpad.net

This proposal supersedes a proposal from 2011-02-24.

This proposal has been superseded by a proposal from 2011-03-03.

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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

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.

Revision history for this message
Henrik Rydberg (rydberg) wrote : Posted in a previous version of this proposal

Fix of the fix - the first regression was pretty complex, and revealed some
additional assumptions that were not true. Hopefully this version will do better.

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

Things are progressing :). I want to test this some more before approving, and we will also need to resolve the SYSFLAG issue before we merge as well.

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

Ok, here is a stop-gap measure for the sysflag issue. Apparently the solution has issues overall, both in the X drivers and in grail. But frankly, it does not seem important enough to stop progress at this stage. Uploaded new version with added sysflag patch.

lp:~oif-team/grail/trunk.fixes updated
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 'configure.ac'
--- configure.ac 2011-02-21 19:20:28 +0000
+++ configure.ac 2011-03-03 22:51:32 +0000
@@ -1,7 +1,7 @@
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 [1.0.19],4 [1.0.20],
5 [],5 [],
6 [utouch-grail])6 [utouch-grail])
7AC_CONFIG_SRCDIR([Makefile.am])7AC_CONFIG_SRCDIR([Makefile.am])
88
=== modified file 'src/evbuf.h'
--- src/evbuf.h 2010-08-06 20:30:20 +0000
+++ src/evbuf.h 2011-03-03 22:51:32 +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-03-03 22:51:32 +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-03-03 22:51:32 +0000
@@ -54,7 +54,7 @@
54 struct combo_model *state = &gru->pinch;54 struct combo_model *state = &gru->pinch;
55 struct move_model *move = &gru->move;55 struct move_model *move = &gru->move;
56 int mask = state->active ? (move->active & fm_mask) : fm_mask;56 int mask = state->active ? (move->active & fm_mask) : fm_mask;
57 if (!move->multi) {57 if (!move->multi && !move->single) {
58 if (state->active) {58 if (state->active) {
59 gru_end(ge, state->gid, move,59 gru_end(ge, state->gid, move,
60 state->prop, state->nprop);60 state->prop, state->nprop);
@@ -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-03-03 22:51:32 +0000
@@ -53,7 +53,7 @@
53 struct combo_model *state = &gru->rotate;53 struct combo_model *state = &gru->rotate;
54 struct move_model *move = &gru->move;54 struct move_model *move = &gru->move;
55 int mask = state->active ? (move->active & fm_mask) : fm_mask;55 int mask = state->active ? (move->active & fm_mask) : fm_mask;
56 if (!move->multi) {56 if (!move->multi && !move->single) {
57 if (state->active) {57 if (state->active) {
58 gru_end(ge, state->gid, move,58 gru_end(ge, state->gid, move,
59 state->prop, state->nprop);59 state->prop, state->nprop);
@@ -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-03-03 22:51:32 +0000
@@ -43,8 +43,10 @@
43 struct tapping_model *state = &gru->tapping;43 struct tapping_model *state = &gru->tapping;
44 struct move_model *move = &gru->move;44 struct move_model *move = &gru->move;
45 state->tap = 0;45 state->tap = 0;
46 if (move->ntouch && move->ntouch < state->mintouch)46 if (frame->num_active && !frame->prev->num_active) {
47 state->end = move->time;47 state->mintouch = 0;
48 state->maxtouch = 0;
49 }
48 if (move->ntouch > state->maxtouch) {50 if (move->ntouch > state->maxtouch) {
49 if (state->active) {51 if (state->active) {
50 gin_gid_discard(ge, state->gid);52 gin_gid_discard(ge, state->gid);
@@ -91,6 +93,8 @@
91 if ((move->active & fm_mask) ||93 if ((move->active & fm_mask) ||
92 move->time - state->start > move->fm[FM_X].bar_ms) {94 move->time - state->start > move->fm[FM_X].bar_ms) {
93 gin_gid_discard(ge, state->gid);95 gin_gid_discard(ge, state->gid);
96 state->mintouch = move->ntouch;
97 state->maxtouch = move->ntouch;
94 state->active = 0;98 state->active = 0;
95 }99 }
96 return 0;100 return 0;
97101
=== modified file 'src/grail-api.c'
--- src/grail-api.c 2011-02-21 01:22:08 +0000
+++ src/grail-api.c 2011-03-03 22:51:32 +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,62 +127,72 @@
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 }
187}
188
189static int gesture_timeout(struct grail *ge, const struct utouch_frame *frame)
190{
191 struct gesture_recognizer *gru = ge->gru;
192 struct gesture_inserter *gin = ge->gin;
193
194 return grail_mask_count(gin->used, sizeof(gin->used)) == 0 &&
195 frame->time - frame->mod_time > gru->move.fm[FM_X].hold_ms;
191}196}
192197
193static void report_frame(struct grail *ge,198static void report_frame(struct grail *ge,
@@ -195,96 +200,27 @@
195 const struct input_event *syn)200 const struct input_event *syn)
196{201{
197 struct grail_impl *impl = ge->impl;202 struct grail_impl *impl = ge->impl;
198 struct gesture_recognizer *gru = ge->gru;
199 struct input_event iev;
200 struct grail_event gev;203 struct grail_event gev;
201204
202 ge->impl->frame = frame;205 ge->impl->frame = frame;
203206
204 /* Reset timer when number of touches changes. */207 if (frame->num_active && !frame->prev->num_active) {
205 if (frame->prev->revision != frame->revision && frame->num_active) {208 impl->ongoing = 1;
206 gru->start_time = frame->time;209 impl->gesture = 0;
207 }210 }
208211
209 /* Once touches have stabilized, check if there are any potential212 if (!impl->ongoing)
210 * gestures registered for the number of touches. */213 return;
211 if (gru->state == RECOGNIZING &&214
212 frame->time > gru->start_time + stable_time &&215 gin_frame_begin(ge, frame);
213 check_potential_gestures(ge, frame) == 0)216 gru_recognize(ge, frame);
214 gru->state = UNRECOGNIZED;217 gin_frame_end(ge, frame);
215218
216 /* Process the frame for gestures unless we're sure there are none. */219 if (!grailbuf_empty(&impl->gbuf))
217 if (gru->state != UNRECOGNIZED) {220 impl->gesture = 1;
218 gin_frame_begin(ge, frame);221
219 gru_recognize(ge, frame);222 if (frame->num_active == 0 || gesture_timeout(ge, frame))
220 gin_frame_end(ge, frame);223 impl->ongoing &= impl->gesture;
221 }
222
223 if (gru->state == RECOGNIZING) {
224 /* If a gesture is recognized and either all touches lifted or
225 * we are within the recognition interval, set state to
226 * recognized. Note that taps do not stay in the used array, so
227 * we must check if any gesture events are buffered. */
228 if ((grail_mask_count(ge->gin->used, DIM_INSTANCE_BYTES) ||
229 !grailbuf_empty(&impl->gbuf)) &&
230 (frame->num_active == 0 ||
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}224}
289225
290static void grail_pump_mtdev(struct grail *ge, const struct input_event *ev)226static void grail_pump_mtdev(struct grail *ge, const struct input_event *ev)
@@ -292,21 +228,6 @@
292 struct grail_impl *impl = ge->impl;228 struct grail_impl *impl = ge->impl;
293 const struct utouch_frame *frame;229 const struct utouch_frame *frame;
294230
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);231 evbuf_put(&impl->evbuf, ev);
311232
312 if (ev->type == EV_SYN || ev->type == EV_ABS) {233 if (ev->type == EV_SYN || ev->type == EV_ABS) {
@@ -314,6 +235,13 @@
314 if (frame)235 if (frame)
315 report_frame(ge, frame, ev);236 report_frame(ge, frame, ev);
316 }237 }
238
239 if (ev->type == EV_SYN) {
240 if (!impl->ongoing)
241 flush_events(ge);
242 if (impl->gesture)
243 flush_gestures(ge);
244 }
317}245}
318246
319int grail_pull(struct grail *ge, int fd)247int grail_pull(struct grail *ge, int fd)
320248
=== modified file 'src/grail-event.c'
--- src/grail-event.c 2011-02-09 15:12:13 +0000
+++ src/grail-event.c 2011-03-03 22:51:32 +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-03-03 22:51:32 +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-03-03 22:51:32 +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};
@@ -97,7 +98,7 @@
97 const struct utouch_frame *frame);98 const struct utouch_frame *frame);
9899
99struct tapping_model {100struct tapping_model {
100 grail_time_t start, end;101 grail_time_t start;
101 int mintouch, maxtouch;102 int mintouch, maxtouch;
102 int active, gid, tap;103 int active, gid, tap;
103 int nprop;104 int nprop;
104105
=== modified file 'src/grail-impl.h'
--- src/grail-impl.h 2011-02-02 22:16:20 +0000
+++ src/grail-impl.h 2011-03-03 22:51:32 +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 ongoing;
46 int gesture;
45};47};
4648
47#endif49#endif
4850
=== modified file 'src/grail-inserter.c'
--- src/grail-inserter.c 2011-01-02 12:08:08 +0000
+++ src/grail-inserter.c 2011-03-03 22:51:32 +0000
@@ -69,6 +69,13 @@
69 for (j = 0; j < nclient; j++) {69 for (j = 0; j < nclient; j++) {
70 if (!grail_mask_get(info[j].mask, s->type))70 if (!grail_mask_get(info[j].mask, s->type))
71 continue;71 continue;
72 if (gin->grab_active &&
73 info[j].id.client != gin->grab_client)
74 continue;
75 if (grail_mask_get(info[j].mask, GRAIL_TYPE_SYSFLAG1)) {
76 gin->grab_active = 1;
77 gin->grab_client = info[j].id.client;
78 }
72 s->client_id[s->nclient++] = info[j].id;79 s->client_id[s->nclient++] = info[j].id;
73 }80 }
74 }81 }
@@ -149,6 +156,9 @@
149 if (s->status == GRAIL_STATUS_END)156 if (s->status == GRAIL_STATUS_END)
150 gin_gid_discard(ge, s->id);157 gin_gid_discard(ge, s->id);
151 }158 }
159
160 if (!frame->num_active)
161 gin->grab_active = 0;
152}162}
153163
154int gin_gid_begin(struct grail *ge, int type, int priority,164int gin_gid_begin(struct grail *ge, int type, int priority,
155165
=== modified file 'src/grail-inserter.h'
--- src/grail-inserter.h 2011-01-02 12:08:08 +0000
+++ src/grail-inserter.h 2011-03-03 22:51:32 +0000
@@ -53,6 +53,8 @@
53 grail_mask_t used[DIM_INSTANCE_BYTES];53 grail_mask_t used[DIM_INSTANCE_BYTES];
54 grail_time_t time;54 grail_time_t time;
55 int gestureid;55 int gestureid;
56 int grab_active;
57 int grab_client;
56 float scale_x, scale_y, scale_r;58 float scale_x, scale_y, scale_r;
57 float trans_x, trans_y;59 float trans_x, trans_y;
58};60};
5961
=== modified file 'src/grail-recognizer.h'
--- src/grail-recognizer.h 2011-02-09 15:12:13 +0000
+++ src/grail-recognizer.h 2011-03-03 22:51:32 +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: