diff --git a/Xi/exglobals.h b/Xi/exglobals.h index 8cbccf294..4c23d84b4 100644 --- a/Xi/exglobals.h +++ b/Xi/exglobals.h @@ -31,6 +31,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #ifdef HAVE_DIX_CONFIG_H #include #endif +#include "privates.h" #ifndef EXGLOBALS_H #define EXGLOBALS_H 1 @@ -75,4 +76,5 @@ extern int DeviceLeaveNotify; extern int RT_INPUTCLIENT; +extern DevPrivateKey XIClientPrivateKey; #endif /* EXGLOBALS_H */ diff --git a/Xi/extinit.c b/Xi/extinit.c index 838efdd1c..a647b9e18 100644 --- a/Xi/extinit.c +++ b/Xi/extinit.c @@ -72,6 +72,7 @@ SOFTWARE. #include "exglobals.h" #include "swaprep.h" #include "registry.h" +#include "privates.h" /* modules local to Xi */ #include "allowev.h" @@ -324,19 +325,42 @@ int RT_INPUTCLIENT; extern XExtensionVersion AllExtensionVersions[]; + Mask PropagateMask[MAX_DEVICES]; +/***************************************************************** + * + * Versioning support + * + */ + +DevPrivateKey XIClientPrivateKey = &XIClientPrivateKey; + +static XExtensionVersion thisversion = { XI_Present, + XI_2_Major, + XI_2_Minor +}; + + /***************************************************************** * * Declarations of local routines. * */ -static XExtensionVersion thisversion = { XI_Present, - XI_2_Major, - XI_2_Minor -}; +static void +XIClientCallback(CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec*)data; + ClientPtr pClient = clientinfo->client; + XIClientPtr pXIClient; + pXIClient = dixLookupPrivate(&pClient->devPrivates, XIClientPrivateKey); + pXIClient->major_version = 0; + pXIClient->minor_version = 0; +} /************************************************************************* * @@ -1080,6 +1104,7 @@ XIGEEventFill(xGenericEvent* ev, DeviceIntPtr pDev, * * This extension has several events and errors. * + * XI is mandatory nowadays, so if we fail to init XI, we die. */ void @@ -1087,6 +1112,12 @@ XInputExtensionInit(void) { ExtensionEntry *extEntry; + if (!dixRequestPrivate(XIClientPrivateKey, sizeof(XIClientRec))) + FatalError("Cannot request private for XI.\n"); + + if (!AddCallback(&ClientStateCallback, XIClientCallback, 0)) + FatalError("Failed to add callback to XI.\n"); + extEntry = AddExtension(INAME, IEVENTS, IERRORS, ProcIDispatch, SProcIDispatch, IResetProc, StandardMinorOpcode); if (extEntry) { diff --git a/Xi/getvers.c b/Xi/getvers.c index 1e17eea5a..43a1a4d26 100644 --- a/Xi/getvers.c +++ b/Xi/getvers.c @@ -59,6 +59,7 @@ SOFTWARE. #include "inputstr.h" /* DeviceIntPtr */ #include #include +#include "exevents.h" #include "exglobals.h" #include "getvers.h" @@ -93,6 +94,7 @@ int ProcXGetExtensionVersion(ClientPtr client) { xGetExtensionVersionReply rep; + XIClientPtr pXIClient; REQUEST(xGetExtensionVersionReq); REQUEST_AT_LEAST_SIZE(xGetExtensionVersionReq); @@ -101,6 +103,21 @@ ProcXGetExtensionVersion(ClientPtr client) stuff->nbytes + 3) >> 2) return BadLength; + pXIClient = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey); + + /* GetExtensionVersionReq before XI 2 didn't supply the client's + * major/minor. So we don't actually have a clue what they support. + * {major|minor}Version was added as part of XI, so if they are set, we + * know we can trust it. In this case the client must set nbytes to 0 + * though, otherwise we have to assume that the version are padding + * garbage. + */ + if (!stuff->nbytes) /* Client using XQueryInputVersion(). */ + { + pXIClient->major_version = stuff->majorVersion; + pXIClient->minor_version = stuff->minorVersion; + } /* else version unknown, leave it at 0.0 */ + rep.repType = X_Reply; rep.RepType = X_GetExtensionVersion; rep.length = 0; diff --git a/include/exevents.h b/include/exevents.h index 0892f4d0a..8d5d5dd49 100644 --- a/include/exevents.h +++ b/include/exevents.h @@ -32,6 +32,15 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include +/** + * Attached to the devPrivates of each client. Specifies the version number as + * supported by the client. + */ +typedef struct _XIClientRec { + int major_version; + int minor_version; +} XIClientRec, *XIClientPtr; + extern void RegisterOtherDevice ( DeviceIntPtr /* device */);