summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPovilas Kanapickas <povilas@radix.lt>2020-10-10 02:53:41 +0300
committerPovilas Kanapickas <povilas@radix.lt>2020-10-10 02:53:41 +0300
commited1788b8c3a78f6dc523487e46e202a5f667407c (patch)
tree5ee9662d673fdd65d6ef0c3d5e0a67f7b1f210e5
parent8b4ea802fa3ba769dc8335f0e72c6f0cb7c9c35e (diff)
downloadxorg-lib-libXi-ed1788b8c3a78f6dc523487e46e202a5f667407c.tar.gz
Add support for XI 2.4 gesture events
-rw-r--r--include/X11/extensions/XInput2.h104
-rw-r--r--man/XIGrabButton.txt65
-rw-r--r--man/XIQueryDevice.txt19
-rw-r--r--src/XExtInt.c184
-rw-r--r--src/XIPassiveGrab.c59
-rw-r--r--src/XIint.h1
6 files changed, 418 insertions, 14 deletions
diff --git a/include/X11/extensions/XInput2.h b/include/X11/extensions/XInput2.h
index 33670eb..2722142 100644
--- a/include/X11/extensions/XInput2.h
+++ b/include/X11/extensions/XInput2.h
@@ -153,6 +153,14 @@ typedef struct
int num_touches;
} XITouchClassInfo;
+/* new in XI 2.4 */
+typedef struct
+{
+ int type;
+ int sourceid;
+ int num_touches;
+} XIGestureClassInfo;
+
typedef struct
{
int deviceid;
@@ -360,6 +368,62 @@ typedef struct {
BarrierEventID eventid;
} XIBarrierEvent;
+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;
+ int detail;
+ Window root;
+ Window event;
+ Window child;
+ double root_x;
+ double root_y;
+ double event_x;
+ double event_y;
+ double delta_x;
+ double delta_y;
+ double delta_unaccel_x;
+ double delta_unaccel_y;
+ double scale;
+ double delta_angle;
+ int flags;
+ XIModifierState mods;
+ XIGroupState group;
+} XIGesturePinchEvent;
+
+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;
+ int detail;
+ Window root;
+ Window event;
+ Window child;
+ double root_x;
+ double root_y;
+ double event_x;
+ double event_y;
+ double delta_x;
+ double delta_y;
+ double delta_unaccel_x;
+ double delta_unaccel_y;
+ int flags;
+ XIModifierState mods;
+ XIGroupState group;
+} XIGestureSwipeEvent;
+
_XFUNCPROTOBEGIN
extern Bool XIQueryPointer(
@@ -553,6 +617,30 @@ extern int XIGrabTouchBegin(
XIGrabModifiers *modifiers_inout
);
+extern int XIGrabPinchGestureBegin(
+ Display* display,
+ int deviceid,
+ Window grab_window,
+ int grab_mode,
+ int paired_device_mode,
+ int owner_events,
+ XIEventMask *mask,
+ int num_modifiers,
+ XIGrabModifiers *modifiers_inout
+);
+
+extern int XIGrabSwipeGestureBegin(
+ Display* display,
+ int deviceid,
+ Window grab_window,
+ int grab_mode,
+ int paired_device_mode,
+ int owner_events,
+ XIEventMask *mask,
+ int num_modifiers,
+ XIGrabModifiers *modifiers_inout
+);
+
extern Status XIUngrabButton(
Display* display,
int deviceid,
@@ -595,6 +683,22 @@ extern Status XIUngrabTouchBegin(
XIGrabModifiers *modifiers
);
+extern Status XIUngrabPinchGestureBegin(
+ Display* display,
+ int deviceid,
+ Window grab_window,
+ int num_modifiers,
+ XIGrabModifiers *modifiers
+);
+
+extern Status XIUngrabSwipeGestureBegin(
+ Display* display,
+ int deviceid,
+ Window grab_window,
+ int num_modifiers,
+ XIGrabModifiers *modifiers
+);
+
extern Atom *XIListProperties(
Display* display,
int deviceid,
diff --git a/man/XIGrabButton.txt b/man/XIGrabButton.txt
index c5100fb..5d638f1 100644
--- a/man/XIGrabButton.txt
+++ b/man/XIGrabButton.txt
@@ -4,7 +4,7 @@ XIGRABBUTTON(libmansuffix)
NAME
----
- XIGrabButton, XIUngrabButton, XIGrabKeycode, XIUngrabKeycode, XIGrabTouchBegin, XIUngrabTouchBegin - grab/ungrab buttons or keys
+ XIGrabButton, XIUngrabButton, XIGrabKeycode, XIUngrabKeycode, XIGrabTouchBegin, XIUngrabTouchBegin, XIGrabPinchGestureBegin, XIUngrabPinchGestureBegin, XIGrabSwipeGestureBegin, XIUngrabSwipeGestureBegin - grab/ungrab buttons or keys
SYNOPSIS
--------
@@ -62,6 +62,38 @@ SYNOPSIS
int num_modifiers,
XIGrabModifiers *modifiers);
+ int XIGrabPinchGestureBegin( Display* display,
+ int deviceid,
+ Window grab_window,
+ int grab_mode,
+ int paired_device_mode,
+ int owner_events,
+ XIEventMask *mask,
+ int num_modifiers,
+ XIGrabModifiers *modifiers_inout);
+
+ int XIUngrabPinchGestureBegin( Display* display,
+ int deviceid,
+ Window grab_window,
+ int num_modifiers,
+ XIGrabModifiers *modifiers);
+
+ int XIGrabSwipeGestureBegin( Display* display,
+ int deviceid,
+ Window grab_window,
+ int grab_mode,
+ int paired_device_mode,
+ int owner_events,
+ XIEventMask *mask,
+ int num_modifiers,
+ XIGrabModifiers *modifiers_inout);
+
+ int XIUngrabSwipeGestureBegin( Display* display,
+ int deviceid,
+ Window grab_window,
+ int num_modifiers,
+ XIGrabModifiers *modifiers);
+
display
Specifies the connection to the X server.
@@ -114,8 +146,9 @@ SYNOPSIS
DESCRIPTION
-----------
- XIGrabButton, XIGrabKeycode and XIGrabTouchBegin establish a passive
- grab. The modifier device for a button grab is the paired master device
+ XIGrabButton, XIGrabKeycode, XIGrabTouchBegin, XIGrabPinchGestureBegin,
+ XIGrabSwipeTouchBegin 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
@@ -123,7 +156,7 @@ 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 or a touch event occurs when the
+ keycode is logically pressed, a touch or a gesture 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
@@ -169,16 +202,20 @@ DESCRIPTION
combination. XIGrabButton and XIGrabKeycode have no effect on an
active grab.
- On success, XIGrabButton, XIGrabKeycode and XIGrabTouchBegin return 0;
+ On success, XIGrabButton, XIGrabKeycode, XIGrabTouchBegin,
+ XIGrabPinchGestureBegin and XIGrabSwipeGestureBegin return 0;
If one or more modifier combinations could not be grabbed,
- XIGrabButton, XIGrabKeycode and XIGrabTouchBegin return the number of
+ XIGrabButton, XIGrabKeycode, XIGrabTouchBegin, XIGrabPinchGestureBegin
+ and XIGrabSwipeGestureBegin return the number of
failed combinations and modifiers_inout contains the failed combinations
and their respective error codes.
- XIGrabButton, XIGrabKeycode and XIGrabTouchBegin can generate BadClass,
+ XIGrabButton, XIGrabKeycode, XIGrabTouchBegin, XIGrabPinchGestureBegin
+ and XIGrabSwipeGestureBegin can generate BadClass,
BadDevice, BadMatch, BadValue, and BadWindow errors.
- XIUngrabButton, XIUngrabKeycode and XIUngrabTouchBegin release the
+ XIUngrabButton, XIUngrabKeycode, XIUngrabTouchBegin, XIUngrabPinchGestureBegin
+ and XIUngrabSwipeGestureBegin 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
@@ -188,12 +225,14 @@ DESCRIPTION
XIUngrabButton and XIUngrabKeycode have no effect on an active
grab.
- XIUngrabButton, XIUngrabKeycode and XIUngrabTouchBegin can generate
+ XIUngrabButton, XIUngrabKeycode, XIUngrabTouchBegin,
+ XIUngrabPinchGestureBegin and XIUngrabSwipeGestureBegin can generate
BadDevice, BadMatch, BadValue and BadWindow errors.
RETURN VALUE
------------
- XIGrabButton, XIGrabKeycode and XIGrabTouchBegin return the number of
+ XIGrabButton, XIGrabKeycode, XIGrabTouchBegin and
+ XIGrabPinchGestureBegin and XIGrabSwipeGestureBegin 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
@@ -209,8 +248,10 @@ DIAGNOSTICS
BadMatch
This error may occur if XIGrabButton specified a device
that has no buttons, or XIGrabKeycode specified a device
- that has no keys, or XIGrabTouchBegin specified a device
- that is not touch-capable.
+ that has no keys,
+ or XIGrabTouchBegin specified a device that is not touch-capable,
+ or XIGrabPinchGestureBegin specified a device that is not gesture-capable,
+ or XIGrabSwipeGestureBegin specified a device that is not gesture-capable.
BadValue
Some numeric value falls outside the range of values
diff --git a/man/XIQueryDevice.txt b/man/XIQueryDevice.txt
index 232d735..bc9e36f 100644
--- a/man/XIQueryDevice.txt
+++ b/man/XIQueryDevice.txt
@@ -101,7 +101,7 @@ DESCRIPTION
The type field specifies the type of the input class.
Currently, the following types are defined:
XIKeyClass, XIButtonClass, XIValuatorClass, XIScrollClass,
- XITouchClass
+ XITouchClass, XIGestureClass.
In the future, additional types may be added. Clients are
required to ignore unknown input classes.
@@ -259,6 +259,23 @@ DESCRIPTION
valuators must be defined with the respective XIValuatorClass
classes. A valuator may send both pointer and touch-events.
+ typedef struct
+ {
+ int type;
+ int sourceid;
+ int num_touches;
+ } XIGestureClassInfo;
+
+ A device may have zero or one XIGestureClassInfo, denoting
+ touchpad gesture capability on the device. A device with a XIGestureClassInfo
+ may send GestureSwipeBegin, GestureSwipeUpdate, GestureSwipeEnd,
+ GesturePinchBegin, GesturePinchUpdate, GesturePinchEnd.
+
+ 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.
+
XIQueryDevice can generate a BadDevice error.
XIFreeDeviceInfo frees the information returned by
diff --git a/src/XExtInt.c b/src/XExtInt.c
index d379876..f2b5a75 100644
--- a/src/XExtInt.c
+++ b/src/XExtInt.c
@@ -127,6 +127,12 @@ wireToTouchOwnershipEvent(xXITouchOwnershipEvent *in,
static int
wireToBarrierEvent(xXIBarrierEvent *in,
XGenericEventCookie *cookie);
+static int
+wireToPinchEvent(xXIGesturePinchEvent *in,
+ XGenericEventCookie *cookie);
+static int
+wireToSwipeEvent(xXIGestureSwipeEvent *in,
+ XGenericEventCookie *cookie);
static /* const */ XEvent emptyevent;
@@ -1035,6 +1041,28 @@ XInputWireToCookie(
break;
}
return ENQUEUE_EVENT;
+ case XI_GesturePinchBegin:
+ case XI_GesturePinchUpdate:
+ case XI_GesturePinchEnd:
+ *cookie = *(XGenericEventCookie*)save;
+ if (!wireToPinchEvent((xXIGesturePinchEndEvent*)event, cookie))
+ {
+ printf("XInputWireToCookie: CONVERSION FAILURE! evtype=%d\n",
+ ge->evtype);
+ break;
+ }
+ return ENQUEUE_EVENT;
+ case XI_GestureSwipeBegin:
+ case XI_GestureSwipeUpdate:
+ case XI_GestureSwipeEnd:
+ *cookie = *(XGenericEventCookie*)save;
+ if (!wireToSwipeEvent((xXIGestureSwipeEndEvent*)event, cookie))
+ {
+ printf("XInputWireToCookie: CONVERSION FAILURE! evtype=%d\n",
+ ge->evtype);
+ break;
+ }
+ return ENQUEUE_EVENT;
default:
printf("XInputWireToCookie: Unknown generic event. type %d\n", ge->evtype);
@@ -1065,7 +1093,7 @@ sizeDeviceEvent(int buttons_len, int valuators_len,
/* Return the size with added padding so next element would be
double-aligned unless the architecture is known to allow unaligned
data accesses. Not doing this can cause a bus error on
- MIPS N32. */
+ MIPS N32. */
static int
pad_to_double(int size)
{
@@ -1143,6 +1171,9 @@ sizeDeviceClassType(int type, int num_elements)
case XITouchClass:
l = pad_to_double(sizeof(XITouchClassInfo));
break;
+ case XIGestureClass:
+ l = pad_to_double(sizeof(XIGestureClassInfo));
+ break;
default:
printf("sizeDeviceClassType: unknown type %d\n", type);
break;
@@ -1432,6 +1463,41 @@ copyBarrierEvent(XGenericEventCookie *in_cookie,
return True;
}
+
+static Bool
+copyGesturePinchEvent(XGenericEventCookie *cookie_in,
+ XGenericEventCookie *cookie_out)
+{
+ XIGesturePinchEvent *in, *out;
+
+ in = cookie_in->data;
+
+ out = cookie_out->data = malloc(sizeof(XIGesturePinchEvent));
+ if (!out)
+ return False;
+
+ *out = *in;
+
+ return True;
+}
+
+static Bool
+copyGestureSwipeEvent(XGenericEventCookie *cookie_in,
+ XGenericEventCookie *cookie_out)
+{
+ XIGestureSwipeEvent *in, *out;
+
+ in = cookie_in->data;
+
+ out = cookie_out->data = malloc(sizeof(XIGestureSwipeEvent));
+ if (!out)
+ return False;
+
+ *out = *in;
+
+ return True;
+}
+
static Bool
XInputCopyCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out)
{
@@ -1493,6 +1559,16 @@ XInputCopyCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out
case XI_BarrierLeave:
ret = copyBarrierEvent(in, out);
break;
+ case XI_GesturePinchBegin:
+ case XI_GesturePinchUpdate:
+ case XI_GesturePinchEnd:
+ ret = copyGesturePinchEvent(in, out);
+ break;
+ case XI_GestureSwipeBegin:
+ case XI_GestureSwipeUpdate:
+ case XI_GestureSwipeEnd:
+ ret = copyGestureSwipeEvent(in, out);
+ break;
default:
printf("XInputCopyCookie: unknown evtype %d\n", in->evtype);
ret = False;
@@ -1607,6 +1683,9 @@ size_classes(xXIAnyInfo* from, int nclasses)
case XITouchClass:
l = sizeDeviceClassType(XITouchClass, 0);
break;
+ case XIGestureClass:
+ l = sizeDeviceClassType(XIGestureClass, 0);
+ break;
}
len += l;
@@ -1770,6 +1849,21 @@ copy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int *nclasses)
to->classes[cls_idx++] = any_lib;
}
break;
+ case XIGestureClass:
+ {
+ XIGestureClassInfo *cls_lib;
+ xXIGestureInfo *cls_wire;
+
+ cls_wire = (xXIGestureInfo*)any_wire;
+ cls_lib = next_block(&ptr_lib, sizeof(XIGestureClassInfo));
+
+ cls_lib->type = cls_wire->type;
+ cls_lib->sourceid = cls_wire->sourceid;
+ 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;
@@ -2029,3 +2123,91 @@ wireToBarrierEvent(xXIBarrierEvent *in, XGenericEventCookie *cookie)
return 1;
}
+
+static int
+wireToPinchEvent(xXIGesturePinchEvent *in,
+ XGenericEventCookie *cookie)
+{
+ XIGesturePinchEvent *out;
+
+ cookie->data = out = malloc(sizeof(XIGesturePinchEvent));
+
+ out->display = cookie->display;
+ out->type = in->type;
+ out->serial = cookie->serial;
+ 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->detail = in->detail;
+ out->root = in->root;
+ out->event = in->event;
+ out->child = in->child;
+ out->root_x = FP1616toDBL(in->root_x);
+ out->root_y = FP1616toDBL(in->root_y);
+ out->event_x = FP1616toDBL(in->event_x);
+ out->event_y = FP1616toDBL(in->event_y);
+ out->delta_x = FP1616toDBL(in->delta_x);
+ out->delta_y = FP1616toDBL(in->delta_y);
+ out->delta_unaccel_x = FP1616toDBL(in->delta_unaccel_x);
+ out->delta_unaccel_y = FP1616toDBL(in->delta_unaccel_y);
+ out->scale = FP1616toDBL(in->scale);
+ out->delta_angle = FP1616toDBL(in->delta_angle);
+ out->flags = in->flags;
+
+ out->mods.base = in->mods.base_mods;
+ out->mods.locked = in->mods.locked_mods;
+ out->mods.latched = in->mods.latched_mods;
+ out->mods.effective = in->mods.effective_mods;
+ out->group.base = in->group.base_group;
+ out->group.locked = in->group.locked_group;
+ out->group.latched = in->group.latched_group;
+ out->group.effective = in->group.effective_group;
+
+ return 1;
+}
+
+static int
+wireToSwipeEvent(xXIGestureSwipeEvent *in,
+ XGenericEventCookie *cookie)
+{
+ XIGestureSwipeEvent *out;
+
+ cookie->data = out = malloc(sizeof(XIGestureSwipeEvent));
+
+ out->display = cookie->display;
+ out->type = in->type;
+ out->serial = cookie->serial;
+ 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->detail = in->detail;
+ out->root = in->root;
+ out->event = in->event;
+ out->child = in->child;
+ out->root_x = FP1616toDBL(in->root_x);
+ out->root_y = FP1616toDBL(in->root_y);
+ out->event_x = FP1616toDBL(in->event_x);
+ out->event_y = FP1616toDBL(in->event_y);
+ out->delta_x = FP1616toDBL(in->delta_x);
+ out->delta_y = FP1616toDBL(in->delta_y);
+ out->delta_unaccel_x = FP1616toDBL(in->delta_unaccel_x);
+ out->delta_unaccel_y = FP1616toDBL(in->delta_unaccel_y);
+ out->flags = in->flags;
+
+ out->mods.base = in->mods.base_mods;
+ out->mods.locked = in->mods.locked_mods;
+ out->mods.latched = in->mods.latched_mods;
+ out->mods.effective = in->mods.effective_mods;
+ out->group.base = in->group.base_group;
+ out->group.locked = in->group.locked_group;
+ out->group.latched = in->group.latched_group;
+ out->group.effective = in->group.effective_group;
+
+ return 1;
+}
diff --git a/src/XIPassiveGrab.c b/src/XIPassiveGrab.c
index 32b0ab3..310e523 100644
--- a/src/XIPassiveGrab.c
+++ b/src/XIPassiveGrab.c
@@ -177,6 +177,37 @@ XIGrabTouchBegin(Display *dpy, int deviceid, Window grab_window,
num_modifiers, modifiers_inout, CurrentTime);
}
+int XIGrabPinchGestureBegin(Display* dpy, int deviceid, Window grab_window, int grab_mode,
+ int paired_device_mode, int owner_events,
+ XIEventMask *mask, int num_modifiers, XIGrabModifiers *modifiers_inout)
+{
+ XExtDisplayInfo *extinfo = XInput_find_display(dpy);
+
+ LockDisplay(dpy);
+ if (_XiCheckExtInit(dpy, XInput_2_4, extinfo) == -1)
+ return -1;
+ UnlockDisplay(dpy);
+
+ return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeGesturePinchBegin, 0,
+ grab_window, None, grab_mode, paired_device_mode,
+ owner_events, mask, num_modifiers, modifiers_inout, CurrentTime);
+}
+
+int XIGrabSwipeGestureBegin(Display* dpy, int deviceid, Window grab_window, int grab_mode,
+ int paired_device_mode, int owner_events,
+ XIEventMask *mask, int num_modifiers, XIGrabModifiers *modifiers_inout)
+{
+ XExtDisplayInfo *extinfo = XInput_find_display(dpy);
+
+ LockDisplay(dpy);
+ if (_XiCheckExtInit(dpy, XInput_2_4, extinfo) == -1)
+ return -1;
+ UnlockDisplay(dpy);
+
+ return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeGestureSwipeBegin, 0,
+ grab_window, None, grab_mode, paired_device_mode,
+ owner_events, mask, num_modifiers, modifiers_inout, CurrentTime);
+}
static int
_XIPassiveUngrabDevice(Display* dpy, int deviceid, int grabtype, int detail,
@@ -256,3 +287,31 @@ XIUngrabTouchBegin(Display* display, int deviceid, Window grab_window,
return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeTouchBegin, 0,
grab_window, num_modifiers, modifiers);
}
+
+int XIUngrabPinchGestureBegin(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_4, extinfo) == -1)
+ return -1;
+ UnlockDisplay(display);
+
+ return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeGesturePinchBegin, 0,
+ grab_window, num_modifiers, modifiers);
+}
+
+int XIUngrabSwipeGestureBegin(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_4, extinfo) == -1)
+ return -1;
+ UnlockDisplay(display);
+
+ return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeGestureSwipeBegin, 0,
+ grab_window, num_modifiers, modifiers);
+}
diff --git a/src/XIint.h b/src/XIint.h
index 9479a79..40dec0b 100644
--- a/src/XIint.h
+++ b/src/XIint.h
@@ -23,6 +23,7 @@
#define XInput_2_1 8
#define XInput_2_2 9
#define XInput_2_3 10
+#define XInput_2_4 11
extern XExtDisplayInfo *XInput_find_display(Display *);