1706f2543Smrg/* 2706f2543Smrg 3706f2543SmrgCopyright 1987, 1998 The Open Group 4706f2543Smrg 5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its 6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that 7706f2543Smrgthe above copyright notice appear in all copies and that both that 8706f2543Smrgcopyright notice and this permission notice appear in supporting 9706f2543Smrgdocumentation. 10706f2543Smrg 11706f2543SmrgThe above copyright notice and this permission notice shall be included 12706f2543Smrgin all copies or substantial portions of the Software. 13706f2543Smrg 14706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15706f2543SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16706f2543SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17706f2543SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18706f2543SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19706f2543SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20706f2543SmrgOTHER DEALINGS IN THE SOFTWARE. 21706f2543Smrg 22706f2543SmrgExcept as contained in this notice, the name of The Open Group shall 23706f2543Smrgnot be used in advertising or otherwise to promote the sale, use or 24706f2543Smrgother dealings in this Software without prior written authorization 25706f2543Smrgfrom The Open Group. 26706f2543Smrg 27706f2543Smrg 28706f2543SmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, 29706f2543Smrg 30706f2543Smrg All Rights Reserved 31706f2543Smrg 32706f2543SmrgPermission to use, copy, modify, and distribute this software and its 33706f2543Smrgdocumentation for any purpose and without fee is hereby granted, 34706f2543Smrgprovided that the above copyright notice appear in all copies and that 35706f2543Smrgboth that copyright notice and this permission notice appear in 36706f2543Smrgsupporting documentation, and that the name of Digital not be 37706f2543Smrgused in advertising or publicity pertaining to distribution of the 38706f2543Smrgsoftware without specific, written prior permission. 39706f2543SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 40706f2543SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 41706f2543SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 42706f2543SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 43706f2543SmrgWHETHER IN AN action OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 44706f2543SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 45706f2543SmrgSOFTWARE. 46706f2543Smrg 47706f2543Smrg*/ 48706f2543Smrg 49706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 50706f2543Smrg#include <dix-config.h> 51706f2543Smrg#endif 52706f2543Smrg 53706f2543Smrg#include <X11/X.h> 54706f2543Smrg#include "misc.h" 55706f2543Smrg#include <X11/Xproto.h> 56706f2543Smrg#include <X11/extensions/XI2.h> 57706f2543Smrg#include "windowstr.h" 58706f2543Smrg#include "inputstr.h" 59706f2543Smrg#include "cursorstr.h" 60706f2543Smrg#include "dixgrabs.h" 61706f2543Smrg#include "xace.h" 62706f2543Smrg#include "exevents.h" 63706f2543Smrg 64706f2543Smrg#define BITMASK(i) (((Mask)1) << ((i) & 31)) 65706f2543Smrg#define MASKIDX(i) ((i) >> 5) 66706f2543Smrg#define MASKWORD(buf, i) buf[MASKIDX(i)] 67706f2543Smrg#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) 68706f2543Smrg#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) 69706f2543Smrg#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) 70706f2543Smrg 71706f2543SmrgGrabPtr 72706f2543SmrgCreateGrab( 73706f2543Smrg int client, 74706f2543Smrg DeviceIntPtr device, 75706f2543Smrg DeviceIntPtr modDevice, 76706f2543Smrg WindowPtr window, 77706f2543Smrg GrabType grabtype, 78706f2543Smrg GrabMask *mask, 79706f2543Smrg GrabParameters *param, 80706f2543Smrg int type, 81706f2543Smrg KeyCode keybut, /* key or button */ 82706f2543Smrg WindowPtr confineTo, 83706f2543Smrg CursorPtr cursor) 84706f2543Smrg{ 85706f2543Smrg GrabPtr grab; 86706f2543Smrg 87706f2543Smrg grab = calloc(1, sizeof(GrabRec)); 88706f2543Smrg if (!grab) 89706f2543Smrg return (GrabPtr)NULL; 90706f2543Smrg grab->resource = FakeClientID(client); 91706f2543Smrg grab->device = device; 92706f2543Smrg grab->window = window; 93706f2543Smrg grab->eventMask = mask->core; /* same for XI */ 94706f2543Smrg grab->deviceMask = 0; 95706f2543Smrg grab->ownerEvents = param->ownerEvents; 96706f2543Smrg grab->keyboardMode = param->this_device_mode; 97706f2543Smrg grab->pointerMode = param->other_devices_mode; 98706f2543Smrg grab->modifiersDetail.exact = param->modifiers; 99706f2543Smrg grab->modifiersDetail.pMask = NULL; 100706f2543Smrg grab->modifierDevice = modDevice; 101706f2543Smrg grab->type = type; 102706f2543Smrg grab->grabtype = grabtype; 103706f2543Smrg grab->detail.exact = keybut; 104706f2543Smrg grab->detail.pMask = NULL; 105706f2543Smrg grab->confineTo = confineTo; 106706f2543Smrg grab->cursor = cursor; 107706f2543Smrg grab->next = NULL; 108706f2543Smrg 109706f2543Smrg if (grabtype == GRABTYPE_XI2) 110706f2543Smrg memcpy(grab->xi2mask, mask->xi2mask, sizeof(mask->xi2mask)); 111706f2543Smrg if (cursor) 112706f2543Smrg cursor->refcnt++; 113706f2543Smrg return grab; 114706f2543Smrg 115706f2543Smrg} 116706f2543Smrg 117706f2543Smrgstatic void 118706f2543SmrgFreeGrab(GrabPtr pGrab) 119706f2543Smrg{ 120706f2543Smrg free(pGrab->modifiersDetail.pMask); 121706f2543Smrg free(pGrab->detail.pMask); 122706f2543Smrg 123706f2543Smrg if (pGrab->cursor) 124706f2543Smrg FreeCursor(pGrab->cursor, (Cursor)0); 125706f2543Smrg 126706f2543Smrg free(pGrab); 127706f2543Smrg} 128706f2543Smrg 129706f2543Smrgint 130706f2543SmrgDeletePassiveGrab(pointer value, XID id) 131706f2543Smrg{ 132706f2543Smrg GrabPtr g, prev; 133706f2543Smrg GrabPtr pGrab = (GrabPtr)value; 134706f2543Smrg 135706f2543Smrg /* it is OK if the grab isn't found */ 136706f2543Smrg prev = 0; 137706f2543Smrg for (g = (wPassiveGrabs (pGrab->window)); g; g = g->next) 138706f2543Smrg { 139706f2543Smrg if (pGrab == g) 140706f2543Smrg { 141706f2543Smrg if (prev) 142706f2543Smrg prev->next = g->next; 143706f2543Smrg else 144706f2543Smrg if (!(pGrab->window->optional->passiveGrabs = g->next)) 145706f2543Smrg CheckWindowOptionalNeed (pGrab->window); 146706f2543Smrg break; 147706f2543Smrg } 148706f2543Smrg prev = g; 149706f2543Smrg } 150706f2543Smrg FreeGrab(pGrab); 151706f2543Smrg return Success; 152706f2543Smrg} 153706f2543Smrg 154706f2543Smrgstatic Mask * 155706f2543SmrgDeleteDetailFromMask(Mask *pDetailMask, unsigned int detail) 156706f2543Smrg{ 157706f2543Smrg Mask *mask; 158706f2543Smrg int i; 159706f2543Smrg 160706f2543Smrg mask = malloc(sizeof(Mask) * MasksPerDetailMask); 161706f2543Smrg if (mask) 162706f2543Smrg { 163706f2543Smrg if (pDetailMask) 164706f2543Smrg for (i = 0; i < MasksPerDetailMask; i++) 165706f2543Smrg mask[i]= pDetailMask[i]; 166706f2543Smrg else 167706f2543Smrg for (i = 0; i < MasksPerDetailMask; i++) 168706f2543Smrg mask[i]= ~0L; 169706f2543Smrg BITCLEAR(mask, detail); 170706f2543Smrg } 171706f2543Smrg return mask; 172706f2543Smrg} 173706f2543Smrg 174706f2543Smrgstatic Bool 175706f2543SmrgIsInGrabMask( 176706f2543Smrg DetailRec firstDetail, 177706f2543Smrg DetailRec secondDetail, 178706f2543Smrg unsigned int exception) 179706f2543Smrg{ 180706f2543Smrg if (firstDetail.exact == exception) 181706f2543Smrg { 182706f2543Smrg if (firstDetail.pMask == NULL) 183706f2543Smrg return TRUE; 184706f2543Smrg 185706f2543Smrg /* (at present) never called with two non-null pMasks */ 186706f2543Smrg if (secondDetail.exact == exception) 187706f2543Smrg return FALSE; 188706f2543Smrg 189706f2543Smrg if (GETBIT(firstDetail.pMask, secondDetail.exact)) 190706f2543Smrg return TRUE; 191706f2543Smrg } 192706f2543Smrg 193706f2543Smrg return FALSE; 194706f2543Smrg} 195706f2543Smrg 196706f2543Smrgstatic Bool 197706f2543SmrgIdenticalExactDetails( 198706f2543Smrg unsigned int firstExact, 199706f2543Smrg unsigned int secondExact, 200706f2543Smrg unsigned int exception) 201706f2543Smrg{ 202706f2543Smrg if ((firstExact == exception) || (secondExact == exception)) 203706f2543Smrg return FALSE; 204706f2543Smrg 205706f2543Smrg if (firstExact == secondExact) 206706f2543Smrg return TRUE; 207706f2543Smrg 208706f2543Smrg return FALSE; 209706f2543Smrg} 210706f2543Smrg 211706f2543Smrgstatic Bool 212706f2543SmrgDetailSupersedesSecond( 213706f2543Smrg DetailRec firstDetail, 214706f2543Smrg DetailRec secondDetail, 215706f2543Smrg unsigned int exception) 216706f2543Smrg{ 217706f2543Smrg if (IsInGrabMask(firstDetail, secondDetail, exception)) 218706f2543Smrg return TRUE; 219706f2543Smrg 220706f2543Smrg if (IdenticalExactDetails(firstDetail.exact, secondDetail.exact, 221706f2543Smrg exception)) 222706f2543Smrg return TRUE; 223706f2543Smrg 224706f2543Smrg return FALSE; 225706f2543Smrg} 226706f2543Smrg 227706f2543Smrgstatic Bool 228706f2543SmrgGrabSupersedesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab) 229706f2543Smrg{ 230706f2543Smrg unsigned int any_modifier = (pFirstGrab->grabtype == GRABTYPE_XI2) ? 231706f2543Smrg (unsigned int)XIAnyModifier : 232706f2543Smrg (unsigned int)AnyModifier; 233706f2543Smrg if (!DetailSupersedesSecond(pFirstGrab->modifiersDetail, 234706f2543Smrg pSecondGrab->modifiersDetail, 235706f2543Smrg any_modifier)) 236706f2543Smrg return FALSE; 237706f2543Smrg 238706f2543Smrg if (DetailSupersedesSecond(pFirstGrab->detail, 239706f2543Smrg pSecondGrab->detail, (unsigned int)AnyKey)) 240706f2543Smrg return TRUE; 241706f2543Smrg 242706f2543Smrg return FALSE; 243706f2543Smrg} 244706f2543Smrg 245706f2543Smrg/** 246706f2543Smrg * Compares two grabs and returns TRUE if the first grab matches the second 247706f2543Smrg * grab. 248706f2543Smrg * 249706f2543Smrg * A match is when 250706f2543Smrg * - the devices set for the grab are equal (this is optional). 251706f2543Smrg * - the event types for both grabs are equal. 252706f2543Smrg * - XXX 253706f2543Smrg * 254706f2543Smrg * @param ignoreDevice TRUE if the device settings on the grabs are to be 255706f2543Smrg * ignored. 256706f2543Smrg * @return TRUE if the grabs match or FALSE otherwise. 257706f2543Smrg */ 258706f2543SmrgBool 259706f2543SmrgGrabMatchesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab, Bool ignoreDevice) 260706f2543Smrg{ 261706f2543Smrg unsigned int any_modifier = (pFirstGrab->grabtype == GRABTYPE_XI2) ? 262706f2543Smrg (unsigned int)XIAnyModifier : 263706f2543Smrg (unsigned int)AnyModifier; 264706f2543Smrg 265706f2543Smrg if (pFirstGrab->grabtype != pSecondGrab->grabtype) 266706f2543Smrg return FALSE; 267706f2543Smrg 268706f2543Smrg if (pFirstGrab->grabtype == GRABTYPE_XI2) 269706f2543Smrg { 270706f2543Smrg if (pFirstGrab->device == inputInfo.all_devices || 271706f2543Smrg pSecondGrab->device == inputInfo.all_devices) 272706f2543Smrg { 273706f2543Smrg /* do nothing */ 274706f2543Smrg } else if (pFirstGrab->device == inputInfo.all_master_devices) 275706f2543Smrg { 276706f2543Smrg if (pSecondGrab->device != inputInfo.all_master_devices && 277706f2543Smrg !IsMaster(pSecondGrab->device)) 278706f2543Smrg return FALSE; 279706f2543Smrg } else if (pSecondGrab->device == inputInfo.all_master_devices) 280706f2543Smrg { 281706f2543Smrg if (pFirstGrab->device != inputInfo.all_master_devices && 282706f2543Smrg !IsMaster(pFirstGrab->device)) 283706f2543Smrg return FALSE; 284706f2543Smrg } else if (pSecondGrab->device != pFirstGrab->device) 285706f2543Smrg return FALSE; 286706f2543Smrg } else if (!ignoreDevice && 287706f2543Smrg ((pFirstGrab->device != pSecondGrab->device) || 288706f2543Smrg (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice))) 289706f2543Smrg return FALSE; 290706f2543Smrg 291706f2543Smrg if (pFirstGrab->type != pSecondGrab->type) 292706f2543Smrg return FALSE; 293706f2543Smrg 294706f2543Smrg if (GrabSupersedesSecond(pFirstGrab, pSecondGrab) || 295706f2543Smrg GrabSupersedesSecond(pSecondGrab, pFirstGrab)) 296706f2543Smrg return TRUE; 297706f2543Smrg 298706f2543Smrg if (DetailSupersedesSecond(pSecondGrab->detail, pFirstGrab->detail, 299706f2543Smrg (unsigned int)AnyKey) 300706f2543Smrg && 301706f2543Smrg DetailSupersedesSecond(pFirstGrab->modifiersDetail, 302706f2543Smrg pSecondGrab->modifiersDetail, 303706f2543Smrg any_modifier)) 304706f2543Smrg return TRUE; 305706f2543Smrg 306706f2543Smrg if (DetailSupersedesSecond(pFirstGrab->detail, pSecondGrab->detail, 307706f2543Smrg (unsigned int)AnyKey) 308706f2543Smrg && 309706f2543Smrg DetailSupersedesSecond(pSecondGrab->modifiersDetail, 310706f2543Smrg pFirstGrab->modifiersDetail, 311706f2543Smrg any_modifier)) 312706f2543Smrg return TRUE; 313706f2543Smrg 314706f2543Smrg return FALSE; 315706f2543Smrg} 316706f2543Smrg 317706f2543Smrgstatic Bool 318706f2543SmrgGrabsAreIdentical(GrabPtr pFirstGrab, GrabPtr pSecondGrab) 319706f2543Smrg{ 320706f2543Smrg unsigned int any_modifier = (pFirstGrab->grabtype == GRABTYPE_XI2) ? 321706f2543Smrg (unsigned int)XIAnyModifier : 322706f2543Smrg (unsigned int)AnyModifier; 323706f2543Smrg 324706f2543Smrg if (pFirstGrab->grabtype != pSecondGrab->grabtype) 325706f2543Smrg return FALSE; 326706f2543Smrg 327706f2543Smrg if (pFirstGrab->device != pSecondGrab->device || 328706f2543Smrg (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice) || 329706f2543Smrg (pFirstGrab->type != pSecondGrab->type)) 330706f2543Smrg return FALSE; 331706f2543Smrg 332706f2543Smrg if (!(DetailSupersedesSecond(pFirstGrab->detail, 333706f2543Smrg pSecondGrab->detail, 334706f2543Smrg (unsigned int)AnyKey) && 335706f2543Smrg DetailSupersedesSecond(pSecondGrab->detail, 336706f2543Smrg pFirstGrab->detail, 337706f2543Smrg (unsigned int)AnyKey))) 338706f2543Smrg return FALSE; 339706f2543Smrg 340706f2543Smrg 341706f2543Smrg if (!(DetailSupersedesSecond(pFirstGrab->modifiersDetail, 342706f2543Smrg pSecondGrab->modifiersDetail, 343706f2543Smrg any_modifier) && 344706f2543Smrg DetailSupersedesSecond(pSecondGrab->modifiersDetail, 345706f2543Smrg pFirstGrab->modifiersDetail, 346706f2543Smrg any_modifier))) 347706f2543Smrg return FALSE; 348706f2543Smrg 349706f2543Smrg return TRUE; 350706f2543Smrg} 351706f2543Smrg 352706f2543Smrg 353706f2543Smrg/** 354706f2543Smrg * Prepend the new grab to the list of passive grabs on the window. 355706f2543Smrg * Any previously existing grab that matches the new grab will be removed. 356706f2543Smrg * Adding a new grab that would override another client's grab will result in 357706f2543Smrg * a BadAccess. 358706f2543Smrg * 359706f2543Smrg * @return Success or X error code on failure. 360706f2543Smrg */ 361706f2543Smrgint 362706f2543SmrgAddPassiveGrabToList(ClientPtr client, GrabPtr pGrab) 363706f2543Smrg{ 364706f2543Smrg GrabPtr grab; 365706f2543Smrg Mask access_mode = DixGrabAccess; 366706f2543Smrg int rc; 367706f2543Smrg 368706f2543Smrg for (grab = wPassiveGrabs(pGrab->window); grab; grab = grab->next) 369706f2543Smrg { 370706f2543Smrg if (GrabMatchesSecond(pGrab, grab, FALSE)) 371706f2543Smrg { 372706f2543Smrg if (CLIENT_BITS(pGrab->resource) != CLIENT_BITS(grab->resource)) 373706f2543Smrg { 374706f2543Smrg FreeGrab(pGrab); 375706f2543Smrg return BadAccess; 376706f2543Smrg } 377706f2543Smrg } 378706f2543Smrg } 379706f2543Smrg 380706f2543Smrg if (pGrab->keyboardMode == GrabModeSync||pGrab->pointerMode == GrabModeSync) 381706f2543Smrg access_mode |= DixFreezeAccess; 382706f2543Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, pGrab->device, access_mode); 383706f2543Smrg if (rc != Success) 384706f2543Smrg return rc; 385706f2543Smrg 386706f2543Smrg /* Remove all grabs that match the new one exactly */ 387706f2543Smrg for (grab = wPassiveGrabs(pGrab->window); grab; grab = grab->next) 388706f2543Smrg { 389706f2543Smrg if (GrabsAreIdentical(pGrab, grab)) 390706f2543Smrg { 391706f2543Smrg DeletePassiveGrabFromList(grab); 392706f2543Smrg break; 393706f2543Smrg } 394706f2543Smrg } 395706f2543Smrg 396706f2543Smrg if (!pGrab->window->optional && !MakeWindowOptional (pGrab->window)) 397706f2543Smrg { 398706f2543Smrg FreeGrab(pGrab); 399706f2543Smrg return BadAlloc; 400706f2543Smrg } 401706f2543Smrg 402706f2543Smrg pGrab->next = pGrab->window->optional->passiveGrabs; 403706f2543Smrg pGrab->window->optional->passiveGrabs = pGrab; 404706f2543Smrg if (AddResource(pGrab->resource, RT_PASSIVEGRAB, (pointer)pGrab)) 405706f2543Smrg return Success; 406706f2543Smrg return BadAlloc; 407706f2543Smrg} 408706f2543Smrg 409706f2543Smrg/* the following is kinda complicated, because we need to be able to back out 410706f2543Smrg * if any allocation fails 411706f2543Smrg */ 412706f2543Smrg 413706f2543SmrgBool 414706f2543SmrgDeletePassiveGrabFromList(GrabPtr pMinuendGrab) 415706f2543Smrg{ 416706f2543Smrg GrabPtr grab; 417706f2543Smrg GrabPtr *deletes, *adds; 418706f2543Smrg Mask ***updates, **details; 419706f2543Smrg int i, ndels, nadds, nups; 420706f2543Smrg Bool ok; 421706f2543Smrg unsigned int any_modifier; 422706f2543Smrg unsigned int any_key; 423706f2543Smrg 424706f2543Smrg#define UPDATE(mask,exact) \ 425706f2543Smrg if (!(details[nups] = DeleteDetailFromMask(mask, exact))) \ 426706f2543Smrg ok = FALSE; \ 427706f2543Smrg else \ 428706f2543Smrg updates[nups++] = &(mask) 429706f2543Smrg 430706f2543Smrg i = 0; 431706f2543Smrg for (grab = wPassiveGrabs(pMinuendGrab->window); grab; grab = grab->next) 432706f2543Smrg i++; 433706f2543Smrg if (!i) 434706f2543Smrg return TRUE; 435706f2543Smrg deletes = malloc(i * sizeof(GrabPtr)); 436706f2543Smrg adds = malloc(i * sizeof(GrabPtr)); 437706f2543Smrg updates = malloc(i * sizeof(Mask **)); 438706f2543Smrg details = malloc(i * sizeof(Mask *)); 439706f2543Smrg if (!deletes || !adds || !updates || !details) 440706f2543Smrg { 441706f2543Smrg free(details); 442706f2543Smrg free(updates); 443706f2543Smrg free(adds); 444706f2543Smrg free(deletes); 445706f2543Smrg return FALSE; 446706f2543Smrg } 447706f2543Smrg 448706f2543Smrg any_modifier = (pMinuendGrab->grabtype == GRABTYPE_XI2) ? 449706f2543Smrg (unsigned int)XIAnyModifier : (unsigned int)AnyModifier; 450706f2543Smrg any_key = (pMinuendGrab->grabtype == GRABTYPE_XI2) ? 451706f2543Smrg (unsigned int)XIAnyKeycode : (unsigned int)AnyKey; 452706f2543Smrg ndels = nadds = nups = 0; 453706f2543Smrg ok = TRUE; 454706f2543Smrg for (grab = wPassiveGrabs(pMinuendGrab->window); 455706f2543Smrg grab && ok; 456706f2543Smrg grab = grab->next) 457706f2543Smrg { 458706f2543Smrg if ((CLIENT_BITS(grab->resource) != CLIENT_BITS(pMinuendGrab->resource)) || 459706f2543Smrg !GrabMatchesSecond(grab, pMinuendGrab, 460706f2543Smrg (grab->grabtype == GRABTYPE_CORE))) 461706f2543Smrg continue; 462706f2543Smrg if (GrabSupersedesSecond(pMinuendGrab, grab)) 463706f2543Smrg { 464706f2543Smrg deletes[ndels++] = grab; 465706f2543Smrg } 466706f2543Smrg else if ((grab->detail.exact == any_key) 467706f2543Smrg && (grab->modifiersDetail.exact != any_modifier)) 468706f2543Smrg { 469706f2543Smrg UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact); 470706f2543Smrg } 471706f2543Smrg else if ((grab->modifiersDetail.exact == any_modifier) 472706f2543Smrg && (grab->detail.exact != any_key)) 473706f2543Smrg { 474706f2543Smrg UPDATE(grab->modifiersDetail.pMask, 475706f2543Smrg pMinuendGrab->modifiersDetail.exact); 476706f2543Smrg } 477706f2543Smrg else if ((pMinuendGrab->detail.exact != any_key) 478706f2543Smrg && (pMinuendGrab->modifiersDetail.exact != any_modifier)) 479706f2543Smrg { 480706f2543Smrg GrabPtr pNewGrab; 481706f2543Smrg GrabParameters param; 482706f2543Smrg 483706f2543Smrg UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact); 484706f2543Smrg 485706f2543Smrg memset(¶m, 0, sizeof(param)); 486706f2543Smrg param.ownerEvents = grab->ownerEvents; 487706f2543Smrg param.this_device_mode = grab->keyboardMode; 488706f2543Smrg param.other_devices_mode = grab->pointerMode; 489706f2543Smrg param.modifiers = any_modifier; 490706f2543Smrg 491706f2543Smrg pNewGrab = CreateGrab(CLIENT_ID(grab->resource), grab->device, 492706f2543Smrg grab->modifierDevice, grab->window, 493706f2543Smrg grab->grabtype, 494706f2543Smrg (GrabMask*)&grab->eventMask, 495706f2543Smrg ¶m, (int)grab->type, 496706f2543Smrg pMinuendGrab->detail.exact, 497706f2543Smrg grab->confineTo, grab->cursor); 498706f2543Smrg if (!pNewGrab) 499706f2543Smrg ok = FALSE; 500706f2543Smrg else if (!(pNewGrab->modifiersDetail.pMask = 501706f2543Smrg DeleteDetailFromMask(grab->modifiersDetail.pMask, 502706f2543Smrg pMinuendGrab->modifiersDetail.exact)) 503706f2543Smrg || 504706f2543Smrg (!pNewGrab->window->optional && 505706f2543Smrg !MakeWindowOptional(pNewGrab->window))) 506706f2543Smrg { 507706f2543Smrg FreeGrab(pNewGrab); 508706f2543Smrg ok = FALSE; 509706f2543Smrg } 510706f2543Smrg else if (!AddResource(pNewGrab->resource, RT_PASSIVEGRAB, 511706f2543Smrg (pointer)pNewGrab)) 512706f2543Smrg ok = FALSE; 513706f2543Smrg else 514706f2543Smrg adds[nadds++] = pNewGrab; 515706f2543Smrg } 516706f2543Smrg else if (pMinuendGrab->detail.exact == any_key) 517706f2543Smrg { 518706f2543Smrg UPDATE(grab->modifiersDetail.pMask, 519706f2543Smrg pMinuendGrab->modifiersDetail.exact); 520706f2543Smrg } 521706f2543Smrg else 522706f2543Smrg { 523706f2543Smrg UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact); 524706f2543Smrg } 525706f2543Smrg } 526706f2543Smrg 527706f2543Smrg if (!ok) 528706f2543Smrg { 529706f2543Smrg for (i = 0; i < nadds; i++) 530706f2543Smrg FreeResource(adds[i]->resource, RT_NONE); 531706f2543Smrg for (i = 0; i < nups; i++) 532706f2543Smrg free(details[i]); 533706f2543Smrg } 534706f2543Smrg else 535706f2543Smrg { 536706f2543Smrg for (i = 0; i < ndels; i++) 537706f2543Smrg FreeResource(deletes[i]->resource, RT_NONE); 538706f2543Smrg for (i = 0; i < nadds; i++) 539706f2543Smrg { 540706f2543Smrg grab = adds[i]; 541706f2543Smrg grab->next = grab->window->optional->passiveGrabs; 542706f2543Smrg grab->window->optional->passiveGrabs = grab; 543706f2543Smrg } 544706f2543Smrg for (i = 0; i < nups; i++) 545706f2543Smrg { 546706f2543Smrg free(*updates[i]); 547706f2543Smrg *updates[i] = details[i]; 548706f2543Smrg } 549706f2543Smrg } 550706f2543Smrg free(details); 551706f2543Smrg free(updates); 552706f2543Smrg free(adds); 553706f2543Smrg free(deletes); 554706f2543Smrg return ok; 555706f2543Smrg 556706f2543Smrg#undef UPDATE 557706f2543Smrg} 558