PassivGrab.c revision 0568f49b
11477040fSmrg/* 21477040fSmrg 3249c3046SmrgCopyright (c) 1993, Oracle and/or its affiliates. All rights reserved. 41477040fSmrg 51477040fSmrgPermission is hereby granted, free of charge, to any person obtaining a 61477040fSmrgcopy of this software and associated documentation files (the "Software"), 71477040fSmrgto deal in the Software without restriction, including without limitation 81477040fSmrgthe rights to use, copy, modify, merge, publish, distribute, sublicense, 91477040fSmrgand/or sell copies of the Software, and to permit persons to whom the 101477040fSmrgSoftware is furnished to do so, subject to the following conditions: 111477040fSmrg 121477040fSmrgThe above copyright notice and this permission notice (including the next 131477040fSmrgparagraph) shall be included in all copies or substantial portions of the 141477040fSmrgSoftware. 15444c061aSmrg 161477040fSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 171477040fSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 181477040fSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 191477040fSmrgTHE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 201477040fSmrgLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 211477040fSmrgFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 221477040fSmrgDEALINGS IN THE SOFTWARE. 231477040fSmrg 241477040fSmrg*/ 25444c061aSmrg/******************************************************** 26444c061aSmrg 27444c061aSmrgCopyright 1988 by Hewlett-Packard Company 28444c061aSmrgCopyright 1987, 1988, 1989,1990 by Digital Equipment Corporation, Maynard, Massachusetts 29444c061aSmrg 30444c061aSmrgPermission to use, copy, modify, and distribute this software 31444c061aSmrgand its documentation for any purpose and without fee is hereby 32444c061aSmrggranted, provided that the above copyright notice appear in all 33444c061aSmrgcopies and that both that copyright notice and this permission 34444c061aSmrgnotice appear in supporting documentation, and that the names of 351477040fSmrgHewlett-Packard or Digital not be used in advertising or 36444c061aSmrgpublicity pertaining to distribution of the software without specific, 37444c061aSmrgwritten prior permission. 38444c061aSmrg 39444c061aSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 40444c061aSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 41444c061aSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 42444c061aSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 43444c061aSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 44444c061aSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 45444c061aSmrgSOFTWARE. 46444c061aSmrg 47444c061aSmrg********************************************************/ 48444c061aSmrg 49444c061aSmrg/* 50444c061aSmrg 51444c061aSmrgCopyright 1987, 1988, 1989, 1990, 1994, 1998 The Open Group 52444c061aSmrg 53444c061aSmrgPermission to use, copy, modify, distribute, and sell this software and its 54444c061aSmrgdocumentation for any purpose is hereby granted without fee, provided that 55444c061aSmrgthe above copyright notice appear in all copies and that both that 56444c061aSmrgcopyright notice and this permission notice appear in supporting 57444c061aSmrgdocumentation. 58444c061aSmrg 59444c061aSmrgThe above copyright notice and this permission notice shall be included in 60444c061aSmrgall copies or substantial portions of the Software. 61444c061aSmrg 62444c061aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 63444c061aSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 64444c061aSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 65444c061aSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 66444c061aSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 67444c061aSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 68444c061aSmrg 69444c061aSmrgExcept as contained in this notice, the name of The Open Group shall not be 70444c061aSmrgused in advertising or otherwise to promote the sale, use or other dealings 71444c061aSmrgin this Software without prior written authorization from The Open Group. 72444c061aSmrg 73444c061aSmrg*/ 74444c061aSmrg 75444c061aSmrg#ifdef HAVE_CONFIG_H 76444c061aSmrg#include <config.h> 77444c061aSmrg#endif 78444c061aSmrg#include "IntrinsicI.h" 79444c061aSmrg#include "StringDefs.h" 80444c061aSmrg#include "PassivGraI.h" 81444c061aSmrg 82444c061aSmrg/* typedef unsigned long Mask; */ 83444c061aSmrg#define BITMASK(i) (((Mask)1) << ((i) & 31)) 84444c061aSmrg#define MASKIDX(i) ((i) >> 5) 85444c061aSmrg#define MASKWORD(buf, i) buf[MASKIDX(i)] 86444c061aSmrg#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) 87444c061aSmrg#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) 88444c061aSmrg#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) 89444c061aSmrg#define MasksPerDetailMask 8 90444c061aSmrg 91444c061aSmrg#define pDisplay(grabPtr) (((grabPtr)->widget)->core.screen->display) 92444c061aSmrg#define pWindow(grabPtr) (((grabPtr)->widget)->core.window) 93444c061aSmrg 94444c061aSmrg 95444c061aSmrg/***************************************************************************/ 96444c061aSmrg/*********************** Internal Support Routines *************************/ 97444c061aSmrg/***************************************************************************/ 98444c061aSmrg 99444c061aSmrg/* 100444c061aSmrg * Turn off (clear) the bit in the specified detail mask which is associated 101444c061aSmrg * with the detail. 102444c061aSmrg */ 103444c061aSmrg 104444c061aSmrgstatic void DeleteDetailFromMask( 105444c061aSmrg Mask **ppDetailMask, 106444c061aSmrg unsigned short detail) 107444c061aSmrg{ 108444c061aSmrg Mask *pDetailMask = *ppDetailMask; 109444c061aSmrg 110444c061aSmrg if (!pDetailMask) { 111444c061aSmrg int i; 112444c061aSmrg pDetailMask = (Mask *)__XtMalloc(sizeof(Mask) * MasksPerDetailMask); 113444c061aSmrg for (i = MasksPerDetailMask; --i >= 0; ) 1140568f49bSmrg pDetailMask[i] = (unsigned long) (~0); 115444c061aSmrg *ppDetailMask = pDetailMask; 116444c061aSmrg } 117444c061aSmrg BITCLEAR((pDetailMask), detail); 118444c061aSmrg} 119444c061aSmrg 120444c061aSmrg 121444c061aSmrg/* 122444c061aSmrg * Make an exact copy of the specified detail mask. 123444c061aSmrg */ 124444c061aSmrg 125444c061aSmrgstatic Mask *CopyDetailMask( 126444c061aSmrg Mask *pOriginalDetailMask) 127444c061aSmrg{ 128444c061aSmrg Mask *pTempMask; 129444c061aSmrg int i; 130444c061aSmrg 131444c061aSmrg if (!pOriginalDetailMask) 132444c061aSmrg return NULL; 133444c061aSmrg 134444c061aSmrg pTempMask = (Mask *)__XtMalloc(sizeof(Mask) * MasksPerDetailMask); 135444c061aSmrg 136444c061aSmrg for ( i = 0; i < MasksPerDetailMask; i++) 137444c061aSmrg pTempMask[i]= pOriginalDetailMask[i]; 138444c061aSmrg 139444c061aSmrg return pTempMask; 140444c061aSmrg} 141444c061aSmrg 142444c061aSmrg 143444c061aSmrg/* 144444c061aSmrg * Allocate a new grab entry, and fill in all of the fields using the 145444c061aSmrg * specified parameters. 146444c061aSmrg */ 147444c061aSmrg 148444c061aSmrgstatic XtServerGrabPtr CreateGrab( 149444c061aSmrg Widget widget, 150444c061aSmrg Boolean ownerEvents, 151444c061aSmrg Modifiers modifiers, 152444c061aSmrg KeyCode keybut, 153444c061aSmrg int pointer_mode, 154444c061aSmrg int keyboard_mode, 155444c061aSmrg Mask event_mask, 156444c061aSmrg Window confine_to, 157444c061aSmrg Cursor cursor, 158444c061aSmrg Boolean need_ext) 159444c061aSmrg{ 160444c061aSmrg XtServerGrabPtr grab; 161444c061aSmrg 162444c061aSmrg if (confine_to || cursor) 163444c061aSmrg need_ext = True; 164444c061aSmrg grab = (XtServerGrabPtr)__XtMalloc(sizeof(XtServerGrabRec) + 165444c061aSmrg (need_ext ? sizeof(XtServerGrabExtRec) 166444c061aSmrg : 0)); 167444c061aSmrg grab->next = NULL; 168444c061aSmrg grab->widget = widget; 1690568f49bSmrg XtSetBit(grab->ownerEvents, ownerEvents); 1700568f49bSmrg XtSetBit(grab->pointerMode, pointer_mode); 1710568f49bSmrg XtSetBit(grab->keyboardMode, keyboard_mode); 1720568f49bSmrg grab->eventMask = (unsigned short)event_mask; 1730568f49bSmrg XtSetBit(grab->hasExt, need_ext); 174444c061aSmrg grab->confineToIsWidgetWin = (XtWindow (widget) == confine_to); 1750568f49bSmrg grab->modifiers = (unsigned short) modifiers; 176444c061aSmrg grab->keybut = keybut; 177444c061aSmrg if (need_ext) { 178444c061aSmrg XtServerGrabExtPtr ext = GRABEXT(grab); 179444c061aSmrg ext->pModifiersMask = NULL; 180444c061aSmrg ext->pKeyButMask = NULL; 181444c061aSmrg ext->confineTo = confine_to; 182444c061aSmrg ext->cursor = cursor; 183444c061aSmrg } 184444c061aSmrg return grab; 185444c061aSmrg} 186444c061aSmrg 187444c061aSmrg 188444c061aSmrg/* 189444c061aSmrg * Free up the space occupied by a grab entry. 190444c061aSmrg */ 191444c061aSmrg 192444c061aSmrgstatic void FreeGrab( 193444c061aSmrg XtServerGrabPtr pGrab) 194444c061aSmrg{ 195444c061aSmrg if (pGrab->hasExt) { 196444c061aSmrg XtServerGrabExtPtr ext = GRABEXT(pGrab); 197444c061aSmrg if (ext->pModifiersMask) 198444c061aSmrg XtFree((char *)ext->pModifiersMask); 199444c061aSmrg if (ext->pKeyButMask) 200444c061aSmrg XtFree((char *)ext->pKeyButMask); 201444c061aSmrg } 202444c061aSmrg XtFree((char *)pGrab); 203444c061aSmrg} 204444c061aSmrg 205444c061aSmrgtypedef struct _DetailRec { 206444c061aSmrg unsigned short exact; 207444c061aSmrg Mask *pMask; 208444c061aSmrg} DetailRec, *DetailPtr; 209444c061aSmrg 210444c061aSmrg/* 211444c061aSmrg * If the first detail is set to 'exception' and the second detail 212444c061aSmrg * is contained in the mask of the first, then TRUE is returned. 213444c061aSmrg */ 214444c061aSmrg 215444c061aSmrgstatic Bool IsInGrabMask( 216444c061aSmrg register DetailPtr firstDetail, 217444c061aSmrg register DetailPtr secondDetail, 218444c061aSmrg unsigned short exception) 219444c061aSmrg{ 220444c061aSmrg if (firstDetail->exact == exception) { 221444c061aSmrg if (!firstDetail->pMask) 222444c061aSmrg return TRUE; 223444c061aSmrg 224444c061aSmrg /* (at present) never called with two non-null pMasks */ 225444c061aSmrg if (secondDetail->exact == exception) 226444c061aSmrg return FALSE; 227444c061aSmrg 228444c061aSmrg if (GETBIT(firstDetail->pMask, secondDetail->exact)) 229444c061aSmrg return TRUE; 230444c061aSmrg } 231444c061aSmrg 232444c061aSmrg return FALSE; 233444c061aSmrg} 234444c061aSmrg 235444c061aSmrg 236444c061aSmrg/* 237444c061aSmrg * If neither of the details is set to 'exception', and they match 238444c061aSmrg * exactly, then TRUE is returned. 239444c061aSmrg */ 240444c061aSmrg 241444c061aSmrgstatic Bool IdenticalExactDetails( 242444c061aSmrg unsigned short firstExact, 243444c061aSmrg unsigned short secondExact, 244444c061aSmrg unsigned short exception) 245444c061aSmrg{ 246444c061aSmrg if ((firstExact == exception) || (secondExact == exception)) 247444c061aSmrg return FALSE; 248444c061aSmrg 249444c061aSmrg if (firstExact == secondExact) 250444c061aSmrg return TRUE; 251444c061aSmrg 252444c061aSmrg return FALSE; 253444c061aSmrg} 254444c061aSmrg 255444c061aSmrg 256444c061aSmrg/* 257444c061aSmrg * If the first detail is set to 'exception', and its mask has the bit 258444c061aSmrg * enabled which corresponds to the second detail, OR if neither of the 259444c061aSmrg * details is set to 'exception' and the details match exactly, then 260444c061aSmrg * TRUE is returned. 261444c061aSmrg */ 262444c061aSmrg 263444c061aSmrgstatic Bool DetailSupersedesSecond( 264444c061aSmrg register DetailPtr firstDetail, 265444c061aSmrg register DetailPtr secondDetail, 266444c061aSmrg unsigned short exception) 267444c061aSmrg{ 268444c061aSmrg if (IsInGrabMask(firstDetail, secondDetail, exception)) 269444c061aSmrg return TRUE; 270444c061aSmrg 271444c061aSmrg if (IdenticalExactDetails(firstDetail->exact, secondDetail->exact, 272444c061aSmrg exception)) 273444c061aSmrg return TRUE; 274444c061aSmrg 275444c061aSmrg return FALSE; 276444c061aSmrg} 277444c061aSmrg 278444c061aSmrg 279444c061aSmrg/* 280444c061aSmrg * If the two grab events match exactly, or if the first grab entry 281444c061aSmrg * 'encompasses' the second grab entry, then TRUE is returned. 282444c061aSmrg */ 283444c061aSmrg 284444c061aSmrgstatic Bool GrabSupersedesSecond( 285444c061aSmrg register XtServerGrabPtr pFirstGrab, 286444c061aSmrg register XtServerGrabPtr pSecondGrab) 287444c061aSmrg{ 288444c061aSmrg DetailRec first, second; 289444c061aSmrg 290444c061aSmrg first.exact = pFirstGrab->modifiers; 291444c061aSmrg if (pFirstGrab->hasExt) 292444c061aSmrg first.pMask = GRABEXT(pFirstGrab)->pModifiersMask; 293444c061aSmrg else 294444c061aSmrg first.pMask = NULL; 295444c061aSmrg second.exact = pSecondGrab->modifiers; 296444c061aSmrg if (pSecondGrab->hasExt) 297444c061aSmrg second.pMask = GRABEXT(pSecondGrab)->pModifiersMask; 298444c061aSmrg else 299444c061aSmrg second.pMask = NULL; 300444c061aSmrg if (!DetailSupersedesSecond(&first, &second, (unsigned short)AnyModifier)) 301444c061aSmrg return FALSE; 302444c061aSmrg 303444c061aSmrg first.exact = pFirstGrab->keybut; 304444c061aSmrg if (pFirstGrab->hasExt) 305444c061aSmrg first.pMask = GRABEXT(pFirstGrab)->pKeyButMask; 306444c061aSmrg else 307444c061aSmrg first.pMask = NULL; 308444c061aSmrg second.exact = pSecondGrab->keybut; 309444c061aSmrg if (pSecondGrab->hasExt) 310444c061aSmrg second.pMask = GRABEXT(pSecondGrab)->pKeyButMask; 311444c061aSmrg else 312444c061aSmrg second.pMask = NULL; 313444c061aSmrg if (DetailSupersedesSecond(&first, &second, (unsigned short)AnyKey)) 314444c061aSmrg return TRUE; 315444c061aSmrg 316444c061aSmrg return FALSE; 317444c061aSmrg} 318444c061aSmrg 319444c061aSmrg 320444c061aSmrg/* 321444c061aSmrg * Two grabs are considered to be matching if either of the following are true: 322444c061aSmrg * 323444c061aSmrg * 1) The two grab entries match exactly, or the first grab entry 324444c061aSmrg * encompasses the second grab entry. 325444c061aSmrg * 2) The second grab entry encompasses the first grab entry. 326444c061aSmrg * 3) The keycodes match exactly, and one entry's modifiers encompasses 327444c061aSmrg * the others. 328444c061aSmrg * 4) The keycode for one entry encompasses the other, and the detail 329444c061aSmrg * for the other entry encompasses the first. 330444c061aSmrg */ 331444c061aSmrg 332444c061aSmrgstatic Bool GrabMatchesSecond( 333444c061aSmrg register XtServerGrabPtr pFirstGrab, 334444c061aSmrg register XtServerGrabPtr pSecondGrab) 335444c061aSmrg{ 336444c061aSmrg DetailRec firstD, firstM, secondD, secondM; 337444c061aSmrg 338444c061aSmrg if (pDisplay(pFirstGrab) != pDisplay(pSecondGrab)) 339444c061aSmrg return FALSE; 340444c061aSmrg 341444c061aSmrg if (GrabSupersedesSecond(pFirstGrab, pSecondGrab)) 342444c061aSmrg return TRUE; 343444c061aSmrg 344444c061aSmrg if (GrabSupersedesSecond(pSecondGrab, pFirstGrab)) 345444c061aSmrg return TRUE; 346444c061aSmrg 347444c061aSmrg firstD.exact = pFirstGrab->keybut; 348444c061aSmrg firstM.exact = pFirstGrab->modifiers; 349444c061aSmrg if (pFirstGrab->hasExt) { 350444c061aSmrg firstD.pMask = GRABEXT(pFirstGrab)->pKeyButMask; 351444c061aSmrg firstM.pMask = GRABEXT(pFirstGrab)->pModifiersMask; 352444c061aSmrg } else { 353444c061aSmrg firstD.pMask = NULL; 354444c061aSmrg firstM.pMask = NULL; 355444c061aSmrg } 356444c061aSmrg secondD.exact = pSecondGrab->keybut; 357444c061aSmrg secondM.exact = pSecondGrab->modifiers; 358444c061aSmrg if (pSecondGrab->hasExt) { 359444c061aSmrg secondD.pMask = GRABEXT(pSecondGrab)->pKeyButMask; 360444c061aSmrg secondM.pMask = GRABEXT(pSecondGrab)->pModifiersMask; 361444c061aSmrg } else { 362444c061aSmrg secondD.pMask = NULL; 363444c061aSmrg secondM.pMask = NULL; 364444c061aSmrg } 365444c061aSmrg 366444c061aSmrg if (DetailSupersedesSecond(&secondD, &firstD, (unsigned short)AnyKey) && 367444c061aSmrg DetailSupersedesSecond(&firstM, &secondM, (unsigned short)AnyModifier)) 368444c061aSmrg return TRUE; 369444c061aSmrg 370444c061aSmrg if (DetailSupersedesSecond(&firstD, &secondD, (unsigned short)AnyKey) && 371444c061aSmrg DetailSupersedesSecond(&secondM, &firstM, (unsigned short)AnyModifier)) 372444c061aSmrg return TRUE; 373444c061aSmrg 374444c061aSmrg return FALSE; 375444c061aSmrg} 376444c061aSmrg 377444c061aSmrg 378444c061aSmrg/* 379444c061aSmrg * Delete a grab combination from the passive grab list. Each entry will 380444c061aSmrg * be checked to see if it is affected by the grab being deleted. This 381444c061aSmrg * may result in multiple entries being modified/deleted. 382444c061aSmrg */ 383444c061aSmrg 384444c061aSmrgstatic void DeleteServerGrabFromList( 385444c061aSmrg XtServerGrabPtr *passiveListPtr, 386444c061aSmrg XtServerGrabPtr pMinuendGrab) 387444c061aSmrg{ 388444c061aSmrg register XtServerGrabPtr *next; 389444c061aSmrg register XtServerGrabPtr grab; 390444c061aSmrg register XtServerGrabExtPtr ext; 391444c061aSmrg 392444c061aSmrg for (next = passiveListPtr; (grab = *next); ) 393444c061aSmrg { 394444c061aSmrg if (GrabMatchesSecond(grab, pMinuendGrab) && 395444c061aSmrg (pDisplay(grab) == pDisplay(pMinuendGrab))) 396444c061aSmrg { 397444c061aSmrg if (GrabSupersedesSecond(pMinuendGrab, grab)) 398444c061aSmrg { 399444c061aSmrg /* 400444c061aSmrg * The entry being deleted encompasses the list entry, 401444c061aSmrg * so delete the list entry. 402444c061aSmrg */ 403444c061aSmrg *next = grab->next; 404444c061aSmrg FreeGrab(grab); 405444c061aSmrg continue; 406444c061aSmrg } 407444c061aSmrg 408444c061aSmrg if (!grab->hasExt) { 409444c061aSmrg grab = (XtServerGrabPtr) 410444c061aSmrg XtRealloc((char *)grab, (sizeof(XtServerGrabRec) + 411444c061aSmrg sizeof(XtServerGrabExtRec))); 412444c061aSmrg *next = grab; 413444c061aSmrg grab->hasExt = True; 414444c061aSmrg ext = GRABEXT(grab); 415444c061aSmrg ext->pKeyButMask = NULL; 416444c061aSmrg ext->pModifiersMask = NULL; 417444c061aSmrg ext->confineTo = None; 418444c061aSmrg ext->cursor = None; 419444c061aSmrg } else 420444c061aSmrg ext = GRABEXT(grab); 421444c061aSmrg if ((grab->keybut == AnyKey) && (grab->modifiers != AnyModifier)) 422444c061aSmrg { 423444c061aSmrg /* 424444c061aSmrg * If the list entry has the key detail of AnyKey, and 425444c061aSmrg * a modifier detail not set to AnyModifier, then we 426444c061aSmrg * simply need to turn off the key detail bit in the 427444c061aSmrg * list entry's key detail mask. 428444c061aSmrg */ 429444c061aSmrg DeleteDetailFromMask(&ext->pKeyButMask, pMinuendGrab->keybut); 430444c061aSmrg } else if ((grab->modifiers == AnyModifier) && 431444c061aSmrg (grab->keybut != AnyKey)) { 432444c061aSmrg /* 433444c061aSmrg * The list entry has a specific key detail, but its 434444c061aSmrg * modifier detail is set to AnyModifier; so, we only 435444c061aSmrg * need to turn off the specified modifier combination 436444c061aSmrg * in the list entry's modifier mask. 437444c061aSmrg */ 438444c061aSmrg DeleteDetailFromMask(&ext->pModifiersMask, 439444c061aSmrg pMinuendGrab->modifiers); 440444c061aSmrg } else if ((pMinuendGrab->keybut != AnyKey) && 441444c061aSmrg (pMinuendGrab->modifiers != AnyModifier)) { 442444c061aSmrg /* 443444c061aSmrg * The list entry has a key detail of AnyKey and a 444444c061aSmrg * modifier detail of AnyModifier; the entry being 445444c061aSmrg * deleted has a specific key and a specific modifier 446444c061aSmrg * combination. Therefore, we need to mask off the 447444c061aSmrg * keycode from the list entry, and also create a 448444c061aSmrg * new entry for this keycode, which has a modifier 449444c061aSmrg * mask set to AnyModifier & ~(deleted modifiers). 450444c061aSmrg */ 451444c061aSmrg XtServerGrabPtr pNewGrab; 452444c061aSmrg 453444c061aSmrg DeleteDetailFromMask(&ext->pKeyButMask, pMinuendGrab->keybut); 454444c061aSmrg pNewGrab = CreateGrab(grab->widget, 455444c061aSmrg (Boolean)grab->ownerEvents, 456444c061aSmrg (Modifiers)AnyModifier, 457444c061aSmrg pMinuendGrab->keybut, 458444c061aSmrg (int)grab->pointerMode, 459444c061aSmrg (int)grab->keyboardMode, 460444c061aSmrg (Mask)0, (Window)0, (Cursor)0, True); 461444c061aSmrg GRABEXT(pNewGrab)->pModifiersMask = 462444c061aSmrg CopyDetailMask(ext->pModifiersMask); 463444c061aSmrg 464444c061aSmrg DeleteDetailFromMask(&GRABEXT(pNewGrab)->pModifiersMask, 465444c061aSmrg pMinuendGrab->modifiers); 466444c061aSmrg 467444c061aSmrg pNewGrab->next = *passiveListPtr; 468444c061aSmrg *passiveListPtr = pNewGrab; 469444c061aSmrg } else if (pMinuendGrab->keybut == AnyKey) { 470444c061aSmrg /* 471444c061aSmrg * The list entry has keycode AnyKey and modifier 472444c061aSmrg * AnyModifier; the entry being deleted has 473444c061aSmrg * keycode AnyKey and specific modifiers. So we 474444c061aSmrg * simply need to mask off the specified modifier 475444c061aSmrg * combination. 476444c061aSmrg */ 477444c061aSmrg DeleteDetailFromMask(&ext->pModifiersMask, 478444c061aSmrg pMinuendGrab->modifiers); 479444c061aSmrg } else { 480444c061aSmrg /* 481444c061aSmrg * The list entry has keycode AnyKey and modifier 482444c061aSmrg * AnyModifier; the entry being deleted has a 483444c061aSmrg * specific keycode and modifier AnyModifier. So 484444c061aSmrg * we simply need to mask off the specified 485444c061aSmrg * keycode. 486444c061aSmrg */ 487444c061aSmrg DeleteDetailFromMask(&ext->pKeyButMask, pMinuendGrab->keybut); 488444c061aSmrg } 489444c061aSmrg } 490444c061aSmrg next = &(*next)->next; 491444c061aSmrg } 492444c061aSmrg} 493444c061aSmrg 494444c061aSmrgstatic void DestroyPassiveList( 495444c061aSmrg XtServerGrabPtr *passiveListPtr) 496444c061aSmrg{ 497444c061aSmrg XtServerGrabPtr next, grab; 498444c061aSmrg 499444c061aSmrg for (next = *passiveListPtr; next; ) { 500444c061aSmrg grab = next; 501444c061aSmrg next = grab->next; 502444c061aSmrg 503444c061aSmrg /* not necessary to explicitly ungrab key or button; 504444c061aSmrg * window is being destroyed so server will take care of it. 505444c061aSmrg */ 506444c061aSmrg 507444c061aSmrg FreeGrab(grab); 508444c061aSmrg } 509444c061aSmrg} 510444c061aSmrg 511444c061aSmrg 512444c061aSmrg/* 513444c061aSmrg * This function is called at widget destroy time to clean up 514444c061aSmrg */ 515444c061aSmrg/*ARGSUSED*/ 516444c061aSmrgvoid _XtDestroyServerGrabs( 517444c061aSmrg Widget w, 518444c061aSmrg XtPointer closure, 519444c061aSmrg XtPointer call_data) /* unused */ 520444c061aSmrg{ 521444c061aSmrg XtPerWidgetInput pwi = (XtPerWidgetInput)closure; 522444c061aSmrg XtPerDisplayInput pdi; 523444c061aSmrg 524444c061aSmrg LOCK_PROCESS; 525444c061aSmrg pdi = _XtGetPerDisplayInput(XtDisplay(w)); 526444c061aSmrg _XtClearAncestorCache(w); 527444c061aSmrg UNLOCK_PROCESS; 528444c061aSmrg 529444c061aSmrg /* Remove the active grab, if necessary */ 530444c061aSmrg if ((pdi->keyboard.grabType != XtNoServerGrab) && 531444c061aSmrg (pdi->keyboard.grab.widget == w)) { 532444c061aSmrg pdi->keyboard.grabType = XtNoServerGrab; 533444c061aSmrg pdi->activatingKey = (KeyCode)0; 534444c061aSmrg } 535444c061aSmrg if ((pdi->pointer.grabType != XtNoServerGrab) && 536444c061aSmrg (pdi->pointer.grab.widget == w)) 537444c061aSmrg pdi->pointer.grabType = XtNoServerGrab; 538444c061aSmrg 539444c061aSmrg DestroyPassiveList(&pwi->keyList); 540444c061aSmrg DestroyPassiveList(&pwi->ptrList); 541444c061aSmrg 542444c061aSmrg _XtFreePerWidgetInput(w, pwi); 543444c061aSmrg} 544444c061aSmrg 545444c061aSmrg/* 546444c061aSmrg * If the incoming event is on the passive grab list, then activate 547444c061aSmrg * the grab. The grab will remain in effect until the key is released. 548444c061aSmrg */ 549444c061aSmrg 550444c061aSmrgXtServerGrabPtr _XtCheckServerGrabsOnWidget ( 551444c061aSmrg XEvent *event, 552444c061aSmrg Widget widget, 553444c061aSmrg _XtBoolean isKeyboard) 554444c061aSmrg{ 555444c061aSmrg register XtServerGrabPtr grab; 556444c061aSmrg XtServerGrabRec tempGrab; 557444c061aSmrg XtServerGrabPtr *passiveListPtr; 558444c061aSmrg XtPerWidgetInput pwi; 559444c061aSmrg 560444c061aSmrg LOCK_PROCESS; 561444c061aSmrg pwi = _XtGetPerWidgetInput(widget, FALSE); 562444c061aSmrg UNLOCK_PROCESS; 563444c061aSmrg if (!pwi) 564444c061aSmrg return (XtServerGrabPtr)NULL; 565444c061aSmrg if (isKeyboard) 566444c061aSmrg passiveListPtr = &pwi->keyList; 567444c061aSmrg else 568444c061aSmrg passiveListPtr = &pwi->ptrList; 569444c061aSmrg 570444c061aSmrg /* 571444c061aSmrg * if either there is no entry in the context manager or the entry 572444c061aSmrg * is empty, or the keyboard is grabed, then no work to be done 573444c061aSmrg */ 574444c061aSmrg if (!*passiveListPtr) 575444c061aSmrg return (XtServerGrabPtr)NULL; 576444c061aSmrg 577444c061aSmrg /* Take only the lower thirteen bits as modifier state. The X Keyboard 578444c061aSmrg * Extension may be representing keyboard group state in two upper bits. 579444c061aSmrg */ 580444c061aSmrg tempGrab.widget = widget; 5810568f49bSmrg tempGrab.keybut = (KeyCode) event->xkey.keycode; /* also xbutton.button */ 582444c061aSmrg tempGrab.modifiers = event->xkey.state & 0x1FFF; /*also xbutton.state*/ 583444c061aSmrg tempGrab.hasExt = False; 584444c061aSmrg 585444c061aSmrg for (grab = *passiveListPtr; grab; grab = grab->next) { 586444c061aSmrg if (GrabMatchesSecond(&tempGrab, grab)) 587444c061aSmrg return (grab); 588444c061aSmrg } 589444c061aSmrg return (XtServerGrabPtr)NULL; 590444c061aSmrg} 591444c061aSmrg 592444c061aSmrg/* 593444c061aSmrg * This handler is needed to guarantee that we see releases on passive 594444c061aSmrg * button grabs for widgets that haven't selected for button release. 595444c061aSmrg */ 596444c061aSmrg 597444c061aSmrg/*ARGSUSED*/ 598444c061aSmrgstatic void ActiveHandler ( 599444c061aSmrg Widget widget, 600444c061aSmrg XtPointer pdi, 601444c061aSmrg XEvent *event, 602444c061aSmrg Boolean *cont) 603444c061aSmrg{ 604444c061aSmrg /* nothing */ 605444c061aSmrg} 606444c061aSmrg 607444c061aSmrg 608444c061aSmrg/* 609444c061aSmrg * MakeGrab 610444c061aSmrg */ 611444c061aSmrgstatic void MakeGrab( 612444c061aSmrg XtServerGrabPtr grab, 613444c061aSmrg XtServerGrabPtr *passiveListPtr, 614444c061aSmrg Boolean isKeyboard, 615444c061aSmrg XtPerDisplayInput pdi, 616444c061aSmrg XtPerWidgetInput pwi) 617444c061aSmrg{ 618444c061aSmrg if (!isKeyboard && !pwi->active_handler_added) { 619444c061aSmrg XtAddEventHandler(grab->widget, ButtonReleaseMask, FALSE, 620444c061aSmrg ActiveHandler, (XtPointer)pdi); 621444c061aSmrg pwi->active_handler_added = TRUE; 622444c061aSmrg } 623444c061aSmrg 624444c061aSmrg if (isKeyboard) { 625444c061aSmrg XGrabKey(pDisplay(grab), 626444c061aSmrg grab->keybut, grab->modifiers, 627444c061aSmrg pWindow(grab), grab->ownerEvents, 628444c061aSmrg grab->pointerMode, grab->keyboardMode); 629444c061aSmrg } else { 630444c061aSmrg Window confineTo = None; 631444c061aSmrg Cursor cursor = None; 632444c061aSmrg 633444c061aSmrg if (grab->hasExt) { 634444c061aSmrg if (grab->confineToIsWidgetWin) 635444c061aSmrg confineTo = XtWindow (grab->widget); 636444c061aSmrg else 637444c061aSmrg confineTo = GRABEXT(grab)->confineTo; 638444c061aSmrg cursor = GRABEXT(grab)->cursor; 639444c061aSmrg } 640444c061aSmrg XGrabButton(pDisplay(grab), 641444c061aSmrg grab->keybut, grab->modifiers, 642444c061aSmrg pWindow(grab), grab->ownerEvents, grab->eventMask, 643444c061aSmrg grab->pointerMode, grab->keyboardMode, 644444c061aSmrg confineTo, cursor); 645444c061aSmrg } 646444c061aSmrg 647444c061aSmrg /* Add the new grab entry to the passive key grab list */ 648444c061aSmrg grab->next = *passiveListPtr; 649444c061aSmrg *passiveListPtr = grab; 650444c061aSmrg} 651444c061aSmrg 652444c061aSmrgstatic void MakeGrabs( 653444c061aSmrg XtServerGrabPtr *passiveListPtr, 654444c061aSmrg Boolean isKeyboard, 655444c061aSmrg XtPerDisplayInput pdi) 656444c061aSmrg{ 657444c061aSmrg XtServerGrabPtr next = *passiveListPtr; 658444c061aSmrg /* 659444c061aSmrg * make MakeGrab build a new list that has had the merge 660444c061aSmrg * processing done on it. Start with an empty list 661444c061aSmrg * (passiveListPtr). 662444c061aSmrg */ 663444c061aSmrg LOCK_PROCESS; 664444c061aSmrg *passiveListPtr = NULL; 665444c061aSmrg while (next) 666444c061aSmrg { 6670568f49bSmrg XtServerGrabPtr grab; 6680568f49bSmrg XtPerWidgetInput pwi; 6690568f49bSmrg 670444c061aSmrg grab = next; 671444c061aSmrg next = grab->next; 672444c061aSmrg pwi = _XtGetPerWidgetInput(grab->widget, FALSE); 673444c061aSmrg MakeGrab(grab, passiveListPtr, isKeyboard, pdi, pwi); 674444c061aSmrg } 675444c061aSmrg UNLOCK_PROCESS; 676444c061aSmrg} 677444c061aSmrg 678444c061aSmrg/* 679444c061aSmrg * This function is the event handler attached to the associated widget 680444c061aSmrg * when grabs need to be added, but the widget is not yet realized. When 681444c061aSmrg * it is first mapped, this handler will be invoked, and it will add all 682444c061aSmrg * needed grabs. 683444c061aSmrg */ 684444c061aSmrg 685444c061aSmrg/*ARGSUSED*/ 686444c061aSmrgstatic void RealizeHandler ( 687444c061aSmrg Widget widget, 688444c061aSmrg XtPointer closure, 689444c061aSmrg XEvent *event, /* unused */ 690444c061aSmrg Boolean *cont) /* unused */ 691444c061aSmrg{ 692444c061aSmrg XtPerWidgetInput pwi = (XtPerWidgetInput)closure; 693444c061aSmrg XtPerDisplayInput pdi; 694444c061aSmrg 695444c061aSmrg LOCK_PROCESS; 696444c061aSmrg pdi = _XtGetPerDisplayInput(XtDisplay(widget)); 697444c061aSmrg UNLOCK_PROCESS; 698444c061aSmrg MakeGrabs(&pwi->keyList, KEYBOARD, pdi); 699444c061aSmrg MakeGrabs(&pwi->ptrList, POINTER, pdi); 700444c061aSmrg 701444c061aSmrg XtRemoveEventHandler(widget, XtAllEvents, True, 702444c061aSmrg RealizeHandler, (XtPointer)pwi); 703444c061aSmrg pwi->realize_handler_added = FALSE; 704444c061aSmrg} 705444c061aSmrg 706444c061aSmrg/***************************************************************************/ 707444c061aSmrg/**************************** Global Routines ******************************/ 708444c061aSmrg/***************************************************************************/ 709444c061aSmrg 710444c061aSmrg 711444c061aSmrg/* 712444c061aSmrg * Routine used by an application to set up a passive grab for a key/modifier 713444c061aSmrg * combination. 714444c061aSmrg */ 715444c061aSmrg 716444c061aSmrgstatic 717444c061aSmrgvoid GrabKeyOrButton ( 718444c061aSmrg Widget widget, 719444c061aSmrg KeyCode keyOrButton, 720444c061aSmrg Modifiers modifiers, 721444c061aSmrg Boolean owner_events, 722444c061aSmrg int pointer_mode, 723444c061aSmrg int keyboard_mode, 724444c061aSmrg Mask event_mask, 725444c061aSmrg Window confine_to, 726444c061aSmrg Cursor cursor, 727444c061aSmrg Boolean isKeyboard) 728444c061aSmrg{ 729444c061aSmrg XtServerGrabPtr *passiveListPtr; 730444c061aSmrg XtServerGrabPtr newGrab; 731444c061aSmrg XtPerWidgetInput pwi; 732444c061aSmrg XtPerDisplayInput pdi; 733444c061aSmrg 734444c061aSmrg 735444c061aSmrg XtCheckSubclass(widget, coreWidgetClass, "in XtGrabKey or XtGrabButton"); 736444c061aSmrg LOCK_PROCESS; 737444c061aSmrg pwi = _XtGetPerWidgetInput(widget, TRUE); 738444c061aSmrg if (isKeyboard) 739444c061aSmrg passiveListPtr = &pwi->keyList; 740444c061aSmrg else 741444c061aSmrg passiveListPtr = &pwi->ptrList; 742444c061aSmrg pdi = _XtGetPerDisplayInput(XtDisplay(widget)); 743444c061aSmrg UNLOCK_PROCESS; 744444c061aSmrg newGrab = CreateGrab(widget, owner_events, modifiers, 745444c061aSmrg keyOrButton, pointer_mode, keyboard_mode, 746444c061aSmrg event_mask, confine_to, cursor, False); 747444c061aSmrg /* 748444c061aSmrg * if the widget is realized then process the entry into the grab 749444c061aSmrg * list. else if the list is empty (i.e. first time) then add the 750444c061aSmrg * event handler. then add the raw entry to the list for processing 751444c061aSmrg * in the handler at realize time. 752444c061aSmrg */ 753444c061aSmrg if (XtIsRealized(widget)) 754444c061aSmrg MakeGrab(newGrab, passiveListPtr, isKeyboard, pdi, pwi); 755444c061aSmrg else { 756444c061aSmrg if (!pwi->realize_handler_added) 757444c061aSmrg { 758444c061aSmrg XtAddEventHandler(widget, StructureNotifyMask, FALSE, 759444c061aSmrg RealizeHandler, 760444c061aSmrg (XtPointer)pwi); 761444c061aSmrg pwi->realize_handler_added = TRUE; 762444c061aSmrg } 763444c061aSmrg 764444c061aSmrg while (*passiveListPtr) 765444c061aSmrg passiveListPtr = &(*passiveListPtr)->next; 766444c061aSmrg *passiveListPtr = newGrab; 767444c061aSmrg } 768444c061aSmrg} 769444c061aSmrg 770444c061aSmrg 771444c061aSmrgstatic 772444c061aSmrgvoid UngrabKeyOrButton ( 773444c061aSmrg Widget widget, 774444c061aSmrg int keyOrButton, 775444c061aSmrg Modifiers modifiers, 776444c061aSmrg Boolean isKeyboard) 777444c061aSmrg{ 778444c061aSmrg XtServerGrabRec tempGrab; 779444c061aSmrg XtPerWidgetInput pwi; 780444c061aSmrg 781444c061aSmrg XtCheckSubclass(widget, coreWidgetClass, 782444c061aSmrg "in XtUngrabKey or XtUngrabButton"); 783444c061aSmrg 784444c061aSmrg /* Build a temporary grab list entry */ 785444c061aSmrg tempGrab.widget = widget; 7860568f49bSmrg tempGrab.modifiers = (unsigned short) modifiers; 7870568f49bSmrg tempGrab.keybut = (KeyCode) keyOrButton; 788444c061aSmrg tempGrab.hasExt = False; 789444c061aSmrg 790444c061aSmrg LOCK_PROCESS; 791444c061aSmrg pwi = _XtGetPerWidgetInput(widget, FALSE); 792444c061aSmrg UNLOCK_PROCESS; 793444c061aSmrg /* 794444c061aSmrg * if there is no entry in the context manager then somethings wrong 795444c061aSmrg */ 796444c061aSmrg if (!pwi) 797444c061aSmrg { 798444c061aSmrg XtAppWarningMsg(XtWidgetToApplicationContext(widget), 799444c061aSmrg "invalidGrab", "ungrabKeyOrButton", XtCXtToolkitError, 800444c061aSmrg "Attempt to remove nonexistent passive grab", 8010568f49bSmrg NULL, NULL); 802444c061aSmrg return; 803444c061aSmrg } 804444c061aSmrg 805444c061aSmrg if (XtIsRealized(widget)) 806444c061aSmrg { 807444c061aSmrg if (isKeyboard) 808444c061aSmrg XUngrabKey(widget->core.screen->display, 809444c061aSmrg keyOrButton, (unsigned int)modifiers, 810444c061aSmrg widget->core.window); 811444c061aSmrg else 812444c061aSmrg XUngrabButton(widget->core.screen->display, 8130568f49bSmrg (unsigned) keyOrButton, (unsigned int)modifiers, 814444c061aSmrg widget->core.window); 815444c061aSmrg } 816444c061aSmrg 817444c061aSmrg 818444c061aSmrg /* Delete all entries which are encompassed by the specified grab. */ 819444c061aSmrg DeleteServerGrabFromList(isKeyboard ? &pwi->keyList : &pwi->ptrList, 820444c061aSmrg &tempGrab); 821444c061aSmrg} 822444c061aSmrg 823444c061aSmrgvoid XtGrabKey ( 824444c061aSmrg Widget widget, 825444c061aSmrg _XtKeyCode keycode, 826444c061aSmrg Modifiers modifiers, 827444c061aSmrg _XtBoolean owner_events, 828444c061aSmrg int pointer_mode, 829444c061aSmrg int keyboard_mode) 830444c061aSmrg{ 831444c061aSmrg WIDGET_TO_APPCON(widget); 832444c061aSmrg 833444c061aSmrg LOCK_APP(app); 8340568f49bSmrg GrabKeyOrButton(widget, (KeyCode)keycode, modifiers, (Boolean) owner_events, 835444c061aSmrg pointer_mode, keyboard_mode, 836444c061aSmrg (Mask)0, (Window)None, (Cursor)None, KEYBOARD); 837444c061aSmrg UNLOCK_APP(app); 838444c061aSmrg} 839444c061aSmrg 840444c061aSmrgvoid XtGrabButton( 841444c061aSmrg Widget widget, 842444c061aSmrg int button, 843444c061aSmrg Modifiers modifiers, 844444c061aSmrg _XtBoolean owner_events, 845444c061aSmrg unsigned int event_mask, 846444c061aSmrg int pointer_mode, 847444c061aSmrg int keyboard_mode, 848444c061aSmrg Window confine_to, 849444c061aSmrg Cursor cursor) 850444c061aSmrg{ 851444c061aSmrg WIDGET_TO_APPCON(widget); 852444c061aSmrg 853444c061aSmrg LOCK_APP(app); 8540568f49bSmrg GrabKeyOrButton(widget, (KeyCode)button, modifiers, (Boolean) owner_events, 855444c061aSmrg pointer_mode, keyboard_mode, 856444c061aSmrg (Mask)event_mask, confine_to, cursor, POINTER); 857444c061aSmrg UNLOCK_APP(app); 858444c061aSmrg} 859444c061aSmrg 860444c061aSmrg 861444c061aSmrg/* 862444c061aSmrg * Routine used by an application to clear a passive grab for a key/modifier 863444c061aSmrg * combination. 864444c061aSmrg */ 865444c061aSmrg 866444c061aSmrgvoid XtUngrabKey ( 867444c061aSmrg Widget widget, 868444c061aSmrg _XtKeyCode keycode, 869444c061aSmrg Modifiers modifiers) 870444c061aSmrg{ 871444c061aSmrg WIDGET_TO_APPCON(widget); 872444c061aSmrg 873444c061aSmrg LOCK_APP(app); 874444c061aSmrg UngrabKeyOrButton(widget, (int)keycode, modifiers, KEYBOARD); 875444c061aSmrg UNLOCK_APP(app); 876444c061aSmrg} 877444c061aSmrg 878444c061aSmrgvoid XtUngrabButton ( 879444c061aSmrg Widget widget, 880444c061aSmrg unsigned int button, 881444c061aSmrg Modifiers modifiers) 882444c061aSmrg{ 883444c061aSmrg WIDGET_TO_APPCON(widget); 884444c061aSmrg 885444c061aSmrg LOCK_APP(app); 886444c061aSmrg UngrabKeyOrButton(widget, (KeyCode)button, modifiers, POINTER); 887444c061aSmrg UNLOCK_APP(app); 888444c061aSmrg} 889444c061aSmrg 890444c061aSmrg/* 891444c061aSmrg * Active grab of Device. clear any client side grabs so we dont lock 892444c061aSmrg */ 893444c061aSmrgstatic int GrabDevice ( 894444c061aSmrg Widget widget, 895444c061aSmrg Boolean owner_events, 896444c061aSmrg int pointer_mode, 897444c061aSmrg int keyboard_mode, 898444c061aSmrg Mask event_mask, 899444c061aSmrg Window confine_to, 900444c061aSmrg Cursor cursor, 901444c061aSmrg Time time, 902444c061aSmrg Boolean isKeyboard) 903444c061aSmrg{ 904444c061aSmrg XtPerDisplayInput pdi; 905444c061aSmrg int returnVal; 906444c061aSmrg 907444c061aSmrg XtCheckSubclass(widget, coreWidgetClass, 908444c061aSmrg "in XtGrabKeyboard or XtGrabPointer"); 909444c061aSmrg if (!XtIsRealized(widget)) 910444c061aSmrg return GrabNotViewable; 911444c061aSmrg LOCK_PROCESS; 912444c061aSmrg pdi = _XtGetPerDisplayInput(XtDisplay(widget)); 913444c061aSmrg UNLOCK_PROCESS; 914444c061aSmrg if (!isKeyboard) 915444c061aSmrg returnVal = XGrabPointer(XtDisplay(widget), XtWindow(widget), 9160568f49bSmrg owner_events, (unsigned) event_mask, 917444c061aSmrg pointer_mode, keyboard_mode, 918444c061aSmrg confine_to, cursor, time); 919444c061aSmrg else 920444c061aSmrg returnVal = XGrabKeyboard(XtDisplay(widget), XtWindow(widget), 921444c061aSmrg owner_events, pointer_mode, 922444c061aSmrg keyboard_mode, time); 923444c061aSmrg 924444c061aSmrg if (returnVal == GrabSuccess) { 925444c061aSmrg XtDevice device; 926444c061aSmrg 927444c061aSmrg device = isKeyboard ? &pdi->keyboard : &pdi->pointer; 928444c061aSmrg /* fill in the server grab rec */ 929444c061aSmrg device->grab.widget = widget; 930444c061aSmrg device->grab.modifiers = 0; 931444c061aSmrg device->grab.keybut = 0; 9320568f49bSmrg XtSetBit(device->grab.ownerEvents, owner_events); 9330568f49bSmrg XtSetBit(device->grab.pointerMode, pointer_mode); 9340568f49bSmrg XtSetBit(device->grab.keyboardMode, keyboard_mode); 935444c061aSmrg device->grab.hasExt = False; 936444c061aSmrg device->grabType = XtActiveServerGrab; 937444c061aSmrg pdi->activatingKey = (KeyCode)0; 938444c061aSmrg } 939444c061aSmrg return returnVal; 940444c061aSmrg} 941444c061aSmrg 942444c061aSmrgstatic void UngrabDevice( 943444c061aSmrg Widget widget, 944444c061aSmrg Time time, 945444c061aSmrg Boolean isKeyboard) 946444c061aSmrg{ 947444c061aSmrg XtPerDisplayInput pdi; 948444c061aSmrg XtDevice device; 949444c061aSmrg 950444c061aSmrg LOCK_PROCESS; 951444c061aSmrg pdi = _XtGetPerDisplayInput(XtDisplay(widget)); 952444c061aSmrg UNLOCK_PROCESS; 953444c061aSmrg device = isKeyboard ? &pdi->keyboard : &pdi->pointer; 954444c061aSmrg XtCheckSubclass(widget, coreWidgetClass, 955444c061aSmrg "in XtUngrabKeyboard or XtUngrabPointer"); 956444c061aSmrg 957444c061aSmrg if (device->grabType != XtNoServerGrab) { 958444c061aSmrg 959444c061aSmrg if (device->grabType != XtPseudoPassiveServerGrab 960444c061aSmrg && XtIsRealized(widget)) { 961444c061aSmrg if (isKeyboard) 962444c061aSmrg XUngrabKeyboard(XtDisplay(widget), time); 963444c061aSmrg else 964444c061aSmrg XUngrabPointer(XtDisplay(widget), time); 965444c061aSmrg } 966444c061aSmrg device->grabType = XtNoServerGrab; 967444c061aSmrg pdi->activatingKey = (KeyCode)0; 968444c061aSmrg } 969444c061aSmrg} 970444c061aSmrg 971444c061aSmrg 972444c061aSmrg/* 973444c061aSmrg * Active grab of keyboard. clear any client side grabs so we dont lock 974444c061aSmrg */ 975444c061aSmrgint XtGrabKeyboard ( 976444c061aSmrg Widget widget, 977444c061aSmrg _XtBoolean owner_events, 978444c061aSmrg int pointer_mode, 979444c061aSmrg int keyboard_mode, 980444c061aSmrg Time time) 981444c061aSmrg{ 982444c061aSmrg int retval; 983444c061aSmrg WIDGET_TO_APPCON(widget); 984444c061aSmrg 985444c061aSmrg LOCK_APP(app); 9860568f49bSmrg retval = GrabDevice (widget, (Boolean) owner_events, 987444c061aSmrg pointer_mode, keyboard_mode, 988444c061aSmrg (Mask)0, (Window)None, (Cursor)None, time, KEYBOARD); 989444c061aSmrg UNLOCK_APP(app); 990444c061aSmrg return retval; 991444c061aSmrg} 992444c061aSmrg 993444c061aSmrg 994444c061aSmrg/* 995444c061aSmrg * Ungrab the keyboard 996444c061aSmrg */ 997444c061aSmrg 998444c061aSmrgvoid XtUngrabKeyboard( 999444c061aSmrg Widget widget, 1000444c061aSmrg Time time) 1001444c061aSmrg{ 1002444c061aSmrg WIDGET_TO_APPCON(widget); 1003444c061aSmrg 1004444c061aSmrg LOCK_APP(app); 1005444c061aSmrg UngrabDevice(widget, time, KEYBOARD); 1006444c061aSmrg UNLOCK_APP(app); 1007444c061aSmrg} 1008444c061aSmrg 1009444c061aSmrg 1010444c061aSmrg 1011444c061aSmrg 1012444c061aSmrg/* 1013444c061aSmrg * grab the pointer 1014444c061aSmrg */ 1015444c061aSmrgint XtGrabPointer ( 1016444c061aSmrg Widget widget, 1017444c061aSmrg _XtBoolean owner_events, 1018444c061aSmrg unsigned int event_mask, 1019444c061aSmrg int pointer_mode, 1020444c061aSmrg int keyboard_mode, 1021444c061aSmrg Window confine_to, 1022444c061aSmrg Cursor cursor, 1023444c061aSmrg Time time) 1024444c061aSmrg{ 1025444c061aSmrg int retval; 1026444c061aSmrg WIDGET_TO_APPCON(widget); 1027444c061aSmrg 1028444c061aSmrg LOCK_APP(app); 10290568f49bSmrg retval = GrabDevice (widget, (Boolean) owner_events, 1030444c061aSmrg pointer_mode, keyboard_mode, 1031444c061aSmrg (Mask)event_mask, confine_to, 1032444c061aSmrg cursor, time, POINTER); 1033444c061aSmrg UNLOCK_APP(app); 1034444c061aSmrg return retval; 1035444c061aSmrg} 1036444c061aSmrg 1037444c061aSmrg 1038444c061aSmrg/* 1039444c061aSmrg * Ungrab the pointer 1040444c061aSmrg */ 1041444c061aSmrg 1042444c061aSmrgvoid XtUngrabPointer( 1043444c061aSmrg Widget widget, 1044444c061aSmrg Time time) 1045444c061aSmrg{ 1046444c061aSmrg WIDGET_TO_APPCON(widget); 1047444c061aSmrg 1048444c061aSmrg LOCK_APP(app); 1049444c061aSmrg UngrabDevice(widget, time, POINTER); 1050444c061aSmrg UNLOCK_APP(app); 1051444c061aSmrg} 1052444c061aSmrg 1053444c061aSmrg 1054444c061aSmrgvoid _XtRegisterPassiveGrabs ( 1055444c061aSmrg Widget widget) 1056444c061aSmrg{ 1057444c061aSmrg XtPerWidgetInput pwi = _XtGetPerWidgetInput (widget, FALSE); 1058444c061aSmrg 1059444c061aSmrg if (pwi != NULL && !pwi->realize_handler_added) { 1060444c061aSmrg XtAddEventHandler(widget, StructureNotifyMask, FALSE, 1061444c061aSmrg RealizeHandler, 1062444c061aSmrg (XtPointer)pwi); 1063444c061aSmrg pwi->realize_handler_added = TRUE; 1064444c061aSmrg } 1065444c061aSmrg} 1066