Merge lp:~oif-team/grail/trunk.v1.0.13 into lp:grail

Proposed by Henrik Rydberg
Status: Merged
Merged at revision: 86
Proposed branch: lp:~oif-team/grail/trunk.v1.0.13
Merge into: lp:grail
Diff against target: 326 lines (+148/-9)
8 files modified
configure.ac (+1/-1)
include/grail-touch.h (+1/-0)
src/gestures-tapping.c (+7/-2)
src/grail-api.c (+9/-2)
src/grail-gestures.c (+1/-1)
src/grail-gestures.h (+1/-1)
src/touch-caps.c (+37/-0)
src/touch-dev.c (+91/-2)
To merge this branch: bzr merge lp:~oif-team/grail/trunk.v1.0.13
Reviewer Review Type Date Requested Status
Chase Douglas Pending
Henrik Rydberg Pending
Review via email: mp+35088@code.launchpad.net

This proposal supersedes a proposal from 2010-09-10.

Description of the change

The changes needed to support non-MT devices through the utouch stack.

To post a comment you must log in.
Revision history for this message
Chase Douglas (chasedouglas) wrote : Posted in a previous version of this proposal

Commit 79 makes sense, so no issues there.

However, I'm not sure what to do about commit 80. I think it looks good and it probably can introduce some interesting support for synaptics trackpads. However, it's also really late in the cycle to be adding this much new code.

I know it would be a bit of extra work, but can we keep commit 80 in a separate branch for now and not package it up for Maverick? By strict definition it is clearly out of scope at this point in the development cycle, and it likely won't actually add any new features since synaptics will be used for most of these devices anyways. However, I worry that there could be regressions in the single-touch touchscreen use case.

I guess the most appropriate review state for this is resubmit to include only commit 79. If you aren't meaning to push this into maverick, perhaps this could be merged as 1.1.0 and we would keep maverick on the 1.0.x series that would not include commit 80?

review: Needs Resubmitting
Revision history for this message
Henrik Rydberg (rydberg) wrote : Posted in a previous version of this proposal

Well, I was thinking maverick for this, since there has already been bug reports about it. I see your point clearly, but I also see the conflict between the normal maverick procedure and the interests to make gestures work for as broad an audience as possible.

Revision history for this message
Henrik Rydberg (rydberg) wrote : Posted in a previous version of this proposal

Code now replaces the "has_mtdata" with "is_supported" logic, and lets some non-MT devices
through. That should take care of the risk of regression for other devices.

Revision history for this message
Chase Douglas (chasedouglas) wrote : Posted in a previous version of this proposal

It sounds like we're going to try to push this into maverick. I'm going to do some testing on it to be sure it doesn't kill my cat :).

Revision history for this message
Duncan McGreggor (oubiwann) wrote : Posted in a previous version of this proposal

Yeah, we try to support animal-friendly products. Thanks for keeping that in mind, Chase.

Revision history for this message
Chase Douglas (chasedouglas) wrote : Posted in a previous version of this proposal

Well, it didn't kill my cat, but it did kill my single touch cursor motion.

In lines 148, 153, and 158 in the big diff below, the return value should be 0 instead of 1 (according to Henrik). This fixed my issues.

review: Needs Fixing
Revision history for this message
Henrik Rydberg (rydberg) wrote : Posted in a previous version of this proposal

Pacthes for two problems have been folded into the originals: 1) set minor when not available from the device, and 2) let grail-touch be transparent when driving a non-mt device. The latter caused the pointer position in the legacy emulation in grail-gesture to not be updated.

Revision history for this message
Chase Douglas (chasedouglas) wrote : Posted in a previous version of this proposal

The synaptics functionality seems to work right for me now. However, I noticed another issue: four finger pinches are often recognized as taps. I believe the issue lies in the fact that the motion of the focus point inhibits a tap, but a pinch may not move the focus point. I have a proposed patch to fix this, and I'd like to see a fix end up in 1.0.13.

review: Needs Fixing
Revision history for this message
Henrik Rydberg (rydberg) wrote : Posted in a previous version of this proposal

The triggers are on difference between absolute numbers, whereas here we want to add change, and trigger on the value of that change, which is not consistent (ie wont work properly).

review: Needs Fixing
Revision history for this message
Henrik Rydberg (rydberg) wrote : Posted in a previous version of this proposal

repack3, adding two more patches, thanks to Chase for finding those bugs.

Revision history for this message
Henrik Rydberg (rydberg) wrote : Posted in a previous version of this proposal

repack4, hopefully the final one..

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'configure.ac'
2--- configure.ac 2010-09-01 21:01:08 +0000
3+++ configure.ac 2010-09-10 12:20:58 +0000
4@@ -1,7 +1,7 @@
5 # Initialize Autoconf
6 AC_PREREQ([2.60])
7 AC_INIT([Gesture Recognition And Instantiation Library],
8- [1.0.12],
9+ [1.0.13],
10 [],
11 [utouch-grail])
12 AC_CONFIG_SRCDIR([Makefile.am])
13
14=== modified file 'include/grail-touch.h'
15--- include/grail-touch.h 2010-08-19 20:26:11 +0000
16+++ include/grail-touch.h 2010-09-10 12:20:58 +0000
17@@ -72,6 +72,7 @@
18 int state;
19 };
20
21+int touch_caps_is_supported(struct touch_dev *dev, int fd);
22 void touch_caps_init(struct touch_dev *dev);
23 float touch_angle(const struct touch_dev *dev, int orientation);
24 float touch_pressure(const struct touch_dev *dev, int pressure);
25
26=== modified file 'src/gestures-tapping.c'
27--- src/gestures-tapping.c 2010-08-26 14:41:20 +0000
28+++ src/gestures-tapping.c 2010-09-10 12:20:58 +0000
29@@ -24,8 +24,9 @@
30 #include <math.h>
31
32 static const int TAP_MIN_GAP_MS = 25;
33+static const int TAP_MIN_UP_MS = 200;
34
35-static const int fm_mask = 0x03;
36+static const int fm_mask = 0x07;
37
38 static void set_props(const struct gesture_inserter *gin,
39 struct tapping_model *s, const struct move_model *m,
40@@ -44,6 +45,9 @@
41 struct gesture_recognizer *gru = ge->gru;
42 struct tapping_model *state = &gru->tapping;
43 struct move_model *move = &gru->move;
44+ grail_time_t up = move->time - state->end;
45+ if (move->ntouch && move->ntouch < state->ntouch)
46+ state->end = move->time;
47 if (move->ntouch > state->ntouch) {
48 if (state->active) {
49 gin_gid_discard(ge, state->gid);
50@@ -67,7 +71,8 @@
51 int x = state->prop[GRAIL_PROP_TAP_X];
52 int y = state->prop[GRAIL_PROP_TAP_Y];
53 int t = move->time - state->start;
54- if (t < TAP_MIN_GAP_MS) {
55+ if (t < TAP_MIN_GAP_MS || t > move->fm[FM_X].bar_ms ||
56+ up < TAP_MIN_UP_MS) {
57 gin_gid_discard(ge, state->gid);
58 state->ntouch = move->ntouch;
59 state->active = 0;
60
61=== modified file 'src/grail-api.c'
62--- src/grail-api.c 2010-08-26 14:40:35 +0000
63+++ src/grail-api.c 2010-09-10 12:20:58 +0000
64@@ -92,20 +92,27 @@
65 return nevent;
66 }
67
68+static int pointer_active(const struct grail *ge)
69+{
70+ static const int fm_mask = 0x03;
71+ const struct move_model *move = &ge->gru->move;
72+ const struct tapping_model *tap = &ge->gru->tapping;
73+ return move->single && ((move->active & fm_mask) || tap->active);
74+}
75+
76 static void tp_sync(struct touch_dev *dev,
77 const struct input_event *syn)
78 {
79 struct input_event ev;
80 struct grail *ge = dev->priv;
81 struct grail_impl *impl = ge->impl;
82- struct gesture_recognizer *gru = ge->gru;
83 struct touch_frame *frame = &dev->frame;
84 grail_mask_t filtered[DIM_EV_TYPE_BYTES];
85 int pointer, nevent = 0;
86 gin_frame_begin(ge, frame);
87 gru_recognize(ge, frame);
88 gin_frame_end(ge, filtered, sizeof(filtered), frame);
89- pointer = gru->move.single && !grail_mask_get(filtered, EV_ABS);
90+ pointer = pointer_active(ge) && !grail_mask_get(filtered, EV_ABS);
91
92 if (!ge->event) {
93 evbuf_clear(&impl->evbuf);
94
95=== modified file 'src/grail-gestures.c'
96--- src/grail-gestures.c 2010-09-01 21:00:37 +0000
97+++ src/grail-gestures.c 2010-09-10 12:20:58 +0000
98@@ -26,7 +26,7 @@
99
100 static const float FM_SN[DIM_FM] = { 1000, 1000, 200, 1000 };
101 static const float FM_BAR[DIM_FM] = { 50, 50, 30, 50 };
102-static const grail_time_t FM_BAR_MS[DIM_FM] = { 200, 200, 10000, 10000 };
103+static const grail_time_t FM_BAR_MS[DIM_FM] = { 300, 300, 10000, 10000 };
104 static const grail_time_t SAMPLE_MS = 10;
105 static const float EPS = 1e-3;
106
107
108=== modified file 'src/grail-gestures.h'
109--- src/grail-gestures.h 2010-08-26 14:41:20 +0000
110+++ src/grail-gestures.h 2010-09-10 12:20:58 +0000
111@@ -97,7 +97,7 @@
112 const struct touch_frame *frame);
113
114 struct tapping_model {
115- grail_time_t start;
116+ grail_time_t start, end;
117 int ntouch;
118 int active, gid;
119 int nprop;
120
121=== modified file 'src/touch-caps.c'
122--- src/touch-caps.c 2010-08-31 12:20:32 +0000
123+++ src/touch-caps.c 2010-09-10 12:20:58 +0000
124@@ -21,6 +21,7 @@
125 ****************************************************************************/
126
127 #include <grail-touch.h>
128+#include <errno.h>
129 #include <math.h>
130
131 /* see mtdev-mapping.h */
132@@ -29,6 +30,42 @@
133 #define MTDEV_ORIENTATION 4
134 #define MTDEV_PRESSURE 10
135
136+#define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
137+
138+static const int bits_per_long = 8 * sizeof(long);
139+
140+static inline int nlongs(int nbit)
141+{
142+ return (nbit + bits_per_long - 1) / bits_per_long;
143+}
144+
145+static inline int getbit(const unsigned long *map, int key)
146+{
147+ return (map[key / bits_per_long] >> (key % bits_per_long)) & 0x01;
148+}
149+
150+int touch_caps_is_supported(struct touch_dev *dev, int fd)
151+{
152+ unsigned long keybits[nlongs(KEY_MAX)];
153+ unsigned long absbits[nlongs(ABS_MAX)];
154+ int rc;
155+
156+ if (dev->mtdev.caps.has_mtdata)
157+ return 1;
158+
159+ SYSCALL(rc = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits));
160+ if (rc < 0)
161+ return 0;
162+ SYSCALL(rc = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits));
163+ if (rc < 0)
164+ return 0;
165+
166+ return getbit(absbits, ABS_X) &&
167+ getbit(absbits, ABS_Y) &&
168+ getbit(keybits, BTN_TOUCH) &&
169+ getbit(keybits, BTN_TOOL_DOUBLETAP);
170+}
171+
172 void touch_caps_init(struct touch_dev *dev)
173 {
174 const struct mtdev_caps *mt = &dev->mtdev.caps;
175
176=== modified file 'src/touch-dev.c'
177--- src/touch-dev.c 2010-08-19 20:26:11 +0000
178+++ src/touch-dev.c 2010-09-10 12:20:58 +0000
179@@ -25,6 +25,9 @@
180 #include <string.h>
181 #include <errno.h>
182
183+/* see mtdev-mapping.h */
184+#define MTDEV_TOUCH_MINOR 1
185+
186 #define SET_PROP(name, value) \
187 if (t->name != value) { \
188 t->name = value; \
189@@ -34,6 +37,9 @@
190 static void finish_touch(struct touch_dev *dev, struct touch_frame *frame)
191 {
192 struct touch *t = &frame->touch[dev->slot];
193+ if (t->touch_major && !t->touch_minor ||
194+ !dev->mtdev.caps.has_abs[MTDEV_TOUCH_MINOR])
195+ SET_PROP(touch_minor, t->touch_major);
196 if (dev->state > 0) {
197 t->active = 1;
198 grail_mask_set(frame->touches, dev->slot);
199@@ -47,13 +53,45 @@
200 dev->state = 0;
201 }
202
203+static void finish_legacy(struct touch_dev *dev, struct touch_frame *frame)
204+{
205+ static int trkid;
206+ int i;
207+ for (i = 0; i < frame->nactive; i++) {
208+ struct touch *t = &frame->touch[i];
209+ t->active = 1;
210+ if (t->id < 0) {
211+ t->id = trkid++ & 0xffff;
212+ frame->ncreate++;
213+ }
214+ if (i > 0) {
215+ SET_PROP(x, frame->touch[0].x);
216+ SET_PROP(y, frame->touch[0].y);
217+ SET_PROP(pressure, frame->touch[0].pressure);
218+ }
219+ grail_mask_set(frame->touches, i);
220+ }
221+ for (i = frame->nactive; i < DIM_TOUCH; i++) {
222+ struct touch *t = &frame->touch[i];
223+ t->active = 0;
224+ if (t->id >= 0) {
225+ t->id = -1;
226+ frame->ndestroy++;
227+ }
228+ grail_mask_clear(frame->touches, i);
229+ }
230+}
231+
232 static void finish_packet(struct touch_dev *dev,
233 const struct input_event *syn)
234 {
235 static const touch_time_t ms = 1000;
236 struct touch_frame *frame = &dev->frame;
237 int i, nslot = 0;
238- finish_touch(dev, frame);
239+ if (dev->mtdev.caps.has_mtdata)
240+ finish_touch(dev, frame);
241+ else
242+ finish_legacy(dev, frame);
243 grail_mask_foreach(i, frame->touches, DIM_TOUCH_BYTES)
244 frame->active[nslot++] = &frame->touch[i];
245 frame->nactive = nslot;
246@@ -71,6 +109,21 @@
247 struct touch_frame *frame = &dev->frame;
248 struct touch *t = &frame->touch[dev->slot];
249 switch (ev->code) {
250+ case ABS_X:
251+ if (dev->mtdev.caps.has_mtdata)
252+ return 0;
253+ SET_PROP(x, ev->value);
254+ return 0;
255+ case ABS_Y:
256+ if (dev->mtdev.caps.has_mtdata)
257+ return 0;
258+ SET_PROP(y, ev->value);
259+ return 0;
260+ case ABS_PRESSURE:
261+ if (dev->mtdev.caps.has_mtdata)
262+ return 0;
263+ SET_PROP(pressure, ev->value);
264+ return 0;
265 case ABS_MT_SLOT:
266 if (ev->value >= 0 && ev->value < DIM_TOUCH) {
267 if (dev->slot != ev->value)
268@@ -122,6 +175,40 @@
269 }
270 }
271
272+static int handle_key_event(struct touch_dev *dev,
273+ const struct input_event *ev)
274+{
275+ struct touch_frame *frame = &dev->frame;
276+ if (dev->mtdev.caps.has_mtdata)
277+ return 0;
278+ switch (ev->code) {
279+ case BTN_TOUCH:
280+ if (ev->value && !frame->nactive)
281+ frame->nactive = 1;
282+ else if (!ev->value && frame->nactive)
283+ frame->nactive = 0;
284+ return 0;
285+ case BTN_TOOL_FINGER:
286+ if (ev->value)
287+ frame->nactive = 1;
288+ return 0;
289+ case BTN_TOOL_DOUBLETAP:
290+ if (ev->value)
291+ frame->nactive = 2;
292+ return 0;
293+ case BTN_TOOL_TRIPLETAP:
294+ if (ev->value)
295+ frame->nactive = 3;
296+ return 0;
297+ case BTN_TOOL_QUADTAP:
298+ if (ev->value)
299+ frame->nactive = 4;
300+ return 0;
301+ default:
302+ return 0;
303+ }
304+}
305+
306 int touch_dev_open(struct touch_dev *dev, int fd)
307 {
308 struct touch_frame *frame = &dev->frame;
309@@ -133,7 +220,7 @@
310 t->id = MT_ID_NULL;
311 }
312 ret = mtdev_open(&dev->mtdev, fd);
313- if (!ret && !dev->mtdev.caps.has_mtdata)
314+ if (!ret && !touch_caps_is_supported(dev, fd))
315 ret = -ENODEV;
316 if (ret)
317 goto error;
318@@ -160,6 +247,8 @@
319 consumed++;
320 } else if (ev.type == EV_ABS) {
321 consumed += handle_abs_event(dev, &ev);
322+ } else if (ev.type == EV_KEY) {
323+ consumed += handle_key_event(dev, &ev);
324 }
325 if (!consumed && dev->event)
326 dev->event(dev, &ev);

Subscribers

People subscribed via source and target branches

to all changes: