summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2011-02-15 14:48:57 +0100
committerHenrik Rydberg <rydberg@euromail.se>2011-02-15 14:48:57 +0100
commit3244deffa1aedbb6c1af8c2dc993f1d771373c6a (patch)
tree2e5a234d628c7065d5a75620639b3a7305fa33ab /src
parent814bc7eb456af9439c88d9c7617816934183b959 (diff)
Optional XI2.1 support
This patchs adds optional XI2.1 support to utouch-frame. The utouch/frame-xi2.h header contains helper functions equivalent to utouch/frame-mtdev.h. In addition, the device-to-screen mapping is handled via XEvents and optionally XIPropertyEvent. The latter allows free device placement via xinput set-prop, useful in multi- head setups, thanks to Chase Douglas. Touch frame events can be tested using the utouch-frame-test-xi2 tool. Use --with-xi to enable. Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am8
-rw-r--r--src/frame-impl.h2
-rw-r--r--src/frame-xi2.c302
-rw-r--r--src/frame.c1
4 files changed, 313 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index a6f98f9..c3fd3b2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,3 +19,11 @@ libutouch_frameincludedir = $(includedir)/utouch
19libutouch_frameinclude_HEADERS = \ 19libutouch_frameinclude_HEADERS = \
20 $(top_srcdir)/include/utouch/frame.h \ 20 $(top_srcdir)/include/utouch/frame.h \
21 $(top_srcdir)/include/utouch/frame-mtdev.h 21 $(top_srcdir)/include/utouch/frame-mtdev.h
22
23if HAVE_XI
24
25libutouch_frame_la_LDFLAGS += $(XINPUT_LIBS) $(X11_LIBS)
26libutouch_frame_la_SOURCES += frame-xi2.c
27libutouch_frameinclude_HEADERS += $(top_srcdir)/include/utouch/frame-xi2.h
28
29endif
diff --git a/src/frame-impl.h b/src/frame-impl.h
index 38affe7..b072de9 100644
--- a/src/frame-impl.h
+++ b/src/frame-impl.h
@@ -33,6 +33,8 @@ struct utouch_frame_engine {
33 struct utouch_surface *surface; 33 struct utouch_surface *surface;
34 struct utouch_frame **frames; 34 struct utouch_frame **frames;
35 struct utouch_frame *next; 35 struct utouch_frame *next;
36 int *evmap;
37 float map[9];
36}; 38};
37 39
38#endif 40#endif
diff --git a/src/frame-xi2.c b/src/frame-xi2.c
new file mode 100644
index 0000000..a78d9bf
--- /dev/null
+++ b/src/frame-xi2.c
@@ -0,0 +1,302 @@
1/*****************************************************************************
2 *
3 * utouch-frame - Touch Frame Library
4 *
5 * Copyright (C) 2010 Canonical Ltd.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21#include <utouch/frame-xi2.h>
22#include <xorg/xserver-properties.h>
23#include <linux/input.h>
24#include "frame-impl.h"
25#include <stdlib.h>
26#include <stdio.h>
27#include <errno.h>
28#include <math.h>
29#include <string.h>
30#include <X11/Xlib.h>
31
32static Atom transform_atom;
33
34#define set_field(fh, name, number, field) \
35 if (!strcmp(name, AXIS_LABEL_PROP_##field) && \
36 (fh->evmap[number] = field))
37
38int utouch_frame_is_supported_xi2(Display *dpy, const XIDeviceInfo *dev)
39{
40
41 int i;
42
43 for (i = 0; i < dev->num_classes; i++)
44 if (dev->classes[i]->type == XITouchClass)
45 return 1;
46
47 return 0;
48}
49
50static void init_properties(utouch_frame_handle fh,
51 Display *dpy, const XIDeviceInfo *dev)
52{
53 struct utouch_surface *s = fh->surface;
54 XITouchClassInfo *v;
55 int i;
56
57 for (i = 0; i < dev->num_classes; i++) {
58 v = (void *)dev->classes[i];
59 if (v->type != XITouchClass)
60 continue;
61 switch(v->mode) {
62 case XIDependentTouch:
63 s->needs_pointer = 1;
64 break;
65 case XIDirectTouch:
66 s->is_direct = 1;
67 break;
68 default:
69 fprintf(stderr, "unknown mode\n");
70 break;
71 }
72 }
73
74 if (transform_atom == None)
75 transform_atom = XInternAtom(dpy, XI_PROP_TRANSFORM, True);
76
77 fh->map[0] = fh->map[4] = fh->map[8] = 1;
78}
79
80static void update_transform(utouch_frame_handle fh, Display *dpy, int devid)
81{
82 unsigned long nitem, nbyte;
83 unsigned char *data;
84 int format;
85 Atom type;
86
87 if (transform_atom == None)
88 return;
89
90 XIGetProperty(dpy, devid, transform_atom, 0, 9, False,
91 AnyPropertyType, &type, &format, &nitem, &nbyte, &data);
92
93 if (format == 32 && nitem == 9 && nbyte == 0)
94 memcpy(fh->map, data, sizeof(fh->map));
95 else
96 fprintf(stderr, "Invalid transform matrix\n");
97
98 XFree(data);
99}
100
101static void update_screen(utouch_frame_handle fh, Display *dpy)
102{
103 struct utouch_surface *s = fh->surface;
104 XWindowAttributes attrs;
105 float x1, y1, x2, y2;
106
107 XGetWindowAttributes(dpy, XDefaultRootWindow(dpy), &attrs);
108
109 x1 = 0;
110 y1 = 0;
111 x2 = attrs.width;
112 y2 = attrs.height;
113
114 s->mapped_min_x = fh->map[0] * x1 + fh->map[1] * y1 + fh->map[2];
115 s->mapped_min_y = fh->map[3] * x1 + fh->map[4] * y1 + fh->map[5];
116 s->mapped_max_x = fh->map[0] * x2 + fh->map[1] * y2 + fh->map[2];
117 s->mapped_max_y = fh->map[3] * x2 + fh->map[4] * y2 + fh->map[5];
118 s->mapped_max_pressure = 1;
119
120 fprintf(stderr, "frame map: %f %f %f %f %f\n",
121 s->mapped_min_x, s->mapped_min_y,
122 s->mapped_max_x, s->mapped_max_y, s->mapped_max_pressure);
123}
124
125static void init_valuators(utouch_frame_handle fh,
126 Display *dpy, const XIDeviceInfo *dev)
127{
128 struct utouch_surface *s = fh->surface;
129 XITouchValuatorClassInfo *v;
130 char *name;
131 int i;
132
133 s->phys_width = 100;
134 s->phys_height = 65;
135 s->phys_pressure = 10;
136 s->max_x = 1024;
137 s->max_y = 768;
138 s->max_pressure = 256;
139 s->max_orient = 1;
140
141 for (i = 0; i < dev->num_classes; i++) {
142 v = (void *)dev->classes[i];
143 if (v->type != XITouchValuatorClass)
144 continue;
145 name = XGetAtomName(dpy, v->label);
146 set_field(fh, name, v->number, ABS_MT_POSITION_X) {
147 s->min_x = v->min;
148 s->max_x = v->max;
149 if (v->resolution > 0)
150 s->phys_width = (v->max - v->min) /
151 v->resolution;
152 }
153 set_field(fh, name, v->number, ABS_MT_POSITION_Y) {
154 s->min_y = v->min;
155 s->max_y = v->max;
156 if (v->resolution > 0)
157 s->phys_height = (v->max - v->min) /
158 v->resolution;
159 }
160 set_field(fh, name, v->number, ABS_MT_TOUCH_MAJOR) {
161 s->use_touch_major = 1;
162 }
163 set_field(fh, name, v->number, ABS_MT_TOUCH_MINOR) {
164 s->use_touch_minor = 1;
165 }
166 set_field(fh, name, v->number, ABS_MT_WIDTH_MAJOR) {
167 s->use_width_major = 1;
168 }
169 set_field(fh, name, v->number, ABS_MT_WIDTH_MINOR) {
170 s->use_width_minor = 1;
171 }
172 set_field(fh, name, v->number, ABS_MT_ORIENTATION) {
173 s->use_orientation = 1;
174 s->max_orient = v->max > 0 ? v->max : 1;
175 }
176 set_field(fh, name, v->number, ABS_MT_PRESSURE) {
177 s->use_pressure = 1;
178 s->max_pressure = v->max > 0 ? v->max : 256;
179 if (v->resolution > 0)
180 s->phys_pressure = v->max / v->resolution;
181 }
182#if 0
183 set_field(fh, name, v->number, ABS_MT_DISTANCE) {
184 s->use_distance = 1;
185 }
186#endif
187 XFree(name);
188 }
189}
190
191int utouch_frame_init_xi2(utouch_frame_handle fh,
192 Display *dpy, const XIDeviceInfo *dev)
193{
194 int event;
195 int err;
196
197 free(fh->evmap);
198 fh->evmap =calloc(dev->num_classes, sizeof(int));
199 if (!fh->evmap)
200 return -ENOMEM;
201
202 if (!utouch_frame_is_supported_xi2(dpy, dev))
203 return -ENODEV;
204
205 init_properties(fh, dpy, dev);
206 init_valuators(fh, dpy, dev);
207 update_transform(fh, dpy, dev->deviceid);
208 update_screen(fh, dpy);
209
210 return 0;
211}
212
213static int handle_event(utouch_frame_handle fh,
214 struct utouch_contact *slot,
215 int ix, float value)
216{
217 switch (fh->evmap[ix]) {
218 case ABS_MT_POSITION_X:
219 slot->x = value;
220 return 1;
221 case ABS_MT_POSITION_Y:
222 slot->y = value;
223 return 1;
224 case ABS_MT_TOUCH_MAJOR:
225 slot->touch_major = value;
226 return 1;
227 case ABS_MT_TOUCH_MINOR:
228 slot->touch_minor = value;
229 return 1;
230 case ABS_MT_WIDTH_MAJOR:
231 slot->width_major = value;
232 return 1;
233 case ABS_MT_WIDTH_MINOR:
234 slot->width_minor = value;
235 return 1;
236 case ABS_MT_ORIENTATION:
237 slot->orientation = value;
238 return 1;
239 case ABS_MT_PRESSURE:
240 slot->pressure = value;
241 return 1;
242#ifdef ABS_MT_DISTANCE
243 case ABS_MT_DISTANCE:
244 slot->distance = value;
245 return 1;
246#endif
247 case ABS_MT_TOOL_TYPE:
248 slot->tool_type = value;
249 return 1;
250 default:
251 fprintf(stderr, "did not get that one: %d\n", ix);
252 return 0;
253 }
254}
255
256int utouch_frame_configure_xi2(utouch_frame_handle fh,
257 const XConfigureEvent *ev)
258{
259 if (ev->display)
260 update_screen(fh, ev->display);
261 return 1;
262}
263
264const struct utouch_frame *
265utouch_frame_pump_xi2(utouch_frame_handle fh, const XIDeviceEvent *ev)
266{
267 const XIPropertyEvent *prop_ev;
268 const double *value;
269 const unsigned char *mask;
270 struct utouch_contact *slot;
271 int touchid, nbyte, nbit, num, i;
272
273 switch (ev->evtype) {
274 case XI_TouchBegin:
275 case XI_TouchMotion:
276 case XI_TouchEnd:
277 value = ev->valuators.values;
278 mask = ev->valuators.mask;
279 touchid = ev->detail;
280 nbyte = ev->valuators.mask_len;
281 nbit = nbyte << 3;
282
283 utouch_frame_set_current_id(fh, touchid);
284 slot = utouch_frame_get_current_slot(fh);
285 num = 0;
286 for (i = 0; i < nbit; i++)
287 if (XIMaskIsSet(mask, i))
288 handle_event(fh, slot, i, value[num++]);
289 if (ev->evtype == XI_TouchEnd)
290 utouch_frame_get_current_slot(fh)->id = -1;
291 return utouch_frame_sync(fh, ev->time);
292 case XI_PropertyEvent:
293 prop_ev = (XIPropertyEvent *)ev;
294 if (prop_ev->property == transform_atom && ev->display) {
295 update_transform(fh, ev->display, ev->deviceid);
296 update_screen(fh, ev->display);
297 }
298 break;
299 }
300
301 return 0;
302}
diff --git a/src/frame.c b/src/frame.c
index 061b170..32bd2cd 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -181,6 +181,7 @@ out:
181 181
182void utouch_frame_delete_engine(utouch_frame_handle fh) 182void utouch_frame_delete_engine(utouch_frame_handle fh)
183{ 183{
184 free(fh->evmap);
184 destroy_frame(fh->next, fh->num_slots); 185 destroy_frame(fh->next, fh->num_slots);
185 destroy_frames(fh->frames, fh->num_frames, fh->num_slots); 186 destroy_frames(fh->frames, fh->num_frames, fh->num_slots);
186 free(fh->surface); 187 free(fh->surface);