[PATCH v2 libXi multitouch 4/4] Implement support for XI 2.2

Peter Hutterer peter.hutterer at who-t.net
Thu Oct 13 22:23:57 PDT 2011


From: Chase Douglas <chase.douglas at canonical.com>

XI 2.1 has not been implemented yet, so this code defines version info
for it too. These will be dropped when XI 2.1 support is merged.

The code is based on what we have in the prototype libXi in Ubuntu. The
main differences are:

* No touch valuator classes
* No TouchUpdateUnownedEvents
* Addition of raw touch events
* Touch grab and ungrab is handled in existing passive grab functions
* XIAllowTouchEvents has been added as an extension of XIAllowEvents
* XIAllowEvents has been extended when XI 2.2 is supported

The last item causes a bit of an issue. The XIAllowEvents handling in
released X.org servers check that the size of the request is exactly the
size published in XI 2.0. Since we are extending the request, we must
get the right request size from the Xlib buffer depending on what
version of XI the server supports.

None of this code has been tested because we don't have a server to test
it with yet.

Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
Changes to v1:
- adjust to current protocol
- rebase on current libXi master
- re-use code in XIAllowTouchEvents and XIAllowEvents 

This patch requires http://patchwork.freedesktop.org/patch/7580/
Untested for lack of a server supporting MT, and it doesn't include the man
pages yet either.

 include/X11/extensions/XInput2.h |   33 +++++++++++++++
 src/XExtInt.c                    |   85 +++++++++++++++++++++++++++++++++++++-
 src/XIAllowEvents.c              |   46 +++++++++++++++++++-
 src/XIint.h                      |    2 +
 4 files changed, 162 insertions(+), 4 deletions(-)

