diff --git a/Xi/extinit.c b/Xi/extinit.c index 7e5111d78..23704b15f 100644 --- a/Xi/extinit.c +++ b/Xi/extinit.c @@ -188,6 +188,9 @@ static struct dev_type CARD8 event_base[numInputClasses]; XExtEventInfo EventInfo[32]; +static DeviceIntRec xi_all_devices; +static DeviceIntRec xi_all_master_devices; + /** * Dispatch vector. Functions defined in here will be called when the matching * request arrives. @@ -1215,6 +1218,17 @@ XInputExtensionInit(void) EventSwapVector[DevicePresenceNotify] = SEventIDispatch; GERegisterExtension(IReqCode, XI2EventSwap); + + + memset(&xi_all_devices, 0, sizeof(xi_all_devices)); + memset(&xi_all_master_devices, 0, sizeof(xi_all_master_devices)); + xi_all_devices.id = XIAllDevices; + xi_all_devices.name = "XIAllDevices"; + xi_all_master_devices.id = XIAllMasterDevices; + xi_all_master_devices.name = "XIAllMasterDevices"; + + inputInfo.all_devices = &xi_all_devices; + inputInfo.all_master_devices = &xi_all_master_devices; } else { FatalError("IExtensionInit: AddExtensions failed\n"); } diff --git a/Xi/xipassivegrab.c b/Xi/xipassivegrab.c index fab333592..0c74544e4 100644 --- a/Xi/xipassivegrab.c +++ b/Xi/xipassivegrab.c @@ -90,9 +90,16 @@ ProcXIPassiveGrabDevice(ClientPtr client) REQUEST(xXIPassiveGrabDeviceReq); REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq); - ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); - if (ret != Success) - return ret; + if (stuff->deviceid == XIAllDevices) + dev = inputInfo.all_devices; + else if (stuff->deviceid == XIAllMasterDevices) + dev = inputInfo.all_master_devices; + else + { + ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); + if (ret != Success) + return ret; + } if (stuff->grab_type != XIGrabtypeButton && stuff->grab_type != XIGrabtypeKeysym && diff --git a/dix/events.c b/dix/events.c index 13ef5b871..d73487afc 100644 --- a/dix/events.c +++ b/dix/events.c @@ -248,6 +248,18 @@ static Bool CheckPassiveGrabsOnWindow(WindowPtr pWin, * * inputInfo.numDevices * Total number of devices. + * + * inputInfo.all_devices + * Virtual device used for XIAllDevices passive grabs. This device is + * not part of the inputInfo.devices list and mostly unset except for + * the deviceid. It exists because passivegrabs need a valid device + * reference. + * + * inputInfo.all_master_devices + * Virtual device used for XIAllMasterDevices passive grabs. This device + * is not part of the inputInfo.devices list and mostly unset except for + * the deviceid. It exists because passivegrabs need a valid device + * reference. */ InputInfo inputInfo; diff --git a/dix/grabs.c b/dix/grabs.c index 02f63f9b4..cc7747714 100644 --- a/dix/grabs.c +++ b/dix/grabs.c @@ -267,7 +267,25 @@ GrabMatchesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab, Bool ignoreDevice) if (pFirstGrab->grabtype != pSecondGrab->grabtype) return FALSE; - if (!ignoreDevice && + if (pFirstGrab->grabtype == GRABTYPE_XI2) + { + if (pFirstGrab->device == inputInfo.all_devices || + pSecondGrab->device == inputInfo.all_devices) + { + /* do nothing */ + } else if (pFirstGrab->device == inputInfo.all_master_devices) + { + if (pSecondGrab->device != inputInfo.all_master_devices && + !IsMaster(pSecondGrab->device)) + return FALSE; + } else if (pSecondGrab->device == inputInfo.all_master_devices) + { + if (pFirstGrab->device != inputInfo.all_master_devices && + !IsMaster(pFirstGrab->device)) + return FALSE; + } else if (pSecondGrab->device != pFirstGrab->device) + return FALSE; + } else if (!ignoreDevice && ((pFirstGrab->device != pSecondGrab->device) || (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice))) return FALSE; diff --git a/include/inputstr.h b/include/inputstr.h index 7f6e6ca77..f233034b0 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -528,6 +528,8 @@ typedef struct { DeviceIntPtr off_devices; /* all devices turned off */ DeviceIntPtr keyboard; /* the main one for the server */ DeviceIntPtr pointer; + DeviceIntPtr all_devices; + DeviceIntPtr all_master_devices; } InputInfo; extern _X_EXPORT InputInfo inputInfo;