1706f2543Smrg/* 2706f2543Smrg * Copyright 2007-2008 Peter Hutterer 3706f2543Smrg * Copyright 2009 Red Hat, Inc. 4706f2543Smrg * 5706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6706f2543Smrg * copy of this software and associated documentation files (the "Software"), 7706f2543Smrg * to deal in the Software without restriction, including without limitation 8706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 10706f2543Smrg * Software is furnished to do so, subject to the following conditions: 11706f2543Smrg * 12706f2543Smrg * The above copyright notice and this permission notice (including the next 13706f2543Smrg * paragraph) shall be included in all copies or substantial portions of the 14706f2543Smrg * Software. 15706f2543Smrg * 16706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19706f2543Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20706f2543Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21706f2543Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22706f2543Smrg * DEALINGS IN THE SOFTWARE. 23706f2543Smrg * 24706f2543Smrg * Author: Peter Hutterer, University of South Australia, NICTA 25706f2543Smrg */ 26706f2543Smrg 27706f2543Smrg/*********************************************************************** 28706f2543Smrg * 29706f2543Smrg * Request change in the device hierarchy. 30706f2543Smrg * 31706f2543Smrg */ 32706f2543Smrg 33706f2543Smrg 34706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 35706f2543Smrg#include <dix-config.h> 36706f2543Smrg#endif 37706f2543Smrg 38706f2543Smrg#include <X11/X.h> /* for inputstr.h */ 39706f2543Smrg#include <X11/Xproto.h> /* Request macro */ 40706f2543Smrg#include "inputstr.h" /* DeviceIntPtr */ 41706f2543Smrg#include "windowstr.h" /* window structure */ 42706f2543Smrg#include "scrnintstr.h" /* screen structure */ 43706f2543Smrg#include <X11/extensions/XI.h> 44706f2543Smrg#include <X11/extensions/XI2proto.h> 45706f2543Smrg#include <X11/extensions/geproto.h> 46706f2543Smrg#include "extnsionst.h" 47706f2543Smrg#include "exevents.h" 48706f2543Smrg#include "exglobals.h" 49706f2543Smrg#include "geext.h" 50706f2543Smrg#include "xace.h" 51706f2543Smrg#include "xiquerydevice.h" /* for GetDeviceUse */ 52706f2543Smrg 53706f2543Smrg#include "xkbsrv.h" 54706f2543Smrg 55706f2543Smrg#include "xichangehierarchy.h" 56706f2543Smrg 57706f2543Smrg/** 58706f2543Smrg * Send the current state of the device hierarchy to all clients. 59706f2543Smrg */ 60706f2543Smrgvoid XISendDeviceHierarchyEvent(int flags[MAXDEVICES]) 61706f2543Smrg{ 62706f2543Smrg xXIHierarchyEvent *ev; 63706f2543Smrg xXIHierarchyInfo *info; 64706f2543Smrg DeviceIntRec dummyDev; 65706f2543Smrg DeviceIntPtr dev; 66706f2543Smrg int i; 67706f2543Smrg 68706f2543Smrg if (!flags) 69706f2543Smrg return; 70706f2543Smrg 71706f2543Smrg ev = calloc(1, sizeof(xXIHierarchyEvent) + 72706f2543Smrg MAXDEVICES * sizeof(xXIHierarchyInfo)); 73706f2543Smrg if (!ev) 74706f2543Smrg return; 75706f2543Smrg ev->type = GenericEvent; 76706f2543Smrg ev->extension = IReqCode; 77706f2543Smrg ev->evtype = XI_HierarchyChanged; 78706f2543Smrg ev->time = GetTimeInMillis(); 79706f2543Smrg ev->flags = 0; 80706f2543Smrg ev->num_info = inputInfo.numDevices; 81706f2543Smrg 82706f2543Smrg info = (xXIHierarchyInfo*)&ev[1]; 83706f2543Smrg for (dev = inputInfo.devices; dev; dev = dev->next) 84706f2543Smrg { 85706f2543Smrg info->deviceid = dev->id; 86706f2543Smrg info->enabled = dev->enabled; 87706f2543Smrg info->use = GetDeviceUse(dev, &info->attachment); 88706f2543Smrg info->flags = flags[dev->id]; 89706f2543Smrg ev->flags |= info->flags; 90706f2543Smrg info++; 91706f2543Smrg } 92706f2543Smrg for (dev = inputInfo.off_devices; dev; dev = dev->next) 93706f2543Smrg { 94706f2543Smrg info->deviceid = dev->id; 95706f2543Smrg info->enabled = dev->enabled; 96706f2543Smrg info->use = GetDeviceUse(dev, &info->attachment); 97706f2543Smrg info->flags = flags[dev->id]; 98706f2543Smrg ev->flags |= info->flags; 99706f2543Smrg info++; 100706f2543Smrg } 101706f2543Smrg 102706f2543Smrg 103706f2543Smrg for (i = 0; i < MAXDEVICES; i++) 104706f2543Smrg { 105706f2543Smrg if (flags[i] & (XIMasterRemoved | XISlaveRemoved)) 106706f2543Smrg { 107706f2543Smrg info->deviceid = i; 108706f2543Smrg info->enabled = FALSE; 109706f2543Smrg info->flags = flags[i]; 110706f2543Smrg info->use = 0; 111706f2543Smrg ev->flags |= info->flags; 112706f2543Smrg ev->num_info++; 113706f2543Smrg info++; 114706f2543Smrg } 115706f2543Smrg } 116706f2543Smrg 117706f2543Smrg ev->length = bytes_to_int32(ev->num_info * sizeof(xXIHierarchyInfo)); 118706f2543Smrg 119706f2543Smrg dummyDev.id = XIAllDevices; 120706f2543Smrg SendEventToAllWindows(&dummyDev, (XI_HierarchyChangedMask >> 8), (xEvent*)ev, 1); 121706f2543Smrg free(ev); 122706f2543Smrg} 123706f2543Smrg 124706f2543Smrg 125706f2543Smrg/*********************************************************************** 126706f2543Smrg * 127706f2543Smrg * This procedure allows a client to change the device hierarchy through 128706f2543Smrg * adding new master devices, removing them, etc. 129706f2543Smrg * 130706f2543Smrg */ 131706f2543Smrg 132706f2543Smrgint SProcXIChangeHierarchy(ClientPtr client) 133706f2543Smrg{ 134706f2543Smrg char n; 135706f2543Smrg 136706f2543Smrg REQUEST(xXIChangeHierarchyReq); 137706f2543Smrg swaps(&stuff->length, n); 138706f2543Smrg return (ProcXIChangeHierarchy(client)); 139706f2543Smrg} 140706f2543Smrg 141706f2543Smrgstatic int 142706f2543Smrgadd_master(ClientPtr client, xXIAddMasterInfo *c, int flags[MAXDEVICES]) 143706f2543Smrg{ 144706f2543Smrg DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd; 145706f2543Smrg char* name; 146706f2543Smrg int rc; 147706f2543Smrg 148706f2543Smrg name = calloc(c->name_len + 1, sizeof(char)); 149706f2543Smrg strncpy(name, (char*)&c[1], c->name_len); 150706f2543Smrg 151706f2543Smrg rc = AllocDevicePair(client, name, &ptr, &keybd, 152706f2543Smrg CorePointerProc, CoreKeyboardProc, TRUE); 153706f2543Smrg if (rc != Success) 154706f2543Smrg goto unwind; 155706f2543Smrg 156706f2543Smrg if (!c->send_core) 157706f2543Smrg ptr->coreEvents = keybd->coreEvents = FALSE; 158706f2543Smrg 159706f2543Smrg /* Allocate virtual slave devices for xtest events */ 160706f2543Smrg rc = AllocXTestDevice(client, name, &XTestptr, &XTestkeybd, ptr, keybd); 161706f2543Smrg if (rc != Success) 162706f2543Smrg { 163706f2543Smrg DeleteInputDeviceRequest(ptr); 164706f2543Smrg DeleteInputDeviceRequest(keybd); 165706f2543Smrg goto unwind; 166706f2543Smrg } 167706f2543Smrg 168706f2543Smrg ActivateDevice(ptr, FALSE); 169706f2543Smrg ActivateDevice(keybd, FALSE); 170706f2543Smrg flags[ptr->id] |= XIMasterAdded; 171706f2543Smrg flags[keybd->id] |= XIMasterAdded; 172706f2543Smrg 173706f2543Smrg ActivateDevice(XTestptr, FALSE); 174706f2543Smrg ActivateDevice(XTestkeybd, FALSE); 175706f2543Smrg flags[XTestptr->id] |= XISlaveAdded; 176706f2543Smrg flags[XTestkeybd->id] |= XISlaveAdded; 177706f2543Smrg 178706f2543Smrg if (c->enable) 179706f2543Smrg { 180706f2543Smrg EnableDevice(ptr, FALSE); 181706f2543Smrg EnableDevice(keybd, FALSE); 182706f2543Smrg flags[ptr->id] |= XIDeviceEnabled; 183706f2543Smrg flags[keybd->id] |= XIDeviceEnabled; 184706f2543Smrg 185706f2543Smrg EnableDevice(XTestptr, FALSE); 186706f2543Smrg EnableDevice(XTestkeybd, FALSE); 187706f2543Smrg flags[XTestptr->id] |= XIDeviceEnabled; 188706f2543Smrg flags[XTestkeybd->id] |= XIDeviceEnabled; 189706f2543Smrg } 190706f2543Smrg 191706f2543Smrg /* Attach the XTest virtual devices to the newly 192706f2543Smrg created master device */ 193706f2543Smrg AttachDevice(NULL, XTestptr, ptr); 194706f2543Smrg AttachDevice(NULL, XTestkeybd, keybd); 195706f2543Smrg flags[XTestptr->id] |= XISlaveAttached; 196706f2543Smrg flags[XTestkeybd->id] |= XISlaveAttached; 197706f2543Smrg 198706f2543Smrgunwind: 199706f2543Smrg free(name); 200706f2543Smrg return rc; 201706f2543Smrg} 202706f2543Smrg 203706f2543Smrgstatic void 204706f2543Smrgdisable_clientpointer(DeviceIntPtr dev) 205706f2543Smrg{ 206706f2543Smrg int i; 207706f2543Smrg 208706f2543Smrg for (i = 0; i < currentMaxClients; i++) 209706f2543Smrg { 210706f2543Smrg ClientPtr client = clients[i]; 211706f2543Smrg if (client && client->clientPtr == dev) 212706f2543Smrg client->clientPtr = NULL; 213706f2543Smrg } 214706f2543Smrg} 215706f2543Smrg 216706f2543Smrgstatic int 217706f2543Smrgremove_master(ClientPtr client, xXIRemoveMasterInfo *r, 218706f2543Smrg int flags[MAXDEVICES]) 219706f2543Smrg{ 220706f2543Smrg DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd; 221706f2543Smrg int rc = Success; 222706f2543Smrg 223706f2543Smrg if (r->return_mode != XIAttachToMaster && 224706f2543Smrg r->return_mode != XIFloating) 225706f2543Smrg return BadValue; 226706f2543Smrg 227706f2543Smrg rc = dixLookupDevice(&ptr, r->deviceid, client, DixDestroyAccess); 228706f2543Smrg if (rc != Success) 229706f2543Smrg goto unwind; 230706f2543Smrg 231706f2543Smrg if (!IsMaster(ptr)) 232706f2543Smrg { 233706f2543Smrg client->errorValue = r->deviceid; 234706f2543Smrg rc = BadDevice; 235706f2543Smrg goto unwind; 236706f2543Smrg } 237706f2543Smrg 238706f2543Smrg /* XXX: For now, don't allow removal of VCP, VCK */ 239706f2543Smrg if (ptr == inputInfo.pointer || ptr == inputInfo.keyboard) 240706f2543Smrg { 241706f2543Smrg rc = BadDevice; 242706f2543Smrg goto unwind; 243706f2543Smrg } 244706f2543Smrg 245706f2543Smrg 246706f2543Smrg ptr = GetMaster(ptr, MASTER_POINTER); 247706f2543Smrg rc = dixLookupDevice(&ptr, ptr->id, client, DixDestroyAccess); 248706f2543Smrg if (rc != Success) 249706f2543Smrg goto unwind; 250706f2543Smrg keybd = GetMaster(ptr, MASTER_KEYBOARD); 251706f2543Smrg rc = dixLookupDevice(&keybd, keybd->id, client, DixDestroyAccess); 252706f2543Smrg if (rc != Success) 253706f2543Smrg goto unwind; 254706f2543Smrg 255706f2543Smrg XTestptr = GetXTestDevice(ptr); 256706f2543Smrg rc = dixLookupDevice(&XTestptr, XTestptr->id, client, DixDestroyAccess); 257706f2543Smrg if (rc != Success) 258706f2543Smrg goto unwind; 259706f2543Smrg 260706f2543Smrg XTestkeybd = GetXTestDevice(keybd); 261706f2543Smrg rc = dixLookupDevice(&XTestkeybd, XTestkeybd->id, client, 262706f2543Smrg DixDestroyAccess); 263706f2543Smrg if (rc != Success) 264706f2543Smrg goto unwind; 265706f2543Smrg 266706f2543Smrg disable_clientpointer(ptr); 267706f2543Smrg 268706f2543Smrg /* Disabling sends the devices floating, reattach them if 269706f2543Smrg * desired. */ 270706f2543Smrg if (r->return_mode == XIAttachToMaster) 271706f2543Smrg { 272706f2543Smrg DeviceIntPtr attached, 273706f2543Smrg newptr, 274706f2543Smrg newkeybd; 275706f2543Smrg 276706f2543Smrg rc = dixLookupDevice(&newptr, r->return_pointer, client, DixAddAccess); 277706f2543Smrg if (rc != Success) 278706f2543Smrg goto unwind; 279706f2543Smrg 280706f2543Smrg if (!IsMaster(newptr)) 281706f2543Smrg { 282706f2543Smrg client->errorValue = r->return_pointer; 283706f2543Smrg rc = BadDevice; 284706f2543Smrg goto unwind; 285706f2543Smrg } 286706f2543Smrg 287706f2543Smrg rc = dixLookupDevice(&newkeybd, r->return_keyboard, 288706f2543Smrg client, DixAddAccess); 289706f2543Smrg if (rc != Success) 290706f2543Smrg goto unwind; 291706f2543Smrg 292706f2543Smrg if (!IsMaster(newkeybd)) 293706f2543Smrg { 294706f2543Smrg client->errorValue = r->return_keyboard; 295706f2543Smrg rc = BadDevice; 296706f2543Smrg goto unwind; 297706f2543Smrg } 298706f2543Smrg 299706f2543Smrg for (attached = inputInfo.devices; attached; attached = attached->next) 300706f2543Smrg { 301706f2543Smrg if (!IsMaster(attached)) { 302706f2543Smrg if (attached->u.master == ptr) 303706f2543Smrg { 304706f2543Smrg AttachDevice(client, attached, newptr); 305706f2543Smrg flags[attached->id] |= XISlaveAttached; 306706f2543Smrg } 307706f2543Smrg if (attached->u.master == keybd) 308706f2543Smrg { 309706f2543Smrg AttachDevice(client, attached, newkeybd); 310706f2543Smrg flags[attached->id] |= XISlaveAttached; 311706f2543Smrg } 312706f2543Smrg } 313706f2543Smrg } 314706f2543Smrg } 315706f2543Smrg 316706f2543Smrg /* can't disable until we removed pairing */ 317706f2543Smrg keybd->spriteInfo->paired = NULL; 318706f2543Smrg ptr->spriteInfo->paired = NULL; 319706f2543Smrg XTestptr->spriteInfo->paired = NULL; 320706f2543Smrg XTestkeybd->spriteInfo->paired = NULL; 321706f2543Smrg 322706f2543Smrg /* disable the remove the devices, XTest devices must be done first 323706f2543Smrg else the sprites they rely on will be destroyed */ 324706f2543Smrg DisableDevice(XTestptr, FALSE); 325706f2543Smrg DisableDevice(XTestkeybd, FALSE); 326706f2543Smrg DisableDevice(keybd, FALSE); 327706f2543Smrg DisableDevice(ptr, FALSE); 328706f2543Smrg flags[XTestptr->id] |= XIDeviceDisabled | XISlaveDetached; 329706f2543Smrg flags[XTestkeybd->id] |= XIDeviceDisabled | XISlaveDetached; 330706f2543Smrg flags[keybd->id] |= XIDeviceDisabled; 331706f2543Smrg flags[ptr->id] |= XIDeviceDisabled; 332706f2543Smrg 333706f2543Smrg RemoveDevice(XTestptr, FALSE); 334706f2543Smrg RemoveDevice(XTestkeybd, FALSE); 335706f2543Smrg RemoveDevice(keybd, FALSE); 336706f2543Smrg RemoveDevice(ptr, FALSE); 337706f2543Smrg flags[XTestptr->id] |= XISlaveRemoved; 338706f2543Smrg flags[XTestkeybd->id] |= XISlaveRemoved; 339706f2543Smrg flags[keybd->id] |= XIMasterRemoved; 340706f2543Smrg flags[ptr->id] |= XIMasterRemoved; 341706f2543Smrg 342706f2543Smrgunwind: 343706f2543Smrg return rc; 344706f2543Smrg} 345706f2543Smrg 346706f2543Smrgstatic int 347706f2543Smrgdetach_slave(ClientPtr client, xXIDetachSlaveInfo *c, int flags[MAXDEVICES]) 348706f2543Smrg{ 349706f2543Smrg DeviceIntPtr dev; 350706f2543Smrg int rc; 351706f2543Smrg 352706f2543Smrg rc = dixLookupDevice(&dev, c->deviceid, client, DixManageAccess); 353706f2543Smrg if (rc != Success) 354706f2543Smrg goto unwind; 355706f2543Smrg 356706f2543Smrg if (IsMaster(dev)) 357706f2543Smrg { 358706f2543Smrg client->errorValue = c->deviceid; 359706f2543Smrg rc = BadDevice; 360706f2543Smrg goto unwind; 361706f2543Smrg } 362706f2543Smrg 363706f2543Smrg /* Don't allow changes to XTest Devices, these are fixed */ 364706f2543Smrg if (IsXTestDevice(dev, NULL)) 365706f2543Smrg { 366706f2543Smrg client->errorValue = c->deviceid; 367706f2543Smrg rc = BadDevice; 368706f2543Smrg goto unwind; 369706f2543Smrg } 370706f2543Smrg 371706f2543Smrg ReleaseButtonsAndKeys(dev); 372706f2543Smrg AttachDevice(client, dev, NULL); 373706f2543Smrg flags[dev->id] |= XISlaveDetached; 374706f2543Smrg 375706f2543Smrgunwind: 376706f2543Smrg return rc; 377706f2543Smrg} 378706f2543Smrg 379706f2543Smrgstatic int 380706f2543Smrgattach_slave(ClientPtr client, xXIAttachSlaveInfo *c, 381706f2543Smrg int flags[MAXDEVICES]) 382706f2543Smrg{ 383706f2543Smrg DeviceIntPtr dev; 384706f2543Smrg DeviceIntPtr newmaster; 385706f2543Smrg int rc; 386706f2543Smrg 387706f2543Smrg rc = dixLookupDevice(&dev, c->deviceid, client, DixManageAccess); 388706f2543Smrg if (rc != Success) 389706f2543Smrg goto unwind; 390706f2543Smrg 391706f2543Smrg if (IsMaster(dev)) 392706f2543Smrg { 393706f2543Smrg client->errorValue = c->deviceid; 394706f2543Smrg rc = BadDevice; 395706f2543Smrg goto unwind; 396706f2543Smrg } 397706f2543Smrg 398706f2543Smrg /* Don't allow changes to XTest Devices, these are fixed */ 399706f2543Smrg if (IsXTestDevice(dev, NULL)) 400706f2543Smrg { 401706f2543Smrg client->errorValue = c->deviceid; 402706f2543Smrg rc = BadDevice; 403706f2543Smrg goto unwind; 404706f2543Smrg } 405706f2543Smrg 406706f2543Smrg rc = dixLookupDevice(&newmaster, c->new_master, client, DixAddAccess); 407706f2543Smrg if (rc != Success) 408706f2543Smrg goto unwind; 409706f2543Smrg if (!IsMaster(newmaster)) 410706f2543Smrg { 411706f2543Smrg client->errorValue = c->new_master; 412706f2543Smrg rc = BadDevice; 413706f2543Smrg goto unwind; 414706f2543Smrg } 415706f2543Smrg 416706f2543Smrg if (!((IsPointerDevice(newmaster) && IsPointerDevice(dev)) || 417706f2543Smrg (IsKeyboardDevice(newmaster) && IsKeyboardDevice(dev)))) 418706f2543Smrg { 419706f2543Smrg rc = BadDevice; 420706f2543Smrg goto unwind; 421706f2543Smrg } 422706f2543Smrg 423706f2543Smrg ReleaseButtonsAndKeys(dev); 424706f2543Smrg AttachDevice(client, dev, newmaster); 425706f2543Smrg flags[dev->id] |= XISlaveAttached; 426706f2543Smrg 427706f2543Smrgunwind: 428706f2543Smrg return rc; 429706f2543Smrg} 430706f2543Smrg 431706f2543Smrg 432706f2543Smrg 433706f2543Smrg#define SWAPIF(cmd) if (client->swapped) { cmd; } 434706f2543Smrg 435706f2543Smrgint 436706f2543SmrgProcXIChangeHierarchy(ClientPtr client) 437706f2543Smrg{ 438706f2543Smrg xXIAnyHierarchyChangeInfo *any; 439706f2543Smrg size_t len; /* length of data remaining in request */ 440706f2543Smrg char n; 441706f2543Smrg int rc = Success; 442706f2543Smrg int flags[MAXDEVICES] = {0}; 4437b5ab33aSmrg enum { 4447b5ab33aSmrg NO_CHANGE, 4457b5ab33aSmrg FLUSH, 4467b5ab33aSmrg CHANGED, 4477b5ab33aSmrg } changes = NO_CHANGE; 448706f2543Smrg 449706f2543Smrg REQUEST(xXIChangeHierarchyReq); 450706f2543Smrg REQUEST_AT_LEAST_SIZE(xXIChangeHierarchyReq); 451706f2543Smrg 452706f2543Smrg if (!stuff->num_changes) 453706f2543Smrg return rc; 454706f2543Smrg 455706f2543Smrg if (stuff->length > (INT_MAX >> 2)) 456706f2543Smrg return BadAlloc; 45748a68b89Smrg len = (stuff->length << 2) - sizeof(xXIChangeHierarchyReq); 458706f2543Smrg 459706f2543Smrg any = (xXIAnyHierarchyChangeInfo*)&stuff[1]; 460706f2543Smrg while(stuff->num_changes--) 461706f2543Smrg { 462706f2543Smrg if (len < sizeof(xXIAnyHierarchyChangeInfo)) { 463706f2543Smrg rc = BadLength; 464706f2543Smrg goto unwind; 465706f2543Smrg } 466706f2543Smrg 467706f2543Smrg SWAPIF(swapl(&any->type, n)); 468706f2543Smrg SWAPIF(swaps(&any->length, n)); 469706f2543Smrg 470706f2543Smrg if ((any->length > (INT_MAX >> 2)) || (len < (any->length << 2))) 471706f2543Smrg return BadLength; 472706f2543Smrg 473706f2543Smrg#define CHANGE_SIZE_MATCH(type) \ 474706f2543Smrg do { \ 475706f2543Smrg if ((len < sizeof(type)) || (any->length != (sizeof(type) >> 2))) { \ 476706f2543Smrg rc = BadLength; \ 477706f2543Smrg goto unwind; \ 478706f2543Smrg } \ 479706f2543Smrg } while(0) 480706f2543Smrg 481706f2543Smrg switch(any->type) 482706f2543Smrg { 483706f2543Smrg case XIAddMaster: 484706f2543Smrg { 485706f2543Smrg xXIAddMasterInfo* c = (xXIAddMasterInfo*)any; 486706f2543Smrg /* Variable length, due to appended name string */ 487706f2543Smrg if (len < sizeof(xXIAddMasterInfo)) { 488706f2543Smrg rc = BadLength; 489706f2543Smrg goto unwind; 490706f2543Smrg } 491706f2543Smrg SWAPIF(swaps(&c->name_len, n)); 492706f2543Smrg if (c->name_len > (len - sizeof(xXIAddMasterInfo))) { 493706f2543Smrg rc = BadLength; 494706f2543Smrg goto unwind; 495706f2543Smrg } 496706f2543Smrg 497706f2543Smrg rc = add_master(client, c, flags); 498706f2543Smrg if (rc != Success) 499706f2543Smrg goto unwind; 5007b5ab33aSmrg changes = FLUSH; 5017b5ab33aSmrg break; 502706f2543Smrg } 503706f2543Smrg case XIRemoveMaster: 504706f2543Smrg { 505706f2543Smrg xXIRemoveMasterInfo* r = (xXIRemoveMasterInfo*)any; 506706f2543Smrg 507706f2543Smrg CHANGE_SIZE_MATCH(xXIRemoveMasterInfo); 508706f2543Smrg rc = remove_master(client, r, flags); 509706f2543Smrg if (rc != Success) 510706f2543Smrg goto unwind; 5117b5ab33aSmrg changes = FLUSH; 5127b5ab33aSmrg break; 513706f2543Smrg } 514706f2543Smrg case XIDetachSlave: 515706f2543Smrg { 516706f2543Smrg xXIDetachSlaveInfo* c = (xXIDetachSlaveInfo*)any; 517706f2543Smrg 518706f2543Smrg CHANGE_SIZE_MATCH(xXIDetachSlaveInfo); 519706f2543Smrg rc = detach_slave(client, c, flags); 520706f2543Smrg if (rc != Success) 521706f2543Smrg goto unwind; 5227b5ab33aSmrg changes = CHANGED; 5237b5ab33aSmrg break; 524706f2543Smrg } 525706f2543Smrg case XIAttachSlave: 526706f2543Smrg { 527706f2543Smrg xXIAttachSlaveInfo* c = (xXIAttachSlaveInfo*)any; 528706f2543Smrg 529706f2543Smrg CHANGE_SIZE_MATCH(xXIAttachSlaveInfo); 530706f2543Smrg rc = attach_slave(client, c, flags); 531706f2543Smrg if (rc != Success) 532706f2543Smrg goto unwind; 5337b5ab33aSmrg changes = CHANGED; 5347b5ab33aSmrg break; 535706f2543Smrg } 5367b5ab33aSmrg default: 537706f2543Smrg break; 538706f2543Smrg } 539706f2543Smrg 5407b5ab33aSmrg if (changes == FLUSH) { 5417b5ab33aSmrg XISendDeviceHierarchyEvent(flags); 5427b5ab33aSmrg memset(flags, 0, sizeof(flags)); 5437b5ab33aSmrg changes = NO_CHANGE; 5447b5ab33aSmrg } 5457b5ab33aSmrg 546706f2543Smrg len -= any->length * 4; 547706f2543Smrg any = (xXIAnyHierarchyChangeInfo*)((char*)any + any->length * 4); 548706f2543Smrg } 549706f2543Smrg 550706f2543Smrgunwind: 551706f2543Smrg 5527b5ab33aSmrg if (changes != NO_CHANGE) 5537b5ab33aSmrg XISendDeviceHierarchyEvent(flags); 554706f2543Smrg return rc; 555706f2543Smrg} 556706f2543Smrg 557