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
=== modified file 'src/grail-api.c'
--- src/grail-api.c 2011-01-02 12:08:08 +0000
+++ src/grail-api.c 2011-02-02 22:53:06 +0000
@@ -29,6 +29,7 @@
29#include <fcntl.h>29#include <fcntl.h>
30#include <malloc.h>30#include <malloc.h>
31#include <errno.h>31#include <errno.h>
32#include <stdlib.h>
3233
33#define DIM_FRAMES 10034#define DIM_FRAMES 100
34#define FRAME_RATE 10035#define FRAME_RATE 100
@@ -39,24 +40,6 @@
39 x->filter_abs = usage;40 x->filter_abs = usage;
40}41}
4142
42static void init_impl(struct grail_impl *x)
43{
44 int i;
45
46 if (evemu_has_event(x->evemu, EV_ABS, ABS_X)) {
47 x->emin_x = evemu_get_abs_minimum(x->evemu, ABS_X);
48 x->emin_y = evemu_get_abs_minimum(x->evemu, ABS_Y);
49 x->emax_x = evemu_get_abs_maximum(x->evemu, ABS_X);
50 x->emax_y = evemu_get_abs_maximum(x->evemu, ABS_Y);
51 } else {
52 struct utouch_surface *s = utouch_frame_get_surface(x->fh);
53 x->emin_x = s->min_x;
54 x->emin_y = s->min_y;
55 x->emax_x = s->max_x;
56 x->emax_y = s->max_y;
57 }
58}
59
60int grail_open(struct grail *ge, int fd)43int grail_open(struct grail *ge, int fd)
61{44{
62 struct grail_impl *x;45 struct grail_impl *x;
@@ -92,7 +75,6 @@
92 if (ret)75 if (ret)
93 goto freeframe;76 goto freeframe;
9477
95 init_impl(x);
96 ge->impl = x;78 ge->impl = x;
9779
98 ret = gin_init(ge);80 ret = gin_init(ge);
@@ -120,7 +102,6 @@
120void grail_close(struct grail *ge, int fd)102void grail_close(struct grail *ge, int fd)
121{103{
122 struct grail_impl *x = ge->impl;104 struct grail_impl *x = ge->impl;
123 void *status;
124 gru_destroy(ge);105 gru_destroy(ge);
125 gin_destroy(ge);106 gin_destroy(ge);
126 utouch_frame_delete_engine(x->fh);107 utouch_frame_delete_engine(x->fh);
@@ -146,140 +127,120 @@
146 max->y = s->max_y;127 max->y = s->max_y;
147}128}
148129
149// legacy glue below130static void check_potential_gestures(struct grail *ge,
150131 const struct utouch_frame *frame)
151static void evput(struct grail_impl *x, struct timeval time,132{
152 unsigned type, unsigned code, int value)133 struct gesture_recognizer *gru = ge->gru;
153{134 grail_mask_t types[DIM_GRAIL_TYPE_BYTES] = {0};
154 struct input_event ev = { time, type, code, value };135 struct grail_client_info client;
155 evbuf_put(&x->evbuf, &ev);136 struct grail_coord pos[frame->num_active];
156}
157
158static void report_down(struct grail_impl *impl)
159{
160 if (impl->report_status)
161 return;
162 evput(impl, impl->report_time, EV_KEY, BTN_TOUCH, 1);
163 evput(impl, impl->report_time, EV_ABS, ABS_X, impl->report_x);
164 evput(impl, impl->report_time, EV_ABS, ABS_Y, impl->report_y);
165 impl->report_status = 1;
166}
167
168static void report_up(struct grail_impl *impl, const struct input_event *syn)
169{
170 if (!impl->report_status)
171 return;
172 evput(impl, syn->time, EV_KEY, BTN_TOUCH, 0);
173 impl->report_status = 0;
174}
175
176static void set_pointer(struct grail_impl *impl)
177{
178 struct utouch_surface *s = utouch_frame_get_surface(impl->fh);
179 const struct utouch_frame *frame = impl->frame;
180 int best_x, best_y, best_d = -1;
181 int i;137 int i;
182138
139 switch (frame->num_active) {
140 case 1:
141 grail_mask_set(types, GRAIL_TYPE_DRAG1);
142 grail_mask_set(types, GRAIL_TYPE_PINCH1);
143 grail_mask_set(types, GRAIL_TYPE_ROTATE1);
144 grail_mask_set(types, GRAIL_TYPE_TAP1);
145 break;
146 case 2:
147 grail_mask_set(types, GRAIL_TYPE_DRAG2);
148 grail_mask_set(types, GRAIL_TYPE_PINCH2);
149 grail_mask_set(types, GRAIL_TYPE_ROTATE2);
150 grail_mask_set(types, GRAIL_TYPE_TAP2);
151 break;
152 case 3:
153 grail_mask_set(types, GRAIL_TYPE_DRAG3);
154 grail_mask_set(types, GRAIL_TYPE_PINCH3);
155 grail_mask_set(types, GRAIL_TYPE_ROTATE3);
156 grail_mask_set(types, GRAIL_TYPE_TAP3);
157 grail_mask_set(types, GRAIL_TYPE_EDRAG);
158 grail_mask_set(types, GRAIL_TYPE_EPINCH);
159 grail_mask_set(types, GRAIL_TYPE_EROTATE);
160 break;
161 case 4:
162 grail_mask_set(types, GRAIL_TYPE_DRAG4);
163 grail_mask_set(types, GRAIL_TYPE_PINCH4);
164 grail_mask_set(types, GRAIL_TYPE_ROTATE4);
165 grail_mask_set(types, GRAIL_TYPE_TAP4);
166 grail_mask_set(types, GRAIL_TYPE_MDRAG);
167 grail_mask_set(types, GRAIL_TYPE_MPINCH);
168 grail_mask_set(types, GRAIL_TYPE_MROTATE);
169 break;
170 case 5:
171 grail_mask_set(types, GRAIL_TYPE_DRAG5);
172 grail_mask_set(types, GRAIL_TYPE_PINCH5);
173 grail_mask_set(types, GRAIL_TYPE_ROTATE5);
174 grail_mask_set(types, GRAIL_TYPE_TAP5);
175 break;
176 }
177
183 for (i = 0; i < frame->num_active; i++) {178 for (i = 0; i < frame->num_active; i++) {
184 const struct utouch_contact *t = frame->active[i];179 pos[i].x = frame->active[i]->x;
185 float u = (t->x - s->min_x) / (s->max_x - s->min_x);180 pos[i].y = frame->active[i]->y;
186 float v = (t->y - s->min_y) / (s->max_y - s->min_y);181 }
187 int x = impl->emin_x + u * (impl->emax_x - impl->emin_x);182
188 int y = impl->emin_y + v * (impl->emax_y - impl->emin_y);183 if (ge->get_clients(ge, &client, 1, pos, frame->num_active,
189 int d = abs(x - impl->pointer_x) + abs(y - impl->pointer_y);184 types, DIM_GRAIL_TYPE_BYTES) == 0)
190 if (best_d < 0 || d < best_d) {185 gru->state = UNRECOGNIZED;
191 best_x = x;
192 best_y = y;
193 best_d = d;
194 }
195 }
196 if (best_d >= 0) {
197 impl->pointer_x = best_x;
198 impl->pointer_y = best_y;
199 }
200}
201
202static void handle_abs_events(struct grail *ge, const struct input_event *syn)
203{
204 static const int fm_mask = 0x03;
205 struct grail_impl *impl = ge->impl;
206 struct gesture_inserter *gin = ge->gin;
207 struct gesture_recognizer *gru = ge->gru;
208 struct move_model *move = &gru->move;
209 struct tapping_model *tap = &gru->tapping;
210 int used_move = grail_mask_count(gin->types, sizeof(gin->types));
211 int used_tap = grail_mask_get(gin->types, GRAIL_TYPE_TAP1);
212 int pointer = move->ntouch == 1;
213 int ismove = pointer && (move->active & fm_mask) && !used_move;
214 int ishold = pointer && tap->active && !used_move;
215 int istap = gru->tapping.tap == 1 && !used_tap;
216
217 set_pointer(impl);
218 if (!impl->pointer_status && pointer) {
219 impl->report_x = impl->pointer_x;
220 impl->report_y = impl->pointer_y;
221 impl->report_time = syn->time;
222 impl->pointer_status = 1;
223 if (!used_move)
224 report_down(impl);
225 return;
226 }
227
228 if (ishold)
229 return;
230
231 if (istap) {
232 report_down(impl);
233 evput(impl, impl->report_time, EV_KEY, BTN_LEFT, 1);
234 evput(impl, impl->report_time, EV_SYN, SYN_REPORT, 0);
235 evput(impl, syn->time, EV_KEY, BTN_LEFT, 0);
236 } else if (ismove) {
237 report_down(impl);
238 if (impl->report_x != impl->pointer_x) {
239 evput(impl, syn->time, EV_ABS, ABS_X, impl->pointer_x);
240 impl->report_x = impl->pointer_x;
241 }
242 if (impl->report_y != impl->pointer_y) {
243 evput(impl, syn->time, EV_ABS, ABS_Y, impl->pointer_y);
244 impl->report_y = impl->pointer_y;
245 }
246 }
247 if (impl->pointer_status && !pointer) {
248 impl->pointer_status = 0;
249 report_up(impl, syn);
250 }
251}186}
252187
253static void report_frame(struct grail *ge,188static void report_frame(struct grail *ge,
254 const struct utouch_frame *frame,189 const struct utouch_frame *frame,
255 const struct input_event *syn)190 const struct input_event *syn)
256{191{
257192 static const int stable_time = 50;
193 static const int recognition_time = 200;
258 struct grail_impl *impl = ge->impl;194 struct grail_impl *impl = ge->impl;
259 int head = impl->evbuf.head;195 struct gesture_recognizer *gru = ge->gru;
260 struct input_event iev;196 struct input_event iev;
261 struct grail_event gev;197 struct grail_event gev;
262198
263 ge->impl->frame = frame;199 ge->impl->frame = frame;
264200
265 gin_frame_begin(ge, frame);201 if (frame->prev->revision != frame->revision && frame->num_active) {
266 gru_recognize(ge, frame);202 ge->gru->start_time = frame->time;
267 gin_frame_end(ge, frame);203 }
268204
269 if (!impl->filter_abs)205 if (gru->state == RECOGNIZING &&
270 handle_abs_events(ge, syn);206 frame->time > ge->gru->start_time + stable_time)
271 if (impl->evbuf.head != head)207 check_potential_gestures(ge, frame);
272 evbuf_put(&impl->evbuf, syn);208
273209 if (gru->state == RECOGNIZED ||
274 while (!grailbuf_empty(&impl->gbuf)) {210 (gru->state == RECOGNIZING &&
275 grailbuf_get(&impl->gbuf, &gev);211 frame->time > ge->gru->start_time + stable_time &&
276 if (ge->gesture)212 frame->time < ge->gru->start_time + recognition_time)) {
277 ge->gesture(ge, &gev);213 gin_frame_begin(ge, frame);
278 }214 gru_recognize(ge, frame);
279 while (!evbuf_empty(&impl->evbuf)) {215 gin_frame_end(ge, frame);
280 evbuf_get(&impl->evbuf, &iev);216
281 if (ge->event)217 if (grail_mask_count(ge->gin->used, DIM_INSTANCE_BYTES))
282 ge->event(ge, &iev);218 gru->state = RECOGNIZED;
219 }
220
221 if (gru->state == UNRECOGNIZED ||
222 (gru->state == RECOGNIZING &&
223 (frame->time >= ge->gru->start_time + recognition_time ||
224 (frame->num_active == 0 && grailbuf_empty(&impl->gbuf))))) {
225 while (!evbuf_empty(&impl->evbuf)) {
226 evbuf_get(&impl->evbuf, &iev);
227 if (ge->event)
228 ge->event(ge, &iev);
229 }
230 grailbuf_clear(&impl->gbuf);
231 if (frame->num_active == 0)
232 gru->state = RECOGNIZING;
233 } else if (gru->state == RECOGNIZED) {
234 while (!grailbuf_empty(&impl->gbuf)) {
235 grailbuf_get(&impl->gbuf, &gev);
236 if (ge->gesture)
237 ge->gesture(ge, &gev);
238 }
239 evbuf_clear(&impl->evbuf);
240
241 if (grail_mask_count(ge->gin->used, DIM_INSTANCE_BYTES) == 0 &&
242 frame->num_active == 0)
243 gru->state = RECOGNIZING;
283 }244 }
284}245}
285246
@@ -289,6 +250,7 @@
289 const struct utouch_frame *frame;250 const struct utouch_frame *frame;
290251
291 if (ev->type == EV_SYN || ev->type == EV_ABS) {252 if (ev->type == EV_SYN || ev->type == EV_ABS) {
253 evbuf_put(&impl->evbuf, ev);
292 frame = utouch_frame_pump_mtdev(impl->fh, ev);254 frame = utouch_frame_pump_mtdev(impl->fh, ev);
293 if (frame)255 if (frame)
294 report_frame(ge, frame, ev);256 report_frame(ge, frame, ev);
295257
=== modified file 'src/grail-impl.h'
--- src/grail-impl.h 2011-01-02 12:08:08 +0000
+++ src/grail-impl.h 2011-02-02 22:53:06 +0000
@@ -41,14 +41,7 @@
41 const struct utouch_frame *frame;41 const struct utouch_frame *frame;
42 struct evbuf evbuf;42 struct evbuf evbuf;
43 struct grailbuf gbuf;43 struct grailbuf gbuf;
44 float emin_x, emin_y;
45 float emax_x, emax_y;
46 int filter_abs;44 int filter_abs;
47 int pointer_status;
48 int pointer_x, pointer_y;
49 int report_status;
50 int report_x, report_y;
51 struct timeval report_time;
52};45};
5346
54#endif47#endif
5548
=== modified file 'src/grail-recognizer.h'
--- src/grail-recognizer.h 2011-01-02 12:08:08 +0000
+++ src/grail-recognizer.h 2011-02-02 22:53:06 +0000
@@ -25,6 +25,12 @@
2525
26#include "grail-gestures.h"26#include "grail-gestures.h"
2727
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 @@
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};
3846
39int gru_init(struct grail *ge);47int gru_init(struct grail *ge);
4048
=== modified file 'tools/grail-gesture.c'
--- tools/grail-gesture.c 2011-01-02 12:06:04 +0000
+++ tools/grail-gesture.c 2011-02-02 22:53:06 +0000
@@ -27,6 +27,7 @@
27#include <stdio.h>27#include <stdio.h>
28#include <unistd.h>28#include <unistd.h>
29#include <fcntl.h>29#include <fcntl.h>
30#include <stdlib.h>
3031
31static grail_mask_t flag_mask[DIM_GRAIL_TYPE_BYTES];32static grail_mask_t flag_mask[DIM_GRAIL_TYPE_BYTES];
3233

Subscribers

People subscribed via source and target branches

to all changes: