summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2009-12-09 13:59:57 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2010-02-22 13:19:13 +1000
commit299de21b2ab3cfa2078823215f84da67e7b3d1a3 (patch)
tree03b47b6d386c1a7baa56654e6dd658da26eb871b
parent4debc545611edd35f8fd35a52f4adf4263e49200 (diff)
Initialize extension with the right number of events.
If the server supports a lower XI version than the client, the Xlib-internal event vector may be smashed. See libXext for more details. http://cgit.freedesktop.org/xorg/lib/libXext/commit/?id=83fdb27df4ddc2fb088ddf2ec65f0db6b7c57287 This patch queries the server for the supported XI extension before registering the extension with Xlib. The number of events registered depends on the server version. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Julien Cristau <jcristau@debian.org>
-rw-r--r--src/XExtInt.c68
-rw-r--r--src/XGetVers.c24
-rw-r--r--src/XIint.h1
3 files changed, 82 insertions, 11 deletions
diff --git a/src/XExtInt.c b/src/XExtInt.c
index e87ead8..80b3fc7 100644
--- a/src/XExtInt.c
+++ b/src/XExtInt.c
@@ -173,6 +173,63 @@ static char *XInputErrorList[] = {
"BadClass, invalid event class", /* BadClass */
};
+/* Get the version supported by the server to know which number of
+* events are support. Otherwise, a wrong number of events may smash
+* the Xlib-internal event processing vector.
+*
+* Since the extension hasn't been initialized yet, we need to
+* manually get the opcode, then the version.
+*/
+static int
+_XiFindEventsSupported(Display *dpy)
+{
+ XExtCodes codes;
+ XExtensionVersion *extversion = NULL;
+ int nevents = 0;
+
+ if (!XQueryExtension(dpy, INAME, &codes.major_opcode,
+ &codes.first_event, &codes.first_error))
+ goto out;
+
+ LockDisplay(dpy);
+ extversion = _XiGetExtensionVersionRequest(dpy, INAME, codes.major_opcode);
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ if (!extversion || !extversion->present)
+ goto out;
+
+ if (extversion->major_version >= 2)
+ nevents = IEVENTS; /* number is fixed, XI2 adds GenericEvents only */
+ else if (extversion->major_version <= 0)
+ {
+ printf("XInput_find_display: invalid extension version %d.%d\n",
+ extversion->major_version, extversion->minor_version);
+ goto out;
+ }
+ else
+ {
+ switch(extversion->minor_version)
+ {
+ case XI_Add_DeviceProperties_Minor:
+ nevents = XI_DevicePropertyNotify + 1;
+ break;
+ case XI_Add_DevicePresenceNotify_Minor:
+ nevents = XI_DevicePresenceNotify + 1;
+ break;
+ default:
+ nevents = XI_DeviceButtonstateNotify + 1;
+ break;
+ }
+ }
+
+out:
+ if (extversion)
+ XFree(extversion);
+ return nevents;
+}
+
+
_X_HIDDEN
XExtDisplayInfo *XInput_find_display (Display *dpy)
{
@@ -180,12 +237,17 @@ XExtDisplayInfo *XInput_find_display (Display *dpy)
if (!xinput_info) { if (!(xinput_info = XextCreateExtension())) return NULL; }
if (!(dpyinfo = XextFindDisplay (xinput_info, dpy)))
{
+ int nevents = _XiFindEventsSupported(dpy);
+
dpyinfo = XextAddDisplay (xinput_info, dpy,
xinput_extension_name,
&xinput_extension_hooks,
- IEVENTS, NULL);
- XESetWireToEventCookie(dpy, dpyinfo->codes->major_opcode, XInputWireToCookie);
- XESetCopyEventCookie(dpy, dpyinfo->codes->major_opcode, XInputCopyCookie);
+ nevents, NULL);
+ if (dpyinfo->codes) /* NULL if XI doesn't exist on the server */
+ {
+ XESetWireToEventCookie(dpy, dpyinfo->codes->major_opcode, XInputWireToCookie);
+ XESetCopyEventCookie(dpy, dpyinfo->codes->major_opcode, XInputCopyCookie);
+ }
}
return dpyinfo;
}
diff --git a/src/XGetVers.c b/src/XGetVers.c
index 3b500ae..4718617 100644
--- a/src/XGetVers.c
+++ b/src/XGetVers.c
@@ -72,19 +72,15 @@ XGetExtensionVersion(register Display * dpy, _Xconst char *name)
return (ext);
}
-_X_HIDDEN XExtensionVersion *
-_XiGetExtensionVersion(register Display * dpy, _Xconst char *name,
- XExtDisplayInfo *info)
+_X_HIDDEN XExtensionVersion*
+_XiGetExtensionVersionRequest(Display *dpy, _Xconst char *name, int xi_opcode)
{
xGetExtensionVersionReq *req;
xGetExtensionVersionReply rep;
XExtensionVersion *ext;
- if (_XiCheckExtInit(dpy, Dont_Check, info) == -1)
- return ((XExtensionVersion *) NoSuchExtension);
-
GetReq(GetExtensionVersion, req);
- req->reqType = info->codes->major_opcode;
+ req->reqType = xi_opcode;
req->ReqType = X_GetExtensionVersion;
req->nbytes = strlen(name);
req->length += (unsigned)(req->nbytes + 3) >> 2;
@@ -93,6 +89,7 @@ _XiGetExtensionVersion(register Display * dpy, _Xconst char *name,
if (!_XReply(dpy, (xReply *) & rep, 0, xTrue)) {
return (XExtensionVersion *) NULL;
}
+
ext = (XExtensionVersion *) Xmalloc(sizeof(XExtensionVersion));
if (ext) {
ext->present = rep.present;
@@ -101,5 +98,16 @@ _XiGetExtensionVersion(register Display * dpy, _Xconst char *name,
ext->minor_version = rep.minor_version;
}
}
- return (ext);
+
+ return ext;
+}
+
+_X_HIDDEN XExtensionVersion *
+_XiGetExtensionVersion(register Display * dpy, _Xconst char *name,
+ XExtDisplayInfo *info)
+{
+ if (_XiCheckExtInit(dpy, Dont_Check, info) == -1)
+ return ((XExtensionVersion *) NoSuchExtension);
+
+ return _XiGetExtensionVersionRequest(dpy, name, info->codes->major_opcode);
}
diff --git a/src/XIint.h b/src/XIint.h
index 400c920..00e84d3 100644
--- a/src/XIint.h
+++ b/src/XIint.h
@@ -14,6 +14,7 @@ extern XExtDisplayInfo *XInput_find_display(Display *);
extern int _XiCheckExtInit(Display *, int, XExtDisplayInfo *);
extern XExtensionVersion *_XiGetExtensionVersion(Display *, _Xconst char *, XExtDisplayInfo *);
+extern XExtensionVersion* _XiGetExtensionVersionRequest(Display *dpy, _Xconst char *name, int xi_opcode);
extern Status _xiQueryVersion(Display *dpy, int*, int*, XExtDisplayInfo *);
extern Status _XiEventToWire(