[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