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

Chase Douglas chase.douglas at canonical.com
Wed Sep 14 22:33:57 PDT 2011


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>
---
 include/X11/extensions/XInput2.h |   33 ++++++++++++++
 src/XExtInt.c                    |   88 +++++++++++++++++++++++++++++++++++++-
 src/XIAllowEvents.c              |   51 +++++++++++++++++++++-
 src/XIint.h                      |    2 +
 4 files changed, 172 insertions(+), 2 deletions(-)

diff --git a/include/X11/extensions/XInput2.h b/include/X11/extensions/XInput2.h
index 3fcf083..93b980d 100644
--- a/include/X11/extensions/XInput2.h
+++ b/include/X11/extensions/XInput2.h
@@ -135,6 +135,14 @@ typedef struct
 
 typedef struct
 {
+    int         type;
+    int         sourceid;
+    int         mode;
+    int         num_touches;
+} XITouchClassInfo;
+
+typedef struct
+{
     int                 deviceid;
     char                *name;
     int                 use;
@@ -292,6 +300,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(
@@ -415,6 +440,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 86a780e..598f302 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;
 
@@ -270,7 +273,9 @@ static XExtensionVersion versions[] = { {XI_Absent, 0, 0},
  XI_Add_DevicePresenceNotify_Minor},
 {XI_Present, XI_Add_DeviceProperties_Major,
  XI_Add_DeviceProperties_Minor},
-{XI_Present, 2, 0}
+{XI_Present, 2, 0},
+{XI_Present, 2, 1},
+{XI_Present, 2, 2}
 };
 
 /***********************************************************************
@@ -923,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))
             {
@@ -949,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))
             {
@@ -1038,6 +1059,9 @@ sizeDeviceClassType(int type, int num_elements)
         case XIValuatorClass:
             l = sizeof(XIValuatorClassInfo);
             break;
+        case XITouchClass:
+            l = sizeof(XITouchClassInfo);
+            break;
         default:
             printf("sizeDeviceClassType: unknown type %d\n", type);
             break;
@@ -1244,6 +1268,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)
 {
@@ -1302,6 +1342,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:
@@ -1319,6 +1362,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:
@@ -1432,6 +1478,9 @@ size_classes(xXIAnyInfo* from, int nclasses)
             case XIValuatorClass:
                 l = sizeDeviceClassType(XIValuatorClass, 0);
                 break;
+            case XITouchClass:
+                l = sizeDeviceClassType(XITouchClass, 0);
+                break;
         }
 
         len += l;
@@ -1536,6 +1585,18 @@ copy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int nclasses)
 
                 }
                 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;
@@ -1726,3 +1787,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..bf2fad5 100644
--- a/src/XIAllowEvents.c
+++ b/src/XIAllowEvents.c
@@ -40,13 +40,62 @@ XIAllowEvents(Display *dpy, int deviceid, int event_mode, Time time)
     if (_XiCheckExtInit(dpy, XInput_2_0, extinfo) == -1)
 	return (NoSuchExtension);
 
-    GetReq(XIAllowEvents, req);
+    if (_XiCheckExtInit(dpy, XInput_2_2, extinfo) == -1)
+    {
+        GetReq(XIAllowEvents, req);
+    }
+    else
+    {
+        int extra_bytes = sz_xXIAllowEvents_2_2Req - sz_xXIAllowEventsReq;
+        GetReqExtra(XIAllowEvents, extra_bytes, req);
+    }
+
     req->reqType = extinfo->codes->major_opcode;
     req->ReqType = X_XIAllowEvents;
     req->deviceid = deviceid;
     req->mode = event_mode;
     req->time = time;
 
+    /* A grab_window of 0 is invalid, so if the event_mode passed in is a touch
+     * mode the server will return an error to the client.
+     */
+    if (_XiCheckExtInit(dpy, XInput_2_2, extinfo) == 0)
+    {
+        xXIAllowEventsReq_2_2 *req_2_2 = (xXIAllowEventsReq_2_2 *)req;
+        req_2_2->touch_id = 0;
+        req_2_2->grab_window = 0;
+    }
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+    return Success;
+}
+
+Status
+XIAllowTouchEvents(Display *dpy, int deviceid, unsigned int touch_id,
+                   Window grab_window, int event_mode)
+{
+    xXIAllowEventsReq *req;
+    xXIAllowEventsReq_2_2 *req_2_2;
+    int extra_bytes = sz_xXIAllowEvents_2_2Req - sz_xXIAllowEventsReq;
+
+    XExtDisplayInfo *extinfo = XInput_find_display(dpy);
+
+    LockDisplay(dpy);
+    if (_XiCheckExtInit(dpy, XInput_2_2, extinfo) == -1)
+	return (NoSuchExtension);
+
+    GetReqExtra(XIAllowEvents, extra_bytes, req);
+    req_2_2 = (xXIAllowEventsReq_2_2 *)req;
+
+    req->reqType = extinfo->codes->major_opcode;
+    req->ReqType = X_XIAllowEvents;
+    req->deviceid = deviceid;
+    req->mode = event_mode;
+    req->time = CurrentTime;
+    req_2_2->touch_id = touch_id;
+    req_2_2->grab_window = grab_window;
+
     UnlockDisplay(dpy);
     SyncHandle();
     return Success;
diff --git a/src/XIint.h b/src/XIint.h
index 8e9cf72..effeee6 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
 
 
-- 
1.7.4.1



More information about the xorg-devel mailing list