dix: rework temporary slave detachment.

Rework addresses two issues:
- storing the master device's pointer is a bad idea, we need to store the ID
  of the device in case it disappears during the grab.
- restoring the old master did not actually reattach the device. Fixed now.
This commit is contained in:
Peter Hutterer 2009-06-02 15:07:53 +10:00
parent b3e4810a28
commit f56ad22e8f

View File

@ -1435,44 +1435,47 @@ CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
/* Only ever used if a grab is called on an attached slave device. */ /* Only ever used if a grab is called on an attached slave device. */
static int GrabPrivateKeyIndex; static int GrabPrivateKeyIndex;
static DevPrivateKey GrabPrivateKey = &GrabPrivateKeyIndex; static DevPrivateKey GrabPrivateKey = &GrabPrivateKeyIndex;
typedef struct _GrabMemoryRec {
DeviceIntPtr oldmaster;
} GrabMemoryRec, *GrabMemoryPtr;
/** /**
* Save the device's master device in the devPrivates. This needs to be done * 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 * 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 * the duration of the grab, the device is detached, ungrabbing re-attaches it
* though. * though.
*
* We store the ID of the master device only in case the master disappears
* while the device has a grab.
*/ */
static void static void
SaveOldMaster(DeviceIntPtr dev) DetachFromMaster(DeviceIntPtr dev)
{ {
GrabMemoryPtr gm; int id;
if (!dev->u.master)
if (!(gm = xalloc(sizeof(GrabMemoryRec))))
{
ErrorF("[dix] Cannot allocate grab private. Grab not "
"possible on device.\n");
return; return;
}
gm->oldmaster = dev->u.master; id = dev->u.master->id;
dixSetPrivate(&dev->devPrivates, GrabPrivateKey, gm);
dixSetPrivate(&dev->devPrivates, GrabPrivateKey, (void *)id);
AttachDevice(NULL, dev, NULL);
} }
static void static void
RestoreOldMaster(DeviceIntPtr dev) ReattachToOldMaster(DeviceIntPtr dev)
{ {
GrabMemoryPtr gm; int id;
void *p;
DeviceIntPtr master = NULL;
if (IsMaster(dev)) if (IsMaster(dev))
return; return;
gm = (GrabMemoryPtr)dixLookupPrivate(&dev->devPrivates, GrabPrivateKey);
if (gm) p = dixLookupPrivate(&dev->devPrivates, GrabPrivateKey);
id = (int)p; /* silence gcc warnings */
dixLookupDevice(&master, id, serverClient, DixUseAccess);
if (master)
{ {
dev->u.master = gm->oldmaster; AttachDevice(serverClient, dev, master);
xfree(gm);
dixSetPrivate(&dev->devPrivates, GrabPrivateKey, NULL); dixSetPrivate(&dev->devPrivates, GrabPrivateKey, NULL);
} }
} }
@ -1504,10 +1507,7 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
/* slave devices need to float for the duration of the grab. */ /* slave devices need to float for the duration of the grab. */
if (!isPassive && !IsMaster(mouse)) if (!isPassive && !IsMaster(mouse))
{ DetachFromMaster(mouse);
SaveOldMaster(mouse);
AttachDevice(NULL, mouse, NULL);
}
if (grab->confineTo) if (grab->confineTo)
{ {
@ -1564,7 +1564,7 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
FreeCursor(grab->cursor, (Cursor)0); FreeCursor(grab->cursor, (Cursor)0);
if (!wasPassive) if (!wasPassive)
RestoreOldMaster(mouse); ReattachToOldMaster(mouse);
ComputeFreezes(); ComputeFreezes();
} }
@ -1582,10 +1582,7 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool pass
/* slave devices need to float for the duration of the grab. */ /* slave devices need to float for the duration of the grab. */
if (!passive && !IsMaster(keybd)) if (!passive && !IsMaster(keybd))
{ DetachFromMaster(keybd);
SaveOldMaster(keybd);
AttachDevice(NULL, keybd, NULL);
}
if (grabinfo->grab) if (grabinfo->grab)
oldWin = grabinfo->grab->window; oldWin = grabinfo->grab->window;
@ -1637,7 +1634,7 @@ DeactivateKeyboardGrab(DeviceIntPtr keybd)
DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
if (!wasPassive) if (!wasPassive)
RestoreOldMaster(keybd); ReattachToOldMaster(keybd);
ComputeFreezes(); ComputeFreezes();
} }