dix: Fix up class restoring when last SD disconnects.

Old code was fundamentally broken, fixes now are:
- free the MDs current device classes
- copy the device classes instead of flipping the pointers
- check for the old MD, not the new one.
This commit is contained in:
Peter Hutterer 2007-11-16 10:45:28 +10:30
parent 83926cb8be
commit 9de1ebe2a8

View File

@ -2390,6 +2390,7 @@ PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
int int
AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master) AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
{ {
DeviceIntPtr oldmaster;
if (!dev || dev->isMaster) if (!dev || dev->isMaster)
return BadDevice; return BadDevice;
@ -2409,6 +2410,7 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
if (!dev->u.master && dev->spriteInfo->sprite) if (!dev->u.master && dev->spriteInfo->sprite)
xfree(dev->spriteInfo->sprite); xfree(dev->spriteInfo->sprite);
oldmaster = dev->u.master;
dev->u.master = master; dev->u.master = master;
/* If device is set to floating, we need to create a sprite for it, /* If device is set to floating, we need to create a sprite for it,
@ -2417,52 +2419,49 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
*/ */
if (!master) if (!master)
{ {
DeviceIntPtr it;
/* current root window */ /* current root window */
InitializeSprite(dev, dev->spriteInfo->sprite->spriteTrace[0]); InitializeSprite(dev, dev->spriteInfo->sprite->spriteTrace[0]);
dev->spriteInfo->spriteOwner = FALSE; dev->spriteInfo->spriteOwner = FALSE;
/* the master may need to restore the original classes, search for a } else
* device that is still paired with our master. */ dev->spriteInfo->sprite = master->spriteInfo->sprite;
/* If we were connected to master device before, this MD may need to
* change back to it's original classes.
*/
if (oldmaster)
{
DeviceIntPtr it;
for (it = inputInfo.devices; it; it = it->next) for (it = inputInfo.devices; it; it = it->next)
if (!it->isMaster && it->u.master == master) if (!it->isMaster && it->u.master == oldmaster)
break; break;
if (!it) /* no dev is paired with our master */ if (!it) /* no dev is paired with old master */
{ {
ClassesPtr classes; ClassesPtr classes;
EventList event = { NULL, 0}; EventList event = { NULL, 0};
char* classbuf; char* classbuf;
DeviceIntRec dummy;
classes = master->devPrivates[MasterDevClassesPrivIdx].ptr; FreeAllDeviceClasses((ClassesPtr)&oldmaster->key);
master->key = classes->key; classes = oldmaster->devPrivates[MasterDevClassesPrivIdx].ptr;
master->valuator = classes->valuator; memcpy(&dummy.key, classes, sizeof(ClassesRec));
master->button = classes->button; DeepCopyDeviceClasses(&dummy, oldmaster);
master->focus = classes->focus;
master->proximity = classes->proximity;
master->absolute = classes->absolute;
master->kbdfeed = classes->kbdfeed;
master->ptrfeed = classes->ptrfeed;
master->intfeed = classes->intfeed;
master->stringfeed = classes->stringfeed;
master->bell = classes->bell;
master->leds = classes->leds;
/* Send event to clients */ /* Send event to clients */
CreateClassesChangedEvent(&event, master, master); CreateClassesChangedEvent(&event, oldmaster, oldmaster);
deviceClassesChangedEvent *dcce = deviceClassesChangedEvent *dcce =
(deviceClassesChangedEvent*)event.event; (deviceClassesChangedEvent*)event.event;
dcce->deviceid = master->id; dcce->deviceid = oldmaster->id;
dcce->num_classes = 0; dcce->num_classes = 0;
classbuf = (char*)&event.event[1]; classbuf = (char*)&event.event[1];
CopySwapClasses(NullClient, master, &dcce->num_classes, &classbuf); CopySwapClasses(NullClient, oldmaster,
SendEventToAllWindows(master, XI_DeviceClassesChangedMask, &dcce->num_classes, &classbuf);
SendEventToAllWindows(oldmaster, XI_DeviceClassesChangedMask,
event.event, 1); event.event, 1);
xfree(event.event); xfree(event.event);
} }
}
} else
dev->spriteInfo->sprite = master->spriteInfo->sprite;
return Success; return Success;
} }