xichangehierarchy.c revision 806e81e9
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 1307e31ba66Smrgint _X_COLD 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 1977e31ba66Smrg for (int i = 0; i < currentMaxClients; i++) 1987e31ba66Smrg XIBarrierNewMasterDevice(clients[i], ptr->id); 199f7df2e56Smrg 200f7df2e56Smrg unwind: 2019ace9065Smrg free(name); 2029ace9065Smrg return rc; 2039ace9065Smrg} 2049ace9065Smrg 205475c125cSmrgstatic void 206475c125cSmrgdisable_clientpointer(DeviceIntPtr dev) 207475c125cSmrg{ 208475c125cSmrg int i; 209475c125cSmrg 210f7df2e56Smrg for (i = 0; i < currentMaxClients; i++) { 211475c125cSmrg ClientPtr client = clients[i]; 212f7df2e56Smrg 213475c125cSmrg if (client && client->clientPtr == dev) 214475c125cSmrg client->clientPtr = NULL; 215475c125cSmrg } 216475c125cSmrg} 217475c125cSmrg 2189ace9065Smrgstatic int 219f7df2e56Smrgremove_master(ClientPtr client, xXIRemoveMasterInfo * r, int flags[MAXDEVICES]) 2209ace9065Smrg{ 2219ace9065Smrg DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd; 2229ace9065Smrg int rc = Success; 2239ace9065Smrg 224f7df2e56Smrg if (r->return_mode != XIAttachToMaster && r->return_mode != XIFloating) 2259ace9065Smrg return BadValue; 2269ace9065Smrg 2279ace9065Smrg rc = dixLookupDevice(&ptr, r->deviceid, client, DixDestroyAccess); 2289ace9065Smrg if (rc != Success) 2299ace9065Smrg goto unwind; 2309ace9065Smrg 231f7df2e56Smrg if (!IsMaster(ptr)) { 2329ace9065Smrg client->errorValue = r->deviceid; 2339ace9065Smrg rc = BadDevice; 2349ace9065Smrg goto unwind; 2359ace9065Smrg } 2369ace9065Smrg 2379ace9065Smrg /* XXX: For now, don't allow removal of VCP, VCK */ 238f7df2e56Smrg if (ptr == inputInfo.pointer ||ptr == inputInfo.keyboard) { 2399ace9065Smrg rc = BadDevice; 2409ace9065Smrg goto unwind; 2419ace9065Smrg } 2429ace9065Smrg 2439ace9065Smrg ptr = GetMaster(ptr, MASTER_POINTER); 2449ace9065Smrg rc = dixLookupDevice(&ptr, ptr->id, client, DixDestroyAccess); 2459ace9065Smrg if (rc != Success) 2469ace9065Smrg goto unwind; 2479ace9065Smrg keybd = GetMaster(ptr, MASTER_KEYBOARD); 2489ace9065Smrg rc = dixLookupDevice(&keybd, keybd->id, client, DixDestroyAccess); 2499ace9065Smrg if (rc != Success) 2509ace9065Smrg goto unwind; 2519ace9065Smrg 2529ace9065Smrg XTestptr = GetXTestDevice(ptr); 2539ace9065Smrg rc = dixLookupDevice(&XTestptr, XTestptr->id, client, DixDestroyAccess); 2549ace9065Smrg if (rc != Success) 2559ace9065Smrg goto unwind; 2569ace9065Smrg 2579ace9065Smrg XTestkeybd = GetXTestDevice(keybd); 258f7df2e56Smrg rc = dixLookupDevice(&XTestkeybd, XTestkeybd->id, client, DixDestroyAccess); 2599ace9065Smrg if (rc != Success) 2609ace9065Smrg goto unwind; 2619ace9065Smrg 262475c125cSmrg disable_clientpointer(ptr); 263475c125cSmrg 2649ace9065Smrg /* Disabling sends the devices floating, reattach them if 2659ace9065Smrg * desired. */ 266f7df2e56Smrg if (r->return_mode == XIAttachToMaster) { 267f7df2e56Smrg DeviceIntPtr attached, newptr, newkeybd; 2689ace9065Smrg 2699ace9065Smrg rc = dixLookupDevice(&newptr, r->return_pointer, client, DixAddAccess); 2709ace9065Smrg if (rc != Success) 2719ace9065Smrg goto unwind; 2729ace9065Smrg 273f7df2e56Smrg if (!IsMaster(newptr)) { 2749ace9065Smrg client->errorValue = r->return_pointer; 2759ace9065Smrg rc = BadDevice; 2769ace9065Smrg goto unwind; 2779ace9065Smrg } 2789ace9065Smrg 2799ace9065Smrg rc = dixLookupDevice(&newkeybd, r->return_keyboard, 2809ace9065Smrg client, DixAddAccess); 2819ace9065Smrg if (rc != Success) 2829ace9065Smrg goto unwind; 2839ace9065Smrg 284f7df2e56Smrg if (!IsMaster(newkeybd)) { 2859ace9065Smrg client->errorValue = r->return_keyboard; 2869ace9065Smrg rc = BadDevice; 2879ace9065Smrg goto unwind; 2889ace9065Smrg } 2899ace9065Smrg 290f7df2e56Smrg for (attached = inputInfo.devices; attached; attached = attached->next) { 2919ace9065Smrg if (!IsMaster(attached)) { 292f7df2e56Smrg if (GetMaster(attached, MASTER_ATTACHED) == ptr) { 2939ace9065Smrg AttachDevice(client, attached, newptr); 2949ace9065Smrg flags[attached->id] |= XISlaveAttached; 2959ace9065Smrg } 296f7df2e56Smrg if (GetMaster(attached, MASTER_ATTACHED) == keybd) { 2979ace9065Smrg AttachDevice(client, attached, newkeybd); 2989ace9065Smrg flags[attached->id] |= XISlaveAttached; 2999ace9065Smrg } 3009ace9065Smrg } 3019ace9065Smrg } 3029ace9065Smrg } 3039ace9065Smrg 3047e31ba66Smrg for (int i = 0; i < currentMaxClients; i++) 3057e31ba66Smrg XIBarrierRemoveMasterDevice(clients[i], ptr->id); 3069ace9065Smrg 3079ace9065Smrg /* disable the remove the devices, XTest devices must be done first 3089ace9065Smrg else the sprites they rely on will be destroyed */ 3099ace9065Smrg DisableDevice(XTestptr, FALSE); 3109ace9065Smrg DisableDevice(XTestkeybd, FALSE); 3119ace9065Smrg DisableDevice(keybd, FALSE); 3129ace9065Smrg DisableDevice(ptr, FALSE); 3139ace9065Smrg flags[XTestptr->id] |= XIDeviceDisabled | XISlaveDetached; 3149ace9065Smrg flags[XTestkeybd->id] |= XIDeviceDisabled | XISlaveDetached; 3159ace9065Smrg flags[keybd->id] |= XIDeviceDisabled; 3169ace9065Smrg flags[ptr->id] |= XIDeviceDisabled; 3179ace9065Smrg 3189ace9065Smrg flags[XTestptr->id] |= XISlaveRemoved; 3199ace9065Smrg flags[XTestkeybd->id] |= XISlaveRemoved; 3209ace9065Smrg flags[keybd->id] |= XIMasterRemoved; 3219ace9065Smrg flags[ptr->id] |= XIMasterRemoved; 3229ace9065Smrg 323f7df2e56Smrg RemoveDevice(XTestptr, FALSE); 324f7df2e56Smrg RemoveDevice(XTestkeybd, FALSE); 325f7df2e56Smrg RemoveDevice(keybd, FALSE); 326f7df2e56Smrg RemoveDevice(ptr, FALSE); 327f7df2e56Smrg 328f7df2e56Smrg unwind: 3299ace9065Smrg return rc; 3309ace9065Smrg} 3319ace9065Smrg 3329ace9065Smrgstatic int 333f7df2e56Smrgdetach_slave(ClientPtr client, xXIDetachSlaveInfo * c, int flags[MAXDEVICES]) 3349ace9065Smrg{ 3359ace9065Smrg DeviceIntPtr dev; 3369ace9065Smrg int rc; 3379ace9065Smrg 3389ace9065Smrg rc = dixLookupDevice(&dev, c->deviceid, client, DixManageAccess); 3399ace9065Smrg if (rc != Success) 3409ace9065Smrg goto unwind; 3419ace9065Smrg 342f7df2e56Smrg if (IsMaster(dev)) { 3439ace9065Smrg client->errorValue = c->deviceid; 3449ace9065Smrg rc = BadDevice; 3459ace9065Smrg goto unwind; 3469ace9065Smrg } 3479ace9065Smrg 3489ace9065Smrg /* Don't allow changes to XTest Devices, these are fixed */ 349f7df2e56Smrg if (IsXTestDevice(dev, NULL)) { 3509ace9065Smrg client->errorValue = c->deviceid; 3519ace9065Smrg rc = BadDevice; 3529ace9065Smrg goto unwind; 3539ace9065Smrg } 3549ace9065Smrg 3559ace9065Smrg ReleaseButtonsAndKeys(dev); 3569ace9065Smrg AttachDevice(client, dev, NULL); 3579ace9065Smrg flags[dev->id] |= XISlaveDetached; 3589ace9065Smrg 359f7df2e56Smrg unwind: 3609ace9065Smrg return rc; 3619ace9065Smrg} 3629ace9065Smrg 3639ace9065Smrgstatic int 364f7df2e56Smrgattach_slave(ClientPtr client, xXIAttachSlaveInfo * c, int flags[MAXDEVICES]) 3659ace9065Smrg{ 3669ace9065Smrg DeviceIntPtr dev; 3679ace9065Smrg DeviceIntPtr newmaster; 3689ace9065Smrg int rc; 3699ace9065Smrg 3709ace9065Smrg rc = dixLookupDevice(&dev, c->deviceid, client, DixManageAccess); 3719ace9065Smrg if (rc != Success) 3729ace9065Smrg goto unwind; 3739ace9065Smrg 374f7df2e56Smrg if (IsMaster(dev)) { 3759ace9065Smrg client->errorValue = c->deviceid; 3769ace9065Smrg rc = BadDevice; 3779ace9065Smrg goto unwind; 3789ace9065Smrg } 3799ace9065Smrg 3809ace9065Smrg /* Don't allow changes to XTest Devices, these are fixed */ 381f7df2e56Smrg if (IsXTestDevice(dev, NULL)) { 3829ace9065Smrg client->errorValue = c->deviceid; 3839ace9065Smrg rc = BadDevice; 3849ace9065Smrg goto unwind; 3859ace9065Smrg } 3869ace9065Smrg 3879ace9065Smrg rc = dixLookupDevice(&newmaster, c->new_master, client, DixAddAccess); 3889ace9065Smrg if (rc != Success) 3899ace9065Smrg goto unwind; 390f7df2e56Smrg if (!IsMaster(newmaster)) { 3919ace9065Smrg client->errorValue = c->new_master; 3929ace9065Smrg rc = BadDevice; 3939ace9065Smrg goto unwind; 3949ace9065Smrg } 3959ace9065Smrg 3969ace9065Smrg if (!((IsPointerDevice(newmaster) && IsPointerDevice(dev)) || 397f7df2e56Smrg (IsKeyboardDevice(newmaster) && IsKeyboardDevice(dev)))) { 3989ace9065Smrg rc = BadDevice; 3999ace9065Smrg goto unwind; 4009ace9065Smrg } 4019ace9065Smrg 4029ace9065Smrg ReleaseButtonsAndKeys(dev); 4039ace9065Smrg AttachDevice(client, dev, newmaster); 4049ace9065Smrg flags[dev->id] |= XISlaveAttached; 4059ace9065Smrg 406f7df2e56Smrg unwind: 4079ace9065Smrg return rc; 4089ace9065Smrg} 4099ace9065Smrg 4106747b715Smrg#define SWAPIF(cmd) if (client->swapped) { cmd; } 4116747b715Smrg 4126747b715Smrgint 4136747b715SmrgProcXIChangeHierarchy(ClientPtr client) 4146747b715Smrg{ 4156747b715Smrg xXIAnyHierarchyChangeInfo *any; 4160b0d8713Smrg size_t len; /* length of data remaining in request */ 4176747b715Smrg int rc = Success; 418f7df2e56Smrg int flags[MAXDEVICES] = { 0 }; 4196747b715Smrg 4206747b715Smrg REQUEST(xXIChangeHierarchyReq); 4216747b715Smrg REQUEST_AT_LEAST_SIZE(xXIChangeHierarchyReq); 4226747b715Smrg 4236747b715Smrg if (!stuff->num_changes) 4246747b715Smrg return rc; 4256747b715Smrg 426806e81e9Smrg len = ((size_t)client->req_len << 2) - sizeof(xXIChangeHierarchyReq); 4270b0d8713Smrg 428f7df2e56Smrg any = (xXIAnyHierarchyChangeInfo *) &stuff[1]; 429f7df2e56Smrg while (stuff->num_changes--) { 4300b0d8713Smrg if (len < sizeof(xXIAnyHierarchyChangeInfo)) { 4310b0d8713Smrg rc = BadLength; 4320b0d8713Smrg goto unwind; 4330b0d8713Smrg } 4340b0d8713Smrg 435f7df2e56Smrg SWAPIF(swaps(&any->type)); 436f7df2e56Smrg SWAPIF(swaps(&any->length)); 4376747b715Smrg 438f7df2e56Smrg if (len < ((size_t)any->length << 2)) 4396747b715Smrg return BadLength; 4406747b715Smrg 4410b0d8713Smrg#define CHANGE_SIZE_MATCH(type) \ 4420b0d8713Smrg do { \ 4430b0d8713Smrg if ((len < sizeof(type)) || (any->length != (sizeof(type) >> 2))) { \ 4440b0d8713Smrg rc = BadLength; \ 4450b0d8713Smrg goto unwind; \ 4460b0d8713Smrg } \ 4470b0d8713Smrg } while(0) 4480b0d8713Smrg 449f7df2e56Smrg switch (any->type) { 450f7df2e56Smrg case XIAddMaster: 4516747b715Smrg { 452f7df2e56Smrg xXIAddMasterInfo *c = (xXIAddMasterInfo *) any; 453f7df2e56Smrg 454f7df2e56Smrg /* Variable length, due to appended name string */ 455f7df2e56Smrg if (len < sizeof(xXIAddMasterInfo)) { 456f7df2e56Smrg rc = BadLength; 457f7df2e56Smrg goto unwind; 458f7df2e56Smrg } 459f7df2e56Smrg SWAPIF(swaps(&c->name_len)); 460f7df2e56Smrg if (c->name_len > (len - sizeof(xXIAddMasterInfo))) { 461f7df2e56Smrg rc = BadLength; 462f7df2e56Smrg goto unwind; 463f7df2e56Smrg } 464f7df2e56Smrg 465f7df2e56Smrg rc = add_master(client, c, flags); 466f7df2e56Smrg if (rc != Success) 467f7df2e56Smrg goto unwind; 468f7df2e56Smrg } 469f7df2e56Smrg break; 470f7df2e56Smrg case XIRemoveMaster: 471f7df2e56Smrg { 472f7df2e56Smrg xXIRemoveMasterInfo *r = (xXIRemoveMasterInfo *) any; 473f7df2e56Smrg 474f7df2e56Smrg CHANGE_SIZE_MATCH(xXIRemoveMasterInfo); 475f7df2e56Smrg rc = remove_master(client, r, flags); 476f7df2e56Smrg if (rc != Success) 477f7df2e56Smrg goto unwind; 478f7df2e56Smrg } 479f7df2e56Smrg break; 480f7df2e56Smrg case XIDetachSlave: 481f7df2e56Smrg { 482f7df2e56Smrg xXIDetachSlaveInfo *c = (xXIDetachSlaveInfo *) any; 483f7df2e56Smrg 484f7df2e56Smrg CHANGE_SIZE_MATCH(xXIDetachSlaveInfo); 485f7df2e56Smrg rc = detach_slave(client, c, flags); 486f7df2e56Smrg if (rc != Success) 487f7df2e56Smrg goto unwind; 488f7df2e56Smrg } 489f7df2e56Smrg break; 490f7df2e56Smrg case XIAttachSlave: 491f7df2e56Smrg { 492f7df2e56Smrg xXIAttachSlaveInfo *c = (xXIAttachSlaveInfo *) any; 493f7df2e56Smrg 494f7df2e56Smrg CHANGE_SIZE_MATCH(xXIAttachSlaveInfo); 495f7df2e56Smrg rc = attach_slave(client, c, flags); 496f7df2e56Smrg if (rc != Success) 497f7df2e56Smrg goto unwind; 498f7df2e56Smrg } 499f7df2e56Smrg break; 5006747b715Smrg } 5016747b715Smrg 5020b0d8713Smrg len -= any->length * 4; 503f7df2e56Smrg any = (xXIAnyHierarchyChangeInfo *) ((char *) any + any->length * 4); 5046747b715Smrg } 5056747b715Smrg 506f7df2e56Smrg unwind: 5076747b715Smrg 5086747b715Smrg XISendDeviceHierarchyEvent(flags); 5096747b715Smrg return rc; 5106747b715Smrg} 511