Merge lp:~oif-team/grail/trunk.touch into lp:grail
- trunk.touch
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~oif-team/grail/trunk.touch |
Merge into: | lp:grail |
Diff against target: |
425 lines (+176/-29) 12 files modified
include/grail-types.h (+9/-0) src/Makefile.am (+1/-0) src/gestures-drag.c (+4/-8) src/gestures-pinch.c (+2/-6) src/gestures-rotate.c (+2/-6) src/gestures-touch.c (+96/-0) src/grail-gestures.c (+6/-7) src/grail-gestures.h (+4/-0) src/grail-inserter.c (+45/-2) src/grail-inserter.h (+3/-0) src/grail-recognizer.c (+2/-0) src/grail-recognizer.h (+2/-0) |
To merge this branch: | bzr merge lp:~oif-team/grail/trunk.touch |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Chase Douglas (community) | Needs Fixing | ||
Review via email: mp+54924@code.launchpad.net |
This proposal has been superseded by a proposal from 2011-03-25.
Commit message
Description of the change
This patchset introduces gesture touch events.
- 133. By Henrik Rydberg
-
Introduce touch gesture events
Touch gesture events follow the same logic as drags, except they
cannot be held back but are emitted immediately.Signed-off-by: Henrik Rydberg <email address hidden>
- 134. By Henrik Rydberg
-
Decouple timeout from discard
Move the actual gesture discard from the recognition phase
to the instantiation phase.Signed-off-by: Henrik Rydberg <email address hidden>
- 135. By Henrik Rydberg
-
Do not timeout gestures overlapping touch gestures
The notion of listening to touch gestures implies that the
touches of those gestures never timeout. Hence, any pending
gesture that overlaps those touches should not timeout.Signed-off-by: Henrik Rydberg <email address hidden>
- 136. By Henrik Rydberg
-
Never active gestures below activation threshold
Currently, all gestures activate after a certain time, such that
the smallest change result in gesture events. This was designed
to minimize disruption in pointer movement. Since grail no longer
handles pointers, the logic can be simplified to only activate when
the threshold is reached.Signed-off-by: Henrik Rydberg <email address hidden>
- 137. By Henrik Rydberg
-
Do not treat single finger activation differently
Single-finger drags should no longer behave differently from
any other drag gesture. Fixed with this patch.Signed-off-by: Henrik Rydberg <email address hidden>
- 138. By Henrik Rydberg
-
Do not hold back active gestures
Gestures that has once been sent should never be held back. The
current code would under some circumstance hold the gesture end
event and later discard it. This oneliner solves the problem, which
has been around since 241c5ec, Aug 2010. LP: #744391.Signed-off-by: Henrik Rydberg <email address hidden>
Unmerged revisions
Preview Diff
1 | === modified file 'include/grail-types.h' |
2 | --- include/grail-types.h 2010-08-19 20:36:11 +0000 |
3 | +++ include/grail-types.h 2011-03-25 20:48:45 +0000 |
4 | @@ -59,6 +59,15 @@ |
5 | |
6 | #define GRAIL_TYPE_SYSFLAG1 26 /* reserved system flag */ |
7 | |
8 | +/* touch event types use drag properties */ |
9 | +#define GRAIL_TYPE_TOUCH1 32 /* one-finger touch */ |
10 | +#define GRAIL_TYPE_TOUCH2 33 /* two-finger touch */ |
11 | +#define GRAIL_TYPE_TOUCH3 34 /* three-finger touch */ |
12 | +#define GRAIL_TYPE_TOUCH4 35 /* four-finger touch */ |
13 | +#define GRAIL_TYPE_TOUCH5 36 /* five-finger touch */ |
14 | +#define GRAIL_TYPE_ETOUCH 37 /* three-finger environment touch */ |
15 | +#define GRAIL_TYPE_MTOUCH 38 /* four-finger meta touch */ |
16 | + |
17 | #define GRAIL_MAIN_DRAG 0 |
18 | #define GRAIL_MAIN_PINCH 1 |
19 | #define GRAIL_MAIN_ROTATE 2 |
20 | |
21 | === modified file 'src/Makefile.am' |
22 | --- src/Makefile.am 2011-01-02 12:08:42 +0000 |
23 | +++ src/Makefile.am 2011-03-25 20:48:45 +0000 |
24 | @@ -17,6 +17,7 @@ |
25 | grail-inserter.h \ |
26 | grail-gestures.c \ |
27 | grail-gestures.h \ |
28 | + gestures-touch.c \ |
29 | gestures-drag.c \ |
30 | gestures-pinch.c \ |
31 | gestures-rotate.c \ |
32 | |
33 | === modified file 'src/gestures-drag.c' |
34 | --- src/gestures-drag.c 2011-03-17 09:48:13 +0000 |
35 | +++ src/gestures-drag.c 2011-03-25 20:48:45 +0000 |
36 | @@ -70,10 +70,8 @@ |
37 | } |
38 | if ((move->timeout & fm_mask) == fm_mask) { |
39 | if (state->active) { |
40 | - gin_gid_discard(ge, state->gid); |
41 | - state->active = 0; |
42 | + gin_gid_timeout(ge, state->gid); |
43 | } |
44 | - return 0; |
45 | } |
46 | if (!state->active) { |
47 | int type = getype[move->ntouch]; |
48 | @@ -84,7 +82,7 @@ |
49 | } |
50 | if (!(move->tickle & mask)) |
51 | return 0; |
52 | - if (!move->single && !(move->active & fm_mask)) |
53 | + if (!(move->active & fm_mask)) |
54 | return 0; |
55 | set_props(ge->gin, state, move, frame); |
56 | gru_event(ge, state->gid, move, state->prop, state->nprop); |
57 | @@ -107,10 +105,8 @@ |
58 | } |
59 | if ((move->timeout & fm_mask) == fm_mask) { |
60 | if (state->active) { |
61 | - gin_gid_discard(ge, state->gid); |
62 | - state->active = 0; |
63 | + gin_gid_timeout(ge, state->gid); |
64 | } |
65 | - return 0; |
66 | } |
67 | if (!state->active) { |
68 | if (move->ntouch == 4) { |
69 | @@ -131,7 +127,7 @@ |
70 | } |
71 | if (!(move->tickle & mask)) |
72 | return 0; |
73 | - if (!move->single && !(move->active & fm_mask)) |
74 | + if (!(move->active & fm_mask)) |
75 | return 0; |
76 | set_props(ge->gin, state, move, frame); |
77 | gru_event(ge, state->gid, move, state->prop, state->nprop); |
78 | |
79 | === modified file 'src/gestures-pinch.c' |
80 | --- src/gestures-pinch.c 2011-03-17 09:48:13 +0000 |
81 | +++ src/gestures-pinch.c 2011-03-25 20:48:45 +0000 |
82 | @@ -64,10 +64,8 @@ |
83 | } |
84 | if ((move->timeout & fm_mask) == fm_mask) { |
85 | if (state->active) { |
86 | - gin_gid_discard(ge, state->gid); |
87 | - state->active = 0; |
88 | + gin_gid_timeout(ge, state->gid); |
89 | } |
90 | - return 0; |
91 | } |
92 | if (!(move->tickle & mask)) |
93 | return 0; |
94 | @@ -102,10 +100,8 @@ |
95 | } |
96 | if ((move->timeout & fm_mask) == fm_mask) { |
97 | if (state->active) { |
98 | - gin_gid_discard(ge, state->gid); |
99 | - state->active = 0; |
100 | + gin_gid_timeout(ge, state->gid); |
101 | } |
102 | - return 0; |
103 | } |
104 | if (!(move->tickle & mask)) |
105 | return 0; |
106 | |
107 | === modified file 'src/gestures-rotate.c' |
108 | --- src/gestures-rotate.c 2011-02-24 22:51:33 +0000 |
109 | +++ src/gestures-rotate.c 2011-03-25 20:48:45 +0000 |
110 | @@ -63,10 +63,8 @@ |
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 | + gin_gid_timeout(ge, state->gid); |
117 | } |
118 | - return 0; |
119 | } |
120 | if (!(move->tickle & mask)) |
121 | return 0; |
122 | @@ -101,10 +99,8 @@ |
123 | } |
124 | if ((move->timeout & fm_mask) == fm_mask) { |
125 | if (state->active) { |
126 | - gin_gid_discard(ge, state->gid); |
127 | - state->active = 0; |
128 | + gin_gid_timeout(ge, state->gid); |
129 | } |
130 | - return 0; |
131 | } |
132 | if (!(move->tickle & mask)) |
133 | return 0; |
134 | |
135 | === added file 'src/gestures-touch.c' |
136 | --- src/gestures-touch.c 1970-01-01 00:00:00 +0000 |
137 | +++ src/gestures-touch.c 2011-03-25 20:48:45 +0000 |
138 | @@ -0,0 +1,96 @@ |
139 | +/***************************************************************************** |
140 | + * |
141 | + * grail - Gesture Recognition And Instantiation Library |
142 | + * |
143 | + * Copyright (C) 2010 Canonical Ltd. |
144 | + * Copyright (C) 2010 Henrik Rydberg <rydberg@bitmath.org> |
145 | + * |
146 | + * This program is free software: you can redistribute it and/or modify it |
147 | + * under the terms of the GNU General Public License as published by the |
148 | + * Free Software Foundation, either version 3 of the License, or (at your |
149 | + * option) any later version. |
150 | + * |
151 | + * This program is distributed in the hope that it will be useful, but |
152 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
153 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
154 | + * General Public License for more details. |
155 | + * |
156 | + * You should have received a copy of the GNU General Public License along |
157 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
158 | + * |
159 | + ****************************************************************************/ |
160 | + |
161 | +#include "grail-recognizer.h" |
162 | +#include <math.h> |
163 | +#include <stdio.h> |
164 | + |
165 | +static const int getype[DIM_TOUCH + 1] = { |
166 | + -1, |
167 | + GRAIL_TYPE_TOUCH1, |
168 | + GRAIL_TYPE_TOUCH2, |
169 | + GRAIL_TYPE_TOUCH3, |
170 | + GRAIL_TYPE_TOUCH4, |
171 | + GRAIL_TYPE_TOUCH5, |
172 | +}; |
173 | + |
174 | +static const int fm_mask = 0x03; |
175 | + |
176 | +int gru_touch(struct grail *ge, |
177 | + const struct utouch_frame *frame) |
178 | +{ |
179 | + struct gesture_recognizer *gru = ge->gru; |
180 | + struct combo_model *state = &gru->touch; |
181 | + struct move_model *move = &gru->move; |
182 | + if (frame->slot_revision != frame->prev->slot_revision) { |
183 | + if (state->active) { |
184 | + gru_end(ge, state->gid, move, |
185 | + state->prop, state->nprop); |
186 | + state->active = 0; |
187 | + } |
188 | + } |
189 | + if (!state->active) { |
190 | + int type = getype[move->ntouch]; |
191 | + if (type <= 0) |
192 | + return 0; |
193 | + state->gid = gin_gid_begin(ge, type, -PRIO_GESTURE, frame); |
194 | + state->active = 1; |
195 | + } |
196 | + state->nprop = gin_add_contact_props(ge->gin, state->prop, frame); |
197 | + gru_event(ge, state->gid, move, state->prop, state->nprop); |
198 | + return 1; |
199 | +} |
200 | + |
201 | +int gru_wintouch(struct grail *ge, |
202 | + const struct utouch_frame *frame) |
203 | +{ |
204 | + struct gesture_recognizer *gru = ge->gru; |
205 | + struct combo_model *state = &gru->wintouch; |
206 | + struct move_model *move = &gru->move; |
207 | + if (frame->slot_revision != frame->prev->slot_revision) { |
208 | + if (state->active && out_of_bounds(state, move)) { |
209 | + gru_end(ge, state->gid, move, |
210 | + state->prop, state->nprop); |
211 | + state->active = 0; |
212 | + } |
213 | + } |
214 | + if (!state->active) { |
215 | + if (move->ntouch == 4) { |
216 | + state->gid = gin_gid_begin(ge, GRAIL_TYPE_MTOUCH, |
217 | + -PRIO_META, frame); |
218 | + state->mintouch = 1; |
219 | + state->maxtouch = 4; |
220 | + state->active = 1; |
221 | + } else if (move->ntouch == 3) { |
222 | + state->gid = gin_gid_begin(ge, GRAIL_TYPE_ETOUCH, |
223 | + -PRIO_ENV, frame); |
224 | + state->mintouch = 1; |
225 | + state->maxtouch = 3; |
226 | + state->active = 1; |
227 | + } else { |
228 | + return 0; |
229 | + } |
230 | + } |
231 | + state->nprop = gin_add_contact_props(ge->gin, state->prop, frame); |
232 | + gru_event(ge, state->gid, move, state->prop, state->nprop); |
233 | + return 1; |
234 | +} |
235 | |
236 | === modified file 'src/grail-gestures.c' |
237 | --- src/grail-gestures.c 2011-03-17 09:48:13 +0000 |
238 | +++ src/grail-gestures.c 2011-03-25 20:48:45 +0000 |
239 | @@ -133,15 +133,14 @@ |
240 | m->tickle &= ~(1 << i); |
241 | if (m->active & (1 << i)) |
242 | return; |
243 | - fm->action_delta = x - fm->original; |
244 | - if (t - fm->original_ms > fm->hold_ms && |
245 | - fabs(fm->action_delta) > fm->bar) { |
246 | - m->active |= (1 << i); |
247 | + fm->action_delta = 0; |
248 | + if (fabs(x - fm->original) > fm->bar) { |
249 | + if (t - fm->original_ms > fm->hold_ms) { |
250 | + m->active |= (1 << i); |
251 | + fm->action_delta = x - fm->original; |
252 | + } |
253 | } else if (t - fm->original_ms > fm->bar_ms) { |
254 | - m->active |= (1 << i); |
255 | m->timeout |= (1 << i); |
256 | - } else { |
257 | - fm->action_delta = 0; |
258 | } |
259 | } |
260 | |
261 | |
262 | === modified file 'src/grail-gestures.h' |
263 | --- src/grail-gestures.h 2011-02-24 22:51:17 +0000 |
264 | +++ src/grail-gestures.h 2011-03-25 20:48:45 +0000 |
265 | @@ -77,6 +77,8 @@ |
266 | grail_prop_t prop[DIM_GRAIL_PROP]; |
267 | }; |
268 | |
269 | +int gru_touch(struct grail *ge, |
270 | + const struct utouch_frame *frame); |
271 | int gru_drag(struct grail *ge, |
272 | const struct utouch_frame *frame); |
273 | int gru_pinch(struct grail *ge, |
274 | @@ -90,6 +92,8 @@ |
275 | return m->ntouch < s->mintouch || m->ntouch > s->maxtouch; |
276 | } |
277 | |
278 | +int gru_wintouch(struct grail *ge, |
279 | + const struct utouch_frame *frame); |
280 | int gru_windrag(struct grail *ge, |
281 | const struct utouch_frame *frame); |
282 | int gru_winpinch(struct grail *ge, |
283 | |
284 | === modified file 'src/grail-inserter.c' |
285 | --- src/grail-inserter.c 2011-03-17 09:48:13 +0000 |
286 | +++ src/grail-inserter.c 2011-03-25 20:48:45 +0000 |
287 | @@ -38,6 +38,18 @@ |
288 | return -1; |
289 | } |
290 | |
291 | +static int mask_overlap(const grail_mask_t *a, const grail_mask_t *b, |
292 | + int bytes) |
293 | +{ |
294 | + int i; |
295 | + |
296 | + for (i = 0; i < bytes; i++) |
297 | + if (a[i] & b[i]) |
298 | + return 1; |
299 | + |
300 | + return 0; |
301 | +} |
302 | + |
303 | // todo: spanning tree for multi-user case |
304 | static void setup_new_gestures(struct grail *ge, |
305 | const struct utouch_frame *frame) |
306 | @@ -114,8 +126,10 @@ |
307 | void gin_frame_end(struct grail *ge, const struct utouch_frame *frame) |
308 | { |
309 | struct gesture_inserter *gin = ge->gin; |
310 | + grail_mask_t keep[DIM_TOUCH_BYTES]; |
311 | int i, hold = 0, discard = 0; |
312 | |
313 | + memset(keep, 0, sizeof(keep)); |
314 | setup_new_gestures(ge, frame); |
315 | |
316 | grail_mask_foreach(i, gin->used, sizeof(gin->used)) { |
317 | @@ -138,9 +152,24 @@ |
318 | |
319 | grail_mask_foreach(i, gin->used, sizeof(gin->used)) { |
320 | struct slot_state *s = &gin->state[i]; |
321 | + if (!s->allowhold) |
322 | + grail_mask_set_mask(keep, s->span, sizeof(keep)); |
323 | + } |
324 | + |
325 | + grail_mask_foreach(i, gin->used, sizeof(gin->used)) { |
326 | + struct slot_state *s = &gin->state[i]; |
327 | + if (!s->timeout) |
328 | + continue; |
329 | + if (mask_overlap(keep, s->span, sizeof(keep))) |
330 | + continue; |
331 | + gin_gid_discard(ge, s->id); |
332 | + } |
333 | + |
334 | + grail_mask_foreach(i, gin->used, sizeof(gin->used)) { |
335 | + struct slot_state *s = &gin->state[i]; |
336 | struct gesture_event ev; |
337 | grail_mask_set(gin->types, s->type); |
338 | - if (s->priority < hold) |
339 | + if (s->priority < hold && s->allowhold) |
340 | continue; |
341 | while (!gebuf_empty(&s->buf)) { |
342 | gebuf_get(&s->buf, &ev); |
343 | @@ -166,7 +195,14 @@ |
344 | return -1; |
345 | s = &gin->state[i]; |
346 | s->type = type; |
347 | - s->priority = priority; |
348 | + if (priority < 0) { |
349 | + s->priority = -priority; |
350 | + s->allowhold = 0; |
351 | + } else { |
352 | + s->priority = priority; |
353 | + s->allowhold = 1; |
354 | + } |
355 | + s->timeout = 0; |
356 | s->id = gin->gestureid++ & MAX_GESTURE_ID; |
357 | s->status = GRAIL_STATUS_BEGIN; |
358 | s->nclient = 0; |
359 | @@ -193,6 +229,13 @@ |
360 | grail_mask_set(gin->unused, i); |
361 | } |
362 | |
363 | +void gin_gid_timeout(struct grail *ge, int gid) |
364 | +{ |
365 | + int i = find_gslot(ge->gin, gid); |
366 | + if (i >= 0) |
367 | + ge->gin->state[i].timeout = 1; |
368 | +} |
369 | + |
370 | void gin_gid_event(struct grail *ge, int gid, |
371 | float x, float y, int ntouch, |
372 | const grail_prop_t *prop, int nprop, |
373 | |
374 | === modified file 'src/grail-inserter.h' |
375 | --- src/grail-inserter.h 2011-03-17 09:48:13 +0000 |
376 | +++ src/grail-inserter.h 2011-03-25 20:48:45 +0000 |
377 | @@ -37,6 +37,8 @@ |
378 | struct slot_state { |
379 | int type; |
380 | int priority; |
381 | + int allowhold; |
382 | + int timeout; |
383 | int id; |
384 | int status; |
385 | int nclient; |
386 | @@ -78,6 +80,7 @@ |
387 | int gin_gid_begin(struct grail *ge, int type, int priority, |
388 | const struct utouch_frame *frame); |
389 | void gin_gid_discard(struct grail *ge, int gid); |
390 | +void gin_gid_timeout(struct grail *ge, int gid); |
391 | |
392 | void gin_gid_event(struct grail *ge, int gid, |
393 | float x, float y, int ntouch, |
394 | |
395 | === modified file 'src/grail-recognizer.c' |
396 | --- src/grail-recognizer.c 2011-01-02 12:08:08 +0000 |
397 | +++ src/grail-recognizer.c 2011-03-25 20:48:45 +0000 |
398 | @@ -47,9 +47,11 @@ |
399 | if (!ge->gin || !ge->gru) |
400 | return; |
401 | gru_motion(ge, frame); |
402 | + gru_touch(ge, frame); |
403 | gru_drag(ge, frame); |
404 | gru_pinch(ge, frame); |
405 | gru_rotate(ge, frame); |
406 | + gru_wintouch(ge, frame); |
407 | gru_windrag(ge, frame); |
408 | gru_winpinch(ge, frame); |
409 | gru_winrotate(ge, frame); |
410 | |
411 | === modified file 'src/grail-recognizer.h' |
412 | --- src/grail-recognizer.h 2011-02-24 22:49:22 +0000 |
413 | +++ src/grail-recognizer.h 2011-03-25 20:48:45 +0000 |
414 | @@ -27,9 +27,11 @@ |
415 | |
416 | struct gesture_recognizer { |
417 | struct move_model move; |
418 | + struct combo_model touch; |
419 | struct combo_model drag; |
420 | struct combo_model pinch; |
421 | struct combo_model rotate; |
422 | + struct combo_model wintouch; |
423 | struct combo_model windrag; |
424 | struct combo_model winpinch; |
425 | struct combo_model winrotate; |
I'm guessing the functionality is correct, but the header file is missing the TOUCH event attributes (just like there are separate DRAG, PINCH, ROTATE, etc. attributes).