From fe8d122b133a43125cc961d2c3c811fa776f29c8 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 28 Oct 2010 16:13:09 +1000 Subject: Xi: reshuffle conditions for labeling a device as IsXExtensionKeyboard (#29046) From the original bug reporter Ezra Reeves: "I did some more digging on this today, and I found that an HP branded wireless USB mouse has the same issue. With this mouse (as well as the logitech wireless mouse), the return from: xdev = XListInputDevices(GDK_WINDOW_XDISPLAY(rootwin), &ndevices_return); lists the USB device twice, but both have xdev[num].use == 3 (IsXExtensionKeyboard as defined in X11/XI.h). [...] Swapping the order of the test in Xi/listdev.c that determines whether a device is a pointer or a keyboard properly detects my devices (OEM USB wireless mouse/kb combo) -- one as a keyboard and one as a pointer." X.Org Bug 29046 Reported-by: Erik Kilfoil Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- Xi/listdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Xi') diff --git a/Xi/listdev.c b/Xi/listdev.c index 3b2272bc3..b38fbd1c0 100644 --- a/Xi/listdev.c +++ b/Xi/listdev.c @@ -180,10 +180,10 @@ CopySwapDevice(ClientPtr client, DeviceIntPtr d, int num_classes, dev->use = IsXKeyboard; else if (IsMaster(d) && IsPointerDevice(d)) dev->use = IsXPointer; - else if (d->key && d->kbdfeed) - dev->use = IsXExtensionKeyboard; else if (d->valuator && d->button) dev->use = IsXExtensionPointer; + else if (d->key && d->kbdfeed) + dev->use = IsXExtensionKeyboard; else dev->use = IsXExtensionDevice; -- cgit v1.2.3 From 9b89b91c685426c9944f7fc8890f436c18b7583c Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 5 Nov 2010 11:47:43 +1000 Subject: Xi: split hierarchy manipulation into static functions. No functional changes, just code cleanup to improve readability. Signed-off-by: Peter Hutterer Reviewed-by: Julien Cristau --- Xi/xichangehierarchy.c | 518 ++++++++++++++++++++++++++----------------------- 1 file changed, 275 insertions(+), 243 deletions(-) (limited to 'Xi') diff --git a/Xi/xichangehierarchy.c b/Xi/xichangehierarchy.c index c1899e109..5818d2cab 100644 --- a/Xi/xichangehierarchy.c +++ b/Xi/xichangehierarchy.c @@ -136,12 +136,282 @@ int SProcXIChangeHierarchy(ClientPtr client) return (ProcXIChangeHierarchy(client)); } +static int +add_master(ClientPtr client, xXIAddMasterInfo *c, int flags[MAXDEVICES]) +{ + DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd; + char* name; + int rc; + + name = calloc(c->name_len + 1, sizeof(char)); + strncpy(name, (char*)&c[1], c->name_len); + + rc = AllocDevicePair(client, name, &ptr, &keybd, + CorePointerProc, CoreKeyboardProc, TRUE); + if (rc != Success) + goto unwind; + + if (!c->send_core) + ptr->coreEvents = keybd->coreEvents = FALSE; + + /* Allocate virtual slave devices for xtest events */ + rc = AllocXTestDevice(client, name, &XTestptr, &XTestkeybd, ptr, keybd); + if (rc != Success) + goto unwind; + + ActivateDevice(ptr, FALSE); + ActivateDevice(keybd, FALSE); + flags[ptr->id] |= XIMasterAdded; + flags[keybd->id] |= XIMasterAdded; + + ActivateDevice(XTestptr, FALSE); + ActivateDevice(XTestkeybd, FALSE); + flags[XTestptr->id] |= XISlaveAdded; + flags[XTestkeybd->id] |= XISlaveAdded; + + if (c->enable) + { + EnableDevice(ptr, FALSE); + EnableDevice(keybd, FALSE); + flags[ptr->id] |= XIDeviceEnabled; + flags[keybd->id] |= XIDeviceEnabled; + + EnableDevice(XTestptr, FALSE); + EnableDevice(XTestkeybd, FALSE); + flags[XTestptr->id] |= XIDeviceEnabled; + flags[XTestkeybd->id] |= XIDeviceEnabled; + } + + /* Attach the XTest virtual devices to the newly + created master device */ + AttachDevice(NULL, XTestptr, ptr); + AttachDevice(NULL, XTestkeybd, keybd); + flags[XTestptr->id] |= XISlaveAttached; + flags[XTestkeybd->id] |= XISlaveAttached; + +unwind: + free(name); + return rc; +} + +static int +remove_master(ClientPtr client, xXIRemoveMasterInfo *r, + int flags[MAXDEVICES]) +{ + DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd; + int rc = Success; + + if (r->return_mode != XIAttachToMaster && + r->return_mode != XIFloating) + return BadValue; + + rc = dixLookupDevice(&ptr, r->deviceid, client, DixDestroyAccess); + if (rc != Success) + goto unwind; + + if (!IsMaster(ptr)) + { + client->errorValue = r->deviceid; + rc = BadDevice; + goto unwind; + } + + /* XXX: For now, don't allow removal of VCP, VCK */ + if (ptr == inputInfo.pointer || ptr == inputInfo.keyboard) + { + rc = BadDevice; + goto unwind; + } + + + ptr = GetMaster(ptr, MASTER_POINTER); + rc = dixLookupDevice(&ptr, ptr->id, client, DixDestroyAccess); + if (rc != Success) + goto unwind; + keybd = GetMaster(ptr, MASTER_KEYBOARD); + rc = dixLookupDevice(&keybd, keybd->id, client, DixDestroyAccess); + if (rc != Success) + goto unwind; + + XTestptr = GetXTestDevice(ptr); + rc = dixLookupDevice(&XTestptr, XTestptr->id, client, DixDestroyAccess); + if (rc != Success) + goto unwind; + + XTestkeybd = GetXTestDevice(keybd); + rc = dixLookupDevice(&XTestkeybd, XTestkeybd->id, client, + DixDestroyAccess); + if (rc != Success) + goto unwind; + + /* Disabling sends the devices floating, reattach them if + * desired. */ + if (r->return_mode == XIAttachToMaster) + { + DeviceIntPtr attached, + newptr, + newkeybd; + + rc = dixLookupDevice(&newptr, r->return_pointer, client, DixAddAccess); + if (rc != Success) + goto unwind; + + if (!IsMaster(newptr)) + { + client->errorValue = r->return_pointer; + rc = BadDevice; + goto unwind; + } + + rc = dixLookupDevice(&newkeybd, r->return_keyboard, + client, DixAddAccess); + if (rc != Success) + goto unwind; + + if (!IsMaster(newkeybd)) + { + client->errorValue = r->return_keyboard; + rc = BadDevice; + goto unwind; + } + + for (attached = inputInfo.devices; attached; attached = attached->next) + { + if (!IsMaster(attached)) { + if (attached->u.master == ptr) + { + AttachDevice(client, attached, newptr); + flags[attached->id] |= XISlaveAttached; + } + if (attached->u.master == keybd) + { + AttachDevice(client, attached, newkeybd); + flags[attached->id] |= XISlaveAttached; + } + } + } + } + + /* can't disable until we removed pairing */ + keybd->spriteInfo->paired = NULL; + ptr->spriteInfo->paired = NULL; + XTestptr->spriteInfo->paired = NULL; + XTestkeybd->spriteInfo->paired = NULL; + + /* disable the remove the devices, XTest devices must be done first + else the sprites they rely on will be destroyed */ + DisableDevice(XTestptr, FALSE); + DisableDevice(XTestkeybd, FALSE); + DisableDevice(keybd, FALSE); + DisableDevice(ptr, FALSE); + flags[XTestptr->id] |= XIDeviceDisabled | XISlaveDetached; + flags[XTestkeybd->id] |= XIDeviceDisabled | XISlaveDetached; + flags[keybd->id] |= XIDeviceDisabled; + flags[ptr->id] |= XIDeviceDisabled; + + RemoveDevice(XTestptr, FALSE); + RemoveDevice(XTestkeybd, FALSE); + RemoveDevice(keybd, FALSE); + RemoveDevice(ptr, FALSE); + flags[XTestptr->id] |= XISlaveRemoved; + flags[XTestkeybd->id] |= XISlaveRemoved; + flags[keybd->id] |= XIMasterRemoved; + flags[ptr->id] |= XIMasterRemoved; + +unwind: + return rc; +} + +static int +detach_slave(ClientPtr client, xXIDetachSlaveInfo *c, int flags[MAXDEVICES]) +{ + DeviceIntPtr ptr; + int rc; + + rc = dixLookupDevice(&ptr, c->deviceid, client, DixManageAccess); + if (rc != Success) + goto unwind; + + if (IsMaster(ptr)) + { + client->errorValue = c->deviceid; + rc = BadDevice; + goto unwind; + } + + /* Don't allow changes to XTest Devices, these are fixed */ + if (IsXTestDevice(ptr, NULL)) + { + client->errorValue = c->deviceid; + rc = BadDevice; + goto unwind; + } + + AttachDevice(client, ptr, NULL); + flags[ptr->id] |= XISlaveDetached; + +unwind: + return rc; +} + +static int +attach_slave(ClientPtr client, xXIAttachSlaveInfo *c, + int flags[MAXDEVICES]) +{ + DeviceIntPtr ptr; + DeviceIntPtr newmaster; + int rc; + + rc = dixLookupDevice(&ptr, c->deviceid, client, DixManageAccess); + if (rc != Success) + goto unwind; + + if (IsMaster(ptr)) + { + client->errorValue = c->deviceid; + rc = BadDevice; + goto unwind; + } + + /* Don't allow changes to XTest Devices, these are fixed */ + if (IsXTestDevice(ptr, NULL)) + { + client->errorValue = c->deviceid; + rc = BadDevice; + goto unwind; + } + + rc = dixLookupDevice(&newmaster, c->new_master, client, DixAddAccess); + if (rc != Success) + goto unwind; + if (!IsMaster(newmaster)) + { + client->errorValue = c->new_master; + rc = BadDevice; + goto unwind; + } + + if (!((IsPointerDevice(newmaster) && IsPointerDevice(ptr)) || + (IsKeyboardDevice(newmaster) && IsKeyboardDevice(ptr)))) + { + rc = BadDevice; + goto unwind; + } + + AttachDevice(client, ptr, newmaster); + flags[ptr->id] |= XISlaveAttached; + +unwind: + return rc; +} + + + #define SWAPIF(cmd) if (client->swapped) { cmd; } int ProcXIChangeHierarchy(ClientPtr client) { - DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd; xXIAnyHierarchyChangeInfo *any; int required_len = sizeof(xXIChangeHierarchyReq); char n; @@ -169,276 +439,38 @@ ProcXIChangeHierarchy(ClientPtr client) case XIAddMaster: { xXIAddMasterInfo* c = (xXIAddMasterInfo*)any; - char* name; - SWAPIF(swaps(&c->name_len, n)); - name = calloc(c->name_len + 1, sizeof(char)); - strncpy(name, (char*)&c[1], c->name_len); - - - rc = AllocDevicePair(client, name, &ptr, &keybd, - CorePointerProc, CoreKeyboardProc, - TRUE); - if (rc != Success) - { - free(name); - goto unwind; - } - if (!c->send_core) - ptr->coreEvents = keybd->coreEvents = FALSE; - - /* Allocate virtual slave devices for xtest events */ - rc = AllocXTestDevice(client, name, &XTestptr, &XTestkeybd, - ptr, keybd); + rc = add_master(client, c, flags); if (rc != Success) - { - - free(name); goto unwind; - } - - ActivateDevice(ptr, FALSE); - ActivateDevice(keybd, FALSE); - flags[ptr->id] |= XIMasterAdded; - flags[keybd->id] |= XIMasterAdded; - - ActivateDevice(XTestptr, FALSE); - ActivateDevice(XTestkeybd, FALSE); - flags[XTestptr->id] |= XISlaveAdded; - flags[XTestkeybd->id] |= XISlaveAdded; - - if (c->enable) - { - EnableDevice(ptr, FALSE); - EnableDevice(keybd, FALSE); - flags[ptr->id] |= XIDeviceEnabled; - flags[keybd->id] |= XIDeviceEnabled; - - EnableDevice(XTestptr, FALSE); - EnableDevice(XTestkeybd, FALSE); - flags[XTestptr->id] |= XIDeviceEnabled; - flags[XTestkeybd->id] |= XIDeviceEnabled; - } - - /* Attach the XTest virtual devices to the newly - created master device */ - AttachDevice(NULL, XTestptr, ptr); - AttachDevice(NULL, XTestkeybd, keybd); - flags[XTestptr->id] |= XISlaveAttached; - flags[XTestkeybd->id] |= XISlaveAttached; - - free(name); } break; case XIRemoveMaster: { xXIRemoveMasterInfo* r = (xXIRemoveMasterInfo*)any; - if (r->return_mode != XIAttachToMaster && - r->return_mode != XIFloating) - return BadValue; - - rc = dixLookupDevice(&ptr, r->deviceid, client, - DixDestroyAccess); - if (rc != Success) - goto unwind; - - if (!IsMaster(ptr)) - { - client->errorValue = r->deviceid; - rc = BadDevice; - goto unwind; - } - - /* XXX: For now, don't allow removal of VCP, VCK */ - if (ptr == inputInfo.pointer || - ptr == inputInfo.keyboard) - { - rc = BadDevice; - goto unwind; - } - - - ptr = GetMaster(ptr, MASTER_POINTER); - rc = dixLookupDevice(&ptr, - ptr->id, - client, - DixDestroyAccess); - if (rc != Success) - goto unwind; - keybd = GetMaster(ptr, MASTER_KEYBOARD); - rc = dixLookupDevice(&keybd, - keybd->id, - client, - DixDestroyAccess); - if (rc != Success) - goto unwind; - - XTestptr = GetXTestDevice(ptr); - rc = dixLookupDevice(&XTestptr, XTestptr->id, client, - DixDestroyAccess); - if (rc != Success) - goto unwind; - - XTestkeybd = GetXTestDevice(keybd); - rc = dixLookupDevice(&XTestkeybd, XTestkeybd->id, client, - DixDestroyAccess); + rc = remove_master(client, r, flags); if (rc != Success) goto unwind; - - /* Disabling sends the devices floating, reattach them if - * desired. */ - if (r->return_mode == XIAttachToMaster) - { - DeviceIntPtr attached, - newptr, - newkeybd; - - rc = dixLookupDevice(&newptr, r->return_pointer, - client, DixAddAccess); - if (rc != Success) - goto unwind; - - if (!IsMaster(newptr)) - { - client->errorValue = r->return_pointer; - rc = BadDevice; - goto unwind; - } - - rc = dixLookupDevice(&newkeybd, r->return_keyboard, - client, DixAddAccess); - if (rc != Success) - goto unwind; - - if (!IsMaster(newkeybd)) - { - client->errorValue = r->return_keyboard; - rc = BadDevice; - goto unwind; - } - - for (attached = inputInfo.devices; - attached; - attached = attached->next) - { - if (!IsMaster(attached)) { - if (attached->u.master == ptr) - { - AttachDevice(client, attached, newptr); - flags[attached->id] |= XISlaveAttached; - } - if (attached->u.master == keybd) - { - AttachDevice(client, attached, newkeybd); - flags[attached->id] |= XISlaveAttached; - } - } - } - } - - /* can't disable until we removed pairing */ - keybd->spriteInfo->paired = NULL; - ptr->spriteInfo->paired = NULL; - XTestptr->spriteInfo->paired = NULL; - XTestkeybd->spriteInfo->paired = NULL; - - /* disable the remove the devices, XTest devices must be done first - else the sprites they rely on will be destroyed */ - DisableDevice(XTestptr, FALSE); - DisableDevice(XTestkeybd, FALSE); - DisableDevice(keybd, FALSE); - DisableDevice(ptr, FALSE); - flags[XTestptr->id] |= XIDeviceDisabled | XISlaveDetached; - flags[XTestkeybd->id] |= XIDeviceDisabled | XISlaveDetached; - flags[keybd->id] |= XIDeviceDisabled; - flags[ptr->id] |= XIDeviceDisabled; - - RemoveDevice(XTestptr, FALSE); - RemoveDevice(XTestkeybd, FALSE); - RemoveDevice(keybd, FALSE); - RemoveDevice(ptr, FALSE); - flags[XTestptr->id] |= XISlaveRemoved; - flags[XTestkeybd->id] |= XISlaveRemoved; - flags[keybd->id] |= XIMasterRemoved; - flags[ptr->id] |= XIMasterRemoved; } break; case XIDetachSlave: { xXIDetachSlaveInfo* c = (xXIDetachSlaveInfo*)any; - rc = dixLookupDevice(&ptr, c->deviceid, client, - DixManageAccess); + rc = detach_slave(client, c, flags); if (rc != Success) goto unwind; - - if (IsMaster(ptr)) - { - client->errorValue = c->deviceid; - rc = BadDevice; - goto unwind; - } - - /* Don't allow changes to XTest Devices, these are fixed */ - if (IsXTestDevice(ptr, NULL)) - { - client->errorValue = c->deviceid; - rc = BadDevice; - goto unwind; - } - - AttachDevice(client, ptr, NULL); - flags[ptr->id] |= XISlaveDetached; } break; case XIAttachSlave: { xXIAttachSlaveInfo* c = (xXIAttachSlaveInfo*)any; - DeviceIntPtr newmaster; - rc = dixLookupDevice(&ptr, c->deviceid, client, - DixManageAccess); + rc = attach_slave(client, c, flags); if (rc != Success) goto unwind; - - if (IsMaster(ptr)) - { - client->errorValue = c->deviceid; - rc = BadDevice; - goto unwind; - } - - /* Don't allow changes to XTest Devices, these are fixed */ - if (IsXTestDevice(ptr, NULL)) - { - client->errorValue = c->deviceid; - rc = BadDevice; - goto unwind; - } - - rc = dixLookupDevice(&newmaster, c->new_master, - client, DixAddAccess); - if (rc != Success) - goto unwind; - if (!IsMaster(newmaster)) - { - client->errorValue = c->new_master; - rc = BadDevice; - goto unwind; - } - - if (!((IsPointerDevice(newmaster) && - IsPointerDevice(ptr)) || - (IsKeyboardDevice(newmaster) && - IsKeyboardDevice(ptr)))) - { - rc = BadDevice; - goto unwind; - } - AttachDevice(client, ptr, newmaster); - flags[ptr->id] |= XISlaveAttached; } break; } -- cgit v1.2.3 From 5a455e0c80d433adc4109ebf313fd92afa194545 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 5 Nov 2010 11:49:12 +1000 Subject: Xi: rename two variables from ptr to dev. They were named ptr when everything was in one function to save one more variable. Now that the stuff is split out, "dev" makes more sense. Signed-off-by: Peter Hutterer Reviewed-by: Julien Cristau --- Xi/xichangehierarchy.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'Xi') diff --git a/Xi/xichangehierarchy.c b/Xi/xichangehierarchy.c index 5818d2cab..b7140d5e5 100644 --- a/Xi/xichangehierarchy.c +++ b/Xi/xichangehierarchy.c @@ -325,14 +325,14 @@ unwind: static int detach_slave(ClientPtr client, xXIDetachSlaveInfo *c, int flags[MAXDEVICES]) { - DeviceIntPtr ptr; + DeviceIntPtr dev; int rc; - rc = dixLookupDevice(&ptr, c->deviceid, client, DixManageAccess); + rc = dixLookupDevice(&dev, c->deviceid, client, DixManageAccess); if (rc != Success) goto unwind; - if (IsMaster(ptr)) + if (IsMaster(dev)) { client->errorValue = c->deviceid; rc = BadDevice; @@ -340,15 +340,15 @@ detach_slave(ClientPtr client, xXIDetachSlaveInfo *c, int flags[MAXDEVICES]) } /* Don't allow changes to XTest Devices, these are fixed */ - if (IsXTestDevice(ptr, NULL)) + if (IsXTestDevice(dev, NULL)) { client->errorValue = c->deviceid; rc = BadDevice; goto unwind; } - AttachDevice(client, ptr, NULL); - flags[ptr->id] |= XISlaveDetached; + AttachDevice(client, dev, NULL); + flags[dev->id] |= XISlaveDetached; unwind: return rc; @@ -358,15 +358,15 @@ static int attach_slave(ClientPtr client, xXIAttachSlaveInfo *c, int flags[MAXDEVICES]) { - DeviceIntPtr ptr; + DeviceIntPtr dev; DeviceIntPtr newmaster; int rc; - rc = dixLookupDevice(&ptr, c->deviceid, client, DixManageAccess); + rc = dixLookupDevice(&dev, c->deviceid, client, DixManageAccess); if (rc != Success) goto unwind; - if (IsMaster(ptr)) + if (IsMaster(dev)) { client->errorValue = c->deviceid; rc = BadDevice; @@ -374,7 +374,7 @@ attach_slave(ClientPtr client, xXIAttachSlaveInfo *c, } /* Don't allow changes to XTest Devices, these are fixed */ - if (IsXTestDevice(ptr, NULL)) + if (IsXTestDevice(dev, NULL)) { client->errorValue = c->deviceid; rc = BadDevice; @@ -391,15 +391,15 @@ attach_slave(ClientPtr client, xXIAttachSlaveInfo *c, goto unwind; } - if (!((IsPointerDevice(newmaster) && IsPointerDevice(ptr)) || - (IsKeyboardDevice(newmaster) && IsKeyboardDevice(ptr)))) + if (!((IsPointerDevice(newmaster) && IsPointerDevice(dev)) || + (IsKeyboardDevice(newmaster) && IsKeyboardDevice(dev)))) { rc = BadDevice; goto unwind; } - AttachDevice(client, ptr, newmaster); - flags[ptr->id] |= XISlaveAttached; + AttachDevice(client, dev, newmaster); + flags[dev->id] |= XISlaveAttached; unwind: return rc; -- cgit v1.2.3 From 9e999d18b004b8ead9c6c5d79b4a3d4bbf0e3152 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 5 Nov 2010 12:08:11 +1000 Subject: Xi: if XTEST device creation fails, fail the master devices. When getting close to the MAXDEVICES limit, the creation of XTEST devices may fail due to device id exhaustion. In that case, fail the creation of master devices too and return an error to the client. Theoretically, we could alloc the MDs without the XTEST devices but that will get interesting when a client starts sending XTEST events through those devices. Signed-off-by: Peter Hutterer Reviewed-by: Julien Cristau --- Xi/xichangehierarchy.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Xi') diff --git a/Xi/xichangehierarchy.c b/Xi/xichangehierarchy.c index b7140d5e5..b9cdedf77 100644 --- a/Xi/xichangehierarchy.c +++ b/Xi/xichangehierarchy.c @@ -157,7 +157,11 @@ add_master(ClientPtr client, xXIAddMasterInfo *c, int flags[MAXDEVICES]) /* Allocate virtual slave devices for xtest events */ rc = AllocXTestDevice(client, name, &XTestptr, &XTestkeybd, ptr, keybd); if (rc != Success) + { + DeleteInputDeviceRequest(ptr); + DeleteInputDeviceRequest(keybd); goto unwind; + } ActivateDevice(ptr, FALSE); ActivateDevice(keybd, FALSE); -- cgit v1.2.3