[PATCH xinput 1/1] Add experimental multitouch support from XI 2.1
Peter Hutterer
peter.hutterer at who-t.net
Tue Dec 21 18:56:48 PST 2010
On Fri, Dec 17, 2010 at 05:14:49PM +0000, Daniel Stone wrote:
> From: Chase Douglas <chase.douglas at canonical.com>
>
> This patch adds experimental support for listening to touch streams
> (TouchBegin, TouchMotion and TouchEnd) with test-xi2, as well as showing
> TouchClass information with list.
>
> Based on an initial patch by Daniel Stone.
>
> Signed-off-by: Daniel Stone <daniel at fooishbar.org>
> Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
> ---
> configure.ac | 6 ++++
> src/list.c | 28 ++++++++++++++++++++
> src/test_xi2.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++---------
> 3 files changed, 98 insertions(+), 12 deletions(-)
>
> diff --git a/configure.ac b/configure.ac
> index 1dc2ce2..d657a59 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -28,6 +28,12 @@ PKG_CHECK_MODULES(XI2, [xi >= 1.2.99.2] [inputproto >= 1.9.99.15],
> HAVE_XI2="no");
> AM_CONDITIONAL(HAVE_XI2, [ test "$HAVE_XI2" = "yes" ])
>
> +# XI2.1 support
> +PKG_CHECK_MODULES(XI2_1, [xi >= 1.4.99.1] [inputproto >= 2.0.99.1],
> + HAVE_XI2_1="yes"; AC_DEFINE(HAVE_XI2_1, 1, [XI2_1 available]),
> + HAVE_XI2_1="no");
> +AM_CONDITIONAL(HAVE_XI2_1, [ test "$HAVE_XI2_1" = "yes" ])
> +
> AC_SUBST(XINPUT_CFLAGS)
> AC_SUBST(XINPUT_LIBS)
> AC_SUBST(HAVE_XI2)
> diff --git a/src/list.c b/src/list.c
> index 8633c62..8920cad 100644
> --- a/src/list.c
> +++ b/src/list.c
> @@ -24,6 +24,9 @@
> #include "xinput.h"
> #include <string.h>
> #include <X11/extensions/XIproto.h> /* for XI_Device***ChangedNotify */
> +#ifdef HAVE_XI2_1
> +#include <X11/extensions/XI2proto.h> /* for XITouch* */
> +#endif
this strikes me as odd. a client should never have to include the protocol
header unless it's doing something special (and most likely wrong).
I just checked the XIproto.h include and it still builds fine without it.
the line was added in 2007 when XI2 was still a bit too much in flux.
> static void
> print_info(Display* dpy, XDeviceInfo *info, Bool shortformat)
> @@ -178,6 +181,31 @@ print_classes_xi2(Display* display, XIAnyClassInfo **classes,
> XFree(name);
> }
> break;
> +#ifdef HAVE_XI2_1
> + case XITouchClass:
> + {
> + XITouchClassInfo *t = (XITouchClassInfo *)classes[i];
> +
> + printf("\t\tMultitouch capable (max %d touches):\n",
> + t->num_touches);
> + printf("\t\t Mode: %s\n",
> + t->mode == XIDirectTouch ? "direct" : "dependent");
> + }
> + break;
> + case XITouchValuatorClass:
> + {
> + XITouchValuatorClassInfo *tv =
> + (XITouchValuatorClassInfo *)classes[i];
> + char *name = tv->label ?
> + XGetAtomName(display, tv->label) : NULL;
> +
> + printf("\t\tDetail for Touch Valuator %d:\n", tv->number);
> + printf("\t\t Label: %s\n", (name) ? name : "None");
> + printf("\t\t Range: %f - %f\n", tv->min, tv->max);
> + printf("\t\t Resolution: %d units/m\n", tv->resolution);
> + }
not that it really matters, but free(name) would close the leak.
> + break;
> +#endif /* HAVE_XI2_1 */
> }
> }
>
> diff --git a/src/test_xi2.c b/src/test_xi2.c
> index 5b56397..443bbd8 100644
> --- a/src/test_xi2.c
> +++ b/src/test_xi2.c
> @@ -29,26 +29,41 @@
> extern void print_classes_xi2(Display*, XIAnyClassInfo **classes,
> int num_classes);
>
> -static Window create_win(Display *dpy)
> +static void create_win(Display *dpy, Window *win, Window *subwin)
> {
> - Window win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 200,
> - 200, 0, 0, WhitePixel(dpy, 0));
> - Window subwindow = XCreateSimpleWindow(dpy, win, 50, 50, 50, 50, 0, 0,
> - BlackPixel(dpy, 0));
> -
> - XMapWindow(dpy, subwindow);
> - XSelectInput(dpy, win, ExposureMask);
> - return win;
> + *win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 200,
> + 200, 0, 0, WhitePixel(dpy, 0));
> + *subwin = XCreateSimpleWindow(dpy, *win, 50, 50, 50, 50, 0, 0,
> + BlackPixel(dpy, 0));
> + XMapWindow(dpy, *subwin);
> + XSelectInput(dpy, *win, ExposureMask);
> }
>
> static void print_deviceevent(XIDeviceEvent* event)
> {
> double *val;
> int i;
> + static int touch_events_received = 0;
> + static int thong = 0;
thong or flip-flop? this may be a source of much confusion.
> printf(" device: %d (%d)\n", event->deviceid, event->sourceid);
> printf(" detail: %d\n", event->detail);
> - printf(" flags: %s\n", (event->flags & XIKeyRepeat) ? "repeat" : "");
> +
> + switch (event->evtype)
> + {
> + case XI_KeyPress:
indentation inside the switch please.
> + case XI_KeyRelease:
> + printf(" flags: %s\n", (event->flags & XIKeyRepeat) ? "repeat" : "");
> + break;
> + case XI_TouchBegin:
> + case XI_TouchMotion:
> + case XI_TouchEnd:
> + printf(" flags: %s%s%s\n",
> + (event->flags & XITouchOwner) ? "owner " : "",
> + (event->flags & XITouchOwnerAccepted) ? "owner accepted " : "",
> + (event->flags & XITouchPendingFinish) ? "pending finish " : "");
> + break;
> + }
>
> printf(" root: %.2f/%.2f\n", event->root_x, event->root_y);
> printf(" event: %.2f/%.2f\n", event->event_x, event->event_y);
> @@ -74,6 +89,14 @@ static void print_deviceevent(XIDeviceEvent* event)
>
> printf(" windows: root 0x%lx event 0x%lx child 0x%lx\n",
> event->root, event->event, event->child);
> +
> + if (event->evtype == XI_TouchBegin)
> + touch_events_received = 0;
> + else if (event->evtype == XI_TouchMotion && event->event != event->child &&
> + (event->flags & XITouchOwner) && ++touch_events_received == 5)
> + XIAllowTouchEvents(event->display, event->sourceid, event->detail,
> + (thong ^= 1) ? XITouchOwnerAccept :
>
> + XITouchOwnerReject);
some comment about what the effect of this is would be nice. afaict, it
releases the touch after 5 events, once with accept, once with reject?
Any specific reason for this? xinput isn't a demo app but more to test the
event stream from a device for debugging. not sure how the above behaviour
will help with this.
> }
>
> static void print_devicechangedevent(Display *dpy, XIDeviceChangedEvent *event)
> @@ -279,6 +302,11 @@ static const char* type_to_name(int evtype)
> case XI_RawButtonPress: name = "RawButtonPress"; break;
> case XI_RawButtonRelease: name = "RawButtonRelease"; break;
> case XI_RawMotion: name = "RawMotion"; break;
> +#ifdef HAVE_XI2_1
> + case XI_TouchBegin: name = "TouchBegin"; break;
> + case XI_TouchEnd: name = "TouchEnd"; break;
> + case XI_TouchMotion: name = "TouchMotion"; break;
> +#endif
> default:
> name = "unknown event type"; break;
> }
> @@ -294,14 +322,18 @@ test_xi2(Display *display,
> char *desc)
> {
> XIEventMask mask;
> - Window win;
> + Window win, subwin;
>
> list(display, argc, argv, name, desc);
> - win = create_win(display);
> + create_win(display, &win, &subwin);
>
> /* Select for motion events */
> mask.deviceid = XIAllDevices;
> +#ifdef HAVE_XI2_1
> + mask.mask_len = XIMaskLen(XI_TouchMotion);
> +#else
> mask.mask_len = XIMaskLen(XI_RawMotion);
> +#endif
XI_LASTEVENT to avoid the ifdef?
Cheers,
Peter
> mask.mask = calloc(mask.mask_len, sizeof(char));
> XISetMask(mask.mask, XI_ButtonPress);
> XISetMask(mask.mask, XI_ButtonRelease);
> @@ -316,9 +348,17 @@ test_xi2(Display *display,
> XISetMask(mask.mask, XI_HierarchyChanged);
> XISetMask(mask.mask, XI_PropertyEvent);
> XISelectEvents(display, win, &mask, 1);
> +#ifdef HAVE_XI2_1
> + memset(mask.mask, 0, mask.mask_len);
> + XISetMask(mask.mask, XI_TouchBegin);
> + XISetMask(mask.mask, XI_TouchMotion);
> + XISetMask(mask.mask, XI_TouchEnd);
> + XISelectEvents(display, subwin, &mask, 1);
> +#endif
> XMapWindow(display, win);
> XSync(display, False);
>
> +#if 0
> {
> XIGrabModifiers modifiers[] = {{0, 0}, {0, 0x10}, {0, 0x1}, {0, 0x11}};
> int nmods = sizeof(modifiers)/sizeof(modifiers[0]);
> @@ -337,6 +377,18 @@ test_xi2(Display *display,
> XIUngrabButton(display, 3, 1, win, nmods - 2, &modifiers[2]);
> XIUngrabKeycode(display, 3, 24 /* q */, win, nmods - 2, &modifiers[2]);
> }
> +#else
> + {
> + XIGrabModifiers mods = { XIAnyModifier, 0 };
> + mask.deviceid = XIAllMasterDevices;
> + memset(mask.mask, 0, mask.mask_len);
> + XISetMask(mask.mask, XI_TouchBegin);
> + XISetMask(mask.mask, XI_TouchMotion);
> + XISetMask(mask.mask, XI_TouchEnd);
> + XIGrabTouchBegin(display, XIAllMasterDevices, win, False, &mask,
> + 1, &mods);
> + }
> +#endif
>
> mask.deviceid = XIAllMasterDevices;
> memset(mask.mask, 0, mask.mask_len);
> --
> 1.7.2.3
More information about the xorg-devel
mailing list