summaryrefslogtreecommitdiff
path: root/src/XExtInt.c
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 /src/XExtInt.c
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>
Diffstat (limited to 'src/XExtInt.c')
-rw-r--r--src/XExtInt.c68
1 files changed, 65 insertions, 3 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;
}