[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