summaryrefslogtreecommitdiff
path: root/src/grail-api.c
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2011-02-24 23:38:01 +0100
committerHenrik Rydberg <rydberg@euromail.se>2011-03-14 12:55:19 +0100
commitf92c18c344c04a2501e01ae402441a92883da382 (patch)
treefec506ca8784002083babe767505930be2a8d25a /src/grail-api.c
parent609e367b3ee2b587f698b65393aa22357f453add (diff)
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. Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Diffstat (limited to 'src/grail-api.c')
-rw-r--r--src/grail-api.c173
1 files changed, 46 insertions, 127 deletions
diff --git a/src/grail-api.c b/src/grail-api.c
index 1071825..6521f84 100644
--- a/src/grail-api.c
+++ b/src/grail-api.c
@@ -34,11 +34,6 @@
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
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,37 @@ void grail_get_units(const struct grail *ge,
132 max->y = s->max_y; 127 max->y = s->max_y;
133} 128}
134 129
135/* Check for any potential gestures given the number of touch points and where 130static void flush_events(struct grail *ge)
136 * they occur on screen. */
137static int check_potential_gestures(struct grail *ge,
138 const struct utouch_frame *frame)
139{ 131{
140 grail_mask_t types[DIM_GRAIL_TYPE_BYTES] = {0}; 132 struct grail_impl *impl = ge->impl;
141 struct grail_client_info client; 133 struct input_event ev;
142 struct grail_coord pos[frame->num_active]; 134
143 int i; 135 grailbuf_clear(&impl->gbuf);
144 136 while (!evbuf_empty(&impl->evbuf)) {
145 switch (frame->num_active) { 137 evbuf_get(&impl->evbuf, &ev);
146 case 1: 138 if (ge->event)
147 grail_mask_set(types, GRAIL_TYPE_DRAG1); 139 ge->event(ge, &ev);
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 } 140 }
141}
183 142
184 for (i = 0; i < frame->num_active; i++) { 143static void flush_gestures(struct grail *ge)
185 pos[i].x = gin_prop_x(ge->gin, frame->active[i]->x); 144{
186 pos[i].y = gin_prop_y(ge->gin, frame->active[i]->y); 145 struct grail_impl *impl = ge->impl;
146 struct grail_event ev;
147
148 evbuf_clear(&impl->evbuf);
149 while (!grailbuf_empty(&impl->gbuf)) {
150 grailbuf_get(&impl->gbuf, &ev);
151 if (ge->gesture)
152 ge->gesture(ge, &ev);
187 } 153 }
154}
188 155
189 return ge->get_clients(ge, &client, 1, pos, frame->num_active, 156static int gesture_timeout(struct grail *ge, const struct utouch_frame *frame)
190 types, DIM_GRAIL_TYPE_BYTES); 157{
158 struct gesture_inserter *gin = ge->gin;
159
160 return grail_mask_count(gin->used, sizeof(gin->used)) == 0;
191} 161}
192 162
193static void report_frame(struct grail *ge, 163static void report_frame(struct grail *ge,
@@ -195,85 +165,27 @@ static void report_frame(struct grail *ge,
195 const struct input_event *syn) 165 const struct input_event *syn)
196{ 166{
197 struct grail_impl *impl = ge->impl; 167 struct grail_impl *impl = ge->impl;
198 struct gesture_recognizer *gru = ge->gru;
199 struct input_event iev;
200 struct grail_event gev; 168 struct grail_event gev;
201 169
202 ge->impl->frame = frame; 170 ge->impl->frame = frame;
203 171
204 /* Reset timer when number of touches changes. */ 172 if (frame->num_active && !frame->prev->num_active) {
205 if (frame->prev->revision != frame->revision && frame->num_active) { 173 impl->ongoing = 1;
206 gru->start_time = frame->time; 174 impl->gesture = 0;
207 } 175 }
208 176
209 /* Once touches have stabilized, check if there are any potential 177 if (!impl->ongoing)
210 * gestures registered for the number of touches. */ 178 return;
211 if (gru->state == RECOGNIZING &&
212 frame->time > gru->start_time + stable_time &&
213 check_potential_gestures(ge, frame) == 0)
214 gru->state = UNRECOGNIZED;
215
216 /* Process the frame for gestures unless we're sure there are none. */
217 if (gru->state != UNRECOGNIZED) {
218 gin_frame_begin(ge, frame);
219 gru_recognize(ge, frame);
220 gin_frame_end(ge, frame);
221 }
222 179
223 if (gru->state == RECOGNIZING) { 180 gin_frame_begin(ge, frame);
224 /* If a gesture is recognized and either all touches lifted or 181 gru_recognize(ge, frame);
225 * we are within the recognition interval, set state to 182 gin_frame_end(ge, frame);
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 183
240 /* Now we have the state set, process events. */ 184 if (!grailbuf_empty(&impl->gbuf))
241 switch (gru->state) { 185 impl->gesture = 1;
242 case RECOGNIZED: 186
243 while (!grailbuf_empty(&impl->gbuf)) { 187 if (frame->num_active == 0 || gesture_timeout(ge, frame))
244 grailbuf_get(&impl->gbuf, &gev); 188 impl->ongoing &= impl->gesture;
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;
276 }
277} 189}
278 190
279static void grail_pump_mtdev(struct grail *ge, const struct input_event *ev) 191static void grail_pump_mtdev(struct grail *ge, const struct input_event *ev)
@@ -288,6 +200,13 @@ static void grail_pump_mtdev(struct grail *ge, const struct input_event *ev)
288 if (frame) 200 if (frame)
289 report_frame(ge, frame, ev); 201 report_frame(ge, frame, ev);
290 } 202 }
203
204 if (ev->type == EV_SYN) {
205 if (!impl->ongoing)
206 flush_events(ge);
207 if (impl->gesture)
208 flush_gestures(ge);
209 }
291} 210}
292 211
293int grail_pull(struct grail *ge, int fd) 212int grail_pull(struct grail *ge, int fd)