xichangehierarchy.c revision f7df2e56
16747b715Smrg/* 26747b715Smrg * Copyright 2007-2008 Peter Hutterer 36747b715Smrg * Copyright 2009 Red Hat, Inc. 46747b715Smrg * 56747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a 66747b715Smrg * copy of this software and associated documentation files (the "Software"), 76747b715Smrg * to deal in the Software without restriction, including without limitation 86747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 96747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the 106747b715Smrg * Software is furnished to do so, subject to the following conditions: 116747b715Smrg * 126747b715Smrg * The above copyright notice and this permission notice (including the next 136747b715Smrg * paragraph) shall be included in all copies or substantial portions of the 146747b715Smrg * Software. 156747b715Smrg * 166747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 176747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 186747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 196747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 206747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 216747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 226747b715Smrg * DEALINGS IN THE SOFTWARE. 236747b715Smrg * 246747b715Smrg * Author: Peter Hutterer, University of South Australia, NICTA 256747b715Smrg */ 266747b715Smrg 276747b715Smrg/*********************************************************************** 286747b715Smrg * 296747b715Smrg * Request change in the device hierarchy. 306747b715Smrg * 316747b715Smrg */ 326747b715Smrg 336747b715Smrg#ifdef HAVE_DIX_CONFIG_H 346747b715Smrg#include <dix-config.h> 356747b715Smrg#endif 366747b715Smrg 37f7df2e56Smrg#include <X11/X.h> /* for inputstr.h */ 38f7df2e56Smrg#include <X11/Xproto.h> /* Request macro */ 39f7df2e56Smrg#include "inputstr.h" /* DeviceIntPtr */ 40f7df2e56Smrg#include "windowstr.h" /* window structure */ 41f7df2e56Smrg#include "scrnintstr.h" /* screen structure */ 426747b715Smrg#include <X11/extensions/XI.h> 436747b715Smrg#include <X11/extensions/XI2proto.h> 446747b715Smrg#include <X11/extensions/geproto.h> 456747b715Smrg#include "extnsionst.h" 466747b715Smrg#include "exevents.h" 476747b715Smrg#include "exglobals.h" 486747b715Smrg#include "geext.h" 496747b715Smrg#include "xace.h" 50f7df2e56Smrg#include "xiquerydevice.h" /* for GetDeviceUse */ 516747b715Smrg 526747b715Smrg#include "xkbsrv.h" 536747b715Smrg 546747b715Smrg#include "xichangehierarchy.h" 55f7df2e56Smrg#include "xibarriers.h" 566747b715Smrg 576747b715Smrg/** 586747b715Smrg * Send the current state of the device hierarchy to all clients. 596747b715Smrg */ 60f7df2e56Smrgvoid 61f7df2e56SmrgXISendDeviceHierarchyEvent(int flags[MAXDEVICES]) 626747b715Smrg{ 636747b715Smrg xXIHierarchyEvent *ev; 646747b715Smrg xXIHierarchyInfo *info; 656747b715Smrg DeviceIntRec dummyDev; 666747b715Smrg DeviceIntPtr dev; 676747b715Smrg int i; 686747b715Smrg 696747b715Smrg if (!flags) 706747b715Smrg return; 716747b715Smrg 726747b715Smrg ev = calloc(1, sizeof(xXIHierarchyEvent) + 73f7df2e56Smrg MAXDEVICES * sizeof(xXIHierarchyInfo)); 749ace9065Smrg if (!ev) 759ace9065Smrg return; 766747b715Smrg ev->type = GenericEvent; 776747b715Smrg ev->extension = IReqCode; 786747b715Smrg ev->evtype = XI_HierarchyChanged; 796747b715Smrg ev->time = GetTimeInMillis(); 806747b715Smrg ev->flags = 0; 816747b715Smrg ev->num_info = inputInfo.numDevices; 826747b715Smrg 83f7df2e56Smrg info = (xXIHierarchyInfo *) &ev[1]; 84f7df2e56Smrg for (dev = inputInfo.devices; dev; dev = dev->next) { 856747b715Smrg info->deviceid = dev->id; 866747b715Smrg info->enabled = dev->enabled; 876747b715Smrg info->use = GetDeviceUse(dev, &info->attachment); 886747b715Smrg info->flags = flags[dev->id]; 896747b715Smrg ev->flags |= info->flags; 906747b715Smrg info++; 916747b715Smrg } 92f7df2e56Smrg for (dev = inputInfo.off_devices; dev; dev = dev->next) { 936747b715Smrg info->deviceid = dev->id; 946747b715Smrg info->enabled = dev->enabled; 956747b715Smrg info->use = GetDeviceUse(dev, &info->attachment); 966747b715Smrg info->flags = flags[dev->id]; 976747b715Smrg ev->flags |= info->flags; 986747b715Smrg info++; 996747b715Smrg } 1006747b715Smrg 101f7df2e56Smrg for (i = 0; i < MAXDEVICES; i++) { 102f7df2e56Smrg if (flags[i] & (XIMasterRemoved | XISlaveRemoved)) { 1036747b715Smrg info->deviceid = i; 1046747b715Smrg info->enabled = FALSE; 1056747b715Smrg info->flags = flags[i]; 1066747b715Smrg info->use = 0; 1076747b715Smrg ev->flags |= info->flags; 1086747b715Smrg ev->num_info++; 1096747b715Smrg info++; 1106747b715Smrg } 1116747b715Smrg } 1126747b715Smrg 1136747b715Smrg ev->length = bytes_to_int32(ev->num_info * sizeof(xXIHierarchyInfo)); 1146747b715Smrg 115f7df2e56Smrg memset(&dummyDev, 0, sizeof(dummyDev)); 1166747b715Smrg dummyDev.id = XIAllDevices; 117f7df2e56Smrg dummyDev.type = SLAVE; 118f7df2e56Smrg SendEventToAllWindows(&dummyDev, (XI_HierarchyChangedMask >> 8), 119f7df2e56Smrg (xEvent *) ev, 1); 1206747b715Smrg free(ev); 1216747b715Smrg} 1226747b715Smrg 1236747b715Smrg/*********************************************************************** 1246747b715Smrg * 1256747b715Smrg * This procedure allows a client to change the device hierarchy through 1266747b715Smrg * adding new master devices, removing them, etc. 1276747b715Smrg * 1286747b715Smrg */ 1296747b715Smrg 130f7df2e56Smrgint 131f7df2e56SmrgSProcXIChangeHierarchy(ClientPtr client) 1326747b715Smrg{ 1336747b715Smrg REQUEST(xXIChangeHierarchyReq); 134f7df2e56Smrg swaps(&stuff->length); 1356747b715Smrg return (ProcXIChangeHierarchy(client)); 1366747b715Smrg} 1376747b715Smrg 1389ace9065Smrgstatic int 139f7df2e56Smrgadd_master(ClientPtr client, xXIAddMasterInfo * c, int flags[MAXDEVICES]) 1409ace9065Smrg{ 1419ace9065Smrg DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd; 142f7df2e56Smrg char *name; 1439ace9065Smrg int rc; 1449ace9065Smrg 1459ace9065Smrg name = calloc(c->name_len + 1, sizeof(char)); 146f7df2e56Smrg if (name == NULL) { 147f7df2e56Smrg rc = BadAlloc; 148f7df2e56Smrg goto unwind; 149f7df2e56Smrg } 150f7df2e56Smrg strncpy(name, (char *) &c[1], c->name_len); 1519ace9065Smrg 1529ace9065Smrg rc = AllocDevicePair(client, name, &ptr, &keybd, 1539ace9065Smrg CorePointerProc, CoreKeyboardProc, TRUE); 1549ace9065Smrg if (rc != Success) 1559ace9065Smrg goto unwind; 1569ace9065Smrg 1579ace9065Smrg if (!c->send_core) 158f7df2e56Smrg ptr->coreEvents = keybd->coreEvents = FALSE; 1599ace9065Smrg 1609ace9065Smrg /* Allocate virtual slave devices for xtest events */ 1619ace9065Smrg rc = AllocXTestDevice(client, name, &XTestptr, &XTestkeybd, ptr, keybd); 162f7df2e56Smrg if (rc != Success) { 1639ace9065Smrg DeleteInputDeviceRequest(ptr); 1649ace9065Smrg DeleteInputDeviceRequest(keybd); 1659ace9065Smrg goto unwind; 1669ace9065Smrg } 1679ace9065Smrg 1689ace9065Smrg ActivateDevice(ptr, FALSE); 1699ace9065Smrg ActivateDevice(keybd, FALSE); 1709ace9065Smrg flags[ptr->id] |= XIMasterAdded; 1719ace9065Smrg flags[keybd->id] |= XIMasterAdded; 1729ace9065Smrg 1739ace9065Smrg ActivateDevice(XTestptr, FALSE); 1749ace9065Smrg ActivateDevice(XTestkeybd, FALSE); 1759ace9065Smrg flags[XTestptr->id] |= XISlaveAdded; 1769ace9065Smrg flags[XTestkeybd->id] |= XISlaveAdded; 1779ace9065Smrg 178f7df2e56Smrg if (c->enable) { 1799ace9065Smrg EnableDevice(ptr, FALSE); 1809ace9065Smrg EnableDevice(keybd, FALSE); 1819ace9065Smrg flags[ptr->id] |= XIDeviceEnabled; 1829ace9065Smrg flags[keybd->id] |= XIDeviceEnabled; 1839ace9065Smrg 1849ace9065Smrg EnableDevice(XTestptr, FALSE); 1859ace9065Smrg EnableDevice(XTestkeybd, FALSE); 1869ace9065Smrg flags[XTestptr->id] |= XIDeviceEnabled; 1879ace9065Smrg flags[XTestkeybd->id] |= XIDeviceEnabled; 1889ace9065Smrg } 1899ace9065Smrg 1909ace9065Smrg /* Attach the XTest virtual devices to the newly 1919ace9065Smrg created master device */ 1929ace9065Smrg AttachDevice(NULL, XTestptr, ptr); 1939ace9065Smrg AttachDevice(NULL, XTestkeybd, keybd); 1949ace9065Smrg flags[XTestptr->id] |= XISlaveAttached; 1959ace9065Smrg flags[XTestkeybd->id] |= XISlaveAttached; 1969ace9065Smrg 197f7df2e56Smrg XIBarrierNewMasterDevice(client, ptr->id); 198f7df2e56Smrg 199f7df2e56Smrg unwind: 2009ace9065Smrg free(name); 2019ace9065Smrg return rc; 2029ace9065Smrg} 2039ace9065Smrg 204475c125cSmrgstatic void 205475c125cSmrgdisable_clientpointer(DeviceIntPtr dev) 206475c125cSmrg{ 207475c125cSmrg int i; 208475c125cSmrg 209f7df2e56Smrg for (i = 0; i < currentMaxClients; i++) { 210475c125cSmrg ClientPtr client = clients[i]; 211f7df2e56Smrg 212475c125cSmrg if (client && client->clientPtr == dev) 213475c125cSmrg client->clientPtr = NULL; 214475c125cSmrg } 215475c125cSmrg} 216475c125cSmrg 2179ace9065Smrgstatic int 218f7df2e56Smrgremove_master(ClientPtr client, xXIRemoveMasterInfo * r, int flags[MAXDEVICES]) 2199ace9065Smrg{ 2209ace9065Smrg DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd; 2219ace9065Smrg int rc = Success; 2229ace9065Smrg 223f7df2e56Smrg if (r->return_mode != XIAttachToMaster && r->return_mode != XIFloating) 2249ace9065Smrg return BadValue; 2259ace9065Smrg 2269ace9065Smrg rc = dixLookupDevice(&ptr, r->deviceid, client, DixDestroyAccess); 2279ace9065Smrg if (rc != Success) 2289ace9065Smrg goto unwind; 2299ace9065Smrg 230f7df2e56Smrg if (!IsMaster(ptr)) { 2319ace9065Smrg client->errorValue = r->deviceid; 2329ace9065Smrg rc = BadDevice; 2339ace9065Smrg goto unwind; 2349ace9065Smrg } 2359ace9065Smrg 2369ace9065Smrg /* XXX: For now, don't allow removal of VCP, VCK */ 237f7df2e56Smrg if (ptr == inputInfo.pointer ||ptr == inputInfo.keyboard) { 2389ace9065Smrg rc = BadDevice; 2399ace9065Smrg goto unwind; 2409ace9065Smrg } 2419ace9065Smrg 2429ace9065Smrg ptr = GetMaster(ptr, MASTER_POINTER); 2439ace9065Smrg rc = dixLookupDevice(&ptr, ptr->id, client, DixDestroyAccess); 2449ace9065Smrg if (rc != Success) 2459ace9065Smrg goto unwind; 2469ace9065Smrg keybd = GetMaster(ptr, MASTER_KEYBOARD); 2479ace9065Smrg rc = dixLookupDevice(&keybd, keybd->id, client, DixDestroyAccess); 2489ace9065Smrg if (rc != Success) 2499ace9065Smrg goto unwind; 2509ace9065Smrg 2519ace9065Smrg XTestptr = GetXTestDevice(ptr); 2529ace9065Smrg rc = dixLookupDevice(&XTestptr, XTestptr->id, client, DixDestroyAccess); 2539ace9065Smrg if (rc != Success) 2549ace9065Smrg goto unwind; 2559ace9065Smrg 2569ace9065Smrg XTestkeybd = GetXTestDevice(keybd); 257f7df2e56Smrg rc = dixLookupDevice(&XTestkeybd, XTestkeybd->id, client, DixDestroyAccess); 2589ace9065Smrg if (rc != Success) 2599ace9065Smrg goto unwind; 2609ace9065Smrg 261475c125cSmrg disable_clientpointer(ptr); 262475c125cSmrg 2639ace9065Smrg /* Disabling sends the devices floating, reattach them if 2649ace9065Smrg * desired. */ 265f7df2e56Smrg if (r->return_mode == XIAttachToMaster) { 266f7df2e56Smrg DeviceIntPtr attached, newptr, newkeybd; 2679ace9065Smrg 2689ace9065Smrg rc = dixLookupDevice(&newptr, r->return_pointer, client, DixAddAccess); 2699ace9065Smrg if (rc != Success) 2709ace9065Smrg goto unwind; 2719ace9065Smrg 272f7df2e56Smrg if (!IsMaster(newptr)) { 2739ace9065Smrg client->errorValue = r->return_pointer; 2749ace9065Smrg rc = BadDevice; 2759ace9065Smrg goto unwind; 2769ace9065Smrg } 2779ace9065Smrg 2789ace9065Smrg rc = dixLookupDevice(&newkeybd, r->return_keyboard, 2799ace9065Smrg client, DixAddAccess); 2809ace9065Smrg if (rc != Success) 2819ace9065Smrg goto unwind; 2829ace9065Smrg 283f7df2e56Smrg if (!IsMaster(newkeybd)) { 2849ace9065Smrg client->errorValue = r->return_keyboard; 2859ace9065Smrg rc = BadDevice; 2869ace9065Smrg goto unwind; 2879ace9065Smrg } 2889ace9065Smrg 289f7df2e56Smrg for (attached = inputInfo.devices; attached; attached = attached->next) { 2909ace9065Smrg if (!IsMaster(attached)) { 291f7df2e56Smrg if (GetMaster(attached, MASTER_ATTACHED) == ptr) { 2929ace9065Smrg AttachDevice(client, attached, newptr); 2939ace9065Smrg flags[attached->id] |= XISlaveAttached; 2949ace9065Smrg } 295f7df2e56Smrg if (GetMaster(attached, MASTER_ATTACHED) == keybd) { 2969ace9065Smrg AttachDevice(client, attached, newkeybd); 2979ace9065Smrg flags[attached->id] |= XISlaveAttached; 2989ace9065Smrg } 2999ace9065Smrg } 3009ace9065Smrg } 3019ace9065Smrg } 3029ace9065Smrg 303f7df2e56Smrg XIBarrierRemoveMasterDevice(client, ptr->id); 3049ace9065Smrg 3059ace9065Smrg /* disable the remove the devices, XTest devices must be done first 3069ace9065Smrg else the sprites they rely on will be destroyed */ 3079ace9065Smrg DisableDevice(XTestptr, FALSE); 3089ace9065Smrg DisableDevice(XTestkeybd, FALSE); 3099ace9065Smrg DisableDevice(keybd, FALSE); 3109ace9065Smrg DisableDevice(ptr, FALSE); 3119ace9065Smrg flags[XTestptr->id] |= XIDeviceDisabled | XISlaveDetached; 3129ace9065Smrg flags[XTestkeybd->id] |= XIDeviceDisabled | XISlaveDetached; 3139ace9065Smrg flags[keybd->id] |= XIDeviceDisabled; 3149ace9065Smrg flags[ptr->id] |= XIDeviceDisabled; 3159ace9065Smrg 3169ace9065Smrg flags[XTestptr->id] |= XISlaveRemoved; 3179ace9065Smrg flags[XTestkeybd->id] |= XISlaveRemoved; 3189ace9065Smrg flags[keybd->id] |= XIMasterRemoved; 3199ace9065Smrg flags[ptr->id] |= XIMasterRemoved; 3209ace9065Smrg 321f7df2e56Smrg RemoveDevice(XTestptr, FALSE); 322f7df2e56Smrg RemoveDevice(XTestkeybd, FALSE); 323f7df2e56Smrg RemoveDevice(keybd, FALSE); 324f7df2e56Smrg RemoveDevice(ptr, FALSE); 325f7df2e56Smrg 326f7df2e56Smrg unwind: 3279ace9065Smrg return rc; 3289ace9065Smrg} 3299ace9065Smrg 3309ace9065Smrgstatic int 331f7df2e56Smrgdetach_slave(ClientPtr client, xXIDetachSlaveInfo * c, int flags[MAXDEVICES]) 3329ace9065Smrg{ 3339ace9065Smrg DeviceIntPtr dev; 3349ace9065Smrg int rc; 3359ace9065Smrg 3369ace9065Smrg rc = dixLookupDevice(&dev, c->deviceid, client, DixManageAccess); 3379ace9065Smrg if (rc != Success) 3389ace9065Smrg goto unwind; 3399ace9065Smrg 340f7df2e56Smrg if (IsMaster(dev)) { 3419ace9065Smrg client->errorValue = c->deviceid; 3429ace9065Smrg rc = BadDevice; 3439ace9065Smrg goto unwind; 3449ace9065Smrg } 3459ace9065Smrg 3469ace9065Smrg /* Don't allow changes to XTest Devices, these are fixed */ 347f7df2e56Smrg if (IsXTestDevice(dev, NULL)) { 3489ace9065Smrg client->errorValue = c->deviceid; 3499ace9065Smrg rc = BadDevice; 3509ace9065Smrg goto unwind; 3519ace9065Smrg } 3529ace9065Smrg 3539ace9065Smrg ReleaseButtonsAndKeys(dev); 3549ace9065Smrg AttachDevice(client, dev, NULL); 3559ace9065Smrg flags[dev->id] |= XISlaveDetached; 3569ace9065Smrg 357f7df2e56Smrg unwind: 3589ace9065Smrg return rc; 3599ace9065Smrg} 3609ace9065Smrg 3619ace9065Smrgstatic int 362f7df2e56Smrgattach_slave(ClientPtr client, xXIAttachSlaveInfo * c, int flags[MAXDEVICES]) 3639ace9065Smrg{ 3649ace9065Smrg DeviceIntPtr dev; 3659ace9065Smrg DeviceIntPtr newmaster; 3669ace9065Smrg int rc; 3679ace9065Smrg 3689ace9065Smrg rc = dixLookupDevice(&dev, c->deviceid, client, DixManageAccess); 3699ace9065Smrg if (rc != Success) 3709ace9065Smrg goto unwind; 3719ace9065Smrg 372f7df2e56Smrg if (IsMaster(dev)) { 3739ace9065Smrg client->errorValue = c->deviceid; 3749ace9065Smrg rc = BadDevice; 3759ace9065Smrg goto unwind; 3769ace9065Smrg } 3779ace9065Smrg 3789ace9065Smrg /* Don't allow changes to XTest Devices, these are fixed */ 379f7df2e56Smrg if (IsXTestDevice(dev, NULL)) { 3809ace9065Smrg client->errorValue = c->deviceid; 3819ace9065Smrg rc = BadDevice; 3829ace9065Smrg goto unwind; 3839ace9065Smrg } 3849ace9065Smrg 3859ace9065Smrg rc = dixLookupDevice(&newmaster, c->new_master, client, DixAddAccess); 3869ace9065Smrg if (rc != Success) 3879ace9065Smrg goto unwind; 388f7df2e56Smrg if (!IsMaster(newmaster)) { 3899ace9065Smrg client->errorValue = c->new_master; 3909ace9065Smrg rc = BadDevice; 3919ace9065Smrg goto unwind; 3929ace9065Smrg } 3939ace9065Smrg 3949ace9065Smrg if (!((IsPointerDevice(newmaster) && IsPointerDevice(dev)) || 395f7df2e56Smrg (IsKeyboardDevice(newmaster) && IsKeyboardDevice(dev)))) { 3969ace9065Smrg rc = BadDevice; 3979ace9065Smrg goto unwind; 3989ace9065Smrg } 3999ace9065Smrg 4009ace9065Smrg ReleaseButtonsAndKeys(dev); 4019ace9065Smrg AttachDevice(client, dev, newmaster); 4029ace9065Smrg flags[dev->id] |= XISlaveAttached; 4039ace9065Smrg 404f7df2e56Smrg unwind: 4059ace9065Smrg return rc; 4069ace9065Smrg} 4079ace9065Smrg 4086747b715Smrg#define SWAPIF(cmd) if (client->swapped) { cmd; } 4096747b715Smrg 4106747b715Smrgint 4116747b715SmrgProcXIChangeHierarchy(ClientPtr client) 4126747b715Smrg{ 4136747b715Smrg xXIAnyHierarchyChangeInfo *any; 4140b0d8713Smrg size_t len; /* length of data remaining in request */ 4156747b715Smrg int rc = Success; 416f7df2e56Smrg int flags[MAXDEVICES] = { 0 }; 4176747b715Smrg 4186747b715Smrg REQUEST(xXIChangeHierarchyReq); 4196747b715Smrg REQUEST_AT_LEAST_SIZE(xXIChangeHierarchyReq); 4206747b715Smrg 4216747b715Smrg if (!stuff->num_changes) 4226747b715Smrg return rc; 4236747b715Smrg 424f7df2e56Smrg#if 0 4250b0d8713Smrg if (stuff->length > (INT_MAX >> 2)) 4260b0d8713Smrg return BadAlloc; 427f7df2e56Smrg#endif 428f7df2e56Smrg len = ((size_t)stuff->length << 2) - sizeof(xXIAnyHierarchyChangeInfo); 4290b0d8713Smrg 430f7df2e56Smrg any = (xXIAnyHierarchyChangeInfo *) &stuff[1]; 431f7df2e56Smrg while (stuff->num_changes--) { 4320b0d8713Smrg if (len < sizeof(xXIAnyHierarchyChangeInfo)) { 4330b0d8713Smrg rc = BadLength; 4340b0d8713Smrg goto unwind; 4350b0d8713Smrg } 4360b0d8713Smrg 437f7df2e56Smrg SWAPIF(swaps(&any->type)); 438f7df2e56Smrg SWAPIF(swaps(&any->length)); 4396747b715Smrg 440f7df2e56Smrg if (len < ((size_t)any->length << 2)) 4416747b715Smrg return BadLength; 4426747b715Smrg 4430b0d8713Smrg#define CHANGE_SIZE_MATCH(type) \ 4440b0d8713Smrg do { \ 4450b0d8713Smrg if ((len < sizeof(type)) || (any->length != (sizeof(type) >> 2))) { \ 4460b0d8713Smrg rc = BadLength; \ 4470b0d8713Smrg goto unwind; \ 4480b0d8713Smrg } \ 4490b0d8713Smrg } while(0) 4500b0d8713Smrg 451f7df2e56Smrg switch (any->type) { 452f7df2e56Smrg case XIAddMaster: 4536747b715Smrg { 454f7df2e56Smrg xXIAddMasterInfo *c = (xXIAddMasterInfo *) any; 455f7df2e56Smrg 456f7df2e56Smrg /* Variable length, due to appended name string */ 457f7df2e56Smrg if (len < sizeof(xXIAddMasterInfo)) { 458f7df2e56Smrg rc = BadLength; 459f7df2e56Smrg goto unwind; 460f7df2e56Smrg } 461f7df2e56Smrg SWAPIF(swaps(&c->name_len)); 462f7df2e56Smrg if (c->name_len > (len - sizeof(xXIAddMasterInfo))) { 463f7df2e56Smrg rc = BadLength; 464f7df2e56Smrg goto unwind; 465f7df2e56Smrg } 466f7df2e56Smrg 467f7df2e56Smrg rc = add_master(client, c, flags); 468f7df2e56Smrg if (rc != Success) 469f7df2e56Smrg goto unwind; 470f7df2e56Smrg } 471f7df2e56Smrg break; 472f7df2e56Smrg case XIRemoveMaster: 473f7df2e56Smrg { 474f7df2e56Smrg xXIRemoveMasterInfo *r = (xXIRemoveMasterInfo *) any; 475f7df2e56Smrg 476f7df2e56Smrg CHANGE_SIZE_MATCH(xXIRemoveMasterInfo); 477f7df2e56Smrg rc = remove_master(client, r, flags); 478f7df2e56Smrg if (rc != Success) 479f7df2e56Smrg goto unwind; 480f7df2e56Smrg } 481f7df2e56Smrg break; 482f7df2e56Smrg case XIDetachSlave: 483f7df2e56Smrg { 484f7df2e56Smrg xXIDetachSlaveInfo *c = (xXIDetachSlaveInfo *) any; 485f7df2e56Smrg 486f7df2e56Smrg CHANGE_SIZE_MATCH(xXIDetachSlaveInfo); 487f7df2e56Smrg rc = detach_slave(client, c, flags); 488f7df2e56Smrg if (rc != Success) 489f7df2e56Smrg goto unwind; 490f7df2e56Smrg } 491f7df2e56Smrg break; 492f7df2e56Smrg case XIAttachSlave: 493f7df2e56Smrg { 494f7df2e56Smrg xXIAttachSlaveInfo *c = (xXIAttachSlaveInfo *) any; 495f7df2e56Smrg 496f7df2e56Smrg CHANGE_SIZE_MATCH(xXIAttachSlaveInfo); 497f7df2e56Smrg rc = attach_slave(client, c, flags); 498f7df2e56Smrg if (rc != Success) 499f7df2e56Smrg goto unwind; 500f7df2e56Smrg } 501f7df2e56Smrg break; 5026747b715Smrg } 5036747b715Smrg 5040b0d8713Smrg len -= any->length * 4; 505f7df2e56Smrg any = (xXIAnyHierarchyChangeInfo *) ((char *) any + any->length * 4); 5066747b715Smrg } 5076747b715Smrg 508f7df2e56Smrg unwind: 5096747b715Smrg 5106747b715Smrg XISendDeviceHierarchyEvent(flags); 5116747b715Smrg return rc; 5126747b715Smrg} 513