summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gestures-drag.c14
-rw-r--r--src/gestures-pinch.c14
-rw-r--r--src/gestures-rotate.c14
-rw-r--r--src/grail-api.c173
-rw-r--r--src/grail-gestures.c10
-rw-r--r--src/grail-gestures.h2
-rw-r--r--src/grail-impl.h2
-rw-r--r--src/grail-recognizer.h8
8 files changed, 98 insertions, 139 deletions
diff --git a/src/gestures-drag.c b/src/gestures-drag.c
index 05272da..9f2bcaf 100644
--- a/src/gestures-drag.c
+++ b/src/gestures-drag.c
@@ -72,6 +72,13 @@ int gru_drag(struct grail *ge,
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 @@ int gru_windrag(struct grail *ge,
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,
diff --git a/src/gestures-pinch.c b/src/gestures-pinch.c
index fa8a626..e022e8d 100644
--- a/src/gestures-pinch.c
+++ b/src/gestures-pinch.c
@@ -62,6 +62,13 @@ int gru_pinch(struct grail *ge,
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 @@ int gru_winpinch(struct grail *ge,
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) {
diff --git a/src/gestures-rotate.c b/src/gestures-rotate.c
index fde0db8..dd95c32 100644
--- a/src/gestures-rotate.c
+++ b/src/gestures-rotate.c
@@ -61,6 +61,13 @@ int gru_rotate(struct grail *ge,
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 @@ int gru_winrotate(struct grail *ge,
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) {
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)
diff --git a/src/grail-gestures.c b/src/grail-gestures.c
index 035a199..efadde5 100644
--- a/src/grail-gestures.c
+++ b/src/grail-gestures.c
@@ -111,6 +111,7 @@ static void move_reset(struct move_model *m, int i, float x, grail_time_t t)
111 fm->sample_ms = t; 111 fm->sample_ms = t;
112 m->tickle &= ~(1 << i); 112 m->tickle &= ~(1 << i);
113 m->active &= ~(1 << i); 113 m->active &= ~(1 << i);
114 m->timeout &= ~(1 << i);
114} 115}
115 116
116static void move_update(struct move_model *m, int i, float x, grail_time_t t) 117static void move_update(struct move_model *m, int i, float x, grail_time_t t)
@@ -132,11 +133,14 @@ static void move_update(struct move_model *m, int i, float x, grail_time_t t)
132 if (m->active & (1 << i)) 133 if (m->active & (1 << i))
133 return; 134 return;
134 fm->action_delta = x - fm->original; 135 fm->action_delta = x - fm->original;
135 if (fabs(fm->action_delta) > fm->bar || 136 if (fabs(fm->action_delta) > fm->bar) {
136 t - fm->original_ms > fm->bar_ms)
137 m->active |= (1 << i); 137 m->active |= (1 << i);
138 else 138 } else if (t - fm->original_ms > fm->bar_ms) {
139 m->active |= (1 << i);
140 m->timeout |= (1 << i);
141 } else {
139 fm->action_delta = 0; 142 fm->action_delta = 0;
143 }
140} 144}
141 145
142void gru_init_motion(struct grail *ge) 146void gru_init_motion(struct grail *ge)
diff --git a/src/grail-gestures.h b/src/grail-gestures.h
index a6d51d5..c4c46c2 100644
--- a/src/grail-gestures.h
+++ b/src/grail-gestures.h
@@ -54,7 +54,7 @@ struct filter_model {
54 54
55struct move_model { 55struct move_model {
56 struct filter_model fm[DIM_FM]; 56 struct filter_model fm[DIM_FM];
57 int tickle, active; 57 int tickle, active, timeout;
58 int single, multi, ntouch; 58 int single, multi, ntouch;
59 grail_time_t time; 59 grail_time_t time;
60}; 60};
diff --git a/src/grail-impl.h b/src/grail-impl.h
index 595f0fb..2c63b90 100644
--- a/src/grail-impl.h
+++ b/src/grail-impl.h
@@ -42,6 +42,8 @@ struct grail_impl {
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};
46 48
47#endif 49#endif
diff --git a/src/grail-recognizer.h b/src/grail-recognizer.h
index b08ff34..56e5b8d 100644
--- a/src/grail-recognizer.h
+++ b/src/grail-recognizer.h
@@ -25,12 +25,6 @@
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
34struct gesture_recognizer { 28struct gesture_recognizer {
35 struct move_model move; 29 struct move_model move;
36 struct combo_model drag; 30 struct combo_model drag;
@@ -40,8 +34,6 @@ struct gesture_recognizer {
40 struct combo_model winpinch; 34 struct combo_model winpinch;
41 struct combo_model winrotate; 35 struct combo_model winrotate;
42 struct tapping_model tapping; 36 struct tapping_model tapping;
43 utouch_frame_time_t start_time;
44 enum recognition_state state;
45}; 37};
46 38
47int gru_init(struct grail *ge); 39int gru_init(struct grail *ge);