diff options
author | Peter Hutterer <peter@cs.unisa.edu.au> | 2007-11-09 11:33:27 +1030 |
---|---|---|
committer | Peter Hutterer <peter@cs.unisa.edu.au> | 2007-11-09 14:32:06 +1030 |
commit | 5bbc468b702f62d7c91d41aabcc27eeb553f6959 (patch) | |
tree | 49ab006190f94304a0a3c3baa36adb07ce635cf0 /dix/events.c | |
parent | 676b26ca3e9b142cf007af3f439aa1993f2247c4 (diff) |
dix: grabbing an attached SD sets it floating for the duration of the grab.
Diffstat (limited to 'dix/events.c')
-rw-r--r-- | dix/events.c | 91 |
1 files changed, 83 insertions, 8 deletions
diff --git a/dix/events.c b/dix/events.c index 8a8761855..c3589f0c8 100644 --- a/dix/events.c +++ b/dix/events.c @@ -237,6 +237,7 @@ _X_EXPORT CallbackListPtr DeviceEventCallback; Mask DontPropagateMasks[DNPMCOUNT]; static int DontPropagateRefCnts[DNPMCOUNT]; + /** * Main input device struct. * inputInfo.pointer @@ -1540,6 +1541,54 @@ CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode) ComputeFreezes(); } +/* Only ever used if a grab is called on an attached slave device. */ +static int GrabPrivateIndex = -1; +typedef struct _GrabMemoryRec { + DeviceIntPtr oldmaster; +} GrabMemoryRec, *GrabMemoryPtr; + +/** + * 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. + */ +static void +SaveOldMaster(DeviceIntPtr dev) +{ + GrabMemoryPtr gm; + + if (GrabPrivateIndex == -1) + GrabPrivateIndex = AllocateDevicePrivateIndex(); + + if (!AllocateDevicePrivate(dev, GrabPrivateIndex) || + !(gm = xalloc(sizeof(GrabMemoryRec)))) + { + ErrorF("[dix] Cannot allocate grab private. Grab not " + "possible on device.\n"); + return; + } + gm->oldmaster = dev->u.master; + dev->devPrivates[GrabPrivateIndex].ptr = gm; +} + +static void +RestoreOldMaster(DeviceIntPtr dev) +{ + GrabMemoryPtr gm; + + if (dev->isMaster || GrabPrivateIndex == -1) + return; + + gm = ((GrabMemoryPtr)dev->devPrivates[GrabPrivateIndex].ptr); + if (gm) + { + dev->u.master = gm->oldmaster; + xfree(gm); + dev->devPrivates[GrabPrivateIndex].ptr = 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. @@ -1563,6 +1612,14 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, WindowPtr oldWin = (grabinfo->grab) ? grabinfo->grab->window : mouse->spriteInfo->sprite->win; + Bool isPassive = autoGrab & ~ImplicitGrabMask; + + /* slave devices need to float for the duration of the grab. */ + if (!isPassive && !mouse->isMaster) + { + SaveOldMaster(mouse); + AttachDevice(NULL, mouse, NULL); + } if (grab->confineTo) { @@ -1582,7 +1639,7 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, grab->cursor->refcnt++; grabinfo->activeGrab = *grab; grabinfo->grab = &grabinfo->activeGrab; - grabinfo->fromPassiveGrab = autoGrab & ~ImplicitGrabMask; + grabinfo->fromPassiveGrab = isPassive; grabinfo->implicitGrab = autoGrab & ImplicitGrabMask; PostNewCursor(mouse); CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); @@ -1598,6 +1655,7 @@ DeactivatePointerGrab(DeviceIntPtr mouse) { GrabPtr grab = mouse->deviceGrab.grab; DeviceIntPtr dev; + Bool wasPassive= mouse->deviceGrab.fromPassiveGrab; mouse->valuator->motionHintWindow = NullWindow; mouse->deviceGrab.grab = NullGrab; @@ -1615,6 +1673,10 @@ DeactivatePointerGrab(DeviceIntPtr mouse) PostNewCursor(mouse); if (grab->cursor) FreeCursor(grab->cursor, (Cursor)0); + + if (!wasPassive) + RestoreOldMaster(mouse); + ComputeFreezes(); } @@ -1629,6 +1691,13 @@ 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 && !keybd->isMaster) + { + SaveOldMaster(keybd); + AttachDevice(NULL, keybd, NULL); + } + if (grabinfo->grab) oldWin = grabinfo->grab->window; else if (keybd->focus) @@ -1660,9 +1729,7 @@ DeactivateKeyboardGrab(DeviceIntPtr keybd) DeviceIntPtr dev; WindowPtr focusWin = keybd->focus ? keybd->focus->win : keybd->spriteInfo->sprite->win; - - if (!grab) - grab = keybd->deviceGrab.grab; + Bool wasPassive = keybd->deviceGrab.fromPassiveGrab; if (focusWin == FollowKeyboardWin) focusWin = inputInfo.keyboard->focus->win; @@ -1677,6 +1744,10 @@ DeactivateKeyboardGrab(DeviceIntPtr keybd) dev->deviceGrab.sync.other = NullGrab; } DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); + + if (!wasPassive) + RestoreOldMaster(keybd); + ComputeFreezes(); } @@ -4243,13 +4314,17 @@ EnterLeaveEvent( #ifdef XKB if (!noXkbExtension) { event.u.enterLeave.state = mouse->button->state & 0x1f00; - event.u.enterLeave.state |= - XkbGrabStateFromRec(&keybd->key->xkbInfo->state); + if (keybd) + event.u.enterLeave.state |= + XkbGrabStateFromRec(&keybd->key->xkbInfo->state); } else #endif - event.u.enterLeave.state = keybd->key->state | mouse->button->state; + { + event.u.enterLeave.state = (keybd) ? keybd->key->state : 0; + event.u.enterLeave.state |+ mouse->button->state; + } event.u.enterLeave.mode = mode; - focus = keybd->focus->win; + focus = (keybd) ? keybd->focus->win : None; if ((focus != NoneWin) && ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin))) |