Merge lp:~oif-team/grail/cooperate-with-xi2.1 into lp:grail

Proposed by Chase Douglas
Status: Merged
Merged at revision: 108
Proposed branch: lp:~oif-team/grail/cooperate-with-xi2.1
Merge into: lp:grail
Diff against target: 356 lines (+110/-146)
4 files modified
src/grail-api.c (+101/-139)
src/grail-impl.h (+0/-7)
src/grail-recognizer.h (+8/-0)
tools/grail-gesture.c (+1/-0)
To merge this branch: bzr merge lp:~oif-team/grail/cooperate-with-xi2.1
Reviewer Review Type Date Requested Status
Stephen M. Webb (community) Approve
Review via email: mp+48399@code.launchpad.net

Description of the change

Before XI 2.1, we were fine just grabbing events and dropping them on the floor or emulating pointer motion. Now, we need to play nicely with X. This includes sending X the unadulterated event stream if there are no gestures found. This branch has two main commits: one to remove the old pointer emulation code, and one to add new code for sending events to X when appropriate.

I'll be pushing this to the xorg-unstable ppa soon.

To post a comment you must log in.
Revision history for this message
Stephen M. Webb (bregma) wrote :

The changes look sensible, but the magic timing constants are buried in the code. I think it would be beneficial to future maintainers if they were moved to the top of the source file (as defines or static consts) and comments added to each reiterating what is in the change log.

Other than that stylistic suggestion this is good to go.

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

I liked the stylistic simplicity of having the consts within the function they are used. Keeping things in scope. But I also agree that it's nice having constants defined at the top. I'll move them up there when I merge it tomorrow.

Thanks!

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

