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