From 088067c891a78670d9509f48f56bf3ff9c16a30d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 18 Feb 2008 16:46:07 +1030 Subject: [PATCH] Xi: even if ChangeDeviceHierarchy fails, we may need to send an event. Changes are committed instantly, so if at least one change was successful, we must send an event to the client, even if subsequent ones fail. --- Xi/chdevhier.c | 68 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/Xi/chdevhier.c b/Xi/chdevhier.c index b7495678a..e9a5076a9 100644 --- a/Xi/chdevhier.c +++ b/Xi/chdevhier.c @@ -84,6 +84,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client) int required_len = sizeof(xChangeDeviceHierarchyReq); char n; int rc; + int nchanges = 0; deviceHierarchyChangedEvent ev; REQUEST(xChangeDeviceHierarchyReq); @@ -115,7 +116,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client) if (rc != Success) { xfree(name); - return rc; + goto unwind; } if (!c->sendCore) @@ -130,6 +131,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client) EnableDevice(keybd); } xfree(name); + nchanges++; } break; case CH_RemoveMasterDevice: @@ -143,18 +145,22 @@ ProcXChangeDeviceHierarchy(ClientPtr client) rc = dixLookupDevice(&ptr, r->deviceid, client, DixDestroyAccess); if (rc != Success) - return rc; + goto unwind; if (!ptr->isMaster) { client->errorValue = r->deviceid; - return BadDevice; + rc = BadDevice; + goto unwind; } /* XXX: For now, don't allow removal of VCP, VCK */ if (ptr == inputInfo.pointer || ptr == inputInfo.keyboard) - return BadDevice; + { + rc = BadDevice; + goto unwind; + } /* disable keyboards first */ if (IsPointerDevice(ptr)) @@ -164,7 +170,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client) client, DixDestroyAccess); if (rc != Success) - return rc; + goto unwind; } else { @@ -174,7 +180,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client) client, DixDestroyAccess); if (rc != Success) - return rc; + goto unwind; } @@ -189,23 +195,25 @@ ProcXChangeDeviceHierarchy(ClientPtr client) rc = dixLookupDevice(&newptr, r->returnPointer, client, DixWriteAccess); if (rc != Success) - return rc; + goto unwind; if (!newptr->isMaster) { client->errorValue = r->returnPointer; - return BadDevice; + rc = BadDevice; + goto unwind; } rc = dixLookupDevice(&newkeybd, r->returnKeyboard, client, DixWriteAccess); if (rc != Success) - return rc; + goto unwind; if (!newkeybd->isMaster) { client->errorValue = r->returnKeyboard; - return BadDevice; + rc = BadDevice; + goto unwind; } for (attached = inputInfo.devices; @@ -229,6 +237,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client) RemoveDevice(keybd); RemoveDevice(ptr); + nchanges++; } break; case CH_ChangeAttachment: @@ -238,12 +247,13 @@ ProcXChangeDeviceHierarchy(ClientPtr client) rc = dixLookupDevice(&ptr, c->deviceid, client, DixWriteAccess); if (rc != Success) - return rc; + goto unwind; if (ptr->isMaster) { client->errorValue = c->deviceid; - return BadDevice; + rc = BadDevice; + goto unwind; } if (c->changeMode == Floating) @@ -254,21 +264,25 @@ ProcXChangeDeviceHierarchy(ClientPtr client) rc = dixLookupDevice(&newmaster, c->newMaster, client, DixWriteAccess); if (rc != Success) - return rc; + goto unwind; if (!newmaster->isMaster) { client->errorValue = c->newMaster; - return BadDevice; + rc = BadDevice; + goto unwind; } if ((IsPointerDevice(newmaster) && !IsPointerDevice(ptr)) || (IsKeyboardDevice(newmaster) && !IsKeyboardDevice(ptr))) - return BadDevice; + { + rc = BadDevice; + goto unwind; + } AttachDevice(client, ptr, newmaster); } - + nchanges++; } break; } @@ -276,14 +290,20 @@ ProcXChangeDeviceHierarchy(ClientPtr client) any = (xAnyHierarchyChangeInfo*)((char*)any + any->length); } - ev.type = GenericEvent; - ev.extension = IReqCode; - ev.length = 0; - ev.evtype = XI_DeviceHierarchyChangedNotify; - ev.time = GetTimeInMillis(); +unwind: - SendEventToAllWindows(&dummyDev, XI_DeviceHierarchyChangedMask, - (xEvent*)&ev, 1); - return Success; + if (nchanges > 0) /* even if an error occured, we need to send an event if + we changed anything in the hierarchy. */ + { + ev.type = GenericEvent; + ev.extension = IReqCode; + ev.length = 0; + ev.evtype = XI_DeviceHierarchyChangedNotify; + ev.time = GetTimeInMillis(); + + SendEventToAllWindows(&dummyDev, XI_DeviceHierarchyChangedMask, + (xEvent*)&ev, 1); + } + return rc; }