summaryrefslogtreecommitdiff
path: root/dix/events.c
diff options
context:
space:
mode:
authorPeter Hutterer <peter@cs.unisa.edu.au>2007-11-09 11:33:27 +1030
committerPeter Hutterer <peter@cs.unisa.edu.au>2007-11-09 14:32:06 +1030
commit5bbc468b702f62d7c91d41aabcc27eeb553f6959 (patch)
tree49ab006190f94304a0a3c3baa36adb07ce635cf0 /dix/events.c
parent676b26ca3e9b142cf007af3f439aa1993f2247c4 (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.c91
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)))