diff --git a/include/X11/extensions/XInput2.h b/include/X11/extensions/XInput2.h
index 910b25f..f979c30 100644
--- a/include/X11/extensions/XInput2.h
+++ b/include/X11/extensions/XInput2.h
@@ -146,6 +146,14 @@ typedef struct
 
 typedef struct
 {
+    int         type;
+    int         sourceid;
+    int         mode;
+    int         num_touches;
+} XITouchClassInfo;
+
+typedef struct
+{
     int                 deviceid;
     char                *name;
     int                 use;
@@ -303,6 +311,23 @@ typedef struct {
     int           what;
 } XIPropertyEvent;
 
+typedef struct {
+    int           type;         /* GenericEvent */
+    unsigned long serial;       /* # of last request processed by server */
+    Bool          send_event;   /* true if this came from a SendEvent request */
+    Display       *display;     /* Display the event was read from */
+    int           extension;    /* XI extension offset */
+    int           evtype;
+    Time          time;
+    int           deviceid;
+    int           sourceid;
+    unsigned int  touchid;
+    Window        root;
+    Window        event;
+    Window        child;
+    int           flags;
+} XITouchOwnershipEvent;
+
 _XFUNCPROTOBEGIN
 
 extern Bool     XIQueryPointer(
@@ -426,6 +451,14 @@ extern Status XIAllowEvents(
     Time                time
 );
 
+extern Status XIAllowTouchEvents(
+    Display*            display,
+    int                 deviceid,
+    unsigned int        touch_id,
+    Window              grab_window,
+    int                 event_mode
+);
+
 extern int XIGrabButton(
     Display*            display,
     int                 deviceid,
diff --git a/src/XExtInt.c b/src/XExtInt.c
index d74a8d4..5805dab 100644
--- a/src/XExtInt.c
+++ b/src/XExtInt.c
@@ -146,6 +146,9 @@ static int
 wireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie);
 static int
 wireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie);
+static int
+wireToTouchOwnershipEvent(xXITouchOwnershipEvent *in,
+                          XGenericEventCookie *cookie);
 
 static /* const */ XEvent emptyevent;
 
@@ -271,7 +274,8 @@ static XExtensionVersion versions[] = { {XI_Absent, 0, 0},
 {XI_Present, XI_Add_DeviceProperties_Major,
  XI_Add_DeviceProperties_Minor},
 {XI_Present, 2, 0},
-{XI_Present, 2, 1}
+{XI_Present, 2, 1},
+{XI_Present, 2, 2}
 };
 
 /***********************************************************************
@@ -924,6 +928,9 @@ XInputWireToCookie(
         case XI_ButtonRelease:
         case XI_KeyPress:
         case XI_KeyRelease:
+        case XI_TouchBegin:
+        case XI_TouchUpdate:
+        case XI_TouchEnd:
             *cookie = *(XGenericEventCookie*)save;
             if (!wireToDeviceEvent((xXIDeviceEvent*)event, cookie))
             {
@@ -950,12 +957,25 @@ XInputWireToCookie(
                 break;
             }
             return ENQUEUE_EVENT;
+        case XI_TouchOwnership:
+            *cookie = *(XGenericEventCookie*)save;
+            if (!wireToTouchOwnershipEvent((xXITouchOwnershipEvent*)event,
+                                           cookie))
+            {
+                printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
+                        ge->evtype);
+                break;
+            }
+            return ENQUEUE_EVENT;
 
         case XI_RawKeyPress:
         case XI_RawKeyRelease:
         case XI_RawButtonPress:
         case XI_RawButtonRelease:
         case XI_RawMotion:
+        case XI_RawTouchBegin:
+        case XI_RawTouchUpdate:
+        case XI_RawTouchEnd:
             *cookie = *(XGenericEventCookie*)save;
             if (!wireToRawEvent((xXIRawEvent*)event, cookie))
             {
@@ -1041,6 +1061,8 @@ sizeDeviceClassType(int type, int num_elements)
             break;
         case XIScrollClass:
             l = sizeof(XIScrollClassInfo);
+        case XITouchClass:
+            l = sizeof(XITouchClassInfo);
             break;
         default:
             printf("sizeDeviceClassType: unknown type %d\n", type);
@@ -1260,6 +1282,22 @@ copyPropertyEvent(XGenericEventCookie *cookie_in,
 }
 
 static Bool
+copyTouchOwnershipEvent(XGenericEventCookie *cookie_in,
+                        XGenericEventCookie *cookie_out)
+{
+    XITouchOwnershipEvent *in, *out;
+
+    in = cookie_in->data;
+
+    out = cookie_out->data = malloc(sizeof(XITouchOwnershipEvent));
+    if (!out)
+        return False;
+
+    *out = *in;
+    return True;
+}
+
+static Bool
 copyRawEvent(XGenericEventCookie *cookie_in,
              XGenericEventCookie *cookie_out)
 {
@@ -1318,6 +1356,9 @@ XInputCopyCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out
         case XI_ButtonRelease:
         case XI_KeyPress:
         case XI_KeyRelease:
+        case XI_TouchBegin:
+        case XI_TouchUpdate:
+        case XI_TouchEnd:
             ret = copyDeviceEvent(in, out);
             break;
         case XI_DeviceChanged:
@@ -1335,6 +1376,9 @@ XInputCopyCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out
         case XI_PropertyEvent:
             ret = copyPropertyEvent(in, out);
             break;
+        case XI_TouchOwnership:
+            ret = copyTouchOwnershipEvent(in, out);
+            break;
         case XI_RawKeyPress:
         case XI_RawKeyRelease:
         case XI_RawButtonPress:
@@ -1450,6 +1494,8 @@ size_classes(xXIAnyInfo* from, int nclasses)
                 break;
             case XIScrollClass:
                 l = sizeDeviceClassType(XIScrollClass, 0);
+            case XITouchClass:
+                l = sizeDeviceClassType(XITouchClass, 0);
                 break;
         }
 
@@ -1582,6 +1628,18 @@ copy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int *nclasses)
                     to->classes[cls_idx++] = any_lib;
                 }
                 break;
+            case XITouchClass:
+                {
+                    XITouchClassInfo *cls_lib;
+                    xXITouchInfo *cls_wire;
+
+                    cls_wire = (xXITouchInfo*)any_wire;
+                    cls_lib = next_block(&ptr_lib, sizeof(XITouchClassInfo));
+
+                    cls_lib->mode = cls_wire->mode;
+                    cls_lib->num_touches = cls_wire->num_touches;
+                }
+                break;
         }
         len += any_wire->length * 4;
         ptr_wire += any_wire->length * 4;
@@ -1776,3 +1834,28 @@ wireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie)
 
     return 1;
 }
+
+static int
+wireToTouchOwnershipEvent(xXITouchOwnershipEvent *in,
+                          XGenericEventCookie *cookie)
+{
+    XITouchOwnershipEvent *out = malloc(sizeof(XITouchOwnershipEvent));
+
+    cookie->data = out;
+
+    out->type           = in->type;
+    out->display        = cookie->display;
+    out->extension      = in->extension;
+    out->evtype         = in->evtype;
+    out->send_event     = ((in->type & 0x80) != 0);
+    out->time           = in->time;
+    out->deviceid       = in->deviceid;
+    out->sourceid       = in->sourceid;
+    out->touchid        = in->touchid;
+    out->root           = in->root;
+    out->event          = in->event;
+    out->child          = in->child;
+    out->flags          = in->flags;
+
+    return 1;
+}
diff --git a/src/XIAllowEvents.c b/src/XIAllowEvents.c
index 1d388b3..e53cf25 100644
--- a/src/XIAllowEvents.c
+++ b/src/XIAllowEvents.c
@@ -29,9 +29,12 @@
 #include <X11/extensions/extutil.h>
 #include "XIint.h"
 
-Status
-XIAllowEvents(Display *dpy, int deviceid, int event_mode, Time time)
+static Status
+_XIAllowEvents(Display *dpy, int deviceid, int event_mode, Time time,
+                    unsigned int touch_id, Window grab_window)
 {
+    Bool have_XI22 = False;
+    int req_len = sz_xXIAllowEventsReq; /* in bytes */
     xXIAllowEventsReq *req;
 
     XExtDisplayInfo *extinfo = XInput_find_display(dpy);
@@ -40,14 +43,51 @@ XIAllowEvents(Display *dpy, int deviceid, int event_mode, Time time)
     if (_XiCheckExtInit(dpy, XInput_2_0, extinfo) == -1)
 	return (NoSuchExtension);
 
-    GetReq(XIAllowEvents, req);
+    /* 2.2's XIAllowEvents is 8 bytes longer than 2.0 */
+    if (_XiCheckExtInit(dpy, XInput_2_2, extinfo) == -1) {
+        req_len -= 8;
+        have_XI22 = True;
+    }
+
+    GetReqSized(XIAllowEvents, req_len/4, req);
+
     req->reqType = extinfo->codes->major_opcode;
     req->ReqType = X_XIAllowEvents;
     req->deviceid = deviceid;
     req->mode = event_mode;
     req->time = time;
 
+    if (have_XI22) {
+        req->touch_id = touch_id;
+        req->grab_window = grab_window;
+    }
+
     UnlockDisplay(dpy);
     SyncHandle();
     return Success;
 }
