[PATCH libXi] Implement support for XI 2.2
Peter Hutterer
peter.hutterer at who-t.net
Sun Dec 18 16:04:16 PST 2011
Adds support for the new TouchClass for multitouch-capable servers/devices.
New events:
XITouchOwnershipEvent
New event types handled:
XITouchBegin, XITouchUpdate, XITouchEnd
XIRawTouchBegin, XIRawTouchUpdate, XIRawTouchEnd
New functions:
XIGrabTouchBegin ... passive grabs on touches
XIUngrabTouchBegin
XIAllowTouchEvents ... Allow/reject touch event sequences
New XIQueryDevice classes:
XITouchClassInfo
Requires libX11 1.5 for GetReqSized
Co-authored by: Chase Douglas <chase.douglas at canonical.com>
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
configure.ac | 2 +-
include/X11/extensions/XInput2.h | 51 +++++++++++++++++++++
man/XIGrabButton.txt | 60 ++++++++++++++++---------
man/XIQueryDevice.txt | 30 ++++++++++++-
src/XExtInt.c | 91 +++++++++++++++++++++++++++++++++++++-
src/XIAllowEvents.c | 46 ++++++++++++++++++-
src/XIPassiveGrab.c | 33 ++++++++++++++
src/XIint.h | 1 +
8 files changed, 286 insertions(+), 28 deletions(-)
diff --git a/configure.ac b/configure.ac
index c6565a8..0a7bdfa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -28,7 +28,7 @@ XORG_WITH_ASCIIDOC(8.4.5)
XORG_CHECK_MALLOC_ZERO
# Obtain compiler/linker options for depedencies
-PKG_CHECK_MODULES(XI, [xproto >= 7.0.13] [x11 >= 1.2.99.1] [xextproto >= 7.0.3] [xext >= 1.0.99.1] [inputproto >= 2.0.99.1])
+PKG_CHECK_MODULES(XI, [xproto >= 7.0.13] [x11 >= 1.4.99.1] [xextproto >= 7.0.3] [xext >= 1.0.99.1] [inputproto >= 2.1.99.3])
# Check for xmlto and asciidoc for man page conversion
# (only needed by people building tarballs)
diff --git a/include/X11/extensions/XInput2.h b/include/X11/extensions/XInput2.h
index 910b25f..26de695 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 touchid,
+ Window grab_window,
+ int event_mode
+);
+
extern int XIGrabButton(
Display* display,
int deviceid,
@@ -477,6 +510,17 @@ extern int XIGrabFocusIn(
int num_modifiers,
XIGrabModifiers *modifiers_inout
);
+
+extern int XIGrabTouchBegin(
+ Display* display,
+ int deviceid,
+ Window grab_window,
+ int owner_events,
+ XIEventMask *mask,
+ int num_modifiers,
+ XIGrabModifiers *modifiers_inout
+);
+
extern Status XIUngrabButton(
Display* display,
int deviceid,
@@ -511,6 +555,13 @@ extern Status XIUngrabFocusIn(
XIGrabModifiers *modifiers
);
+extern Status XIUngrabTouchBegin(
+ Display* display,
+ int deviceid,
+ Window grab_window,
+ int num_modifiers,
+ XIGrabModifiers *modifiers
+);
extern Atom *XIListProperties(
Display* display,
diff --git a/man/XIGrabButton.txt b/man/XIGrabButton.txt
index 45ac25e..a046ac7 100644
--- a/man/XIGrabButton.txt
+++ b/man/XIGrabButton.txt
@@ -49,6 +49,20 @@ SYNOPSIS
int num_modifiers,
XIGrabModifiers *modifiers);
+ int XIGrabTouchBegin( Display *display,
+ int deviceid,
+ Window grab_window,
+ Bool owner_events,
+ XIEventMask *mask,
+ int num_modifiers,
+ XIGrabModifiers *modifiers_inout);
+
+ int XIUngrabTouchBegin( Display *display,
+ int deviceid,
+ Window grab_window,
+ int num_modifiers,
+ XIGrabModifiers *modifiers);
+
display
Specifies the connection to the X server.
@@ -101,8 +115,8 @@ SYNOPSIS
DESCRIPTION
-----------
- XIGrabButton and XIGrabKeycode establishes a passive grab. The
- modifier device for a button grab is the paired master device
+ XIGrabButton, XIGrabKeycode and XIGrabTouchBegin establish a passive
+ grab. The modifier device for a button grab is the paired master device
if deviceid specifies a master pointer. Otherwise, the modifier
device is the device specified with deviceid. In the future,
the device is actively grabbed (as for XIGrabDevice, the
@@ -110,9 +124,9 @@ DESCRIPTION
was pressed and the XI_ButtonPress or XI_KeyPress event is
reported if all of the following conditions are true:
* The device is not grabbed, and the specified button or
- keycode is logically pressed when the specified modifier
- keys are logically down on the modifier device and no other
- buttons or modifier keys are logically down.
+ keycode is logically pressed or a touch event occurs when the
+ specified modifier keys are logically down on the modifier device
+ and no other buttons or modifier keys are logically down.
* Either the grab window is an ancestor of (or is) the focus
window, OR the grab window is a descendent of the focus
window and contains the device.
@@ -156,35 +170,36 @@ DESCRIPTION
combination. XIGrabButton and XIGrabKeycode have no effect on an
active grab.
- On success, XIGrabButton and XIGrabKeycode return 0;
+ On success, XIGrabButton, XIGrabKeycode and XIGrabTouchBegin return 0;
If one or more modifier combinations could not be grabbed,
- XIGrabButton and XIGrabKeycode return the number of failed
- combinations and modifiers_inout contains the failed combinations
+ XIGrabButton, XIGrabKeycode and XIGrabTouchBegin return the number of
+ failed combinations and modifiers_inout contains the failed combinations
and their respective error codes.
- XIGrabButton and XIGrabKeycode can generate BadClass, BadDevice,
- BadMatch, BadValue, and BadWindow errors.
+ XIGrabButton, XIGrabKeycode and XIGrabTouchBegin can generate BadClass,
+ BadDevice, BadMatch, BadValue, and BadWindow errors.
- XIUngrabButton and XIUngrabKeycode releases the passive grab for
- a button/modifier or keycode/modifier combination on the
- specified window if it was grabbed by this client. A modifier
- of XIAnyModifier is equivalent to issuing the ungrab request
+ XIUngrabButton, XIUngrabKeycode and XIUngrabTouchBegin release the
+ passive grab for a button/modifier, keycode/modifier or touch/modifier
+ combination on the specified window if it was grabbed by this client. A
+ modifier of XIAnyModifier is equivalent to issuing the ungrab request
for all possible modifier combinations, including the
combination of no modifiers. A button of XIAnyButton is
equivalent to issuing the request for all possible buttons.
XIUngrabButton and XIUngrabKeycode have no effect on an active
grab.
- XIUngrabButton and XIUngrabKeycode can generate BadDevice,
- BadMatch, BadValue and BadWindow errors.
+ XIUngrabButton, XIUngrabKeycode and XIUngrabTouchBegin can generate
+ BadDevice, BadMatch, BadValue and BadWindow errors.
RETURN VALUE
------------
- XIGrabButton and XIGrabKeycode return the number of modifier combination
- that could not establish a passive grab. The modifiers are returned in
- modifiers_inout, along with the respective error for this modifier
- combination. If XIGrabButton or XIGrabKeycode return zero, passive grabs
- with all requested modifier combinations were established successfully.
+ XIGrabButton, XIGrabKeycode and XIGrabTouchBegin return the number of
+ modifier combination that could not establish a passive grab. The
+ modifiers are returned in modifiers_inout, along with the respective
+ error for this modifier combination. If XIGrabButton, XIGrabKeycode
+ or XIGrabTouchBegin return zero, passive grabs with all requested
+ modifier combinations were established successfully.
DIAGNOSTICS
-----------
@@ -195,7 +210,8 @@ DIAGNOSTICS
BadMatch
This error may occur if XIGrabButton specified a device
that has no buttons, or XIGrabKeycode specified a device
- that has no keys.
+ that has no keys, or XIGrabTouchBegin specified a device
+ that is not touch-capable.
BadValue
Some numeric value falls outside the range of values
diff --git a/man/XIQueryDevice.txt b/man/XIQueryDevice.txt
index 6b5a622..e5e8251 100644
--- a/man/XIQueryDevice.txt
+++ b/man/XIQueryDevice.txt
@@ -100,7 +100,8 @@ DESCRIPTION
The type field specifies the type of the input class.
Currently, the following types are defined:
- XIKeyClass, XIButtonClass, XIValuatorClass, XIScrollClass
+ XIKeyClass, XIButtonClass, XIValuatorClass, XIScrollClass,
+ XITouchClass
In the future, additional types may be added. Clients are
required to ignore unknown input classes.
@@ -231,6 +232,33 @@ DESCRIPTION
the emulation of XI_Motion events when the driver submits
legacy scroll button events.
+ typedef struct
+ {
+ int type;
+ int sourceid;
+ int mode;
+ int num_touches;
+ } XITouchClassInfo;
+
+ A device may have zero or one XITouchClassInfo, denoting
+ multi-touch capability on the device. A device with a XITouchClassInfo
+ may send TouchBegin, TouchUpdate, TouchEnd and TouchOwnership events.
+
+ The mode field is either XIDirectTouch for direct-input touch devices
+ such as touchscreens or XIDependentTouch for indirect input devices such
+ as touchpads. For XIDirectTouch devices, touch events are sent to window
+ at the position the touch occured. For XIDependentTouch devices, touch
+ events are sent to the window at the position of the device's sprite.
+
+ The num_touches field defines the maximum number of simultaneous touches
+ the device supports. A num_touches of 0 means the maximum number of
+ simultaneous touches is undefined or unspecified. This field should be
+ used as a guide only, devices will lie about their capabilities.
+
+ A device with an XITouchClassInfo may still send pointer events. The
+ valuators must be defined with the respective XIValuatorClass
+ classes. A valuator may send both pointer and touch-events.
+
XIQueryDevice can generate a BadDevice error.
XIFreeDeviceInfo frees the information returned by
diff --git a/src/XExtInt.c b/src/XExtInt.c
index 29ecfa3..b12886d 100644
--- a/src/XExtInt.c
+++ b/src/XExtInt.c
@@ -150,6 +150,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;
@@ -275,7 +278,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}
};
/***********************************************************************
@@ -928,6 +932,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))
{
@@ -954,12 +961,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))
{
@@ -1046,6 +1066,9 @@ sizeDeviceClassType(int type, int num_elements)
case XIScrollClass:
l = sizeof(XIScrollClassInfo);
break;
+ case XITouchClass:
+ l = sizeof(XITouchClassInfo);
+ break;
default:
printf("sizeDeviceClassType: unknown type %d\n", type);
break;
@@ -1264,6 +1287,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)
{
@@ -1322,6 +1361,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:
@@ -1339,6 +1381,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:
@@ -1455,6 +1500,9 @@ size_classes(xXIAnyInfo* from, int nclasses)
case XIScrollClass:
l = sizeDeviceClassType(XIScrollClass, 0);
break;
+ case XITouchClass:
+ l = sizeDeviceClassType(XITouchClass, 0);
+ break;
}
len += l;
@@ -1586,6 +1634,22 @@ 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->type = cls_wire->type;
+ cls_lib->sourceid = cls_wire->sourceid;
+ cls_lib->mode = cls_wire->mode;
+ cls_lib->num_touches = cls_wire->num_touches;
+
+ to->classes[cls_idx++] = any_lib;
+ }
+ break;
}
len += any_wire->length * 4;
ptr_wire += any_wire->length * 4;
@@ -1780,3 +1844,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 d4da6d0..d987549 100644
--- a/src/XIAllowEvents.c
+++ b/src/XIAllowEvents.c
@@ -33,9 +33,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 touchid, Window grab_window)
{
+ Bool have_XI22 = True;
+ int req_len = sz_xXIAllowEventsReq; /* in bytes */
xXIAllowEventsReq *req;
XExtDisplayInfo *extinfo = XInput_find_display(dpy);
@@ -44,14 +47,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 = False;
+ }
+
+ GetReqSized(XIAllowEvents, req_len, 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->touchid = touchid;
+ 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 touchid,
+ 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, touchid, grab_window);
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ return status;
+}
diff --git a/src/XIPassiveGrab.c b/src/XIPassiveGrab.c
index 7625521..f8eafed 100644
--- a/src/XIPassiveGrab.c
+++ b/src/XIPassiveGrab.c
@@ -148,6 +148,25 @@ XIGrabFocusIn(Display *dpy, int deviceid, Window grab_window, int grab_mode,
modifiers_inout);
}
+int
+XIGrabTouchBegin(Display *dpy, int deviceid, Window grab_window,
+ Bool owner_events, XIEventMask *mask,
+ int num_modifiers, XIGrabModifiers *modifiers_inout)
+{
+ XExtDisplayInfo *extinfo = XInput_find_display(dpy);
+
+ LockDisplay(dpy);
+ if (_XiCheckExtInit(dpy, XInput_2_2, extinfo) == -1)
+ return -1;
+
+ /* FIXME: allow selection of GrabMode for paired devices? */
+ return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeTouchBegin, 0,
+ grab_window, None, GrabModeAsync,
+ GrabModeAsync, owner_events, mask,
+ num_modifiers, modifiers_inout);
+}
+
+
static int
_XIPassiveUngrabDevice(Display* dpy, int deviceid, int grabtype, int detail,
Window grab_window, int num_modifiers, XIGrabModifiers *modifiers)
@@ -211,3 +230,17 @@ XIUngrabFocusIn(Display* display, int deviceid, Window grab_window,
return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeFocusIn, 0,
grab_window, num_modifiers, modifiers);
}
+
+int
+XIUngrabTouchBegin(Display* display, int deviceid, Window grab_window,
+ int num_modifiers, XIGrabModifiers *modifiers)
+{
+ XExtDisplayInfo *extinfo = XInput_find_display(display);
+
+ LockDisplay(display);
+ if (_XiCheckExtInit(display, XInput_2_2, extinfo) == -1)
+ return -1;
+
+ return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeTouchBegin, 0,
+ grab_window, num_modifiers, modifiers);
+}
diff --git a/src/XIint.h b/src/XIint.h
index 41d99b3..cc46754 100644
--- a/src/XIint.h
+++ b/src/XIint.h
@@ -21,6 +21,7 @@
#define XInput_2_0 7
#endif
#define XInput_2_1 8
+#define XInput_2_2 9
extern XExtDisplayInfo *XInput_find_display(Display *);
--
1.7.7.1
More information about the xorg-devel
mailing list