PassivGrab.c revision 249c3046
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; ) 114444c061aSmrg pDetailMask[i] = ~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; 169444c061aSmrg grab->ownerEvents = ownerEvents; 170444c061aSmrg grab->pointerMode = pointer_mode; 171444c061aSmrg grab->keyboardMode = keyboard_mode; 172444c061aSmrg grab->eventMask = event_mask; 173444c061aSmrg grab->hasExt = need_ext; 174444c061aSmrg grab->confineToIsWidgetWin = (XtWindow (widget) == confine_to); 175444c061aSmrg grab->modifiers = 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; 581444c061aSmrg tempGrab.keybut = 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 XtServerGrabPtr grab; 659444c061aSmrg XtPerWidgetInput pwi; 660444c061aSmrg /* 661444c061aSmrg * make MakeGrab build a new list that has had the merge 662444c061aSmrg * processing done on it. Start with an empty list 663444c061aSmrg * (passiveListPtr). 664444c061aSmrg */ 665444c061aSmrg LOCK_PROCESS; 666444c061aSmrg *passiveListPtr = NULL; 667444c061aSmrg while (next) 668444c061aSmrg { 669444c061aSmrg grab = next; 670444c061aSmrg next = grab->next; 671444c061aSmrg pwi = _XtGetPerWidgetInput(grab->widget, FALSE); 672444c061aSmrg MakeGrab(grab, passiveListPtr, isKeyboard, pdi, pwi); 673444c061aSmrg } 674444c061aSmrg UNLOCK_PROCESS; 675444c061aSmrg} 676444c061aSmrg 677444c061aSmrg/* 678444c061aSmrg * This function is the event handler attached to the associated widget 679444c061aSmrg * when grabs need to be added, but the widget is not yet realized. When 680444c061aSmrg * it is first mapped, this handler will be invoked, and it will add all 681444c061aSmrg * needed grabs. 682444c061aSmrg */ 683444c061aSmrg 684444c061aSmrg/*ARGSUSED*/ 685444c061aSmrgstatic void RealizeHandler ( 686444c061aSmrg Widget widget, 687444c061aSmrg XtPointer closure, 688444c061aSmrg XEvent *event, /* unused */ 689444c061aSmrg Boolean *cont) /* unused */ 690444c061aSmrg{ 691444c061aSmrg XtPerWidgetInput pwi = (XtPerWidgetInput)closure; 692444c061aSmrg XtPerDisplayInput pdi; 693444c061aSmrg 694444c061aSmrg LOCK_PROCESS; 695444c061aSmrg pdi = _XtGetPerDisplayInput(XtDisplay(widget)); 696444c061aSmrg UNLOCK_PROCESS; 697444c061aSmrg MakeGrabs(&pwi->keyList, KEYBOARD, pdi); 698444c061aSmrg MakeGrabs(&pwi->ptrList, POINTER, pdi); 699444c061aSmrg 700444c061aSmrg XtRemoveEventHandler(widget, XtAllEvents, True, 701444c061aSmrg RealizeHandler, (XtPointer)pwi); 702444c061aSmrg pwi->realize_handler_added = FALSE; 703444c061aSmrg} 704444c061aSmrg 705444c061aSmrg/***************************************************************************/ 706444c061aSmrg/**************************** Global Routines ******************************/ 707444c061aSmrg/***************************************************************************/ 708444c061aSmrg 709444c061aSmrg 710444c061aSmrg/* 711444c061aSmrg * Routine used by an application to set up a passive grab for a key/modifier 712444c061aSmrg * combination. 713444c061aSmrg */ 714444c061aSmrg 715444c061aSmrgstatic 716444c061aSmrgvoid GrabKeyOrButton ( 717444c061aSmrg Widget widget, 718444c061aSmrg KeyCode keyOrButton, 719444c061aSmrg Modifiers modifiers, 720444c061aSmrg Boolean owner_events, 721444c061aSmrg int pointer_mode, 722444c061aSmrg int keyboard_mode, 723444c061aSmrg Mask event_mask, 724444c061aSmrg Window confine_to, 725444c061aSmrg Cursor cursor, 726444c061aSmrg Boolean isKeyboard) 727444c061aSmrg{ 728444c061aSmrg XtServerGrabPtr *passiveListPtr; 729444c061aSmrg XtServerGrabPtr newGrab; 730444c061aSmrg XtPerWidgetInput pwi; 731444c061aSmrg XtPerDisplayInput pdi; 732444c061aSmrg 733444c061aSmrg 734444c061aSmrg XtCheckSubclass(widget, coreWidgetClass, "in XtGrabKey or XtGrabButton"); 735444c061aSmrg LOCK_PROCESS; 736444c061aSmrg pwi = _XtGetPerWidgetInput(widget, TRUE); 737444c061aSmrg if (isKeyboard) 738444c061aSmrg passiveListPtr = &pwi->keyList; 739444c061aSmrg else 740444c061aSmrg passiveListPtr = &pwi->ptrList; 741444c061aSmrg pdi = _XtGetPerDisplayInput(XtDisplay(widget)); 742444c061aSmrg UNLOCK_PROCESS; 743444c061aSmrg newGrab = CreateGrab(widget, owner_events, modifiers, 744444c061aSmrg keyOrButton, pointer_mode, keyboard_mode, 745444c061aSmrg event_mask, confine_to, cursor, False); 746444c061aSmrg /* 747444c061aSmrg * if the widget is realized then process the entry into the grab 748444c061aSmrg * list. else if the list is empty (i.e. first time) then add the 749444c061aSmrg * event handler. then add the raw entry to the list for processing 750444c061aSmrg * in the handler at realize time. 751444c061aSmrg */ 752444c061aSmrg if (XtIsRealized(widget)) 753444c061aSmrg MakeGrab(newGrab, passiveListPtr, isKeyboard, pdi, pwi); 754444c061aSmrg else { 755444c061aSmrg if (!pwi->realize_handler_added) 756444c061aSmrg { 757444c061aSmrg XtAddEventHandler(widget, StructureNotifyMask, FALSE, 758444c061aSmrg RealizeHandler, 759444c061aSmrg (XtPointer)pwi); 760444c061aSmrg pwi->realize_handler_added = TRUE; 761444c061aSmrg } 762444c061aSmrg 763444c061aSmrg while (*passiveListPtr) 764444c061aSmrg passiveListPtr = &(*passiveListPtr)->next; 765444c061aSmrg *passiveListPtr = newGrab; 766444c061aSmrg } 767444c061aSmrg} 768444c061aSmrg 769444c061aSmrg 770444c061aSmrgstatic 771444c061aSmrgvoid UngrabKeyOrButton ( 772444c061aSmrg Widget widget, 773444c061aSmrg int keyOrButton, 774444c061aSmrg Modifiers modifiers, 775444c061aSmrg Boolean isKeyboard) 776444c061aSmrg{ 777444c061aSmrg XtServerGrabRec tempGrab; 778444c061aSmrg XtPerWidgetInput pwi; 779444c061aSmrg 780444c061aSmrg XtCheckSubclass(widget, coreWidgetClass, 781444c061aSmrg "in XtUngrabKey or XtUngrabButton"); 782444c061aSmrg 783444c061aSmrg /* Build a temporary grab list entry */ 784444c061aSmrg tempGrab.widget = widget; 785444c061aSmrg tempGrab.modifiers = modifiers; 786444c061aSmrg tempGrab.keybut = keyOrButton; 787444c061aSmrg tempGrab.hasExt = False; 788444c061aSmrg 789444c061aSmrg LOCK_PROCESS; 790444c061aSmrg pwi = _XtGetPerWidgetInput(widget, FALSE); 791444c061aSmrg UNLOCK_PROCESS; 792444c061aSmrg /* 793444c061aSmrg * if there is no entry in the context manager then somethings wrong 794444c061aSmrg */ 795444c061aSmrg if (!pwi) 796444c061aSmrg { 797444c061aSmrg XtAppWarningMsg(XtWidgetToApplicationContext(widget), 798444c061aSmrg "invalidGrab", "ungrabKeyOrButton", XtCXtToolkitError, 799444c061aSmrg "Attempt to remove nonexistent passive grab", 800444c061aSmrg (String *)NULL, (Cardinal *)NULL); 801444c061aSmrg return; 802444c061aSmrg } 803444c061aSmrg 804444c061aSmrg if (XtIsRealized(widget)) 805444c061aSmrg { 806444c061aSmrg if (isKeyboard) 807444c061aSmrg XUngrabKey(widget->core.screen->display, 808444c061aSmrg keyOrButton, (unsigned int)modifiers, 809444c061aSmrg widget->core.window); 810444c061aSmrg else 811444c061aSmrg XUngrabButton(widget->core.screen->display, 812444c061aSmrg keyOrButton, (unsigned int)modifiers, 813444c061aSmrg widget->core.window); 814444c061aSmrg } 815444c061aSmrg 816444c061aSmrg 817444c061aSmrg /* Delete all entries which are encompassed by the specified grab. */ 818444c061aSmrg DeleteServerGrabFromList(isKeyboard ? &pwi->keyList : &pwi->ptrList, 819444c061aSmrg &tempGrab); 820444c061aSmrg} 821444c061aSmrg 822444c061aSmrgvoid XtGrabKey ( 823444c061aSmrg Widget widget, 824444c061aSmrg _XtKeyCode keycode, 825444c061aSmrg Modifiers modifiers, 826444c061aSmrg _XtBoolean owner_events, 827444c061aSmrg int pointer_mode, 828444c061aSmrg int keyboard_mode) 829444c061aSmrg{ 830444c061aSmrg WIDGET_TO_APPCON(widget); 831444c061aSmrg 832444c061aSmrg LOCK_APP(app); 833444c061aSmrg GrabKeyOrButton(widget, (KeyCode)keycode, modifiers, owner_events, 834444c061aSmrg pointer_mode, keyboard_mode, 835444c061aSmrg (Mask)0, (Window)None, (Cursor)None, KEYBOARD); 836444c061aSmrg UNLOCK_APP(app); 837444c061aSmrg} 838444c061aSmrg 839444c061aSmrgvoid XtGrabButton( 840444c061aSmrg Widget widget, 841444c061aSmrg int button, 842444c061aSmrg Modifiers modifiers, 843444c061aSmrg _XtBoolean owner_events, 844444c061aSmrg unsigned int event_mask, 845444c061aSmrg int pointer_mode, 846444c061aSmrg int keyboard_mode, 847444c061aSmrg Window confine_to, 848444c061aSmrg Cursor cursor) 849444c061aSmrg{ 850444c061aSmrg WIDGET_TO_APPCON(widget); 851444c061aSmrg 852444c061aSmrg LOCK_APP(app); 853444c061aSmrg GrabKeyOrButton(widget, (KeyCode)button, modifiers, owner_events, 854444c061aSmrg pointer_mode, keyboard_mode, 855444c061aSmrg (Mask)event_mask, confine_to, cursor, POINTER); 856444c061aSmrg UNLOCK_APP(app); 857444c061aSmrg} 858444c061aSmrg 859444c061aSmrg 860444c061aSmrg/* 861444c061aSmrg * Routine used by an application to clear a passive grab for a key/modifier 862444c061aSmrg * combination. 863444c061aSmrg */ 864444c061aSmrg 865444c061aSmrgvoid XtUngrabKey ( 866444c061aSmrg Widget widget, 867444c061aSmrg _XtKeyCode keycode, 868444c061aSmrg Modifiers modifiers) 869444c061aSmrg{ 870444c061aSmrg WIDGET_TO_APPCON(widget); 871444c061aSmrg 872444c061aSmrg LOCK_APP(app); 873444c061aSmrg UngrabKeyOrButton(widget, (int)keycode, modifiers, KEYBOARD); 874444c061aSmrg UNLOCK_APP(app); 875444c061aSmrg} 876444c061aSmrg 877444c061aSmrgvoid XtUngrabButton ( 878444c061aSmrg Widget widget, 879444c061aSmrg unsigned int button, 880444c061aSmrg Modifiers modifiers) 881444c061aSmrg{ 882444c061aSmrg WIDGET_TO_APPCON(widget); 883444c061aSmrg 884444c061aSmrg LOCK_APP(app); 885444c061aSmrg UngrabKeyOrButton(widget, (KeyCode)button, modifiers, POINTER); 886444c061aSmrg UNLOCK_APP(app); 887444c061aSmrg} 888444c061aSmrg 889444c061aSmrg/* 890444c061aSmrg * Active grab of Device. clear any client side grabs so we dont lock 891444c061aSmrg */ 892444c061aSmrgstatic int GrabDevice ( 893444c061aSmrg Widget widget, 894444c061aSmrg Boolean owner_events, 895444c061aSmrg int pointer_mode, 896444c061aSmrg int keyboard_mode, 897444c061aSmrg Mask event_mask, 898444c061aSmrg Window confine_to, 899444c061aSmrg Cursor cursor, 900444c061aSmrg Time time, 901444c061aSmrg Boolean isKeyboard) 902444c061aSmrg{ 903444c061aSmrg XtPerDisplayInput pdi; 904444c061aSmrg int returnVal; 905444c061aSmrg 906444c061aSmrg XtCheckSubclass(widget, coreWidgetClass, 907444c061aSmrg "in XtGrabKeyboard or XtGrabPointer"); 908444c061aSmrg if (!XtIsRealized(widget)) 909444c061aSmrg return GrabNotViewable; 910444c061aSmrg LOCK_PROCESS; 911444c061aSmrg pdi = _XtGetPerDisplayInput(XtDisplay(widget)); 912444c061aSmrg UNLOCK_PROCESS; 913444c061aSmrg if (!isKeyboard) 914444c061aSmrg returnVal = XGrabPointer(XtDisplay(widget), XtWindow(widget), 915444c061aSmrg owner_events, event_mask, 916444c061aSmrg pointer_mode, keyboard_mode, 917444c061aSmrg confine_to, cursor, time); 918444c061aSmrg else 919444c061aSmrg returnVal = XGrabKeyboard(XtDisplay(widget), XtWindow(widget), 920444c061aSmrg owner_events, pointer_mode, 921444c061aSmrg keyboard_mode, time); 922444c061aSmrg 923444c061aSmrg if (returnVal == GrabSuccess) { 924444c061aSmrg XtDevice device; 925444c061aSmrg 926444c061aSmrg device = isKeyboard ? &pdi->keyboard : &pdi->pointer; 927444c061aSmrg /* fill in the server grab rec */ 928444c061aSmrg device->grab.widget = widget; 929444c061aSmrg device->grab.modifiers = 0; 930444c061aSmrg device->grab.keybut = 0; 931444c061aSmrg device->grab.ownerEvents = owner_events; 932444c061aSmrg device->grab.pointerMode = pointer_mode; 933444c061aSmrg device->grab.keyboardMode = keyboard_mode; 934444c061aSmrg device->grab.hasExt = False; 935444c061aSmrg device->grabType = XtActiveServerGrab; 936444c061aSmrg pdi->activatingKey = (KeyCode)0; 937444c061aSmrg } 938444c061aSmrg return returnVal; 939444c061aSmrg} 940444c061aSmrg 941444c061aSmrgstatic void UngrabDevice( 942444c061aSmrg Widget widget, 943444c061aSmrg Time time, 944444c061aSmrg Boolean isKeyboard) 945444c061aSmrg{ 946444c061aSmrg XtPerDisplayInput pdi; 947444c061aSmrg XtDevice device; 948444c061aSmrg 949444c061aSmrg LOCK_PROCESS; 950444c061aSmrg pdi = _XtGetPerDisplayInput(XtDisplay(widget)); 951444c061aSmrg UNLOCK_PROCESS; 952444c061aSmrg device = isKeyboard ? &pdi->keyboard : &pdi->pointer; 953444c061aSmrg XtCheckSubclass(widget, coreWidgetClass, 954444c061aSmrg "in XtUngrabKeyboard or XtUngrabPointer"); 955444c061aSmrg 956444c061aSmrg if (device->grabType != XtNoServerGrab) { 957444c061aSmrg 958444c061aSmrg if (device->grabType != XtPseudoPassiveServerGrab 959444c061aSmrg && XtIsRealized(widget)) { 960444c061aSmrg if (isKeyboard) 961444c061aSmrg XUngrabKeyboard(XtDisplay(widget), time); 962444c061aSmrg else 963444c061aSmrg XUngrabPointer(XtDisplay(widget), time); 964444c061aSmrg } 965444c061aSmrg device->grabType = XtNoServerGrab; 966444c061aSmrg pdi->activatingKey = (KeyCode)0; 967444c061aSmrg } 968444c061aSmrg} 969444c061aSmrg 970444c061aSmrg 971444c061aSmrg/* 972444c061aSmrg * Active grab of keyboard. clear any client side grabs so we dont lock 973444c061aSmrg */ 974444c061aSmrgint XtGrabKeyboard ( 975444c061aSmrg Widget widget, 976444c061aSmrg _XtBoolean owner_events, 977444c061aSmrg int pointer_mode, 978444c061aSmrg int keyboard_mode, 979444c061aSmrg Time time) 980444c061aSmrg{ 981444c061aSmrg int retval; 982444c061aSmrg WIDGET_TO_APPCON(widget); 983444c061aSmrg 984444c061aSmrg LOCK_APP(app); 985444c061aSmrg retval = GrabDevice (widget, owner_events, 986444c061aSmrg pointer_mode, keyboard_mode, 987444c061aSmrg (Mask)0, (Window)None, (Cursor)None, time, KEYBOARD); 988444c061aSmrg UNLOCK_APP(app); 989444c061aSmrg return retval; 990444c061aSmrg} 991444c061aSmrg 992444c061aSmrg 993444c061aSmrg/* 994444c061aSmrg * Ungrab the keyboard 995444c061aSmrg */ 996444c061aSmrg 997444c061aSmrgvoid XtUngrabKeyboard( 998444c061aSmrg Widget widget, 999444c061aSmrg Time time) 1000444c061aSmrg{ 1001444c061aSmrg WIDGET_TO_APPCON(widget); 1002444c061aSmrg 1003444c061aSmrg LOCK_APP(app); 1004444c061aSmrg UngrabDevice(widget, time, KEYBOARD); 1005444c061aSmrg UNLOCK_APP(app); 1006444c061aSmrg} 1007444c061aSmrg 1008444c061aSmrg 1009444c061aSmrg 1010444c061aSmrg 1011444c061aSmrg/* 1012444c061aSmrg * grab the pointer 1013444c061aSmrg */ 1014444c061aSmrgint XtGrabPointer ( 1015444c061aSmrg Widget widget, 1016444c061aSmrg _XtBoolean owner_events, 1017444c061aSmrg unsigned int event_mask, 1018444c061aSmrg int pointer_mode, 1019444c061aSmrg int keyboard_mode, 1020444c061aSmrg Window confine_to, 1021444c061aSmrg Cursor cursor, 1022444c061aSmrg Time time) 1023444c061aSmrg{ 1024444c061aSmrg int retval; 1025444c061aSmrg WIDGET_TO_APPCON(widget); 1026444c061aSmrg 1027444c061aSmrg LOCK_APP(app); 1028444c061aSmrg retval = GrabDevice (widget, owner_events, 1029444c061aSmrg pointer_mode, keyboard_mode, 1030444c061aSmrg (Mask)event_mask, confine_to, 1031444c061aSmrg cursor, time, POINTER); 1032444c061aSmrg UNLOCK_APP(app); 1033444c061aSmrg return retval; 1034444c061aSmrg} 1035444c061aSmrg 1036444c061aSmrg 1037444c061aSmrg/* 1038444c061aSmrg * Ungrab the pointer 1039444c061aSmrg */ 1040444c061aSmrg 1041444c061aSmrgvoid XtUngrabPointer( 1042444c061aSmrg Widget widget, 1043444c061aSmrg Time time) 1044444c061aSmrg{ 1045444c061aSmrg WIDGET_TO_APPCON(widget); 1046444c061aSmrg 1047444c061aSmrg LOCK_APP(app); 1048444c061aSmrg UngrabDevice(widget, time, POINTER); 1049444c061aSmrg UNLOCK_APP(app); 1050444c061aSmrg} 1051444c061aSmrg 1052444c061aSmrg 1053444c061aSmrgvoid _XtRegisterPassiveGrabs ( 1054444c061aSmrg Widget widget) 1055444c061aSmrg{ 1056444c061aSmrg XtPerWidgetInput pwi = _XtGetPerWidgetInput (widget, FALSE); 1057444c061aSmrg 1058444c061aSmrg if (pwi != NULL && !pwi->realize_handler_added) { 1059444c061aSmrg XtAddEventHandler(widget, StructureNotifyMask, FALSE, 1060444c061aSmrg RealizeHandler, 1061444c061aSmrg (XtPointer)pwi); 1062444c061aSmrg pwi->realize_handler_added = TRUE; 1063444c061aSmrg } 1064444c061aSmrg} 1065