Merge lp:~oif-team/frame/trunk.v1.0.2 into lp:frame

Proposed by Henrik Rydberg
Status: Superseded
Proposed branch: lp:~oif-team/frame/trunk.v1.0.2
Merge into: lp:frame
Diff against target: 1217 lines (+836/-87)
15 files modified
.gitignore (+1/-0)
configure.ac (+9/-1)
include/utouch/frame-mtdev.h (+8/-0)
include/utouch/frame-xi2.h (+49/-0)
include/utouch/frame.h (+61/-6)
src/Makefile.am (+9/-1)
src/frame-impl.h (+2/-1)
src/frame-mtdev.c (+14/-10)
src/frame-xi2.c (+304/-0)
src/frame.c (+80/-7)
tools/Makefile.am (+13/-1)
tools/common-defs.h (+85/-0)
tools/utouch-frame-test-mtdev.c (+2/-60)
tools/utouch-frame-test-xi2.c (+177/-0)
tools/utouch-frame-test-xi2.txt (+22/-0)
To merge this branch: bzr merge lp:~oif-team/frame/trunk.v1.0.2
Reviewer Review Type Date Requested Status
Chase Douglas (community) Needs Fixing
Stephen M. Webb (community) Approve
Review via email: mp+50582@code.launchpad.net

This proposal has been superseded by a proposal from 2011-02-22.

Description of the change

New version, fixing Chase's comment and adding yet more functionality.

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

Inconsistent #ifdef'ing around ABS_MT_DISTANCE: sometimes #if 0, sometimes #ifdef ABS_MT_DISTANCE.

You might want to fix that before committing.

Other than that, I find no obvious problems.

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

1. Velocity compensation for unchanged touches seems to work fine for mtdev, but works terribly for xi 2.1. I think this is due to the X timestamps being poorly correlated to evdev/device timing. We need to disable velocity compensation in the xi 2.1 branch for now. I think we should look into adding device timestamps as a valuator in xi.

2. I've changed the version number of libXi for our multitouch changes. There could be a 1.4.2 released between now and when the upstream libXI has xi 2.1 support, so I downgraded the version to 1.4.1.99.1. This change is not in the ppa, but will be in the ubuntu version of the package. Thus, the configure.ac check should be updated for it.

3. A minor nitpick :). configure.ac is checking for the x11 package twice. You can get rid of the following line:

PKG_CHECK_MODULES([X11], [x11])

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

Here is a patch for position filter inhibit for xi, please test :-)

diff --git a/src/frame-xi2.c b/src/frame-xi2.c
index 7fc38fd..98a43bd 100644
--- a/src/frame-xi2.c
+++ b/src/frame-xi2.c
@@ -288,6 +288,8 @@ utouch_frame_pump_xi2(utouch_frame_handle fh, const XIDevice
Event *ev)
   for (i = 0; i < nbit; i++)
    if (XIMaskIsSet(mask, i))
     handle_event(fh, slot, i, value[num++]);
+ /* no velocity adjustments without device time stamps */
+ slot->vx = slot->vy = 0;
   if (ev->evtype == XI_TouchEnd)
    utouch_frame_get_current_slot(fh)->id = -1;
   return utouch_frame_sync(fh, ev->time);

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

> Inconsistent #ifdef'ing around ABS_MT_DISTANCE: sometimes #if 0, sometimes
> #ifdef ABS_MT_DISTANCE.
>
> You might want to fix that before committing.
>
> Other than that, I find no obvious problems.

This is obviously not right, but placed here because of a missing variable in xserver-properties.h. I will add that variable to the ifdef instead.

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

I think all comments are now addressed. Pushed a new version of v1.0.2.

lp:~oif-team/frame/trunk.v1.0.2 updated
15. By Henrik Rydberg

Simplify XInput package test

The XI2.1 support is present in sufficiently recent xinput packages,
so simplify the testing accordingly.

16. By Henrik Rydberg

Fix ABS_MT_DISTANCE compilation conditional

The ABS_MT_DISTANCE is new, and the corresponding entry in
xserver-properties.h is even newer. Make compilation conditional on
the existence of those two defines.

17. By Henrik Rydberg

Disable time-dependent filtering for current XI2.1

Velocity-adjusted positioning and Kalman filters depend on accurate
time stamps on events. Until we have device event times, disable this
functionality for XI2.1

18. By Henrik Rydberg

