[PATCH xinput] Add experimental multitouch support from Xi 2.1

Daniel Stone daniel at fooishbar.org
Sun Sep 19 22:03:09 PDT 2010


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.

Currently, test-xi2 also takes a grab for touch events on the main
window, and will replay touch events down to the subwindow if they
occurred in the child.  This is for testing only.

Signed-off-by: Daniel Stone <daniel at fooishbar.org>
---
 src/list.c     |   31 ++++++++++++++++++++
 src/test_xi2.c |   85 +++++++++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 103 insertions(+), 13 deletions(-)

diff --git a/src/list.c b/src/list.c
index 8633c62..7a27bdc 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
+#include <X11/extensions/XI2proto.h> /* for XITouch* */
+#endif
 
 static void
 print_info(Display* dpy, XDeviceInfo	*info, Bool shortformat)
@@ -178,6 +181,34 @@ print_classes_xi2(Display* display, XIAnyClassInfo **classes,
                     XFree(name);
                 }
                 break;
+            case XITouchClass:
+                {
+                    XITouchClassInfo *t = (XITouchClassInfo *) classes[i];
+                    XITouchInfo *tp = (XITouchInfo *) &t[1];
+
+                    printf("\t\tMultitouch capable (%d touches, max %d):\n",
+                           t->num_touches, t->max_touches);
+                    printf("\t\t  Mode: %s\n",
+                           t->mode == Absolute ? "absolute" : "relative");
+                    printf("\t\t  x range: %f - %f\n", t->min_x, t->max_x);
+                    printf("\t\t  y range: %f - %f\n", t->min_y, t->max_y);
+                    printf("\t\t  Touch size range: %f - %f\n",
+                           t->min_touch_width, t->max_touch_width);
+                    for (j = 0; j < t->num_touches; j++) {
+                        printf("\t\t  Detail for touch %d:\n", tp->touchid);
+                        printf("\t\t    Tool: %d\n", tp->tool);
+                        printf("\t\t    Current co-ords: (%f, %f)\n",
+                               tp->x, tp->y);
+                        printf("\t\t    Current contact width: (%f, %f)\n",
+                               tp->touch_major, tp->touch_minor);
+                        printf("\t\t    Current tool width: (%f, %f)\n",
+                               tp->tool_major, tp->tool_minor);
+                        printf("\t\t    Current orientation: %d°\n",
+                               tp->orientation);
+                        tp++;
+                    }
+                }
+                break;
         }
     }
 
diff --git a/src/test_xi2.c b/src/test_xi2.c
index c59ba26..9c3bbaf 100644
--- a/src/test_xi2.c
+++ b/src/test_xi2.c
@@ -29,16 +29,15 @@
 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, 250,
+                               250, 0, 0, WhitePixel(dpy, 0));
+    *subwin = XCreateSimpleWindow(dpy, *win, 50, 50, 150, 150, 0, 0,
+                                  BlackPixel(dpy, 0));
+
+    XMapWindow(dpy, *subwin);
+    XSelectInput(dpy, *win, ExposureMask);
 }
 
 static void print_deviceevent(XIDeviceEvent* event)
@@ -213,6 +212,43 @@ static void print_propertyevent(Display *display, XIPropertyEvent* event)
 
     XFree(name);
 }
+
+
+static void print_touchstate(Display *display, XITouchStateEvent* event)
+{
+    printf("    touch %d (tool %d) %sed\n", event->touchid, event->tool,
+           event->type == XI_TouchBegin ? "start" : "end");
+    printf("    window 0x%x, child 0x%x, root 0x%x\n",
+           event->event, event->child, event->root);
+    if (event->child)
+    {
+        printf("      replaying touch\n");
+        XIAllowTouchEvents(display, event->deviceid, XIReplayTouch,
+                           CurrentTime, event->touchid);
+    }
+}
+
+static void print_touchmotion(Display *display, XITouchMotionEvent* event)
+{
+    printf("    touch %d moved\n", event->touchid);
+    printf("    window 0x%x, child 0x%x, root 0x%x\n",
+           event->event, event->child, event->root);
+    if (event->mask & XITouchXMask)
+        printf("    x: %f (root %f, event %f)\n",
+               event->x, event->root_x, event->event_x);
+    if (event->mask & XITouchYMask)
+        printf("    y: %f (root %f, event %f)\n",
+               event->y, event->root_y, event->event_y);
+    if (event->mask & XITouchTouchSizeMask)
+        printf("    touch width: %f, %f\n",
+               event->touch_width_major, event->touch_width_minor);
+    if (event->mask & XITouchToolSizeMask)
+        printf("    tool width: %f, %f\n",
+               event->tool_width_major, event->tool_width_minor);
+    if (event->mask & XITouchOrientationMask)
+        printf("    orientation: %d°\n", event->orientation);
+}
+
 void
 test_sync_grab(Display *display, Window win)
 {
@@ -279,6 +315,9 @@ 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;
+        case XI_TouchBegin:       name = "TouchBegin";          break;
+        case XI_TouchEnd:         name = "TouchEnd";            break;
+        case XI_TouchMotion:      name = "TouchMotion";         break;
         default:
                                   name = "unknown event type"; break;
     }
@@ -294,14 +333,15 @@ 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 */
+    /* Select for all useful events on the main window, and TouchBegin on
+     * the child. */
     mask.deviceid = XIAllDevices;
-    mask.mask_len = XIMaskLen(XI_RawMotion);
+    mask.mask_len = XIMaskLen(XI_TouchMotion);
     mask.mask = calloc(mask.mask_len, sizeof(char));
     XISetMask(mask.mask, XI_ButtonPress);
     XISetMask(mask.mask, XI_ButtonRelease);
@@ -315,7 +355,11 @@ test_xi2(Display	*display,
     XISetMask(mask.mask, XI_FocusOut);
     XISetMask(mask.mask, XI_HierarchyChanged);
     XISetMask(mask.mask, XI_PropertyEvent);
+    XISetMask(mask.mask, XI_TouchBegin);
     XISelectEvents(display, win, &mask, 1);
+    memset(mask.mask, 0, mask.mask_len);
+    XISetMask(mask.mask, XI_TouchBegin);
+    XISelectEvents(display, subwin, &mask, 1);
     XMapWindow(display, win);
     XSync(display, False);
 
@@ -338,6 +382,14 @@ test_xi2(Display	*display,
         XIUngrabKeycode(display, 3, 24 /* q */, win, nmods - 2, &modifiers[2]);
     }
 
+    {
+        XIGrabModifiers mods = { XIAnyModifier, 0 };
+        mask.deviceid = 12;
+        memset(mask.mask, 0, mask.mask_len);
+        XISetMask(mask.mask, XI_TouchBegin);
+        XIGrabTouchBegin(display, 12, win, GrabModeSync, False, &mask, 1, &mods);
+    }
+
     mask.deviceid = XIAllMasterDevices;
     memset(mask.mask, 0, 2);
     XISetMask(mask.mask, XI_RawKeyPress);
@@ -394,6 +446,13 @@ test_xi2(Display	*display,
                 case XI_PropertyEvent:
                     print_propertyevent(display, cookie->data);
                     break;
+                case XI_TouchBegin:
+                case XI_TouchEnd:
+                    print_touchstate(display, cookie->data);
+                    break;
+                case XI_TouchMotion:
+                    print_touchmotion(display, cookie->data);
+                    break;
                 default:
                     print_deviceevent(cookie->data);
                     break;
-- 
1.7.1



More information about the xorg-devel mailing list