diff options
-rw-r--r-- | dix/events.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/dix/events.c b/dix/events.c index de8d5598e..916a6da1c 100644 --- a/dix/events.c +++ b/dix/events.c @@ -1441,6 +1441,54 @@ CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode) ComputeFreezes(); } +/* Only ever used if a grab is called on an attached slave device. */ +static int GrabPrivateKeyIndex; +static DevPrivateKey GrabPrivateKey = &GrabPrivateKeyIndex; + +/** + * Save the device's master device in the devPrivates. This needs to be done + * if a client directly grabs a slave device that is attached to a master. For + * the duration of the grab, the device is detached, ungrabbing re-attaches it + * though. + * + * We store the ID of the master device only in case the master disappears + * while the device has a grab. + */ +static void +DetachFromMaster(DeviceIntPtr dev) +{ + int id; + if (!dev->u.master) + return; + + id = dev->u.master->id; + + dixSetPrivate(&dev->devPrivates, GrabPrivateKey, (void *)id); + AttachDevice(NULL, dev, NULL); +} + +static void +ReattachToOldMaster(DeviceIntPtr dev) +{ + int id; + void *p; + DeviceIntPtr master = NULL; + + if (IsMaster(dev)) + return; + + + p = dixLookupPrivate(&dev->devPrivates, GrabPrivateKey); + id = (int)p; /* silence gcc warnings */ + dixLookupDevice(&master, id, serverClient, DixUseAccess); + + if (master) + { + AttachDevice(serverClient, dev, master); + dixSetPrivate(&dev->devPrivates, GrabPrivateKey, NULL); + } +} + /** * Activate a pointer grab on the given device. A pointer grab will cause all * core pointer events of this device to be delivered to the grabbing client only. @@ -1466,6 +1514,10 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, : mouse->spriteInfo->sprite->win; Bool isPassive = autoGrab & ~ImplicitGrabMask; + /* slave devices need to float for the duration of the grab. */ + if (!(autoGrab & ImplicitGrabMask) && !IsMaster(mouse)) + DetachFromMaster(mouse); + if (grab->confineTo) { if (grab->confineTo->drawable.pScreen @@ -1500,6 +1552,8 @@ DeactivatePointerGrab(DeviceIntPtr mouse) { GrabPtr grab = mouse->deviceGrab.grab; DeviceIntPtr dev; + Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab && + mouse->deviceGrab.implicitGrab); mouse->valuator->motionHintWindow = NullWindow; mouse->deviceGrab.grab = NullGrab; @@ -1519,6 +1573,9 @@ DeactivatePointerGrab(DeviceIntPtr mouse) if (grab->cursor) FreeCursor(grab->cursor, (Cursor)0); + if (!wasImplicit) + ReattachToOldMaster(mouse); + ComputeFreezes(); } @@ -1533,6 +1590,10 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool pass GrabInfoPtr grabinfo = &keybd->deviceGrab; WindowPtr oldWin; + /* slave devices need to float for the duration of the grab. */ + if (!(passive & ImplicitGrabMask) && !IsMaster(keybd)) + DetachFromMaster(keybd); + if (grabinfo->grab) oldWin = grabinfo->grab->window; else if (keybd->focus) @@ -1565,6 +1626,8 @@ DeactivateKeyboardGrab(DeviceIntPtr keybd) DeviceIntPtr dev; WindowPtr focusWin = keybd->focus ? keybd->focus->win : keybd->spriteInfo->sprite->win; + Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab && + keybd->deviceGrab.implicitGrab); if (focusWin == FollowKeyboardWin) focusWin = inputInfo.keyboard->focus->win; @@ -1581,6 +1644,9 @@ DeactivateKeyboardGrab(DeviceIntPtr keybd) } DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); + if (!wasImplicit) + ReattachToOldMaster(keybd); + ComputeFreezes(); } |