+
+Status
+XIAllowEvents(Display *dpy, int deviceid, int event_mode, Time time)
+{
+    return _XIAllowEvents(dpy, deviceid, event_mode, time, 0, None);
+}
+
+Status
+XIAllowTouchEvents(Display *dpy, int deviceid, unsigned int touch_id,
+                   Window grab_window, int event_mode)
+{
+    int status;
+    XExtDisplayInfo *extinfo = XInput_find_display(dpy);
+
+    LockDisplay(dpy);
+    if (_XiCheckExtInit(dpy, XInput_2_2, extinfo) == -1)
+	return (NoSuchExtension);
+
+    status = _XIAllowEvents(dpy, deviceid, event_mode, CurrentTime, touch_id, grab_window);
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+
+    return status;
+}
diff --git a/src/XIint.h b/src/XIint.h
index 41d99b3..e746374 100644
--- a/src/XIint.h
+++ b/src/XIint.h
@@ -19,6 +19,8 @@
 #define XInput_Add_DevicePresenceNotify	5
 #define XInput_Add_DeviceProperties	6
 #define XInput_2_0			7
+#define XInput_2_1			8
+#define XInput_2_2			9
 #endif
 #define XInput_2_1			8
 
-- 
1.7.6.4


More information about the xorg-devel mailing list