I found a few issues, added comments, and cleaned up the code just a little bit more before merging. Nothing logically has changed though.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/grail-api.c'
2--- src/grail-api.c 2011-01-02 12:08:08 +0000
3+++ src/grail-api.c 2011-02-02 22:53:06 +0000
4@@ -29,6 +29,7 @@
5 #include <fcntl.h>
6 #include <malloc.h>
7 #include <errno.h>
8+#include <stdlib.h>
9
10 #define DIM_FRAMES 100
11 #define FRAME_RATE 100
12@@ -39,24 +40,6 @@
13 x->filter_abs = usage;
14 }
15
16-static void init_impl(struct grail_impl *x)
17-{
18- int i;
19-
20- if (evemu_has_event(x->evemu, EV_ABS, ABS_X)) {
21- x->emin_x = evemu_get_abs_minimum(x->evemu, ABS_X);
22- x->emin_y = evemu_get_abs_minimum(x->evemu, ABS_Y);
23- x->emax_x = evemu_get_abs_maximum(x->evemu, ABS_X);
24- x->emax_y = evemu_get_abs_maximum(x->evemu, ABS_Y);
25- } else {
26- struct utouch_surface *s = utouch_frame_get_surface(x->fh);
27- x->emin_x = s->min_x;
28- x->emin_y = s->min_y;
29- x->emax_x = s->max_x;
30- x->emax_y = s->max_y;
31- }
32-}
33-
34 int grail_open(struct grail *ge, int fd)
35 {
36 struct grail_impl *x;
37@@ -92,7 +75,6 @@
38 if (ret)
39 goto freeframe;
40
41- init_impl(x);
42 ge->impl = x;
43
44 ret = gin_init(ge);
45@@ -120,7 +102,6 @@
46 void grail_close(struct grail *ge, int fd)
47 {
48 struct grail_impl *x = ge->impl;
49- void *status;
50 gru_destroy(ge);
51 gin_destroy(ge);
52 utouch_frame_delete_engine(x->fh);
53@@ -146,140 +127,120 @@
54 max->y = s->max_y;
55 }
56
57-// legacy glue below
58-
59-static void evput(struct grail_impl *x, struct timeval time,
60- unsigned type, unsigned code, int value)
61-{
62- struct input_event ev = { time, type, code, value };
63- evbuf_put(&x->evbuf, &ev);
64-}
65-
66-static void report_down(struct grail_impl *impl)
67-{
68- if (impl->report_status)
69- return;
70- evput(impl, impl->report_time, EV_KEY, BTN_TOUCH, 1);
71- evput(impl, impl->report_time, EV_ABS, ABS_X, impl->report_x);
72- evput(impl, impl->report_time, EV_ABS, ABS_Y, impl->report_y);
73- impl->report_status = 1;
74-}
75-
76-static void report_up(struct grail_impl *impl, const struct input_event *syn)
77-{
78- if (!impl->report_status)
79- return;
80- evput(impl, syn->time, EV_KEY, BTN_TOUCH, 0);
81- impl->report_status = 0;
82-}
83-
84-static void set_pointer(struct grail_impl *impl)
85-{
86- struct utouch_surface *s = utouch_frame_get_surface(impl->fh);
87- const struct utouch_frame *frame = impl->frame;
88- int best_x, best_y, best_d = -1;
89+static void check_potential_gestures(struct grail *ge,
90+ const struct utouch_frame *frame)
91+{
92+ struct gesture_recognizer *gru = ge->gru;
93+ grail_mask_t types[DIM_GRAIL_TYPE_BYTES] = {0};
94+ struct grail_client_info client;
95+ struct grail_coord pos[frame->num_active];
96 int i;
97
98+ switch (frame->num_active) {
99+ case 1:
100+ grail_mask_set(types, GRAIL_TYPE_DRAG1);
101+ grail_mask_set(types, GRAIL_TYPE_PINCH1);
102+ grail_mask_set(types, GRAIL_TYPE_ROTATE1);
103+ grail_mask_set(types, GRAIL_TYPE_TAP1);
104+ break;
105+ case 2:
106+ grail_mask_set(types, GRAIL_TYPE_DRAG2);
107+ grail_mask_set(types, GRAIL_TYPE_PINCH2);
108+ grail_mask_set(types, GRAIL_TYPE_ROTATE2);
109+ grail_mask_set(types, GRAIL_TYPE_TAP2);
110+ break;
111+ case 3:
112+ grail_mask_set(types, GRAIL_TYPE_DRAG3);
113+ grail_mask_set(types, GRAIL_TYPE_PINCH3);
114+ grail_mask_set(types, GRAIL_TYPE_ROTATE3);
115+ grail_mask_set(types, GRAIL_TYPE_TAP3);
116+ grail_mask_set(types, GRAIL_TYPE_EDRAG);
117+ grail_mask_set(types, GRAIL_TYPE_EPINCH);
118+ grail_mask_set(types, GRAIL_TYPE_EROTATE);
119+ break;
120+ case 4:
121+ grail_mask_set(types, GRAIL_TYPE_DRAG4);
122+ grail_mask_set(types, GRAIL_TYPE_PINCH4);
123+ grail_mask_set(types, GRAIL_TYPE_ROTATE4);
124+ grail_mask_set(types, GRAIL_TYPE_TAP4);
125+ grail_mask_set(types, GRAIL_TYPE_MDRAG);
126+ grail_mask_set(types, GRAIL_TYPE_MPINCH);
127+ grail_mask_set(types, GRAIL_TYPE_MROTATE);
128+ break;
129+ case 5:
130+ grail_mask_set(types, GRAIL_TYPE_DRAG5);
131+ grail_mask_set(types, GRAIL_TYPE_PINCH5);
132+ grail_mask_set(types, GRAIL_TYPE_ROTATE5);
133+ grail_mask_set(types, GRAIL_TYPE_TAP5);
134+ break;
135+ }
136+
137 for (i = 0; i < frame->num_active; i++) {
138- const struct utouch_contact *t = frame->active[i];
139- float u = (t->x - s->min_x) / (s->max_x - s->min_x);
140- float v = (t->y - s->min_y) / (s->max_y - s->min_y);
141- int x = impl->emin_x + u * (impl->emax_x - impl->emin_x);
142- int y = impl->emin_y + v * (impl->emax_y - impl->emin_y);
143- int d = abs(x - impl->pointer_x) + abs(y - impl->pointer_y);
144- if (best_d < 0 || d < best_d) {
145- best_x = x;
146- best_y = y;
147- best_d = d;
148- }
149- }
150- if (best_d >= 0) {
151- impl->pointer_x = best_x;
152- impl->pointer_y = best_y;
153- }
154-}
155-
156-static void handle_abs_events(struct grail *ge, const struct input_event *syn)
157-{
158- static const int fm_mask = 0x03;
159- struct grail_impl *impl = ge->impl;
160- struct gesture_inserter *gin = ge->gin;
161- struct gesture_recognizer *gru = ge->gru;
162- struct move_model *move = &gru->move;
163- struct tapping_model *tap = &gru->tapping;
164- int used_move = grail_mask_count(gin->types, sizeof(gin->types));
165- int used_tap = grail_mask_get(gin->types, GRAIL_TYPE_TAP1);
166- int pointer = move->ntouch == 1;
167- int ismove = pointer && (move->active & fm_mask) && !used_move;
168- int ishold = pointer && tap->active && !used_move;
169- int istap = gru->tapping.tap == 1 && !used_tap;
170-
171- set_pointer(impl);
172- if (!impl->pointer_status && pointer) {
173- impl->report_x = impl->pointer_x;
174- impl->report_y = impl->pointer_y;
175- impl->report_time = syn->time;
176- impl->pointer_status = 1;
177- if (!used_move)
178- report_down(impl);
179- return;
180- }
181-
182- if (ishold)
183- return;
184-
185- if (istap) {
186- report_down(impl);
187- evput(impl, impl->report_time, EV_KEY, BTN_LEFT, 1);
188- evput(impl, impl->report_time, EV_SYN, SYN_REPORT, 0);
189- evput(impl, syn->time, EV_KEY, BTN_LEFT, 0);
190- } else if (ismove) {
191- report_down(impl);
192- if (impl->report_x != impl->pointer_x) {
193- evput(impl, syn->time, EV_ABS, ABS_X, impl->pointer_x);
194- impl->report_x = impl->pointer_x;
195- }
196- if (impl->report_y != impl->pointer_y) {
197- evput(impl, syn->time, EV_ABS, ABS_Y, impl->pointer_y);
198- impl->report_y = impl->pointer_y;
199- }
200- }
201- if (impl->pointer_status && !pointer) {
202- impl->pointer_status = 0;
203- report_up(impl, syn);
204- }
205+ pos[i].x = frame->active[i]->x;
206+ pos[i].y = frame->active[i]->y;
207+ }
208+
209+ if (ge->get_clients(ge, &client, 1, pos, frame->num_active,
210+ types, DIM_GRAIL_TYPE_BYTES) == 0)
211+ gru->state = UNRECOGNIZED;
212 }
213
214 static void report_frame(struct grail *ge,
215 const struct utouch_frame *frame,
216 const struct input_event *syn)
217 {
218-
219+ static const int stable_time = 50;
220+ static const int recognition_time = 200;
221 struct grail_impl *impl = ge->impl;
222- int head = impl->evbuf.head;
223+ struct gesture_recognizer *gru = ge->gru;
224 struct input_event iev;
225 struct grail_event gev;
226
227 ge->impl->frame = frame;
228
229- gin_frame_begin(ge, frame);
230- gru_recognize(ge, frame);
231- gin_frame_end(ge, frame);
232-
233- if (!impl->filter_abs)
234- handle_abs_events(ge, syn);
235- if (impl->evbuf.head != head)
236- evbuf_put(&impl->evbuf, syn);
237-
238- while (!grailbuf_empty(&impl->gbuf)) {
239- grailbuf_get(&impl->gbuf, &gev);
240- if (ge->gesture)
241- ge->gesture(ge, &gev);
242- }
243- while (!evbuf_empty(&impl->evbuf)) {
244- evbuf_get(&impl->evbuf, &iev);
245- if (ge->event)
246- ge->event(ge, &iev);
247+ if (frame->prev->revision != frame->revision && frame->num_active) {
248+ ge->gru->start_time = frame->time;
249+ }
250+
251+ if (gru->state == RECOGNIZING &&
252+ frame->time > ge->gru->start_time + stable_time)
253+ check_potential_gestures(ge, frame);
254+
255+ if (gru->state == RECOGNIZED ||
256+ (gru->state == RECOGNIZING &&
257+ frame->time > ge->gru->start_time + stable_time &&
258+ frame->time < ge->gru->start_time + recognition_time)) {
259+ gin_frame_begin(ge, frame);
260+ gru_recognize(ge, frame);
261+ gin_frame_end(ge, frame);
262+
263+ if (grail_mask_count(ge->gin->used, DIM_INSTANCE_BYTES))
264+ gru->state = RECOGNIZED;
265+ }
266+
267+ if (gru->state == UNRECOGNIZED ||
268+ (gru->state == RECOGNIZING &&
269+ (frame->time >= ge->gru->start_time + recognition_time ||
270+ (frame->num_active == 0 && grailbuf_empty(&impl->gbuf))))) {
271+ while (!evbuf_empty(&impl->evbuf)) {
272+ evbuf_get(&impl->evbuf, &iev);
273+ if (ge->event)
274+ ge->event(ge, &iev);
275+ }
276+ grailbuf_clear(&impl->gbuf);
277+ if (frame->num_active == 0)
278+ gru->state = RECOGNIZING;
279+ } else if (gru->state == RECOGNIZED) {
280+ while (!grailbuf_empty(&impl->gbuf)) {
281+ grailbuf_get(&impl->gbuf, &gev);
282+ if (ge->gesture)
283+ ge->gesture(ge, &gev);
284+ }
285+ evbuf_clear(&impl->evbuf);
286+
287+ if (grail_mask_count(ge->gin->used, DIM_INSTANCE_BYTES) == 0 &&
288+ frame->num_active == 0)
289+ gru->state = RECOGNIZING;
290 }
291 }
292
293@@ -289,6 +250,7 @@
294 const struct utouch_frame *frame;
295
296 if (ev->type == EV_SYN || ev->type == EV_ABS) {
297+ evbuf_put(&impl->evbuf, ev);
298 frame = utouch_frame_pump_mtdev(impl->fh, ev);
299 if (frame)
300 report_frame(ge, frame, ev);
301
302=== modified file 'src/grail-impl.h'
303--- src/grail-impl.h 2011-01-02 12:08:08 +0000
304+++ src/grail-impl.h 2011-02-02 22:53:06 +0000
305@@ -41,14 +41,7 @@
306 const struct utouch_frame *frame;
307 struct evbuf evbuf;
308 struct grailbuf gbuf;
309- float emin_x, emin_y;
310- float emax_x, emax_y;
311 int filter_abs;
312- int pointer_status;
313- int pointer_x, pointer_y;
314- int report_status;
315- int report_x, report_y;
316- struct timeval report_time;
317 };
318
319 #endif
320
321=== modified file 'src/grail-recognizer.h'
322--- src/grail-recognizer.h 2011-01-02 12:08:08 +0000
323+++ src/grail-recognizer.h 2011-02-02 22:53:06 +0000
324@@ -25,6 +25,12 @@
325
326 #include "grail-gestures.h"
327
328+enum recognition_state {
329+ RECOGNIZING,
330+ RECOGNIZED,
331+ UNRECOGNIZED
332+};
333+
334 struct gesture_recognizer {
335 struct move_model move;
336 struct combo_model drag;
337@@ -34,6 +40,8 @@
338 struct combo_model winpinch;
339 struct combo_model winrotate;
340 struct tapping_model tapping;
341+ utouch_frame_time_t start_time;
342+ enum recognition_state state;
343 };
344
345 int gru_init(struct grail *ge);
346
347=== modified file 'tools/grail-gesture.c'
348--- tools/grail-gesture.c 2011-01-02 12:06:04 +0000
349+++ tools/grail-gesture.c 2011-02-02 22:53:06 +0000
350@@ -27,6 +27,7 @@
351 #include <stdio.h>
352 #include <unistd.h>
353 #include <fcntl.h>
354+#include <stdlib.h>
355
356 static grail_mask_t flag_mask[DIM_GRAIL_TYPE_BYTES];
357

Subscribers

People subscribed via source and target branches

to all changes: