Merge lp:~oif-team/frame/semi-mt-add-touches into lp:frame

Proposed by Chase Douglas
Status: Merged
Merged at revision: 31
Proposed branch: lp:~oif-team/frame/semi-mt-add-touches
Merge into: lp:frame
Diff against target: 234 lines (+97/-9)
5 files modified
include/utouch/frame.h (+3/-1)
src/frame-impl.h (+1/-0)
src/frame-mtdev.c (+48/-1)
src/frame-xi2.c (+7/-2)
src/frame.c (+38/-5)
To merge this branch: bzr merge lp:~oif-team/frame/semi-mt-add-touches
Reviewer Review Type Date Requested Status
Henrik Rydberg (community) Approve
Stephen M. Webb (community) Approve
Review via email: mp+55966@code.launchpad.net

Description of the change

Add the correct number of additional fingers for semi-mt devices. This allows up to three touch gestures on semi-mt synaptics trackpads. I can now perform some unity gestures :).

The new contact has a unique ID and is always placed at the center of the current bounding box. This ensures calculations based on the geometric center of the touches are unaffected.

To post a comment you must log in.
Revision history for this message
Henrik Rydberg (rydberg) wrote :

I like the idea, just some comments on the implementation:

The EV_KEY code could be broken out into its own function, like for EV_ABS events.
Also, the number of active contacts needs to be set also for one touch, etc.

Reusing older touch ids could work, but note that the one chosen is likely to have been
used recently. Also, the tracking id range of the device should be respected. An alternative
is to pick an offset somewhere in the middle of the given tracking range.

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

I'll split out the key code into a separate function.

I think I can set the number of semi-mt touches to 1 by watching BTN_TOOL_FINGER. I had forgotten about its usage being equivalent to BTN_TOOL_*TAP. Note that it's not really necessary, however, since the number of semi-mt touches has an effect only when there are three or more touches.

I'm not sure what the best resolution to the touch ids issue is. It's true that the current solution will choose a recently used touch id, but this shouldn't really be an issue because the utouch-frame "protocol" tells the client when the touch has ended, right? The real issue is that we will be trampling on top of the touch id range reported by the kernel, but there's no way around this without creating a separate tracking id implementation in utouch-frame.

We could choose an id that's half way around the ring if you consider the tracking ids as a circular ring buffer. This would still be ~2^15 touches away, so there's low likelyhood of a tracking id collision. Would that be alright with you?

Revision history for this message
Henrik Rydberg (rydberg) wrote :

Sounds all good, thanks!

32. By Chase Douglas

Split out EV_KEY handling and add support for BTN_TOOL_FINGER

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

I've added all the changes except for the tracking id value change. The issue is that the tracking IDs from utouch-frame don't have a boundary. If you're using the mtdev backend there is the range from the kernel, but this isn't exposed to the utouch-frame clients. As such, the only boundaries are that the tracking ID fits inside an int (32 bits) and is not equal to -1.

Henrik, how do you want to resolve this issue? Should we assume the valid tracking ID range is 0 to 2^32 - 2, 0 to 2^31 - 1 (all positive values of an int), or something else? I'll note that the XI 2.1 spec says it's an unsigned int that can take any value, if that's of any help in determining the best resolution here.

Revision history for this message
Henrik Rydberg (rydberg) wrote :

Having utouch-frame expose the tracking id range seems like a reasonable and simple solution.

33. By Chase Douglas

Provide the range of touch IDs and decouple ID from touch active state

The kernel provides a range of touch IDs for each device, and XI 2.1 will
have its own range as well. The tracking ID from the kernel is set to -1
when the touch goes inactive, but -1 (as an unsigned int) is a valid
value for XI 2.1. To make things work in both environments, the tracking
ID range is provided in the touch surface, and the active state has been
decoupled from the tracking ID value. The backend (mtdev or XI 2.1) must
now set the active value of the touch contact.

Also, to provide for the full range of XI 2.1 touch IDs, the ID value has
been changed to unsigned int.

34. By Chase Douglas

Set the touch ID half way around the ID range to be safe

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

Please review the last two commits which I hope will resolve all outstanding issues.

Thanks!

Revision history for this message
Henrik Rydberg (rydberg) wrote :

Thanks for the changes, some comments:

* I would prefer clean patches before the changes on top.

* I (again) regret admitting to changing the original kernel protocol to allow zero as a tracking id... :-)

* The semantic change regarding id is fine per se, but needs a lot of thought and checks, because it is, indeed, an ABI break. I will have to get back to you on this one.

* The logic for number of fingers still seems to not handle the full range.

review: Needs Fixing
Revision history for this message
Henrik Rydberg (rydberg) wrote :

Regarding the tracking id range, I think the proper solution is to restrict the id range in the X server, using the exact same semantics as the kernel. The kernel protocol relies on there being a value outside the valid range, and using a different semantics in the X server obviously creates problems.

The original intent with the X tracking id was to mimic the kernel behavior for those kernel drivers with no or poor implementation of kernel tracking ids. Since then, the kernel code for tracking has been centralized, so all type B devices behave exactly the same. Maybe the special handling in X can be dropped now?

Revision history for this message
Henrik Rydberg (rydberg) wrote :

Following more IRC discussions, it is alright for utouch-frame to use the pair (active, id) instead of just id to codify touch status and identifier. Combined with the given id range, the api works for both mtdev and XI2.1.

For the next round, the users of utouch-frame (grail, mtview, tools) needs to be checked for special usage of id (in particular id == -1), since the proposed changes will introduce different semantics for non-active touch ids.

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

> Thanks for the changes, some comments:
>
> * I would prefer clean patches before the changes on top.

This is really hard to do with bzr and is just not how it's meant to be used. I've gone with this approach because it's easiest for me and allows one to see how review responses are addressed in the merge request review.

> * The semantic change regarding id is fine per se, but needs a lot of thought
> and checks, because it is, indeed, an ABI break. I will have to get back to
> you on this one.

Is this completely resolved now, or are there any other issues?

> * The logic for number of fingers still seems to not handle the full range.

I believe they are handled appropriately now. The evdev semi-mt number of touches is only provided through BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP, BTN_TOOL_TRIPLETAP, and BTN_TOOL_QUADTAP. What else is there to add?

Thanks!

Revision history for this message
Henrik Rydberg (rydberg) wrote :

> Is this completely resolved now, or are there any other issues?

Yep, outstanding issues, if any, should be dealt with in the users of this package instead.

> I believe they are handled appropriately now.

Right, it does look right for one finger too now. It would not hurt to simplify the logic a bit, though.

35. By Chase Douglas

Clean up semi-mt touch count logic

By watching for BTN_TOUCH == 0 we can drop any logic handling for when
other semi-mt touch count events are sent with value 0.

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

> > I believe they are handled appropriately now.
>
> Right, it does look right for one finger too now. It would not hurt to
> simplify the logic a bit, though.

I had one idea on how the logic should work, and it was needed because I originally didn't handle BTN_TOUCH. The simplified logic in this last patch is a little easier to comprehend.

I hope this is good enough to merge now. Stephen noted a lot of people asking this past weekend for higher touch gestures in synaptics trackpads. With it merged we can at least give them the daily ppa to test with, and we can work on releasing the work and pushing it to the utouch stable ppa.

Revision history for this message
Stephen M. Webb (bregma) wrote :

Even I understand the simplified logic and I see expected data coming from the test tools when tested against actual hardware.

review: Approve
Revision history for this message
Henrik Rydberg (rydberg) wrote :

Found two problems with the current code - lin e 163, missing setting of active variable, and in the identifier code, possible wrap of values, resulting in close by use of identifiers. In addition, I would prefer if the semi-mt code was broken out in its own branch.

I have created a merge request to this branch, fixing the problems above.

36. By Chase Douglas

Merge improvements from Henrik

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

Thanks Henrik! I merged your changes into the branch.

37. By Henrik Rydberg

Merging in semi-mt-addons2 fixes

Revision history for this message
Henrik Rydberg (rydberg) wrote :

I think this branch is ready to be merged now.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/utouch/frame.h'
2--- include/utouch/frame.h 2011-02-21 12:16:00 +0000
3+++ include/utouch/frame.h 2011-04-27 12:16:41 +0000
4@@ -94,6 +94,8 @@
5 float mapped_max_x;
6 float mapped_max_y;
7 float mapped_max_pressure;
8+ unsigned int min_id;
9+ unsigned int max_id;
10 };
11
12 #define UTOUCH_TOOL_FINGER 0
13@@ -129,7 +131,7 @@
14 const struct utouch_contact *prev;
15 int active;
16 int slot;
17- int id;
18+ unsigned int id;
19 int tool_type;
20 float x;
21 float y;
22
23=== modified file 'src/frame-impl.h'
24--- src/frame-impl.h 2011-02-15 14:01:51 +0000
25+++ src/frame-impl.h 2011-04-27 12:16:41 +0000
26@@ -35,6 +35,7 @@
27 struct utouch_frame *next;
28 int *evmap;
29 float map[9];
30+ unsigned int semi_mt_num_active;
31 };
32
33 #endif
34
35=== modified file 'src/frame-mtdev.c'
36--- src/frame-mtdev.c 2011-02-24 14:47:40 +0000
37+++ src/frame-mtdev.c 2011-04-27 12:16:41 +0000
38@@ -92,6 +92,13 @@
39 s->use_distance = evemu_has_event(dev, EV_ABS, ABS_MT_DISTANCE);
40 #endif
41
42+ if (evemu_has_event(dev, EV_ABS, ABS_MT_TRACKING_ID)) {
43+ s->min_id = evemu_get_abs_minimum(dev, ABS_MT_TRACKING_ID);
44+ s->max_id = evemu_get_abs_maximum(dev, ABS_MT_TRACKING_ID);
45+ } else {
46+ s->min_id = MT_ID_MIN;
47+ s->max_id = MT_ID_MAX;
48+ }
49
50 s->min_x = evemu_get_abs_minimum(dev, ABS_MT_POSITION_X);
51 s->min_y = evemu_get_abs_minimum(dev, ABS_MT_POSITION_Y);
52@@ -190,7 +197,45 @@
53 t->tool_type = ev->value;
54 return 1;
55 case ABS_MT_TRACKING_ID:
56- t->id = ev->value;
57+ if (ev->value == -1)
58+ t->active = 0;
59+ else {
60+ t->id = ev->value;
61+ t->active = 1;
62+ }
63+ return 1;
64+ default:
65+ return 0;
66+ }
67+}
68+
69+static int handle_key_event(utouch_frame_handle fh,
70+ const struct input_event *ev)
71+{
72+ /* EV_KEY events are only used for semi-mt touch count */
73+ if (!fh->surface->is_semi_mt)
74+ return 0;
75+
76+ if (ev->code == BTN_TOUCH && ev->value == 0) {
77+ fh->semi_mt_num_active = 0;
78+ return 1;
79+ }
80+
81+ if (ev->value == 0)
82+ return 0;
83+
84+ switch (ev->code) {
85+ case BTN_TOOL_FINGER:
86+ fh->semi_mt_num_active = 1;
87+ return 1;
88+ case BTN_TOOL_DOUBLETAP:
89+ fh->semi_mt_num_active = 2;
90+ return 1;
91+ case BTN_TOOL_TRIPLETAP:
92+ fh->semi_mt_num_active = 3;
93+ return 1;
94+ case BTN_TOOL_QUADTAP:
95+ fh->semi_mt_num_active = 4;
96 return 1;
97 default:
98 return 0;
99@@ -212,6 +257,8 @@
100 f = utouch_frame_sync(fh, get_evtime_ms(ev));
101 else if (ev->type == EV_ABS)
102 handle_abs_event(fh, ev);
103+ else if (ev->type == EV_KEY)
104+ handle_key_event(fh, ev);
105
106 return f;
107 }
108
109=== modified file 'src/frame-xi2.c'
110--- src/frame-xi2.c 2011-02-22 15:32:00 +0000
111+++ src/frame-xi2.c 2011-04-27 12:16:41 +0000
112@@ -27,6 +27,7 @@
113 #include <errno.h>
114 #include <math.h>
115 #include <string.h>
116+#include <limits.h>
117 #include <X11/Xlib.h>
118
119 static Atom transform_atom;
120@@ -130,6 +131,8 @@
121 char *name;
122 int i;
123
124+ s->min_id = 0;
125+ s->max_id = UINT_MAX;
126 s->phys_width = 100;
127 s->phys_height = 65;
128 s->phys_pressure = 10;
129@@ -306,8 +309,10 @@
130 for (i = 0; i < nbit; i++)
131 if (XIMaskIsSet(mask, i))
132 handle_event(fh, slot, i, value[num++]);
133- if (ev->evtype == XI_TouchEnd)
134- utouch_frame_get_current_slot(fh)->id = -1;
135+ if (ev->evtype != XI_TouchBegin)
136+ utouch_frame_get_current_slot(fh)->active = 1;
137+ else if (ev->evtype == XI_TouchEnd)
138+ utouch_frame_get_current_slot(fh)->active = 0;
139 return sync_xi2(fh, ev->time);
140 case XI_PropertyEvent:
141 prop_ev = (XIPropertyEvent *)ev;
142
143=== modified file 'src/frame.c'
144--- src/frame.c 2011-02-21 12:16:00 +0000
145+++ src/frame.c 2011-04-27 12:16:41 +0000
146@@ -90,7 +90,7 @@
147 goto out;
148 slots[i] = s;
149 s->slot = i;
150- s->id = -1;
151+ s->active = 0;
152 }
153
154 return slots;
155@@ -223,12 +223,13 @@
156
157 for (i = 0; i < fh->num_slots; i++) {
158 t = fh->next->slots[i];
159- if (t->id == id)
160+ if (t->active && t->id == id)
161 return utouch_frame_set_current_slot(fh, i);
162 }
163 for (i = 0; i < fh->num_slots; i++) {
164 t = fh->next->slots[i];
165- if (t->id < 0) {
166+ if (!t->active) {
167+ t->active = 1;
168 t->id = id;
169 return utouch_frame_set_current_slot(fh, i);
170 }
171@@ -264,7 +265,7 @@
172 struct utouch_surface *s = fh->surface;
173 const struct utouch_contact *ap = a->prev;
174
175- a->active = b->id != -1;
176+ a->active = b->active;
177 a->id = b->id;
178 a->tool_type = b->tool_type;
179 a->x = b->x;
180@@ -300,7 +301,8 @@
181 static int detect_addrem(const struct utouch_contact *a,
182 const struct utouch_contact *b)
183 {
184- return a->id != b->id || a->tool_type != b->tool_type;
185+ return a->id != b->id || a->tool_type != b->tool_type ||
186+ a->active != b->active;
187 }
188
189 static int detect_mod(const struct utouch_contact *a,
190@@ -324,6 +326,34 @@
191 return tv.tv_usec / ms + tv.tv_sec * ms;
192 }
193
194+static void set_semi_mt_touches(utouch_frame_handle fh)
195+{
196+ struct utouch_frame *next = fh->next;
197+ struct utouch_contact *a = next->slots[0];
198+ struct utouch_contact *b = next->slots[1];
199+ struct utouch_surface *s = fh->surface;
200+ /* use touch ids half way around the ID range */
201+ unsigned int id = a->id + (s->max_id - s->min_id) / 2;
202+ float x = (a->x + b->x) / 2;
203+ float y = (a->y + b->y) / 2;
204+ int i;
205+
206+ for (i = 2; i < fh->semi_mt_num_active; i++) {
207+ struct utouch_contact *c = next->slots[i];
208+
209+ memset(c, 0, sizeof(struct utouch_contact));
210+ c->active = 1;
211+ if (id > s->max_id)
212+ id = s->min_id;
213+ c->id = id++;
214+ c->x = x;
215+ c->y = y;
216+ }
217+
218+ for (i = fh->semi_mt_num_active; i < fh->num_slots; i++)
219+ next->slots[i]->active = 0;
220+}
221+
222 const struct utouch_frame *utouch_frame_sync(utouch_frame_handle fh,
223 utouch_frame_time_t time)
224 {
225@@ -338,6 +368,9 @@
226 frame->num_active = 0;
227 dt = frame->time - prev->time;
228
229+ if (fh->surface->is_semi_mt)
230+ set_semi_mt_touches(fh);
231+
232 for (i = 0; i < fh->num_slots; i++) {
233 struct utouch_contact *p = frame->slots[i];
234 struct utouch_contact *q = next->slots[i];

Subscribers

People subscribed via source and target branches