Bump to version 1.0.2

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.gitignore'
2--- .gitignore 2010-12-30 19:23:24 +0000
3+++ .gitignore 2011-02-21 12:19:53 +0000
4@@ -79,3 +79,4 @@
5 .bzr
6 patches
7 tools/utouch-frame-test-mtdev
8+tools/utouch-frame-test-xi2
9
10=== modified file 'configure.ac'
11--- configure.ac 2011-02-03 16:07:34 +0000
12+++ configure.ac 2011-02-21 12:19:53 +0000
13@@ -1,7 +1,7 @@
14 # Initialize Autoconf
15 AC_PREREQ([2.60])
16 AC_INIT([Touch Frame Library],
17- [1.0.0],
18+ [1.0.2],
19 [],
20 [utouch-frame])
21 AC_CONFIG_SRCDIR([Makefile.am])
22@@ -25,6 +25,14 @@
23 PKG_CHECK_MODULES([MTDEV], [mtdev >= 1.1])
24 PKG_CHECK_MODULES([EVEMU], [utouch-evemu >= 1.0])
25
26+AC_ARG_WITH([xi], AS_HELP_STRING([--with-xi], [Build with XI2.1 support]))
27+AM_CONDITIONAL([HAVE_XI], [test "x$with_xi" != "x"])
28+
29+AS_IF([test "x$with_xi" = "xyes"], [
30+ PKG_CHECK_MODULES([X11], [x11])
31+ PKG_CHECK_MODULES(XINPUT, x11 xext [xi >= 1.4.99.1] [inputproto >= 2.0.99.1])
32+])
33+
34 AC_CHECK_PROG([ASCIIDOC], [a2x], [a2x])
35 AM_CONDITIONAL([HAVE_DOCTOOLS], [test "x$ASCIIDOC" != "x"])
36 AS_IF([test "x$ASCIIDOC" = "x"],
37
38=== modified file 'include/utouch/frame-mtdev.h'
39--- include/utouch/frame-mtdev.h 2010-12-30 19:23:24 +0000
40+++ include/utouch/frame-mtdev.h 2011-02-21 12:19:53 +0000
41@@ -22,6 +22,10 @@
42 #ifndef _UTOUCH_FRAME_MTDEV_H
43 #define _UTOUCH_FRAME_MTDEV_H
44
45+#ifdef __cplusplus
46+extern "C" {
47+#endif
48+
49 #define MTDEV_NO_LEGACY_API
50
51 #include <utouch/frame.h>
52@@ -36,4 +40,8 @@
53 const struct utouch_frame *
54 utouch_frame_pump_mtdev(utouch_frame_handle fh, const struct input_event *ev);
55
56+#ifdef __cplusplus
57+}
58+#endif
59+
60 #endif
61
62=== added file 'include/utouch/frame-xi2.h'
63--- include/utouch/frame-xi2.h 1970-01-01 00:00:00 +0000
64+++ include/utouch/frame-xi2.h 2011-02-21 12:19:53 +0000
65@@ -0,0 +1,49 @@
66+/*****************************************************************************
67+ *
68+ * utouch-frame - Touch Frame Library
69+ *
70+ * Copyright (C) 2010-2011 Canonical Ltd.
71+ *
72+ * This program is free software: you can redistribute it and/or modify it
73+ * under the terms of the GNU General Public License as published by the
74+ * Free Software Foundation, either version 3 of the License, or (at your
75+ * option) any later version.
76+ *
77+ * This program is distributed in the hope that it will be useful, but
78+ * WITHOUT ANY WARRANTY; without even the implied warranty of
79+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
80+ * General Public License for more details.
81+ *
82+ * You should have received a copy of the GNU General Public License along
83+ * with this program. If not, see <http://www.gnu.org/licenses/>.
84+ *
85+ ****************************************************************************/
86+
87+#ifndef _UTOUCH_FRAME_XI2_H
88+#define _UTOUCH_FRAME_XI2_H
89+
90+#ifdef __cplusplus
91+extern "C" {
92+#endif
93+
94+#define MTDEV_NO_LEGACY_API
95+
96+#include <utouch/frame.h>
97+#include <X11/extensions/XInput2.h>
98+
99+int utouch_frame_is_supported_xi2(Display *dpy, const XIDeviceInfo *dev);
100+
101+int utouch_frame_init_xi2(utouch_frame_handle fh,
102+ Display *dpy, const XIDeviceInfo *dev);
103+
104+int utouch_frame_configure_xi2(utouch_frame_handle fh,
105+ const XConfigureEvent *ev);
106+
107+const struct utouch_frame *
108+utouch_frame_pump_xi2(utouch_frame_handle fh, const XIDeviceEvent *ev);
109+
110+#ifdef __cplusplus
111+}
112+#endif
113+
114+#endif
115
116=== modified file 'include/utouch/frame.h'
117--- include/utouch/frame.h 2010-12-30 19:23:24 +0000
118+++ include/utouch/frame.h 2011-02-21 12:19:53 +0000
119@@ -22,9 +22,13 @@
120 #ifndef _UTOUCH_FRAME_H
121 #define _UTOUCH_FRAME_H
122
123+#ifdef __cplusplus
124+extern "C" {
125+#endif
126+
127 #include <stdint.h>
128
129-#define UTOUCH_FRAME_VERSION 0x00001000
130+#define UTOUCH_FRAME_VERSION 0x00001010
131
132 /**
133 * struct utouch_surface - device surface details
134@@ -42,11 +46,23 @@
135 * @phys_width: physical width in millimeters (mm)
136 * @phys_height: physical height in millimeters (mm)
137 * @phys_pressure: maximal physical pressure (N/cm^2)
138- * @min_x: minimum horizontal coordinate value
139- * @min_y: minimum vertical coordinate value
140- * @max_x: maximum horizontal coordinate value
141- * @max_y: maximum vertical coordinate value
142- * @max_pressure: maximum pressure coordinate value
143+ * @min_x: minimum horizontal device coordinate
144+ * @min_y: minimum vertical device coordinate
145+ * @max_x: maximum horizontal device coordinate
146+ * @max_y: maximum vertical device coordinate
147+ * @max_pressure: maximum pressure device coordinate
148+ * @max_orient: maximum orientation device coordinate
149+ * @mapped_min_x: minimum horizontal mapped coordinate
150+ * @mapped_min_y: minimum vertical mapped coordinate
151+ * @mapped_max_x: maximum horizontal mapped coordinate
152+ * @mapped_max_y: maximum vertical mapped coordinate
153+ * @mapped_max_pressure: maximum pressure mapped coordinate
154+ *
155+ * The mutable contact given by utouch_frame_get_current_slot() should
156+ * be set in device coordinates. The contact data is subsequently
157+ * transformed to mapped (e.g., screen) coordinates in
158+ * utouch_frame_sync(). To a frame user, all data will appear in
159+ * mapped coordinates.
160 *
161 * Device properties and touch surface details. Later versions of this
162 * struct may grow in size, but will remain binary compatible with
163@@ -72,6 +88,12 @@
164 float max_x;
165 float max_y;
166 float max_pressure;
167+ float max_orient;
168+ float mapped_min_x;
169+ float mapped_min_y;
170+ float mapped_max_x;
171+ float mapped_max_y;
172+ float mapped_max_pressure;
173 };
174
175 #define UTOUCH_TOOL_FINGER 0
176@@ -93,6 +115,8 @@
177 * @orientation: direction of ellipse (left: -Pi/2, up: 0, right: Pi/2)
178 * @pressure: pressure of contact (pressure units)
179 * @distance: distance of contact (surface units)
180+ * @vx: horizontal velocity coordinate (units / millisecond)
181+ * @vy: vertical velocity coordinate (units / millisecond)
182 *
183 * Surface contact details. Later versions of this struct may grow in
184 * size, but will remain binary compatible with older versions.
185@@ -116,6 +140,8 @@
186 float orientation;
187 float pressure;
188 float distance;
189+ float vx;
190+ float vy;
191 };
192
193 /* time in milliseconds */
194@@ -163,6 +189,20 @@
195 */
196 unsigned int utouch_frame_get_version(void);
197
198+/**
199+ * utouch_frame_get_num_frames - get number of supported frames
200+ *
201+ * Returns the number of frames supported by this engine.
202+ */
203+unsigned int utouch_frame_get_num_frames(utouch_frame_handle fh);
204+
205+/**
206+ * utouch_frame_get_num_slots - get number of supported slots
207+ *
208+ * Returns the number of simultaneous contacts supported by this engine.
209+ */
210+unsigned int utouch_frame_get_num_slots(utouch_frame_handle fh);
211+
212 utouch_frame_handle utouch_frame_new_engine_raw(unsigned int num_frames,
213 unsigned int num_slots,
214 unsigned int frame_rate,
215@@ -228,6 +268,17 @@
216 int utouch_frame_set_current_slot(utouch_frame_handle fh, int slot);
217
218 /**
219+ * utouch_frame_set_current_id - set the current slot by touch id
220+ * @fh: the frame engine in use
221+ * @id: the touch id
222+ *
223+ * Sets the slot currently being modified, by touch id. If the id is
224+ * not currently in use (does not have an active slot), a new slot is
225+ * assigned. Returns zero if successful, negative error otherwise.
226+ */
227+int utouch_frame_set_current_id(utouch_frame_handle fh, int id);
228+
229+/**
230 * utouch_frame_sync - synchronize and return new frame
231 * @fh: the frame engine in use
232 * @time: the frame synchronization time (ms)
233@@ -247,4 +298,8 @@
234 const struct utouch_frame *utouch_frame_sync(utouch_frame_handle fh,
235 utouch_frame_time_t time);
236
237+#ifdef __cplusplus
238+}
239+#endif
240+
241 #endif
242
243=== modified file 'src/Makefile.am'
244--- src/Makefile.am 2010-12-30 19:23:24 +0000
245+++ src/Makefile.am 2011-02-21 12:19:53 +0000
246@@ -3,7 +3,7 @@
247 libutouch_frame_la_LDFLAGS = \
248 -version-info @LIB_VERSION@ \
249 -lm \
250- $(EVEMU_LIBS)
251+ $(EVEMU_LIBS) \
252 $(MTDEV_LIBS)
253
254 libutouch_frame_la_SOURCES = \
255@@ -19,3 +19,11 @@
256 libutouch_frameinclude_HEADERS = \
257 $(top_srcdir)/include/utouch/frame.h \
258 $(top_srcdir)/include/utouch/frame-mtdev.h
259+
260+if HAVE_XI
261+
262+libutouch_frame_la_LDFLAGS += $(XINPUT_LIBS) $(X11_LIBS)
263+libutouch_frame_la_SOURCES += frame-xi2.c
264+libutouch_frameinclude_HEADERS += $(top_srcdir)/include/utouch/frame-xi2.h
265+
266+endif
267
268=== modified file 'src/frame-impl.h'
269--- src/frame-impl.h 2011-02-03 16:12:20 +0000
270+++ src/frame-impl.h 2011-02-21 12:19:53 +0000
271@@ -30,10 +30,11 @@
272 int hold_ms;
273 int frame;
274 int slot;
275- float max_orient;
276 struct utouch_surface *surface;
277 struct utouch_frame **frames;
278 struct utouch_frame *next;
279+ int *evmap;
280+ float map[9];
281 };
282
283 #endif
284
285=== modified file 'src/frame-mtdev.c'
286--- src/frame-mtdev.c 2011-02-08 18:24:27 +0000
287+++ src/frame-mtdev.c 2011-02-21 12:19:53 +0000
288@@ -104,12 +104,12 @@
289 }
290
291 s->max_pressure = evemu_get_abs_maximum(dev, ABS_MT_PRESSURE);
292- if (s->use_pressure && s->max_pressure == 0)
293+ if (s->max_pressure == 0)
294 s->max_pressure = 256;
295
296- fh->max_orient = evemu_get_abs_maximum(dev, ABS_MT_ORIENTATION);
297- if (s->use_orientation && fh->max_orient == 0)
298- fh->max_orient = 1;
299+ s->max_orient = evemu_get_abs_maximum(dev, ABS_MT_ORIENTATION);
300+ if (s->max_orient == 0)
301+ s->max_orient = 1;
302
303 tmp = evemu_get_abs_resolution(dev, ABS_MT_POSITION_X);
304 if (tmp > 0)
305@@ -133,14 +133,16 @@
306 else
307 s->phys_pressure = 10;
308
309+ /* defaults expected by initial frame version */
310+ s->mapped_min_x = s->min_x;
311+ s->mapped_min_y = s->min_y;
312+ s->mapped_max_x = s->max_x;
313+ s->mapped_max_y = s->max_y;
314+ s->mapped_max_pressure = s->max_pressure;
315+
316 return 0;
317 }
318
319-static float touch_angle(utouch_frame_handle fh, int orient)
320-{
321- return orient / fh->max_orient * M_PI_2;
322-}
323-
324 static int handle_abs_event(utouch_frame_handle fh,
325 const struct input_event *ev)
326 {
327@@ -152,9 +154,11 @@
328 return 1;
329 case ABS_MT_POSITION_X:
330 t->x = ev->value;
331+ t->vx = 0;
332 return 1;
333 case ABS_MT_POSITION_Y:
334 t->y = ev->value;
335+ t->vy = 0;
336 return 1;
337 case ABS_MT_TOUCH_MAJOR:
338 t->touch_major = ev->value;
339@@ -169,7 +173,7 @@
340 t->width_minor = ev->value;
341 return 1;
342 case ABS_MT_ORIENTATION:
343- t->orientation = touch_angle(fh, ev->value);
344+ t->orientation = ev->value;
345 return 1;
346 case ABS_MT_PRESSURE:
347 t->pressure = ev->value;
348
349=== added file 'src/frame-xi2.c'
350--- src/frame-xi2.c 1970-01-01 00:00:00 +0000
351+++ src/frame-xi2.c 2011-02-21 12:19:53 +0000
352@@ -0,0 +1,304 @@
353+/*****************************************************************************
354+ *
355+ * utouch-frame - Touch Frame Library
356+ *
357+ * Copyright (C) 2010 Canonical Ltd.
358+ *
359+ * This program is free software: you can redistribute it and/or modify it
360+ * under the terms of the GNU General Public License as published by the
361+ * Free Software Foundation, either version 3 of the License, or (at your
362+ * option) any later version.
363+ *
364+ * This program is distributed in the hope that it will be useful, but
365+ * WITHOUT ANY WARRANTY; without even the implied warranty of
366+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
367+ * General Public License for more details.
368+ *
369+ * You should have received a copy of the GNU General Public License along
370+ * with this program. If not, see <http://www.gnu.org/licenses/>.
371+ *
372+ ****************************************************************************/
373+#include <utouch/frame-xi2.h>
374+#include <xorg/xserver-properties.h>
375+#include <linux/input.h>
376+#include "frame-impl.h"
377+#include <stdlib.h>
378+#include <stdio.h>
379+#include <errno.h>
380+#include <math.h>
381+#include <string.h>
382+#include <X11/Xlib.h>
383+
384+static Atom transform_atom;
385+
386+#define set_field(fh, name, number, field) \
387+ if (!strcmp(name, AXIS_LABEL_PROP_##field) && \
388+ (fh->evmap[number] = field))
389+
390+int utouch_frame_is_supported_xi2(Display *dpy, const XIDeviceInfo *dev)
391+{
392+
393+ int i;
394+
395+ for (i = 0; i < dev->num_classes; i++)
396+ if (dev->classes[i]->type == XITouchClass)
397+ return 1;
398+
399+ return 0;
400+}
401+
402+static void init_properties(utouch_frame_handle fh,
403+ Display *dpy, const XIDeviceInfo *dev)
404+{
405+ struct utouch_surface *s = fh->surface;
406+ XITouchClassInfo *v;
407+ int i;
408+
409+ for (i = 0; i < dev->num_classes; i++) {
410+ v = (void *)dev->classes[i];
411+ if (v->type != XITouchClass)
412+ continue;
413+ switch(v->mode) {
414+ case XIDependentTouch:
415+ s->needs_pointer = 1;
416+ break;
417+ case XIDirectTouch:
418+ s->is_direct = 1;
419+ break;
420+ default:
421+ fprintf(stderr, "unknown mode\n");
422+ break;
423+ }
424+ }
425+
426+ if (transform_atom == None)
427+ transform_atom = XInternAtom(dpy, XI_PROP_TRANSFORM, True);
428+
429+ fh->map[0] = fh->map[4] = fh->map[8] = 1;
430+}
431+
432+static void update_transform(utouch_frame_handle fh, Display *dpy, int devid)
433+{
434+ unsigned long nitem, nbyte;
435+ unsigned char *data;
436+ int format;
437+ Atom type;
438+
439+ if (transform_atom == None)
440+ return;
441+
442+ XIGetProperty(dpy, devid, transform_atom, 0, 9, False,
443+ AnyPropertyType, &type, &format, &nitem, &nbyte, &data);
444+
445+ if (format == 32 && nitem == 9 && nbyte == 0)
446+ memcpy(fh->map, data, sizeof(fh->map));
447+ else
448+ fprintf(stderr, "Invalid transform matrix\n");
449+
450+ XFree(data);
451+}
452+
453+static void update_screen(utouch_frame_handle fh, Display *dpy)
454+{
455+ struct utouch_surface *s = fh->surface;
456+ XWindowAttributes attrs;
457+ float x1, y1, x2, y2;
458+
459+ XGetWindowAttributes(dpy, XDefaultRootWindow(dpy), &attrs);
460+
461+ x1 = 0;
462+ y1 = 0;
463+ x2 = attrs.width;
464+ y2 = attrs.height;
465+
466+ s->mapped_min_x = fh->map[0] * x1 + fh->map[1] * y1 + fh->map[2];
467+ s->mapped_min_y = fh->map[3] * x1 + fh->map[4] * y1 + fh->map[5];
468+ s->mapped_max_x = fh->map[0] * x2 + fh->map[1] * y2 + fh->map[2];
469+ s->mapped_max_y = fh->map[3] * x2 + fh->map[4] * y2 + fh->map[5];
470+ s->mapped_max_pressure = 1;
471+
472+ fprintf(stderr, "frame map: %f %f %f %f %f\n",
473+ s->mapped_min_x, s->mapped_min_y,
474+ s->mapped_max_x, s->mapped_max_y, s->mapped_max_pressure);
475+}
476+
477+static void init_valuators(utouch_frame_handle fh,
478+ Display *dpy, const XIDeviceInfo *dev)
479+{
480+ struct utouch_surface *s = fh->surface;
481+ XITouchValuatorClassInfo *v;
482+ char *name;
483+ int i;
484+
485+ s->phys_width = 100;
486+ s->phys_height = 65;
487+ s->phys_pressure = 10;
488+ s->max_x = 1024;
489+ s->max_y = 768;
490+ s->max_pressure = 256;
491+ s->max_orient = 1;
492+
493+ for (i = 0; i < dev->num_classes; i++) {
494+ v = (void *)dev->classes[i];
495+ if (v->type != XITouchValuatorClass)
496+ continue;
497+ name = XGetAtomName(dpy, v->label);
498+ set_field(fh, name, v->number, ABS_MT_POSITION_X) {
499+ s->min_x = v->min;
500+ s->max_x = v->max;
501+ if (v->resolution > 0)
502+ s->phys_width = (v->max - v->min) /
503+ v->resolution;
504+ }
505+ set_field(fh, name, v->number, ABS_MT_POSITION_Y) {
506+ s->min_y = v->min;
507+ s->max_y = v->max;
508+ if (v->resolution > 0)
509+ s->phys_height = (v->max - v->min) /
510+ v->resolution;
511+ }
512+ set_field(fh, name, v->number, ABS_MT_TOUCH_MAJOR) {
513+ s->use_touch_major = 1;
514+ }
515+ set_field(fh, name, v->number, ABS_MT_TOUCH_MINOR) {
516+ s->use_touch_minor = 1;
517+ }
518+ set_field(fh, name, v->number, ABS_MT_WIDTH_MAJOR) {
519+ s->use_width_major = 1;
520+ }
521+ set_field(fh, name, v->number, ABS_MT_WIDTH_MINOR) {
522+ s->use_width_minor = 1;
523+ }
524+ set_field(fh, name, v->number, ABS_MT_ORIENTATION) {
525+ s->use_orientation = 1;
526+ s->max_orient = v->max > 0 ? v->max : 1;
527+ }
528+ set_field(fh, name, v->number, ABS_MT_PRESSURE) {
529+ s->use_pressure = 1;
530+ s->max_pressure = v->max > 0 ? v->max : 256;
531+ if (v->resolution > 0)
532+ s->phys_pressure = v->max / v->resolution;
533+ }
534+#if 0
535+ set_field(fh, name, v->number, ABS_MT_DISTANCE) {
536+ s->use_distance = 1;
537+ }
538+#endif
539+ XFree(name);
540+ }
541+}
542+
543+int utouch_frame_init_xi2(utouch_frame_handle fh,
544+ Display *dpy, const XIDeviceInfo *dev)
545+{
546+ int event;
547+ int err;
548+
549+ free(fh->evmap);
550+ fh->evmap =calloc(dev->num_classes, sizeof(int));
551+ if (!fh->evmap)
552+ return -ENOMEM;
553+
554+ if (!utouch_frame_is_supported_xi2(dpy, dev))
555+ return -ENODEV;
556+
557+ init_properties(fh, dpy, dev);
558+ init_valuators(fh, dpy, dev);
559+ update_transform(fh, dpy, dev->deviceid);
560+ update_screen(fh, dpy);
561+
562+ return 0;
563+}
564+
565+static int handle_event(utouch_frame_handle fh,
566+ struct utouch_contact *slot,
567+ int ix, float value)
568+{
569+ switch (fh->evmap[ix]) {
570+ case ABS_MT_POSITION_X:
571+ slot->x = value;
572+ slot->vx = 0;
573+ return 1;
574+ case ABS_MT_POSITION_Y:
575+ slot->y = value;
576+ slot->vy = 0;
577+ return 1;
578+ case ABS_MT_TOUCH_MAJOR:
579+ slot->touch_major = value;
580+ return 1;
581+ case ABS_MT_TOUCH_MINOR:
582+ slot->touch_minor = value;
583+ return 1;
584+ case ABS_MT_WIDTH_MAJOR:
585+ slot->width_major = value;
586+ return 1;
587+ case ABS_MT_WIDTH_MINOR:
588+ slot->width_minor = value;
589+ return 1;
590+ case ABS_MT_ORIENTATION:
591+ slot->orientation = value;
592+ return 1;
593+ case ABS_MT_PRESSURE:
594+ slot->pressure = value;
595+ return 1;
596+#ifdef ABS_MT_DISTANCE
597+ case ABS_MT_DISTANCE:
598+ slot->distance = value;
599+ return 1;
600+#endif
601+ case ABS_MT_TOOL_TYPE:
602+ slot->tool_type = value;
603+ return 1;
604+ default:
605+ fprintf(stderr, "did not get that one: %d\n", ix);
606+ return 0;
607+ }
608+}
609+
610+int utouch_frame_configure_xi2(utouch_frame_handle fh,
611+ const XConfigureEvent *ev)
612+{
613+ if (ev->display)
614+ update_screen(fh, ev->display);
615+ return 1;
616+}
617+
618+const struct utouch_frame *
619+utouch_frame_pump_xi2(utouch_frame_handle fh, const XIDeviceEvent *ev)
620+{
621+ const XIPropertyEvent *prop_ev;
622+ const double *value;
623+ const unsigned char *mask;
624+ struct utouch_contact *slot;
625+ int touchid, nbyte, nbit, num, i;
626+
627+ switch (ev->evtype) {
628+ case XI_TouchBegin:
629+ case XI_TouchUpdate:
630+ case XI_TouchEnd:
631+ value = ev->valuators.values;
632+ mask = ev->valuators.mask;
633+ touchid = ev->detail;
634+ nbyte = ev->valuators.mask_len;
635+ nbit = nbyte << 3;
636+
637+ utouch_frame_set_current_id(fh, touchid);
638+ slot = utouch_frame_get_current_slot(fh);
639+ num = 0;
640+ for (i = 0; i < nbit; i++)
641+ if (XIMaskIsSet(mask, i))
642+ handle_event(fh, slot, i, value[num++]);
643+ if (ev->evtype == XI_TouchEnd)
644+ utouch_frame_get_current_slot(fh)->id = -1;
645+ return utouch_frame_sync(fh, ev->time);
646+ case XI_PropertyEvent:
647+ prop_ev = (XIPropertyEvent *)ev;
648+ if (prop_ev->property == transform_atom && ev->display) {
649+ update_transform(fh, ev->display, ev->deviceid);
650+ update_screen(fh, ev->display);
651+ }
652+ break;
653+ }
654+
655+ return 0;
656+}
657
658=== modified file 'src/frame.c'
659--- src/frame.c 2010-12-30 19:23:24 +0000
660+++ src/frame.c 2011-02-21 12:19:53 +0000
661@@ -33,6 +33,16 @@
662 return UTOUCH_FRAME_VERSION;
663 }
664
665+unsigned int utouch_frame_get_num_frames(utouch_frame_handle fh)
666+{
667+ return fh->num_frames;
668+}
669+
670+unsigned int utouch_frame_get_num_slots(utouch_frame_handle fh)
671+{
672+ return fh->num_slots;
673+}
674+
675 static void destroy_slots(struct utouch_contact **slots, int nslot)
676 {
677 int i;
678@@ -181,6 +191,7 @@
679
680 void utouch_frame_delete_engine(utouch_frame_handle fh)
681 {
682+ free(fh->evmap);
683 destroy_frame(fh->next, fh->num_slots);
684 destroy_frames(fh->frames, fh->num_frames, fh->num_slots);
685 free(fh->surface);
686@@ -205,11 +216,53 @@
687 return 0;
688 }
689
690-static void copy_contact(utouch_frame_handle fh,
691- struct utouch_contact *a,
692- const struct utouch_contact *b)
693-{
694+int utouch_frame_set_current_id(utouch_frame_handle fh, int id)
695+{
696+ struct utouch_contact *t;
697+ int i;
698+
699+ for (i = 0; i < fh->num_slots; i++) {
700+ t = fh->next->slots[i];
701+ if (t->id == id)
702+ return utouch_frame_set_current_slot(fh, i);
703+ }
704+ for (i = 0; i < fh->num_slots; i++) {
705+ t = fh->next->slots[i];
706+ if (t->id < 0) {
707+ t->id = id;
708+ return utouch_frame_set_current_slot(fh, i);
709+ }
710+ }
711+ return -ENOMEM;
712+}
713+
714+static void transform_slot(struct utouch_contact *slot,
715+ const struct utouch_surface *s)
716+{
717+ float fx = (s->mapped_max_x - s->mapped_min_x) / (s->max_x - s->min_x);
718+ float fy = (s->mapped_max_y - s->mapped_min_y) / (s->max_y - s->min_y);
719+ /* assume clipped view for asymmetrical scaling */
720+ float f = MAX(fx, fy);
721+
722+ slot->x = fx * (slot->x - s->min_x) + s->mapped_min_x;
723+ slot->y = fy * (slot->y - s->min_y) + s->mapped_min_y;
724+ slot->touch_major *= f;
725+ slot->touch_minor *= f;
726+ slot->width_major *= f;
727+ slot->width_minor *= f;
728+ slot->orientation *= M_PI_2 / s->max_orient;
729+ slot->pressure *= s->mapped_max_pressure / s->max_pressure;
730+ slot->distance *= f;
731+}
732+
733+static void set_contact(utouch_frame_handle fh,
734+ struct utouch_contact *a,
735+ struct utouch_contact *b,
736+ utouch_frame_time_t dt)
737+{
738+ static const float D = 0.333;
739 struct utouch_surface *s = fh->surface;
740+ const struct utouch_contact *ap = a->prev;
741
742 a->active = b->id != -1;
743 a->id = b->id;
744@@ -225,6 +278,23 @@
745 a->orientation = b->orientation;
746 a->pressure = b->pressure;
747 a->distance = b->distance;
748+
749+ transform_slot(a, s);
750+
751+ if (a->active && ap->active && a->id == ap->id) {
752+ a->x += b->vx * dt;
753+ a->y += b->vy * dt;
754+ if (dt > 0) {
755+ a->vx = (1 - D) * ap->vx + D * (a->x - ap->x) / dt;
756+ a->vy = (1 - D) * ap->vy + D * (a->y - ap->y) / dt;
757+ }
758+ } else {
759+ a->vx = 0;
760+ a->vy = 0;
761+ }
762+
763+ b->vx = a->vx;
764+ b->vy = a->vy;
765 }
766
767 static int detect_addrem(const struct utouch_contact *a,
768@@ -261,14 +331,18 @@
769 const struct utouch_frame *prev = frame->prev;
770 struct utouch_frame *next = fh->next;
771 int naddrem = 0, nmod = 0;
772+ utouch_frame_time_t dt;
773 int i;
774
775+ frame->time = time ? time : get_time_ms();
776 frame->num_active = 0;
777+ dt = frame->time - prev->time;
778+
779 for (i = 0; i < fh->num_slots; i++) {
780 struct utouch_contact *p = frame->slots[i];
781- const struct utouch_contact *q = next->slots[i];
782+ struct utouch_contact *q = next->slots[i];
783
784- copy_contact(fh, p, q);
785+ set_contact(fh, p, q, dt);
786 if (p->active)
787 frame->active[frame->num_active++] = p;
788
789@@ -278,7 +352,6 @@
790 if (naddrem + nmod == 0)
791 return 0;
792
793- frame->time = time ? time : get_time_ms();
794 if (naddrem == 0 && frame->time < prev->time + fh->hold_ms)
795 return 0;
796
797
798=== modified file 'tools/Makefile.am'
799--- tools/Makefile.am 2011-02-03 16:07:34 +0000
800+++ tools/Makefile.am 2011-02-21 12:19:53 +0000
801@@ -2,10 +2,22 @@
802
803 INCLUDES=-I$(top_srcdir)/include/
804
805-utouch_frame_test_mtdev_SOURCES = utouch-frame-test-mtdev.c
806+utouch_frame_test_mtdev_SOURCES = common-defs.h utouch-frame-test-mtdev.c
807 utouch_frame_test_mtdev_LDFLAGS = -L$(top_builddir)/src/.libs/ \
808 -lutouch-frame -lutouch-evemu -lmtdev -lm
809
810+if HAVE_XI
811+
812+AM_CFLAGS = $(XINPUT_CFLAGS)
813+
814+bin_PROGRAMS += utouch-frame-test-xi2
815+
816+utouch_frame_test_xi2_SOURCES = common-defs.h utouch-frame-test-xi2.c
817+utouch_frame_test_xi2_LDFLAGS = $(XINPUT_LIBS) $(X11_LIBS) \
818+ -L$(top_builddir)/src/.libs/ -lutouch-frame
819+
820+endif
821+
822 if HAVE_DOCTOOLS
823 dist_man_MANS = utouch-frame-test-mtdev.1
824
825
826=== added file 'tools/common-defs.h'
827--- tools/common-defs.h 1970-01-01 00:00:00 +0000
828+++ tools/common-defs.h 2011-02-21 12:19:53 +0000
829@@ -0,0 +1,85 @@
830+/*****************************************************************************
831+ *
832+ * utouch-frame - Touch Frame Library
833+ *
834+ * Copyright (C) 2010-2011 Canonical Ltd.
835+ *
836+ * This program is free software: you can redistribute it and/or modify it
837+ * under the terms of the GNU General Public License as published by the
838+ * Free Software Foundation, either version 3 of the License, or (at your
839+ * option) any later version.
840+ *
841+ * This program is distributed in the hope that it will be useful, but
842+ * WITHOUT ANY WARRANTY; without even the implied warranty of
843+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
844+ * General Public License for more details.
845+ *
846+ * You should have received a copy of the GNU General Public License along
847+ * with this program. If not, see <http://www.gnu.org/licenses/>.
848+ *
849+ * Authors:
850+ * Henrik Rydberg <rydberg@bitmath.org>
851+ *
852+ ****************************************************************************/
853+
854+static void report_device_caps(utouch_frame_handle fh)
855+{
856+ const struct utouch_surface *s = utouch_frame_get_surface(fh);
857+
858+ fprintf(stderr, "device props:\n");
859+ if (s->needs_pointer)
860+ fprintf(stderr, "\tpointer\n");
861+ if (s->is_direct)
862+ fprintf(stderr, "\tdirect\n");
863+ if (s->is_buttonpad)
864+ fprintf(stderr, "\tbuttonpad\n");
865+ if (s->is_semi_mt)
866+ fprintf(stderr, "\tsemi_mt\n");
867+ fprintf(stderr, "device mt events:\n");
868+ if (s->use_touch_major)
869+ fprintf(stderr, "\ttouch_major\n");
870+ if (s->use_touch_minor)
871+ fprintf(stderr, "\ttouch_minor\n");
872+ if (s->use_width_major)
873+ fprintf(stderr, "\twidth_major\n");
874+ if (s->use_width_minor)
875+ fprintf(stderr, "\twidth_minor\n");
876+ if (s->use_orientation)
877+ fprintf(stderr, "\torientation\n");
878+ if (s->use_pressure)
879+ fprintf(stderr, "\tpressure\n");
880+ if (s->use_distance)
881+ fprintf(stderr, "\tdistance\n");
882+}
883+
884+static void report_frame(const struct utouch_frame *frame)
885+{
886+ int i;
887+
888+ for (i = 0; i < frame->num_active; i++) {
889+ const struct utouch_contact *t = frame->active[i];
890+
891+ fprintf(stderr, "touch %d\n", i);
892+ fprintf(stderr, " slot: %d\n", t->slot);
893+ fprintf(stderr, " id: %d\n", t->id);
894+ fprintf(stderr, " tool_type: %d\n", t->tool_type);
895+ fprintf(stderr, " x: %f\n", t->x);
896+ fprintf(stderr, " y: %f\n", t->y);
897+ fprintf(stderr, " touch_major: %f\n", t->touch_major);
898+ fprintf(stderr, " touch_minor: %f\n", t->touch_minor);
899+ fprintf(stderr, " width_major: %f\n", t->width_major);
900+ fprintf(stderr, " width_minor: %f\n", t->width_minor);
901+ fprintf(stderr, " angle: %f\n", t->orientation);
902+ fprintf(stderr, " pressure: %f\n", t->pressure);
903+ fprintf(stderr, " distance: %f\n", t->distance);
904+ fprintf(stderr, " vx: %f\n", t->vx);
905+ fprintf(stderr, " vy: %f\n", t->vy);
906+ }
907+
908+ fprintf(stderr, "sync %d %ld %d %d %d\n",
909+ frame->num_active,
910+ frame->time,
911+ frame->sequence_id,
912+ frame->revision,
913+ frame->slot_revision);
914+}
915
916=== modified file 'tools/utouch-frame-test-mtdev.c'
917--- tools/utouch-frame-test-mtdev.c 2011-02-08 18:28:09 +0000
918+++ tools/utouch-frame-test-mtdev.c 2011-02-21 12:19:53 +0000
919@@ -30,6 +30,7 @@
920 #include <stdio.h>
921 #include <unistd.h>
922 #include <fcntl.h>
923+#include "common-defs.h"
924
925 struct frame_test {
926 struct evemu_device *evemu;
927@@ -69,36 +70,6 @@
928 memset(test, 0, sizeof(*test));
929 }
930
931-static void report_frame(const struct utouch_frame *frame)
932-{
933- int i;
934-
935- for (i = 0; i < frame->num_active; i++) {
936- const struct utouch_contact *t = frame->active[i];
937-
938- fprintf(stderr, "touch %d\n", i);
939- fprintf(stderr, " slot: %d\n", t->slot);
940- fprintf(stderr, " id: %d\n", t->id);
941- fprintf(stderr, " tool_type: %d\n", t->tool_type);
942- fprintf(stderr, " x: %f\n", t->x);
943- fprintf(stderr, " y: %f\n", t->y);
944- fprintf(stderr, " touch_major: %f\n", t->touch_major);
945- fprintf(stderr, " touch_minor: %f\n", t->touch_minor);
946- fprintf(stderr, " width_major: %f\n", t->width_major);
947- fprintf(stderr, " width_minor: %f\n", t->width_minor);
948- fprintf(stderr, " angle: %f\n", t->orientation);
949- fprintf(stderr, " pressure: %f\n", t->pressure);
950- fprintf(stderr, " distance: %f\n", t->distance);
951- }
952-
953- fprintf(stderr, "sync %d %ld %d %d %d\n",
954- frame->num_active,
955- frame->time,
956- frame->sequence_id,
957- frame->revision,
958- frame->slot_revision);
959-}
960-
961 static void loop_device(struct frame_test *test, int fd)
962 {
963 const struct utouch_frame *frame;
964@@ -113,35 +84,6 @@
965 }
966 }
967
968-static void report_device_caps(struct frame_test *test)
969-{
970- struct utouch_surface *s = utouch_frame_get_surface(test->fh);
971- fprintf(stderr, "device props:\n");
972- if (s->needs_pointer)
973- fprintf(stderr, "\tpointer\n");
974- if (s->is_direct)
975- fprintf(stderr, "\tdirect\n");
976- if (s->is_buttonpad)
977- fprintf(stderr, "\tbuttonpad\n");
978- if (s->is_semi_mt)
979- fprintf(stderr, "\tsemi_mt\n");
980- fprintf(stderr, "device mt events:\n");
981- if (s->use_touch_major)
982- fprintf(stderr, "\ttouch_major\n");
983- if (s->use_touch_minor)
984- fprintf(stderr, "\ttouch_minor\n");
985- if (s->use_width_major)
986- fprintf(stderr, "\twidth_major\n");
987- if (s->use_width_minor)
988- fprintf(stderr, "\twidth_minor\n");
989- if (s->use_orientation)
990- fprintf(stderr, "\torientation\n");
991- if (s->use_pressure)
992- fprintf(stderr, "\tpressure\n");
993- if (s->use_distance)
994- fprintf(stderr, "\tdistance\n");
995-}
996-
997 int main(int argc, char *argv[])
998 {
999 struct frame_test test;
1000@@ -182,7 +124,7 @@
1001 return -1;
1002 }
1003
1004- report_device_caps(&test);
1005+ report_device_caps(test.fh);
1006
1007 loop_device(&test, fd);
1008
1009
1010=== added file 'tools/utouch-frame-test-xi2.c'
1011--- tools/utouch-frame-test-xi2.c 1970-01-01 00:00:00 +0000
1012+++ tools/utouch-frame-test-xi2.c 2011-02-21 12:19:53 +0000
1013@@ -0,0 +1,177 @@
1014+/*****************************************************************************
1015+ *
1016+ * utouch-frame - Touch Frame Library
1017+ *
1018+ * Copyright (C) 2010-2011 Canonical Ltd.
1019+ *
1020+ * This program is free software: you can redistribute it and/or modify it
1021+ * under the terms of the GNU General Public License as published by the
1022+ * Free Software Foundation, either version 3 of the License, or (at your
1023+ * option) any later version.
1024+ *
1025+ * This program is distributed in the hope that it will be useful, but
1026+ * WITHOUT ANY WARRANTY; without even the implied warranty of
1027+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1028+ * General Public License for more details.
1029+ *
1030+ * You should have received a copy of the GNU General Public License along
1031+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1032+ *
1033+ * Authors:
1034+ * Henrik Rydberg <rydberg@bitmath.org>
1035+ *
1036+ ****************************************************************************/
1037+
1038+#define MTDEV_NO_LEGACY_API
1039+
1040+#include <utouch/frame-xi2.h>
1041+#include <string.h>
1042+#include <stdio.h>
1043+#include <unistd.h>
1044+#include <fcntl.h>
1045+#include <stdlib.h>
1046+#include "common-defs.h"
1047+
1048+static int opcode;
1049+
1050+struct frame_test {
1051+ Display *display;
1052+ Window root, win;
1053+ XIDeviceInfo *info, *dev;
1054+ utouch_frame_handle fh;
1055+};
1056+
1057+static int init_xi2(struct frame_test *test, int id)
1058+{
1059+ Display *dpy;
1060+ int ndevices, i;
1061+ int event, error;
1062+
1063+ dpy = XOpenDisplay(NULL);
1064+ if (!dpy)
1065+ return -1;
1066+
1067+ if (!XQueryExtension(dpy, "XInputExtension", &opcode, &event, &error))
1068+ return -1;
1069+
1070+ test->display = dpy;
1071+ test->info = XIQueryDevice(dpy, XIAllDevices, &ndevices);
1072+ test->dev = 0;
1073+ for (i = 0; i < ndevices; i++)
1074+ if (test->info[i].deviceid == id)
1075+ test->dev = &test->info[i];
1076+ if (!test->dev)
1077+ return -1;
1078+
1079+ test->root = DefaultRootWindow(dpy);
1080+ test->win = XCreateSimpleWindow(dpy, test->root,
1081+ 0, 0, 400, 400, 0,
1082+ BlackPixel(dpy, 0),
1083+ WhitePixel(dpy, 0));
1084+
1085+ XMapWindow(test->display, test->win);
1086+ XFlush(test->display);
1087+
1088+ return 0;
1089+}
1090+
1091+static int init_frame(struct frame_test *test)
1092+{
1093+ test->fh = utouch_frame_new_engine(100, 32, 100);
1094+ if (!test->fh)
1095+ return -1;
1096+ return utouch_frame_init_xi2(test->fh, test->display, test->dev);
1097+}
1098+
1099+static void destroy_all(struct frame_test *test)
1100+{
1101+ utouch_frame_delete_engine(test->fh);
1102+ XIFreeDeviceInfo(test->info);
1103+ XDestroyWindow(test->display, test->win);
1104+ XCloseDisplay(test->display);
1105+ memset(test, 0, sizeof(*test));
1106+}
1107+
1108+static void handle_event(struct frame_test *test, XEvent *ev)
1109+{
1110+ XGenericEventCookie *gev = &ev->xcookie;
1111+ const struct utouch_frame *frame;
1112+ XConfigureEvent *cev;
1113+ XIDeviceEvent *dev;
1114+
1115+ switch(ev->type) {
1116+ case ConfigureNotify:
1117+ cev = (XConfigureEvent *)ev;
1118+ if (cev->window == XDefaultRootWindow(cev->display))
1119+ utouch_frame_configure_xi2(test->fh, cev);
1120+ break;
1121+ case GenericEvent:
1122+ if (!XGetEventData(test->display, gev))
1123+ break;
1124+ dev = gev->data;
1125+ /* null for some requests, quite odd */
1126+ dev->display = ev->xany.display;
1127+ if (gev->type == GenericEvent && gev->extension == opcode) {
1128+ frame = utouch_frame_pump_xi2(test->fh, dev);
1129+ if (frame)
1130+ report_frame(frame);
1131+ }
1132+ XFreeEventData(test->display, gev);
1133+ break;
1134+ }
1135+}
1136+
1137+static void loop_device(struct frame_test *test)
1138+{
1139+ XIEventMask mask;
1140+
1141+ mask.deviceid = XIAllDevices;
1142+ mask.mask_len = XIMaskLen(XI_LASTEVENT);
1143+ mask.mask = calloc(mask.mask_len, sizeof(char));
1144+
1145+ XISetMask(mask.mask, XI_TouchBegin);
1146+ XISetMask(mask.mask, XI_TouchUpdate);
1147+ XISetMask(mask.mask, XI_TouchEnd);
1148+ XISetMask(mask.mask, XI_PropertyEvent);
1149+ XISelectEvents(test->display, test->win, &mask, 1);
1150+
1151+ XSelectInput(test->display, test->root, StructureNotifyMask);
1152+
1153+ while (1) {
1154+ XEvent ev;
1155+ XNextEvent(test->display, &ev);
1156+ handle_event(test, &ev);
1157+ }
1158+}
1159+
1160+int main(int argc, char *argv[])
1161+{
1162+ struct frame_test test;
1163+ int id;
1164+
1165+ if (argc < 2) {
1166+ fprintf(stderr, "Usage: %s <xinput_device_number>\n", argv[0]);
1167+ return -1;
1168+ }
1169+ id = atoi(argv[1]);
1170+
1171+ if (init_xi2(&test, id)) {
1172+ fprintf(stderr, "error: could not describe device\n");
1173+ return -1;
1174+ }
1175+ if (!utouch_frame_is_supported_xi2(test.display, test.dev)) {
1176+ fprintf(stderr, "error: unsupported device\n");
1177+ return -1;
1178+ }
1179+ if (init_frame(&test)) {
1180+ fprintf(stderr, "error: could not init frame\n");
1181+ return -1;
1182+ }
1183+
1184+ report_device_caps(test.fh);
1185+
1186+ loop_device(&test);
1187+
1188+ destroy_all(&test);
1189+ return 0;
1190+}
1191
1192=== added file 'tools/utouch-frame-test-xi2.txt'
1193--- tools/utouch-frame-test-xi2.txt 1970-01-01 00:00:00 +0000
1194+++ tools/utouch-frame-test-xi2.txt 2011-02-21 12:19:53 +0000
1195@@ -0,0 +1,22 @@
1196+UTOUCH-FRAME-TEST-XI2(1)
1197+==========================
1198+
1199+NAME
1200+----
1201+
1202+ utouch-frame-test-xi2 - report frame events from an xinput device
1203+
1204+SYNOPSIS
1205+--------
1206+
1207+ utouch-frame-test-xi2 xinput-device-number
1208+
1209+DESCRIPTION
1210+-----------
1211+
1212+A test tool used to analyse the capabilities and act as a test driver for the
1213+uTouch touch frame library.
1214+
1215+AUTHOR
1216+------
1217+utouch-frame-test-xi2 was written by Henrik Rydberg <rydberg@euromail.se>

Subscribers

People subscribed via source and target branches