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

Proposed by Henrik Rydberg
Status: Merged
Merged at revision: 126
Proposed branch: lp:~oif-team/grail/trunk.fixes
Merge into: lp:grail
Diff against target: 666 lines (+174/-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 (+9/-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
Chase Douglas (community) Approve
Stephen M. Webb Pending
Review via email: mp+52149@code.launchpad.net

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

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

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.

Revision history for this message
Chase Douglas (chasedouglas) wrote : Posted in a previous version of this proposal

I think the last commit is all I needed. The log message also summarizes an interesting "bug" that we're going to leave as is for now as SYSFLAG1 is an undocumented "feature". We need to hammer this new grail version in testing so we can upload it as soon as possible. I'll mark this as approved after I've done testing.

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

Argh, I committed the wrong version of the patch - this one is almost the same, but resets grab_active at the start of a new set of touches, rather than at the end. More stable.

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

I've done testing locally and everything seems to operate correctly.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'configure.ac'
2--- configure.ac 2011-02-21 19:20:28 +0000
3+++ configure.ac 2011-03-04 00:06:44 +0000
4@@ -1,7 +1,7 @@
5 # Initialize Autoconf
6 AC_PREREQ([2.60])
7 AC_INIT([Gesture Recognition And Instantiation Library],
8- [1.0.19],
9+ [1.0.20],
10 [],
11 [utouch-grail])
12 AC_CONFIG_SRCDIR([Makefile.am])
13
14=== modified file 'src/evbuf.h'
15--- src/evbuf.h 2010-08-06 20:30:20 +0000
16+++ src/evbuf.h 2011-03-04 00:06:44 +0000
17@@ -29,7 +29,7 @@
18 #ifndef GRAIL_EVBUF_H
19 #define GRAIL_EVBUF_H
20
21-#define DIM_EVENTS 512
22+#define DIM_EVENTS 4096
23
24 struct evbuf {
25 int head;
26
27=== modified file 'src/gestures-drag.c'
28--- src/gestures-drag.c 2011-01-02 12:08:08 +0000
29+++ src/gestures-drag.c 2011-03-04 00:06:44 +0000
30@@ -72,6 +72,13 @@
31 state->active = 0;
32 }
33 }
34+ if ((move->timeout & fm_mask) == fm_mask) {
35+ if (state->active) {
36+ gin_gid_discard(ge, state->gid);
37+ state->active = 0;
38+ }
39+ return 0;
40+ }
41 if (!state->active) {
42 int type = getype[move->ntouch];
43 if (type < 0)
44@@ -102,6 +109,13 @@
45 state->active = 0;
46 }
47 }
48+ if ((move->timeout & fm_mask) == fm_mask) {
49+ if (state->active) {
50+ gin_gid_discard(ge, state->gid);
51+ state->active = 0;
52+ }
53+ return 0;
54+ }
55 if (!state->active) {
56 if (move->ntouch == 4) {
57 state->gid = gin_gid_begin(ge, GRAIL_TYPE_MDRAG,
58
59=== modified file 'src/gestures-pinch.c'
60--- src/gestures-pinch.c 2011-01-02 12:08:08 +0000
61+++ src/gestures-pinch.c 2011-03-04 00:06:44 +0000
62@@ -54,7 +54,7 @@
63 struct combo_model *state = &gru->pinch;
64 struct move_model *move = &gru->move;
65 int mask = state->active ? (move->active & fm_mask) : fm_mask;
66- if (!move->multi) {
67+ if (!move->multi && !move->single) {
68 if (state->active) {
69 gru_end(ge, state->gid, move,
70 state->prop, state->nprop);
71@@ -62,6 +62,13 @@
72 }
73 return 0;
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+ }
82 if (!(move->tickle & mask))
83 return 0;
84 if (!state->active) {
85@@ -93,6 +100,13 @@
86 }
87 return 0;
88 }
89+ if ((move->timeout & fm_mask) == fm_mask) {
90+ if (state->active) {
91+ gin_gid_discard(ge, state->gid);
92+ state->active = 0;
93+ }
94+ return 0;
95+ }
96 if (!(move->tickle & mask))
97 return 0;
98 if (!state->active) {
99
100=== modified file 'src/gestures-rotate.c'
101--- src/gestures-rotate.c 2011-01-02 12:08:08 +0000
102+++ src/gestures-rotate.c 2011-03-04 00:06:44 +0000
103@@ -53,7 +53,7 @@
104 struct combo_model *state = &gru->rotate;
105 struct move_model *move = &gru->move;
106 int mask = state->active ? (move->active & fm_mask) : fm_mask;
107- if (!move->multi) {
108+ if (!move->multi && !move->single) {
109 if (state->active) {
110 gru_end(ge, state->gid, move,
111 state->prop, state->nprop);
112@@ -61,6 +61,13 @@
113 }
114 return 0;
115 }
116+ if ((move->timeout & fm_mask) == fm_mask) {
117+ if (state->active) {
118+ gin_gid_discard(ge, state->gid);
119+ state->active = 0;
120+ }
121+ return 0;
122+ }
123 if (!(move->tickle & mask))
124 return 0;
125 if (!state->active) {
126@@ -92,6 +99,13 @@
127 }
128 return 0;
129 }
130+ if ((move->timeout & fm_mask) == fm_mask) {
131+ if (state->active) {
132+ gin_gid_discard(ge, state->gid);
133+ state->active = 0;
134+ }
135+ return 0;
136+ }
137 if (!(move->tickle & mask))
138 return 0;
139 if (!state->active) {
140
141=== modified file 'src/gestures-tapping.c'
142--- src/gestures-tapping.c 2011-02-09 15:17:50 +0000
143+++ src/gestures-tapping.c 2011-03-04 00:06:44 +0000
144@@ -43,8 +43,10 @@
145 struct tapping_model *state = &gru->tapping;
146 struct move_model *move = &gru->move;
147 state->tap = 0;
148- if (move->ntouch && move->ntouch < state->mintouch)
149- state->end = move->time;
150+ if (frame->num_active && !frame->prev->num_active) {
151+ state->mintouch = 0;
152+ state->maxtouch = 0;
153+ }
154 if (move->ntouch > state->maxtouch) {
155 if (state->active) {
156 gin_gid_discard(ge, state->gid);
157@@ -91,6 +93,8 @@
158 if ((move->active & fm_mask) ||
159 move->time - state->start > move->fm[FM_X].bar_ms) {
160 gin_gid_discard(ge, state->gid);
161+ state->mintouch = move->ntouch;
162+ state->maxtouch = move->ntouch;
163 state->active = 0;
164 }
165 return 0;
166
167=== modified file 'src/grail-api.c'
168--- src/grail-api.c 2011-02-21 01:22:08 +0000
169+++ src/grail-api.c 2011-03-04 00:06:44 +0000
170@@ -34,11 +34,6 @@
171 #define DIM_FRAMES 100
172 #define FRAME_RATE 100
173
174-/* Wait time (ms) for number of touches to stabilize. */
175-static const unsigned int stable_time = 50;
176-/* Maximum time (ms) for gesture to be recognized. */
177-static const unsigned int recognition_time = 300;
178-
179 void grail_filter_abs_events(struct grail *ge, int usage)
180 {
181 struct grail_impl *x = ge->impl;
182@@ -132,62 +127,72 @@
183 max->y = s->max_y;
184 }
185
186-/* Check for any potential gestures given the number of touch points and where
187- * they occur on screen. */
188-static int check_potential_gestures(struct grail *ge,
189- const struct utouch_frame *frame)
190-{
191- grail_mask_t types[DIM_GRAIL_TYPE_BYTES] = {0};
192- struct grail_client_info client;
193- struct grail_coord pos[frame->num_active];
194- int i;
195-
196- switch (frame->num_active) {
197- case 1:
198- grail_mask_set(types, GRAIL_TYPE_DRAG1);
199- grail_mask_set(types, GRAIL_TYPE_PINCH1);
200- grail_mask_set(types, GRAIL_TYPE_ROTATE1);
201- grail_mask_set(types, GRAIL_TYPE_TAP1);
202- break;
203- case 2:
204- grail_mask_set(types, GRAIL_TYPE_DRAG2);
205- grail_mask_set(types, GRAIL_TYPE_PINCH2);
206- grail_mask_set(types, GRAIL_TYPE_ROTATE2);
207- grail_mask_set(types, GRAIL_TYPE_TAP2);
208- break;
209- case 3:
210- grail_mask_set(types, GRAIL_TYPE_DRAG3);
211- grail_mask_set(types, GRAIL_TYPE_PINCH3);
212- grail_mask_set(types, GRAIL_TYPE_ROTATE3);
213- grail_mask_set(types, GRAIL_TYPE_TAP3);
214- grail_mask_set(types, GRAIL_TYPE_EDRAG);
215- grail_mask_set(types, GRAIL_TYPE_EPINCH);
216- grail_mask_set(types, GRAIL_TYPE_EROTATE);
217- break;
218- case 4:
219- grail_mask_set(types, GRAIL_TYPE_DRAG4);
220- grail_mask_set(types, GRAIL_TYPE_PINCH4);
221- grail_mask_set(types, GRAIL_TYPE_ROTATE4);
222- grail_mask_set(types, GRAIL_TYPE_TAP4);
223- grail_mask_set(types, GRAIL_TYPE_MDRAG);
224- grail_mask_set(types, GRAIL_TYPE_MPINCH);
225- grail_mask_set(types, GRAIL_TYPE_MROTATE);
226- break;
227- case 5:
228- grail_mask_set(types, GRAIL_TYPE_DRAG5);
229- grail_mask_set(types, GRAIL_TYPE_PINCH5);
230- grail_mask_set(types, GRAIL_TYPE_ROTATE5);
231- grail_mask_set(types, GRAIL_TYPE_TAP5);
232- break;
233- }
234-
235- for (i = 0; i < frame->num_active; i++) {
236- pos[i].x = gin_prop_x(ge->gin, frame->active[i]->x);
237- pos[i].y = gin_prop_y(ge->gin, frame->active[i]->y);
238- }
239-
240- return ge->get_clients(ge, &client, 1, pos, frame->num_active,
241- types, DIM_GRAIL_TYPE_BYTES);
242+static void flush_events(struct grail *ge)
243+{
244+ struct grail_impl *impl = ge->impl;
245+ struct input_event iev;
246+
247+ grailbuf_clear(&impl->gbuf);
248+ while (!evbuf_empty(&impl->evbuf)) {
249+ evbuf_get(&impl->evbuf, &iev);
250+ if (ge->event)
251+ ge->event(ge, &iev);
252+ }
253+}
254+
255+static int skip_event(const struct input_event *ev, int count)
256+{
257+ switch (ev->type) {
258+ case EV_ABS:
259+ return 1;
260+ case EV_KEY:
261+ return ev->code >= BTN_DIGI && ev->code < BTN_WHEEL;
262+ case EV_SYN:
263+ switch (ev->code) {
264+ case SYN_MT_REPORT:
265+ return 1;
266+ case SYN_REPORT:
267+ return count == 0;
268+ default:
269+ return 0;
270+ }
271+ default:
272+ return 0;
273+ }
274+}
275+
276+static void flush_gestures(struct grail *ge)
277+{
278+ struct grail_impl *impl = ge->impl;
279+ struct input_event iev;
280+ struct grail_event gev;
281+ int count = 0;
282+
283+ while (!evbuf_empty(&impl->evbuf)) {
284+ evbuf_get(&impl->evbuf, &iev);
285+ if (skip_event(&iev, count))
286+ continue;
287+ if (ge->event)
288+ ge->event(ge, &iev);
289+ if (iev.type == EV_SYN && iev.code == SYN_REPORT)
290+ count = 0;
291+ else
292+ count++;
293+ }
294+ while (!grailbuf_empty(&impl->gbuf)) {
295+ grailbuf_get(&impl->gbuf, &gev);
296+ if (ge->gesture)
297+ ge->gesture(ge, &gev);
298+ }
299+}
300+
301+static int gesture_timeout(struct grail *ge, const struct utouch_frame *frame)
302+{
303+ struct gesture_recognizer *gru = ge->gru;
304+ struct gesture_inserter *gin = ge->gin;
305+
306+ return grail_mask_count(gin->used, sizeof(gin->used)) == 0 &&
307+ frame->time - frame->mod_time > gru->move.fm[FM_X].hold_ms;
308 }
309
310 static void report_frame(struct grail *ge,
311@@ -195,96 +200,27 @@
312 const struct input_event *syn)
313 {
314 struct grail_impl *impl = ge->impl;
315- struct gesture_recognizer *gru = ge->gru;
316- struct input_event iev;
317 struct grail_event gev;
318
319 ge->impl->frame = frame;
320
321- /* Reset timer when number of touches changes. */
322- if (frame->prev->revision != frame->revision && frame->num_active) {
323- gru->start_time = frame->time;
324- }
325-
326- /* Once touches have stabilized, check if there are any potential
327- * gestures registered for the number of touches. */
328- if (gru->state == RECOGNIZING &&
329- frame->time > gru->start_time + stable_time &&
330- check_potential_gestures(ge, frame) == 0)
331- gru->state = UNRECOGNIZED;
332-
333- /* Process the frame for gestures unless we're sure there are none. */
334- if (gru->state != UNRECOGNIZED) {
335- gin_frame_begin(ge, frame);
336- gru_recognize(ge, frame);
337- gin_frame_end(ge, frame);
338- }
339-
340- if (gru->state == RECOGNIZING) {
341- /* If a gesture is recognized and either all touches lifted or
342- * we are within the recognition interval, set state to
343- * recognized. Note that taps do not stay in the used array, so
344- * we must check if any gesture events are buffered. */
345- if ((grail_mask_count(ge->gin->used, DIM_INSTANCE_BYTES) ||
346- !grailbuf_empty(&impl->gbuf)) &&
347- (frame->num_active == 0 ||
348- (frame->time > gru->start_time + stable_time &&
349- frame->time <= gru->start_time + recognition_time))) {
350- if (gru->global_client)
351- gru->state = GLOBAL;
352- else
353- gru->state = LOCAL;
354- }
355- /* If there is no gesture and all touches lifted, set state to
356- * unrecognized. */
357- else if (frame->num_active == 0)
358- gru->state = UNRECOGNIZED;
359- }
360-
361- /* Now we have the state set, process events. */
362- switch (gru->state) {
363- case LOCAL:
364- case GLOBAL:
365- while (!grailbuf_empty(&impl->gbuf)) {
366- grailbuf_get(&impl->gbuf, &gev);
367- if (ge->gesture &&
368- ((gru->state == GLOBAL &&
369- gev.client_id.client == gru->global_client) ||
370- (gru->state == LOCAL &&
371- gev.client_id.client != gru->global_client)))
372- ge->gesture(ge, &gev);
373- }
374- evbuf_clear(&impl->evbuf);
375-
376- /* Once all touches are lifted and no gestures are
377- * active, reset recognition state. */
378- if (grail_mask_count(ge->gin->used, DIM_INSTANCE_BYTES) == 0 &&
379- frame->num_active == 0) {
380- gru->state = RECOGNIZING;
381- gru->global_client = 0;
382- }
383- break;
384-
385- case RECOGNIZING:
386- /* If we're still actively recognizing, stop here. */
387- if (frame->time <= gru->start_time + recognition_time)
388- break;
389- gru->state = UNRECOGNIZED;
390-
391- case UNRECOGNIZED:
392- while (!evbuf_empty(&impl->evbuf)) {
393- evbuf_get(&impl->evbuf, &iev);
394- if (ge->event)
395- ge->event(ge, &iev);
396- }
397- grailbuf_clear(&impl->gbuf);
398-
399- if (frame->num_active == 0) {
400- gru->state = RECOGNIZING;
401- gru->global_client = 0;
402- }
403- break;
404- }
405+ if (frame->num_active && !frame->prev->num_active) {
406+ impl->ongoing = 1;
407+ impl->gesture = 0;
408+ }
409+
410+ if (!impl->ongoing)
411+ return;
412+
413+ gin_frame_begin(ge, frame);
414+ gru_recognize(ge, frame);
415+ gin_frame_end(ge, frame);
416+
417+ if (!grailbuf_empty(&impl->gbuf))
418+ impl->gesture = 1;
419+
420+ if (frame->num_active == 0 || gesture_timeout(ge, frame))
421+ impl->ongoing &= impl->gesture;
422 }
423
424 static void grail_pump_mtdev(struct grail *ge, const struct input_event *ev)
425@@ -292,21 +228,6 @@
426 struct grail_impl *impl = ge->impl;
427 const struct utouch_frame *frame;
428
429- if (ev->type == EV_KEY && (ev->code < BTN_DIGI ||
430- ev->code > BTN_TOOL_QUADTAP)) {
431- struct input_event sync_ev;
432-
433- ge->event(ge, ev);
434-
435- sync_ev.type = EV_SYN;
436- sync_ev.code = SYN_REPORT;
437- sync_ev.value = 1;
438- sync_ev.time = ev->time;
439- ge->event(ge, &sync_ev);
440-
441- return;
442- }
443-
444 evbuf_put(&impl->evbuf, ev);
445
446 if (ev->type == EV_SYN || ev->type == EV_ABS) {
447@@ -314,6 +235,13 @@
448 if (frame)
449 report_frame(ge, frame, ev);
450 }
451+
452+ if (ev->type == EV_SYN) {
453+ if (!impl->ongoing)
454+ flush_events(ge);
455+ if (impl->gesture)
456+ flush_gestures(ge);
457+ }
458 }
459
460 int grail_pull(struct grail *ge, int fd)
461
462=== modified file 'src/grail-event.c'
463--- src/grail-event.c 2011-02-09 15:12:13 +0000
464+++ src/grail-event.c 2011-03-04 00:06:44 +0000
465@@ -22,7 +22,6 @@
466
467 #include "grail-inserter.h"
468 #include "grail-impl.h"
469-#include "grail-recognizer.h"
470 #include <malloc.h>
471 #include <string.h>
472 #include <errno.h>
473@@ -83,7 +82,7 @@
474 const struct utouch_frame *frame)
475 {
476 struct grail_coord pos[DIM_TOUCH];
477- int i, npos = 0, num_clients;
478+ int i, npos = 0;
479 if (!ge->get_clients)
480 return 0;
481 grail_mask_foreach(i, span, bspan) {
482@@ -91,20 +90,7 @@
483 pos[npos].y = gin_prop_y(ge->gin, frame->slots[i]->y);
484 npos++;
485 }
486-
487- num_clients = ge->get_clients(ge, info, maxinfo, pos, npos, types,
488- btypes);
489-
490- /* Check if client is handling global gestures, using SYSFLAG1. */
491- if (num_clients > 0 && grail_mask_get(info[0].mask,
492- GRAIL_TYPE_SYSFLAG1)) {
493- /* Save client id, and clear SYSFLAG1 as it isn't a real
494- * gesture type. */
495- ge->gru->global_client = info[0].id.client;
496- grail_mask_clear(info[0].mask, GRAIL_TYPE_SYSFLAG1);
497- }
498-
499- return num_clients;
500+ return ge->get_clients(ge, info, maxinfo, pos, npos, types, btypes);
501 }
502
503 void gin_send_event(struct grail *ge, struct slot_state *s,
504
505=== modified file 'src/grail-gestures.c'
506--- src/grail-gestures.c 2011-01-02 12:08:08 +0000
507+++ src/grail-gestures.c 2011-03-04 00:06:44 +0000
508@@ -24,9 +24,10 @@
509 #include "grail-impl.h"
510 #include <math.h>
511
512-static const float FM_SN[DIM_FM] = { 1000, 1000, 200, 1000 };
513-static const float FM_BAR[DIM_FM] = { 50, 50, 30, 50 };
514-static const grail_time_t FM_BAR_MS[DIM_FM] = { 300, 300, 10000, 10000 };
515+static const float FM_SN[DIM_FM] = { 1000, 1000, 1000, 1000 };
516+static const float FM_BAR[DIM_FM] = { 50, 50, 50, 50 };
517+static const grail_time_t FM_HOLD_MS[DIM_FM] = { 60, 60, 60, 60 };
518+static const grail_time_t FM_BAR_MS[DIM_FM] = { 300, 300, 500, 500 };
519 static const grail_time_t SAMPLE_MS = 10;
520 static const float EPS = 1e-3;
521
522@@ -111,6 +112,7 @@
523 fm->sample_ms = t;
524 m->tickle &= ~(1 << i);
525 m->active &= ~(1 << i);
526+ m->timeout &= ~(1 << i);
527 }
528
529 static void move_update(struct move_model *m, int i, float x, grail_time_t t)
530@@ -132,11 +134,15 @@
531 if (m->active & (1 << i))
532 return;
533 fm->action_delta = x - fm->original;
534- if (fabs(fm->action_delta) > fm->bar ||
535- t - fm->original_ms > fm->bar_ms)
536- m->active |= (1 << i);
537- else
538+ if (t - fm->original_ms > fm->hold_ms &&
539+ fabs(fm->action_delta) > fm->bar) {
540+ m->active |= (1 << i);
541+ } else if (t - fm->original_ms > fm->bar_ms) {
542+ m->active |= (1 << i);
543+ m->timeout |= (1 << i);
544+ } else {
545 fm->action_delta = 0;
546+ }
547 }
548
549 void gru_init_motion(struct grail *ge)
550@@ -153,6 +159,7 @@
551 for (i = 0; i < DIM_FM; i++) {
552 m->fm[i].fuzz = D[i] / FM_SN[i];
553 m->fm[i].bar = D[i] / FM_BAR[i];
554+ m->fm[i].hold_ms = FM_HOLD_MS[i];
555 m->fm[i].bar_ms = FM_BAR_MS[i];
556 }
557 }
558
559=== modified file 'src/grail-gestures.h'
560--- src/grail-gestures.h 2011-01-02 12:08:08 +0000
561+++ src/grail-gestures.h 2011-03-04 00:06:44 +0000
562@@ -49,12 +49,13 @@
563 float bar;
564 grail_time_t original_ms;
565 grail_time_t sample_ms;
566+ grail_time_t hold_ms;
567 grail_time_t bar_ms;
568 };
569
570 struct move_model {
571 struct filter_model fm[DIM_FM];
572- int tickle, active;
573+ int tickle, active, timeout;
574 int single, multi, ntouch;
575 grail_time_t time;
576 };
577@@ -97,7 +98,7 @@
578 const struct utouch_frame *frame);
579
580 struct tapping_model {
581- grail_time_t start, end;
582+ grail_time_t start;
583 int mintouch, maxtouch;
584 int active, gid, tap;
585 int nprop;
586
587=== modified file 'src/grail-impl.h'
588--- src/grail-impl.h 2011-02-02 22:16:20 +0000
589+++ src/grail-impl.h 2011-03-04 00:06:44 +0000
590@@ -42,6 +42,8 @@
591 struct evbuf evbuf;
592 struct grailbuf gbuf;
593 int filter_abs;
594+ int ongoing;
595+ int gesture;
596 };
597
598 #endif
599
600=== modified file 'src/grail-inserter.c'
601--- src/grail-inserter.c 2011-01-02 12:08:08 +0000
602+++ src/grail-inserter.c 2011-03-04 00:06:44 +0000
603@@ -69,6 +69,13 @@
604 for (j = 0; j < nclient; j++) {
605 if (!grail_mask_get(info[j].mask, s->type))
606 continue;
607+ if (gin->grab_active &&
608+ info[j].id.client != gin->grab_client)
609+ continue;
610+ if (grail_mask_get(info[j].mask, GRAIL_TYPE_SYSFLAG1)) {
611+ gin->grab_active = 1;
612+ gin->grab_client = info[j].id.client;
613+ }
614 s->client_id[s->nclient++] = info[j].id;
615 }
616 }
617@@ -105,6 +112,8 @@
618 struct gesture_inserter *gin = ge->gin;
619 memset(gin->types, 0, sizeof(gin->types));
620 gin->time = frame->time;
621+ if (frame->num_active && !frame->prev->num_active)
622+ gin->grab_active = 0;
623 }
624
625 void gin_frame_end(struct grail *ge, const struct utouch_frame *frame)
626
627=== modified file 'src/grail-inserter.h'
628--- src/grail-inserter.h 2011-01-02 12:08:08 +0000
629+++ src/grail-inserter.h 2011-03-04 00:06:44 +0000
630@@ -53,6 +53,8 @@
631 grail_mask_t used[DIM_INSTANCE_BYTES];
632 grail_time_t time;
633 int gestureid;
634+ int grab_active;
635+ int grab_client;
636 float scale_x, scale_y, scale_r;
637 float trans_x, trans_y;
638 };
639
640=== modified file 'src/grail-recognizer.h'
641--- src/grail-recognizer.h 2011-02-09 15:12:13 +0000
642+++ src/grail-recognizer.h 2011-03-04 00:06:44 +0000
643@@ -25,13 +25,6 @@
644
645 #include "grail-gestures.h"
646
647-enum recognition_state {
648- RECOGNIZING,
649- LOCAL,
650- GLOBAL,
651- UNRECOGNIZED
652-};
653-
654 struct gesture_recognizer {
655 struct move_model move;
656 struct combo_model drag;
657@@ -41,9 +34,6 @@
658 struct combo_model winpinch;
659 struct combo_model winrotate;
660 struct tapping_model tapping;
661- utouch_frame_time_t start_time;
662- enum recognition_state state;
663- int global_client;
664 };
665
666 int gru_init(struct grail *ge);

Subscribers

People subscribed via source and target branches

to all changes: