diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | configure.ac | 9 | ||||
| -rw-r--r-- | include/utouch/frame-xi2.h | 49 | ||||
| -rw-r--r-- | src/Makefile.am | 8 | ||||
| -rw-r--r-- | src/frame-impl.h | 2 | ||||
| -rw-r--r-- | src/frame-xi2.c | 302 | ||||
| -rw-r--r-- | src/frame.c | 1 | ||||
| -rw-r--r-- | tools/Makefile.am | 12 | ||||
| -rw-r--r-- | tools/utouch-frame-test-xi2.c | 238 | ||||
| -rw-r--r-- | tools/utouch-frame-test-xi2.txt | 22 |
10 files changed, 644 insertions, 0 deletions
| @@ -79,3 +79,4 @@ core | |||
| 79 | .bzr | 79 | .bzr |
| 80 | patches | 80 | patches |
| 81 | tools/utouch-frame-test-mtdev | 81 | tools/utouch-frame-test-mtdev |
| 82 | tools/utouch-frame-test-xi2 | ||
diff --git a/configure.ac b/configure.ac index 980a044..12b275e 100644 --- a/configure.ac +++ b/configure.ac | |||
| @@ -25,6 +25,15 @@ AC_PROG_INSTALL | |||
| 25 | PKG_CHECK_MODULES([MTDEV], [mtdev >= 1.1]) | 25 | PKG_CHECK_MODULES([MTDEV], [mtdev >= 1.1]) |
| 26 | PKG_CHECK_MODULES([EVEMU], [utouch-evemu >= 1.0]) | 26 | PKG_CHECK_MODULES([EVEMU], [utouch-evemu >= 1.0]) |
| 27 | 27 | ||
| 28 | AC_ARG_WITH([xi], AS_HELP_STRING([--with-xi], [Build with XI2.1 support])) | ||
| 29 | AM_CONDITIONAL([HAVE_XI], [test "x$with_xi" != "x"]) | ||
| 30 | |||
| 31 | AS_IF([test "x$with_xi" = "xyes"], [ | ||
| 32 | PKG_CHECK_MODULES([X11], [x11]) | ||
| 33 | PKG_CHECK_MODULES(XINPUT, x11 xext [xi >= 1.2] [inputproto >= 1.5]) | ||
| 34 | PKG_CHECK_MODULES(XI2_1, [xi >= 1.4.99.1] [inputproto >= 2.0.99.1]) | ||
| 35 | ]) | ||
| 36 | |||
| 28 | AC_CHECK_PROG([ASCIIDOC], [a2x], [a2x]) | 37 | AC_CHECK_PROG([ASCIIDOC], [a2x], [a2x]) |
| 29 | AM_CONDITIONAL([HAVE_DOCTOOLS], [test "x$ASCIIDOC" != "x"]) | 38 | AM_CONDITIONAL([HAVE_DOCTOOLS], [test "x$ASCIIDOC" != "x"]) |
| 30 | AS_IF([test "x$ASCIIDOC" = "x"], | 39 | AS_IF([test "x$ASCIIDOC" = "x"], |
diff --git a/include/utouch/frame-xi2.h b/include/utouch/frame-xi2.h new file mode 100644 index 0000000..5849c40 --- /dev/null +++ b/include/utouch/frame-xi2.h | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | /***************************************************************************** | ||
| 2 | * | ||
| 3 | * utouch-frame - Touch Frame Library | ||
| 4 | * | ||
| 5 | * Copyright (C) 2010-2011 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 | |||
| 22 | #ifndef _UTOUCH_FRAME_XI2_H | ||
| 23 | #define _UTOUCH_FRAME_XI2_H | ||
| 24 | |||
| 25 | #ifdef __cplusplus | ||
| 26 | extern "C" { | ||
| 27 | #endif | ||
| 28 | |||
| 29 | #define MTDEV_NO_LEGACY_API | ||
| 30 | |||
| 31 | #include <utouch/frame.h> | ||
| 32 | #include <X11/extensions/XInput2.h> | ||
| 33 | |||
| 34 | int utouch_frame_is_supported_xi2(Display *dpy, const XIDeviceInfo *dev); | ||
| 35 | |||
| 36 | int utouch_frame_init_xi2(utouch_frame_handle fh, | ||
| 37 | Display *dpy, const XIDeviceInfo *dev); | ||
| 38 | |||
| 39 | int utouch_frame_configure_xi2(utouch_frame_handle fh, | ||
| 40 | const XConfigureEvent *ev); | ||
| 41 | |||
| 42 | const struct utouch_frame * | ||
| 43 | utouch_frame_pump_xi2(utouch_frame_handle fh, const XIDeviceEvent *ev); | ||
| 44 | |||
| 45 | #ifdef __cplusplus | ||
| 46 | } | ||
| 47 | #endif | ||
| 48 | |||
| 49 | #endif | ||
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 | |||
| 19 | libutouch_frameinclude_HEADERS = \ | 19 | libutouch_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 | |||
| 23 | if HAVE_XI | ||
| 24 | |||
| 25 | libutouch_frame_la_LDFLAGS += $(XINPUT_LIBS) $(X11_LIBS) | ||
| 26 | libutouch_frame_la_SOURCES += frame-xi2.c | ||
| 27 | libutouch_frameinclude_HEADERS += $(top_srcdir)/include/utouch/frame-xi2.h | ||
| 28 | |||
| 29 | endif | ||
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 | |||
| 32 | static 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 | |||
| 38 | int 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 | |||
| 50 | static 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 | |||
| 80 | static 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 | |||
| 101 | static 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 | |||
| 125 | static 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 | |||
| 191 | int 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 | |||
| 213 | static 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 | |||
| 256 | int 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 | |||
| 264 | const struct utouch_frame * | ||
| 265 | utouch_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 | ||
| 182 | void utouch_frame_delete_engine(utouch_frame_handle fh) | 182 | void 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); |
diff --git a/tools/Makefile.am b/tools/Makefile.am index 91e99ce..3b612cc 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am | |||
| @@ -6,6 +6,18 @@ utouch_frame_test_mtdev_SOURCES = utouch-frame-test-mtdev.c | |||
| 6 | utouch_frame_test_mtdev_LDFLAGS = -L$(top_builddir)/src/.libs/ \ | 6 | utouch_frame_test_mtdev_LDFLAGS = -L$(top_builddir)/src/.libs/ \ |
| 7 | -lutouch-frame -lutouch-evemu -lmtdev -lm | 7 | -lutouch-frame -lutouch-evemu -lmtdev -lm |
| 8 | 8 | ||
| 9 | if HAVE_XI | ||
| 10 | |||
| 11 | AM_CFLAGS = $(XINPUT_CFLAGS) | ||
| 12 | |||
| 13 | bin_PROGRAMS += utouch-frame-test-xi2 | ||
| 14 | |||
| 15 | utouch_frame_test_xi2_SOURCES = utouch-frame-test-xi2.c | ||
| 16 | utouch_frame_test_xi2_LDFLAGS = $(XINPUT_LIBS) $(X11_LIBS) \ | ||
| 17 | -L$(top_builddir)/src/.libs/ -lutouch-frame | ||
| 18 | |||
| 19 | endif | ||
| 20 | |||
| 9 | if HAVE_DOCTOOLS | 21 | if HAVE_DOCTOOLS |
| 10 | dist_man_MANS = utouch-frame-test-mtdev.1 | 22 | dist_man_MANS = utouch-frame-test-mtdev.1 |
| 11 | 23 | ||
diff --git a/tools/utouch-frame-test-xi2.c b/tools/utouch-frame-test-xi2.c new file mode 100644 index 0000000..df68c1a --- /dev/null +++ b/tools/utouch-frame-test-xi2.c | |||
| @@ -0,0 +1,238 @@ | |||
| 1 | /***************************************************************************** | ||
| 2 | * | ||
| 3 | * utouch-frame - Touch Frame Library | ||
| 4 | * | ||
| 5 | * Copyright (C) 2010-2011 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 | * Authors: | ||
| 21 | * Henrik Rydberg <rydberg@bitmath.org> | ||
| 22 | * | ||
| 23 | ****************************************************************************/ | ||
| 24 | |||
| 25 | #define MTDEV_NO_LEGACY_API | ||
| 26 | |||
| 27 | #include <utouch/frame-xi2.h> | ||
| 28 | #include <string.h> | ||
| 29 | #include <stdio.h> | ||
| 30 | #include <unistd.h> | ||
| 31 | #include <fcntl.h> | ||
| 32 | #include <stdlib.h> | ||
| 33 | |||
| 34 | static int opcode; | ||
| 35 | |||
| 36 | struct frame_test { | ||
| 37 | Display *display; | ||
| 38 | Window root, win; | ||
| 39 | XIDeviceInfo *info, *dev; | ||
| 40 | utouch_frame_handle fh; | ||
| 41 | }; | ||
| 42 | |||
| 43 | static int init_xi2(struct frame_test *test, int id) | ||
| 44 | { | ||
| 45 | Display *dpy; | ||
| 46 | int ndevices, i; | ||
| 47 | int event, error; | ||
| 48 | |||
| 49 | dpy = XOpenDisplay(NULL); | ||
| 50 | if (!dpy) | ||
| 51 | return -1; | ||
| 52 | |||
| 53 | if (!XQueryExtension(dpy, "XInputExtension", &opcode, &event, &error)) | ||
| 54 | return -1; | ||
| 55 | |||
| 56 | test->display = dpy; | ||
| 57 | test->info = XIQueryDevice(dpy, XIAllDevices, &ndevices); | ||
| 58 | test->dev = 0; | ||
| 59 | for (i = 0; i < ndevices; i++) | ||
| 60 | if (test->info[i].deviceid == id) | ||
| 61 | test->dev = &test->info[i]; | ||
| 62 | if (!test->dev) | ||
| 63 | return -1; | ||
| 64 | |||
| 65 | test->root = DefaultRootWindow(dpy); | ||
| 66 | test->win = XCreateSimpleWindow(dpy, test->root, | ||
| 67 | 0, 0, 400, 400, 0, | ||
| 68 | BlackPixel(dpy, 0), | ||
| 69 | WhitePixel(dpy, 0)); | ||
| 70 | |||
| 71 | XMapWindow(test->display, test->win); | ||
| 72 | XFlush(test->display); | ||
| 73 | |||
| 74 | return 0; | ||
| 75 | } | ||
| 76 | |||
| 77 | static int init_frame(struct frame_test *test) | ||
| 78 | { | ||
| 79 | test->fh = utouch_frame_new_engine(100, 32, 100); | ||
| 80 | if (!test->fh) | ||
| 81 | return -1; | ||
| 82 | return utouch_frame_init_xi2(test->fh, test->display, test->dev); | ||
| 83 | } | ||
| 84 | |||
| 85 | static void destroy_all(struct frame_test *test) | ||
| 86 | { | ||
| 87 | utouch_frame_delete_engine(test->fh); | ||
| 88 | XIFreeDeviceInfo(test->info); | ||
| 89 | XDestroyWindow(test->display, test->win); | ||
| 90 | XCloseDisplay(test->display); | ||
| 91 | memset(test, 0, sizeof(*test)); | ||
| 92 | } | ||
| 93 | |||
| 94 | static void report_device_caps(struct frame_test *test) | ||
| 95 | { | ||
| 96 | struct utouch_surface *s = utouch_frame_get_surface(test->fh); | ||
| 97 | fprintf(stderr, "device props:\n"); | ||
| 98 | if (s->needs_pointer) | ||
| 99 | fprintf(stderr, "\tpointer\n"); | ||
| 100 | if (s->is_direct) | ||
| 101 | fprintf(stderr, "\tdirect\n"); | ||
| 102 | if (s->is_buttonpad) | ||
| 103 | fprintf(stderr, "\tbuttonpad\n"); | ||
| 104 | if (s->is_semi_mt) | ||
| 105 | fprintf(stderr, "\tsemi_mt\n"); | ||
| 106 | fprintf(stderr, "device mt events:\n"); | ||
| 107 | if (s->use_touch_major) | ||
| 108 | fprintf(stderr, "\ttouch_major\n"); | ||
| 109 | if (s->use_touch_minor) | ||
| 110 | fprintf(stderr, "\ttouch_minor\n"); | ||
| 111 | if (s->use_width_major) | ||
| 112 | fprintf(stderr, "\twidth_major\n"); | ||
| 113 | if (s->use_width_minor) | ||
| 114 | fprintf(stderr, "\twidth_minor\n"); | ||
| 115 | if (s->use_orientation) | ||
| 116 | fprintf(stderr, "\torientation\n"); | ||
| 117 | if (s->use_pressure) | ||
| 118 | fprintf(stderr, "\tpressure\n"); | ||
| 119 | if (s->use_distance) | ||
| 120 | fprintf(stderr, "\tdistance\n"); | ||
| 121 | } | ||
| 122 | |||
| 123 | static void report_frame(const struct utouch_frame *frame, | ||
| 124 | const XIDeviceEvent *ev) | ||
| 125 | { | ||
| 126 | int i; | ||
| 127 | |||
| 128 | for (i = 0; i < frame->num_active; i++) { | ||
| 129 | const struct utouch_contact *t = frame->active[i]; | ||
| 130 | |||
| 131 | fprintf(stderr, "touch %d\n", i); | ||
| 132 | fprintf(stderr, " slot: %d\n", t->slot); | ||
| 133 | fprintf(stderr, " id: %d\n", t->id); | ||
| 134 | fprintf(stderr, " tool_type: %d\n", t->tool_type); | ||
| 135 | fprintf(stderr, " x: %f\n", t->x); | ||
| 136 | fprintf(stderr, " y: %f\n", t->y); | ||
| 137 | fprintf(stderr, " touch_major: %f\n", t->touch_major); | ||
| 138 | fprintf(stderr, " touch_minor: %f\n", t->touch_minor); | ||
| 139 | fprintf(stderr, " width_major: %f\n", t->width_major); | ||
| 140 | fprintf(stderr, " width_minor: %f\n", t->width_minor); | ||
| 141 | fprintf(stderr, " angle: %f\n", t->orientation); | ||
| 142 | fprintf(stderr, " pressure: %f\n", t->pressure); | ||
| 143 | fprintf(stderr, " distance: %f\n", t->distance); | ||
| 144 | } | ||
| 145 | |||
| 146 | fprintf(stderr, "sync %d %ld %d %d %d %f %f\n", | ||
| 147 | frame->num_active, | ||
| 148 | frame->time, | ||
| 149 | frame->sequence_id, | ||
| 150 | frame->revision, | ||
| 151 | frame->slot_revision, | ||
| 152 | ev->root_x, | ||
| 153 | ev->root_y); | ||
| 154 | } | ||
| 155 | |||
| 156 | static void handle_event(struct frame_test *test, XEvent *ev) | ||
| 157 | { | ||
| 158 | XGenericEventCookie *gev = &ev->xcookie; | ||
| 159 | const struct utouch_frame *frame; | ||
| 160 | XConfigureEvent *cev; | ||
| 161 | XIDeviceEvent *dev; | ||
| 162 | |||
| 163 | switch(ev->type) { | ||
| 164 | case ConfigureNotify: | ||
| 165 | cev = (XConfigureEvent *)ev; | ||
| 166 | if (cev->window == XDefaultRootWindow(cev->display)) | ||
| 167 | utouch_frame_configure_xi2(test->fh, cev); | ||
| 168 | break; | ||
| 169 | case GenericEvent: | ||
| 170 | if (!XGetEventData(test->display, gev)) | ||
| 171 | break; | ||
| 172 | dev = gev->data; | ||
| 173 | /* null for some requests, quite odd */ | ||
| 174 | dev->display = ev->xany.display; | ||
| 175 | if (gev->type == GenericEvent && gev->extension == opcode) { | ||
| 176 | frame = utouch_frame_pump_xi2(test->fh, dev); | ||
| 177 | if (frame) | ||
| 178 | report_frame(frame, dev); | ||
| 179 | } | ||
| 180 | XFreeEventData(test->display, gev); | ||
| 181 | break; | ||
| 182 | } | ||
| 183 | } | ||
| 184 | |||
| 185 | static void loop_device(struct frame_test *test) | ||
| 186 | { | ||
| 187 | XIEventMask mask; | ||
| 188 | |||
| 189 | mask.deviceid = XIAllDevices; | ||
| 190 | mask.mask_len = XIMaskLen(XI_TouchMotion); | ||
| 191 | mask.mask = calloc(mask.mask_len, sizeof(char)); | ||
| 192 | |||
| 193 | XISetMask(mask.mask, XI_TouchBegin); | ||
| 194 | XISetMask(mask.mask, XI_TouchMotion); | ||
| 195 | XISetMask(mask.mask, XI_TouchEnd); | ||
| 196 | XISetMask(mask.mask, XI_PropertyEvent); | ||
| 197 | XISelectEvents(test->display, test->win, &mask, 1); | ||
| 198 | |||
| 199 | XSelectInput(test->display, test->root, StructureNotifyMask); | ||
| 200 | |||
| 201 | while (1) { | ||
| 202 | XEvent ev; | ||
| 203 | XNextEvent(test->display, &ev); | ||
| 204 | handle_event(test, &ev); | ||
| 205 | } | ||
| 206 | } | ||
| 207 | |||
| 208 | int main(int argc, char *argv[]) | ||
| 209 | { | ||
| 210 | struct frame_test test; | ||
| 211 | int id; | ||
| 212 | |||
| 213 | if (argc < 2) { | ||
| 214 | fprintf(stderr, "Usage: %s <xinput_device_number>\n", argv[0]); | ||
| 215 | return -1; | ||
| 216 | } | ||
| 217 | id = atoi(argv[1]); | ||
| 218 | |||
| 219 | if (init_xi2(&test, id)) { | ||
| 220 | fprintf(stderr, "error: could not describe device\n"); | ||
| 221 | return -1; | ||
| 222 | } | ||
| 223 | if (!utouch_frame_is_supported_xi2(test.display, test.dev)) { | ||
| 224 | fprintf(stderr, "error: unsupported device\n"); | ||
| 225 | return -1; | ||
| 226 | } | ||
| 227 | if (init_frame(&test)) { | ||
| 228 | fprintf(stderr, "error: could not init frame\n"); | ||
| 229 | return -1; | ||
| 230 | } | ||
| 231 | |||
| 232 | report_device_caps(&test); | ||
| 233 | |||
| 234 | loop_device(&test); | ||
| 235 | |||
| 236 | destroy_all(&test); | ||
| 237 | return 0; | ||
| 238 | } | ||
diff --git a/tools/utouch-frame-test-xi2.txt b/tools/utouch-frame-test-xi2.txt new file mode 100644 index 0000000..9f79167 --- /dev/null +++ b/tools/utouch-frame-test-xi2.txt | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | UTOUCH-FRAME-TEST-XI2(1) | ||
| 2 | ========================== | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | |||
| 7 | utouch-frame-test-xi2 - report frame events from an xinput device | ||
| 8 | |||
| 9 | SYNOPSIS | ||
| 10 | -------- | ||
| 11 | |||
| 12 | utouch-frame-test-xi2 xinput-device-number | ||
| 13 | |||
| 14 | DESCRIPTION | ||
| 15 | ----------- | ||
| 16 | |||
| 17 | A test tool used to analyse the capabilities and act as a test driver for the | ||
| 18 | uTouch touch frame library. | ||
| 19 | |||
| 20 | AUTHOR | ||
| 21 | ------ | ||
| 22 | utouch-frame-test-xi2 was written by Henrik Rydberg <rydberg@euromail.se> | ||
