summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChase Douglas <chase.douglas@canonical.com>2011-02-14 16:35:13 +0100
committerHenrik Rydberg <rydberg@euromail.se>2011-03-14 12:55:19 +0100
commit296cc6e9d0fe0d69045cb288f9f470f3760c4a43 (patch)
treebe329db8617905c89130432c3f98c44c5371a64e
parentcc2d67d0f9c6381080de1d666bccfb4b99221113 (diff)
Add in time boundaries for recognition
50 ms: Minimum time waiting for touch configuration to settle before flushing touch events to X. We don't want a two finger gesture triggering X events for the first finger before the second finger lands. 200 ms: Maximum time for touches to begin a gesture. If no gesture is found within this time period, the events are flushed to X. If after 50 ms there are no possible gestures for the number of active touches, the events are immediately flushed to X. If events are flushed to X, no more gesture recognition is possible until all touches are lifted. Likewise, if any gesture is recognized, no events may be flushed to X until all touches are lifted. [rydberg@euromail.se: this patch is severely restrictive and not final] Signed-off-by: Chase Douglas <chase.douglas@canonical.com> Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
-rw-r--r--src/grail-api.c154
-rw-r--r--src/grail-recognizer.h8
2 files changed, 144 insertions, 18 deletions
diff --git a/src/grail-api.c b/src/grail-api.c
index 22724ee..1071825 100644
--- a/src/grail-api.c
+++ b/src/grail-api.c
@@ -34,6 +34,11 @@
34#define DIM_FRAMES 100 34#define DIM_FRAMES 100
35#define FRAME_RATE 100 35#define FRAME_RATE 100
36 36
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 = 200;
41
37void grail_filter_abs_events(struct grail *ge, int usage) 42void grail_filter_abs_events(struct grail *ge, int usage)
38{ 43{
39 struct grail_impl *x = ge->impl; 44 struct grail_impl *x = ge->impl;
@@ -127,34 +132,147 @@ void grail_get_units(const struct grail *ge,
127 max->y = s->max_y; 132 max->y = s->max_y;
128} 133}
129 134
135/* Check for any potential gestures given the number of touch points and where
136 * they occur on screen. */
137static int check_potential_gestures(struct grail *ge,
138 const struct utouch_frame *frame)
139{
140 grail_mask_t types[DIM_GRAIL_TYPE_BYTES] = {0};
141 struct grail_client_info client;
142 struct grail_coord pos[frame->num_active];
143 int i;
144
145 switch (frame->num_active) {
146 case 1:
147 grail_mask_set(types, GRAIL_TYPE_DRAG1);
148 grail_mask_set(types, GRAIL_TYPE_PINCH1);
149 grail_mask_set(types, GRAIL_TYPE_ROTATE1);
150 grail_mask_set(types, GRAIL_TYPE_TAP1);
151 break;
152 case 2:
153 grail_mask_set(types, GRAIL_TYPE_DRAG2);
154 grail_mask_set(types, GRAIL_TYPE_PINCH2);
155 grail_mask_set(types, GRAIL_TYPE_ROTATE2);
156 grail_mask_set(types, GRAIL_TYPE_TAP2);
157 break;
158 case 3:
159 grail_mask_set(types, GRAIL_TYPE_DRAG3);
160 grail_mask_set(types, GRAIL_TYPE_PINCH3);
161 grail_mask_set(types, GRAIL_TYPE_ROTATE3);
162 grail_mask_set(types, GRAIL_TYPE_TAP3);
163 grail_mask_set(types, GRAIL_TYPE_EDRAG);
164 grail_mask_set(types, GRAIL_TYPE_EPINCH);
165 grail_mask_set(types, GRAIL_TYPE_EROTATE);
166 break;
167 case 4:
168 grail_mask_set(types, GRAIL_TYPE_DRAG4);
169 grail_mask_set(types, GRAIL_TYPE_PINCH4);
170 grail_mask_set(types, GRAIL_TYPE_ROTATE4);
171 grail_mask_set(types, GRAIL_TYPE_TAP4);
172 grail_mask_set(types, GRAIL_TYPE_MDRAG);
173 grail_mask_set(types, GRAIL_TYPE_MPINCH);
174 grail_mask_set(types, GRAIL_TYPE_MROTATE);
175 break;
176 case 5:
177 grail_mask_set(types, GRAIL_TYPE_DRAG5);
178 grail_mask_set(types, GRAIL_TYPE_PINCH5);
179 grail_mask_set(types, GRAIL_TYPE_ROTATE5);
180 grail_mask_set(types, GRAIL_TYPE_TAP5);
181 break;
182 }
183
184 for (i = 0; i < frame->num_active; i++) {
185 pos[i].x = gin_prop_x(ge->gin, frame->active[i]->x);
186 pos[i].y = gin_prop_y(ge->gin, frame->active[i]->y);
187 }
188
189 return ge->get_clients(ge, &client, 1, pos, frame->num_active,
190 types, DIM_GRAIL_TYPE_BYTES);
191}
192
130static void report_frame(struct grail *ge, 193static void report_frame(struct grail *ge,
131 const struct utouch_frame *frame, 194 const struct utouch_frame *frame,
132 const struct input_event *syn) 195 const struct input_event *syn)
133{ 196{
134
135 struct grail_impl *impl = ge->impl; 197 struct grail_impl *impl = ge->impl;
198 struct gesture_recognizer *gru = ge->gru;
136 struct input_event iev; 199 struct input_event iev;
137 struct grail_event gev; 200 struct grail_event gev;
138 201
139 ge->impl->frame = frame; 202 ge->impl->frame = frame;
140 203
141 gin_frame_begin(ge, frame); 204 /* Reset timer when number of touches changes. */
142 gru_recognize(ge, frame); 205 if (frame->prev->revision != frame->revision && frame->num_active) {
143 gin_frame_end(ge, frame); 206 gru->start_time = frame->time;
144 207 }
145 if (grailbuf_empty(&impl->gbuf)) { 208
146 while (!evbuf_empty(&impl->evbuf)) { 209 /* Once touches have stabilized, check if there are any potential
147 evbuf_get(&impl->evbuf, &iev); 210 * gestures registered for the number of touches. */
148 if (ge->event) 211 if (gru->state == RECOGNIZING &&
149 ge->event(ge, &iev); 212 frame->time > gru->start_time + stable_time &&
150 } 213 check_potential_gestures(ge, frame) == 0)
151 } else { 214 gru->state = UNRECOGNIZED;
152 while (!grailbuf_empty(&impl->gbuf)) { 215
153 grailbuf_get(&impl->gbuf, &gev); 216 /* Process the frame for gestures unless we're sure there are none. */
154 if (ge->gesture) 217 if (gru->state != UNRECOGNIZED) {
155 ge->gesture(ge, &gev); 218 gin_frame_begin(ge, frame);
156 } 219 gru_recognize(ge, frame);
157 evbuf_clear(&impl->evbuf); 220 gin_frame_end(ge, frame);
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 gru->state = RECOGNIZED;
234 /* If there is no gesture and all touches lifted, set state to
235 * unrecognized. */
236 else if (frame->num_active == 0)
237 gru->state = UNRECOGNIZED;
238 }
239
240 /* Now we have the state set, process events. */
241 switch (gru->state) {
242 case RECOGNIZED:
243 while (!grailbuf_empty(&impl->gbuf)) {
244 grailbuf_get(&impl->gbuf, &gev);
245 if (ge->gesture)
246 ge->gesture(ge, &gev);
247 }
248 evbuf_clear(&impl->evbuf);
249
250 /* Once all touches are lifted and no gestures are
251 * active, reset recognition state. */
252 if (grail_mask_count(ge->gin->used, DIM_INSTANCE_BYTES) == 0 &&
253 frame->num_active == 0)
254 gru->state = RECOGNIZING;
255 break;
256
257 case RECOGNIZING:
258 /* If we're still actively recognizing, stop here. */
259 if (frame->time <= gru->start_time + recognition_time)
260 break;
261 gru->state = UNRECOGNIZED;
262
263 case UNRECOGNIZED:
264 while (!evbuf_empty(&impl->evbuf)) {
265 evbuf_get(&impl->evbuf, &iev);
266 if (ge->event)
267 ge->event(ge, &iev);
268 }
269 grailbuf_clear(&impl->gbuf);
270
271 /* Once all touches are lifted, reset recognition
272 * state. */
273 if (frame->num_active == 0)
274 gru->state = RECOGNIZING;
275 break;
158 } 276 }
159} 277}
160 278
diff --git a/src/grail-recognizer.h b/src/grail-recognizer.h
index 56e5b8d..b08ff34 100644
--- a/src/grail-recognizer.h
+++ b/src/grail-recognizer.h
@@ -25,6 +25,12 @@
25 25
26#include "grail-gestures.h" 26#include "grail-gestures.h"
27 27
28enum recognition_state {
29 RECOGNIZING,
30 RECOGNIZED,
31 UNRECOGNIZED
32};
33
28struct gesture_recognizer { 34struct gesture_recognizer {
29 struct move_model move; 35 struct move_model move;
30 struct combo_model drag; 36 struct combo_model drag;
@@ -34,6 +40,8 @@ struct gesture_recognizer {
34 struct combo_model winpinch; 40 struct combo_model winpinch;
35 struct combo_model winrotate; 41 struct combo_model winrotate;
36 struct tapping_model tapping; 42 struct tapping_model tapping;
43 utouch_frame_time_t start_time;
44 enum recognition_state state;
37}; 45};
38 46
39int gru_init(struct grail *ge); 47int gru_init(struct grail *ge);