PassivGrab.c revision a3bd7f05
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/*********************** Internal Support Routines *************************/ 96444c061aSmrg/***************************************************************************/ 97444c061aSmrg 98444c061aSmrg/* 99444c061aSmrg * Turn off (clear) the bit in the specified detail mask which is associated 100444c061aSmrg * with the detail. 101444c061aSmrg */ 102444c061aSmrg 103a3bd7f05Smrgstatic void 104a3bd7f05SmrgDeleteDetailFromMask(Mask **ppDetailMask, unsigned short detail) 105444c061aSmrg{ 106444c061aSmrg Mask *pDetailMask = *ppDetailMask; 107444c061aSmrg 108444c061aSmrg if (!pDetailMask) { 109a3bd7f05Smrg int i; 110a3bd7f05Smrg 111a3bd7f05Smrg pDetailMask = (Mask *) __XtMalloc(sizeof(Mask) * MasksPerDetailMask); 112a3bd7f05Smrg for (i = MasksPerDetailMask; --i >= 0;) 113a3bd7f05Smrg pDetailMask[i] = (unsigned long) (~0); 114a3bd7f05Smrg *ppDetailMask = pDetailMask; 115444c061aSmrg } 116444c061aSmrg BITCLEAR((pDetailMask), detail); 117444c061aSmrg} 118444c061aSmrg 119444c061aSmrg/* 120444c061aSmrg * Make an exact copy of the specified detail mask. 121444c061aSmrg */ 122444c061aSmrg 123a3bd7f05Smrgstatic Mask * 124a3bd7f05SmrgCopyDetailMask(Mask *pOriginalDetailMask) 125444c061aSmrg{ 126444c061aSmrg Mask *pTempMask; 127444c061aSmrg int i; 128444c061aSmrg 129444c061aSmrg if (!pOriginalDetailMask) 130a3bd7f05Smrg return NULL; 131444c061aSmrg 132a3bd7f05Smrg pTempMask = (Mask *) __XtMalloc(sizeof(Mask) * MasksPerDetailMask); 133444c061aSmrg 134a3bd7f05Smrg for (i = 0; i < MasksPerDetailMask; i++) 135a3bd7f05Smrg pTempMask[i] = pOriginalDetailMask[i]; 136444c061aSmrg 137444c061aSmrg return pTempMask; 138444c061aSmrg} 139444c061aSmrg 140444c061aSmrg/* 141444c061aSmrg * Allocate a new grab entry, and fill in all of the fields using the 142444c061aSmrg * specified parameters. 143444c061aSmrg */ 144444c061aSmrg 145a3bd7f05Smrgstatic XtServerGrabPtr 146a3bd7f05SmrgCreateGrab(Widget widget, 147a3bd7f05Smrg Boolean ownerEvents, 148a3bd7f05Smrg Modifiers modifiers, 149a3bd7f05Smrg KeyCode keybut, 150a3bd7f05Smrg int pointer_mode, 151a3bd7f05Smrg int keyboard_mode, 152a3bd7f05Smrg Mask event_mask, 153a3bd7f05Smrg Window confine_to, 154a3bd7f05Smrg Cursor cursor, 155a3bd7f05Smrg Boolean need_ext) 156444c061aSmrg{ 157444c061aSmrg XtServerGrabPtr grab; 158444c061aSmrg 159444c061aSmrg if (confine_to || cursor) 160a3bd7f05Smrg need_ext = True; 161a3bd7f05Smrg grab = (XtServerGrabPtr) __XtMalloc(sizeof(XtServerGrabRec) + 162a3bd7f05Smrg (need_ext ? sizeof(XtServerGrabExtRec) 163a3bd7f05Smrg : 0)); 164444c061aSmrg grab->next = NULL; 165444c061aSmrg grab->widget = widget; 1660568f49bSmrg XtSetBit(grab->ownerEvents, ownerEvents); 1670568f49bSmrg XtSetBit(grab->pointerMode, pointer_mode); 1680568f49bSmrg XtSetBit(grab->keyboardMode, keyboard_mode); 169a3bd7f05Smrg grab->eventMask = (unsigned short) event_mask; 1700568f49bSmrg XtSetBit(grab->hasExt, need_ext); 171a3bd7f05Smrg grab->confineToIsWidgetWin = (XtWindow(widget) == confine_to); 1720568f49bSmrg grab->modifiers = (unsigned short) modifiers; 173444c061aSmrg grab->keybut = keybut; 174444c061aSmrg if (need_ext) { 175a3bd7f05Smrg XtServerGrabExtPtr ext = GRABEXT(grab); 176a3bd7f05Smrg 177a3bd7f05Smrg ext->pModifiersMask = NULL; 178a3bd7f05Smrg ext->pKeyButMask = NULL; 179a3bd7f05Smrg ext->confineTo = confine_to; 180a3bd7f05Smrg ext->cursor = cursor; 181444c061aSmrg } 182444c061aSmrg return grab; 183444c061aSmrg} 184444c061aSmrg 185444c061aSmrg/* 186444c061aSmrg * Free up the space occupied by a grab entry. 187444c061aSmrg */ 188444c061aSmrg 189a3bd7f05Smrgstatic void 190a3bd7f05SmrgFreeGrab(XtServerGrabPtr pGrab) 191444c061aSmrg{ 192444c061aSmrg if (pGrab->hasExt) { 193444c061aSmrg XtServerGrabExtPtr ext = GRABEXT(pGrab); 194a3bd7f05Smrg XtFree((char *)ext->pModifiersMask); 195a3bd7f05Smrg XtFree((char *)ext->pKeyButMask); 196444c061aSmrg } 197a3bd7f05Smrg XtFree((char *) pGrab); 198444c061aSmrg} 199444c061aSmrg 200444c061aSmrgtypedef struct _DetailRec { 201a3bd7f05Smrg unsigned short exact; 202a3bd7f05Smrg Mask *pMask; 203444c061aSmrg} DetailRec, *DetailPtr; 204444c061aSmrg 205444c061aSmrg/* 206444c061aSmrg * If the first detail is set to 'exception' and the second detail 207444c061aSmrg * is contained in the mask of the first, then TRUE is returned. 208444c061aSmrg */ 209444c061aSmrg 210a3bd7f05Smrgstatic Bool 211a3bd7f05SmrgIsInGrabMask(register DetailPtr firstDetail, 212a3bd7f05Smrg register DetailPtr secondDetail, 213a3bd7f05Smrg unsigned short exception) 214444c061aSmrg{ 215444c061aSmrg if (firstDetail->exact == exception) { 216a3bd7f05Smrg if (!firstDetail->pMask) 217a3bd7f05Smrg return TRUE; 218444c061aSmrg 219a3bd7f05Smrg /* (at present) never called with two non-null pMasks */ 220a3bd7f05Smrg if (secondDetail->exact == exception) 221a3bd7f05Smrg return FALSE; 222444c061aSmrg 223a3bd7f05Smrg if (GETBIT(firstDetail->pMask, secondDetail->exact)) 224a3bd7f05Smrg return TRUE; 225444c061aSmrg } 226444c061aSmrg 227444c061aSmrg return FALSE; 228444c061aSmrg} 229444c061aSmrg 230444c061aSmrg/* 231444c061aSmrg * If neither of the details is set to 'exception', and they match 232444c061aSmrg * exactly, then TRUE is returned. 233444c061aSmrg */ 234444c061aSmrg 235a3bd7f05Smrgstatic Bool 236a3bd7f05SmrgIdenticalExactDetails(unsigned short firstExact, 237a3bd7f05Smrg unsigned short secondExact, 238a3bd7f05Smrg unsigned short exception) 239444c061aSmrg{ 240444c061aSmrg if ((firstExact == exception) || (secondExact == exception)) 241a3bd7f05Smrg return FALSE; 242444c061aSmrg 243444c061aSmrg if (firstExact == secondExact) 244a3bd7f05Smrg return TRUE; 245444c061aSmrg 246444c061aSmrg return FALSE; 247444c061aSmrg} 248444c061aSmrg 249444c061aSmrg/* 250444c061aSmrg * If the first detail is set to 'exception', and its mask has the bit 251444c061aSmrg * enabled which corresponds to the second detail, OR if neither of the 252444c061aSmrg * details is set to 'exception' and the details match exactly, then 253444c061aSmrg * TRUE is returned. 254444c061aSmrg */ 255444c061aSmrg 256a3bd7f05Smrgstatic Bool 257a3bd7f05SmrgDetailSupersedesSecond(register DetailPtr firstDetail, 258a3bd7f05Smrg register DetailPtr secondDetail, 259a3bd7f05Smrg unsigned short exception) 260444c061aSmrg{ 261444c061aSmrg if (IsInGrabMask(firstDetail, secondDetail, exception)) 262a3bd7f05Smrg return TRUE; 263444c061aSmrg 264444c061aSmrg if (IdenticalExactDetails(firstDetail->exact, secondDetail->exact, 265a3bd7f05Smrg exception)) 266a3bd7f05Smrg return TRUE; 267444c061aSmrg 268444c061aSmrg return FALSE; 269444c061aSmrg} 270444c061aSmrg 271444c061aSmrg/* 272444c061aSmrg * If the two grab events match exactly, or if the first grab entry 273444c061aSmrg * 'encompasses' the second grab entry, then TRUE is returned. 274444c061aSmrg */ 275444c061aSmrg 276a3bd7f05Smrgstatic Bool 277a3bd7f05SmrgGrabSupersedesSecond(register XtServerGrabPtr pFirstGrab, 278a3bd7f05Smrg register XtServerGrabPtr pSecondGrab) 279444c061aSmrg{ 280444c061aSmrg DetailRec first, second; 281444c061aSmrg 282444c061aSmrg first.exact = pFirstGrab->modifiers; 283444c061aSmrg if (pFirstGrab->hasExt) 284a3bd7f05Smrg first.pMask = GRABEXT(pFirstGrab)->pModifiersMask; 285444c061aSmrg else 286a3bd7f05Smrg first.pMask = NULL; 287444c061aSmrg second.exact = pSecondGrab->modifiers; 288444c061aSmrg if (pSecondGrab->hasExt) 289a3bd7f05Smrg second.pMask = GRABEXT(pSecondGrab)->pModifiersMask; 290444c061aSmrg else 291a3bd7f05Smrg second.pMask = NULL; 292a3bd7f05Smrg if (!DetailSupersedesSecond(&first, &second, (unsigned short) AnyModifier)) 293a3bd7f05Smrg return FALSE; 294444c061aSmrg 295444c061aSmrg first.exact = pFirstGrab->keybut; 296444c061aSmrg if (pFirstGrab->hasExt) 297a3bd7f05Smrg first.pMask = GRABEXT(pFirstGrab)->pKeyButMask; 298444c061aSmrg else 299a3bd7f05Smrg first.pMask = NULL; 300444c061aSmrg second.exact = pSecondGrab->keybut; 301444c061aSmrg if (pSecondGrab->hasExt) 302a3bd7f05Smrg second.pMask = GRABEXT(pSecondGrab)->pKeyButMask; 303444c061aSmrg else 304a3bd7f05Smrg second.pMask = NULL; 305a3bd7f05Smrg if (DetailSupersedesSecond(&first, &second, (unsigned short) AnyKey)) 306a3bd7f05Smrg return TRUE; 307444c061aSmrg 308444c061aSmrg return FALSE; 309444c061aSmrg} 310444c061aSmrg 311444c061aSmrg/* 312444c061aSmrg * Two grabs are considered to be matching if either of the following are true: 313444c061aSmrg * 314444c061aSmrg * 1) The two grab entries match exactly, or the first grab entry 315444c061aSmrg * encompasses the second grab entry. 316444c061aSmrg * 2) The second grab entry encompasses the first grab entry. 317444c061aSmrg * 3) The keycodes match exactly, and one entry's modifiers encompasses 318444c061aSmrg * the others. 319444c061aSmrg * 4) The keycode for one entry encompasses the other, and the detail 320444c061aSmrg * for the other entry encompasses the first. 321444c061aSmrg */ 322444c061aSmrg 323a3bd7f05Smrgstatic Bool 324a3bd7f05SmrgGrabMatchesSecond(register XtServerGrabPtr pFirstGrab, 325a3bd7f05Smrg register XtServerGrabPtr pSecondGrab) 326444c061aSmrg{ 327444c061aSmrg DetailRec firstD, firstM, secondD, secondM; 328444c061aSmrg 329444c061aSmrg if (pDisplay(pFirstGrab) != pDisplay(pSecondGrab)) 330a3bd7f05Smrg return FALSE; 331444c061aSmrg 332444c061aSmrg if (GrabSupersedesSecond(pFirstGrab, pSecondGrab)) 333a3bd7f05Smrg return TRUE; 334444c061aSmrg 335444c061aSmrg if (GrabSupersedesSecond(pSecondGrab, pFirstGrab)) 336a3bd7f05Smrg return TRUE; 337444c061aSmrg 338444c061aSmrg firstD.exact = pFirstGrab->keybut; 339444c061aSmrg firstM.exact = pFirstGrab->modifiers; 340444c061aSmrg if (pFirstGrab->hasExt) { 341a3bd7f05Smrg firstD.pMask = GRABEXT(pFirstGrab)->pKeyButMask; 342a3bd7f05Smrg firstM.pMask = GRABEXT(pFirstGrab)->pModifiersMask; 343a3bd7f05Smrg } 344a3bd7f05Smrg else { 345a3bd7f05Smrg firstD.pMask = NULL; 346a3bd7f05Smrg firstM.pMask = NULL; 347444c061aSmrg } 348444c061aSmrg secondD.exact = pSecondGrab->keybut; 349444c061aSmrg secondM.exact = pSecondGrab->modifiers; 350444c061aSmrg if (pSecondGrab->hasExt) { 351a3bd7f05Smrg secondD.pMask = GRABEXT(pSecondGrab)->pKeyButMask; 352a3bd7f05Smrg secondM.pMask = GRABEXT(pSecondGrab)->pModifiersMask; 353a3bd7f05Smrg } 354a3bd7f05Smrg else { 355a3bd7f05Smrg secondD.pMask = NULL; 356a3bd7f05Smrg secondM.pMask = NULL; 357444c061aSmrg } 358444c061aSmrg 359a3bd7f05Smrg if (DetailSupersedesSecond(&secondD, &firstD, (unsigned short) AnyKey) && 360a3bd7f05Smrg DetailSupersedesSecond(&firstM, &secondM, (unsigned short) AnyModifier)) 361a3bd7f05Smrg return TRUE; 362444c061aSmrg 363a3bd7f05Smrg if (DetailSupersedesSecond(&firstD, &secondD, (unsigned short) AnyKey) && 364a3bd7f05Smrg DetailSupersedesSecond(&secondM, &firstM, (unsigned short) AnyModifier)) 365a3bd7f05Smrg return TRUE; 366444c061aSmrg 367444c061aSmrg return FALSE; 368444c061aSmrg} 369444c061aSmrg 370444c061aSmrg/* 371444c061aSmrg * Delete a grab combination from the passive grab list. Each entry will 372444c061aSmrg * be checked to see if it is affected by the grab being deleted. This 373444c061aSmrg * may result in multiple entries being modified/deleted. 374444c061aSmrg */ 375444c061aSmrg 376a3bd7f05Smrgstatic void 377a3bd7f05SmrgDeleteServerGrabFromList(XtServerGrabPtr *passiveListPtr, 378a3bd7f05Smrg XtServerGrabPtr pMinuendGrab) 379444c061aSmrg{ 380444c061aSmrg register XtServerGrabPtr *next; 381444c061aSmrg register XtServerGrabPtr grab; 382444c061aSmrg register XtServerGrabExtPtr ext; 383444c061aSmrg 384a3bd7f05Smrg for (next = passiveListPtr; (grab = *next);) { 385a3bd7f05Smrg if (GrabMatchesSecond(grab, pMinuendGrab) && 386a3bd7f05Smrg (pDisplay(grab) == pDisplay(pMinuendGrab))) { 387a3bd7f05Smrg if (GrabSupersedesSecond(pMinuendGrab, grab)) { 388a3bd7f05Smrg /* 389a3bd7f05Smrg * The entry being deleted encompasses the list entry, 390a3bd7f05Smrg * so delete the list entry. 391a3bd7f05Smrg */ 392a3bd7f05Smrg *next = grab->next; 393a3bd7f05Smrg FreeGrab(grab); 394a3bd7f05Smrg continue; 395a3bd7f05Smrg } 396a3bd7f05Smrg 397a3bd7f05Smrg if (!grab->hasExt) { 398a3bd7f05Smrg grab = (XtServerGrabPtr) 399a3bd7f05Smrg XtRealloc((char *) grab, (sizeof(XtServerGrabRec) + 400a3bd7f05Smrg sizeof(XtServerGrabExtRec))); 401a3bd7f05Smrg *next = grab; 402a3bd7f05Smrg grab->hasExt = True; 403a3bd7f05Smrg ext = GRABEXT(grab); 404a3bd7f05Smrg ext->pKeyButMask = NULL; 405a3bd7f05Smrg ext->pModifiersMask = NULL; 406a3bd7f05Smrg ext->confineTo = None; 407a3bd7f05Smrg ext->cursor = None; 408a3bd7f05Smrg } 409a3bd7f05Smrg else 410a3bd7f05Smrg ext = GRABEXT(grab); 411a3bd7f05Smrg if ((grab->keybut == AnyKey) && (grab->modifiers != AnyModifier)) { 412a3bd7f05Smrg /* 413a3bd7f05Smrg * If the list entry has the key detail of AnyKey, and 414a3bd7f05Smrg * a modifier detail not set to AnyModifier, then we 415a3bd7f05Smrg * simply need to turn off the key detail bit in the 416a3bd7f05Smrg * list entry's key detail mask. 417a3bd7f05Smrg */ 418a3bd7f05Smrg DeleteDetailFromMask(&ext->pKeyButMask, pMinuendGrab->keybut); 419a3bd7f05Smrg } 420a3bd7f05Smrg else if ((grab->modifiers == AnyModifier) && 421a3bd7f05Smrg (grab->keybut != AnyKey)) { 422a3bd7f05Smrg /* 423a3bd7f05Smrg * The list entry has a specific key detail, but its 424a3bd7f05Smrg * modifier detail is set to AnyModifier; so, we only 425a3bd7f05Smrg * need to turn off the specified modifier combination 426a3bd7f05Smrg * in the list entry's modifier mask. 427a3bd7f05Smrg */ 428a3bd7f05Smrg DeleteDetailFromMask(&ext->pModifiersMask, 429a3bd7f05Smrg pMinuendGrab->modifiers); 430a3bd7f05Smrg } 431a3bd7f05Smrg else if ((pMinuendGrab->keybut != AnyKey) && 432a3bd7f05Smrg (pMinuendGrab->modifiers != AnyModifier)) { 433a3bd7f05Smrg /* 434a3bd7f05Smrg * The list entry has a key detail of AnyKey and a 435a3bd7f05Smrg * modifier detail of AnyModifier; the entry being 436a3bd7f05Smrg * deleted has a specific key and a specific modifier 437a3bd7f05Smrg * combination. Therefore, we need to mask off the 438a3bd7f05Smrg * keycode from the list entry, and also create a 439a3bd7f05Smrg * new entry for this keycode, which has a modifier 440a3bd7f05Smrg * mask set to AnyModifier & ~(deleted modifiers). 441a3bd7f05Smrg */ 442a3bd7f05Smrg XtServerGrabPtr pNewGrab; 443a3bd7f05Smrg 444a3bd7f05Smrg DeleteDetailFromMask(&ext->pKeyButMask, pMinuendGrab->keybut); 445a3bd7f05Smrg pNewGrab = CreateGrab(grab->widget, 446a3bd7f05Smrg (Boolean) grab->ownerEvents, 447a3bd7f05Smrg (Modifiers) AnyModifier, 448a3bd7f05Smrg pMinuendGrab->keybut, 449a3bd7f05Smrg (int) grab->pointerMode, 450a3bd7f05Smrg (int) grab->keyboardMode, 451a3bd7f05Smrg (Mask) 0, (Window) 0, (Cursor) 0, True); 452a3bd7f05Smrg GRABEXT(pNewGrab)->pModifiersMask = 453a3bd7f05Smrg CopyDetailMask(ext->pModifiersMask); 454a3bd7f05Smrg 455a3bd7f05Smrg DeleteDetailFromMask(&GRABEXT(pNewGrab)->pModifiersMask, 456a3bd7f05Smrg pMinuendGrab->modifiers); 457a3bd7f05Smrg 458a3bd7f05Smrg pNewGrab->next = *passiveListPtr; 459a3bd7f05Smrg *passiveListPtr = pNewGrab; 460a3bd7f05Smrg } 461a3bd7f05Smrg else if (pMinuendGrab->keybut == AnyKey) { 462a3bd7f05Smrg /* 463a3bd7f05Smrg * The list entry has keycode AnyKey and modifier 464a3bd7f05Smrg * AnyModifier; the entry being deleted has 465a3bd7f05Smrg * keycode AnyKey and specific modifiers. So we 466a3bd7f05Smrg * simply need to mask off the specified modifier 467a3bd7f05Smrg * combination. 468a3bd7f05Smrg */ 469a3bd7f05Smrg DeleteDetailFromMask(&ext->pModifiersMask, 470a3bd7f05Smrg pMinuendGrab->modifiers); 471a3bd7f05Smrg } 472a3bd7f05Smrg else { 473a3bd7f05Smrg /* 474a3bd7f05Smrg * The list entry has keycode AnyKey and modifier 475a3bd7f05Smrg * AnyModifier; the entry being deleted has a 476a3bd7f05Smrg * specific keycode and modifier AnyModifier. So 477a3bd7f05Smrg * we simply need to mask off the specified 478a3bd7f05Smrg * keycode. 479a3bd7f05Smrg */ 480a3bd7f05Smrg DeleteDetailFromMask(&ext->pKeyButMask, pMinuendGrab->keybut); 481a3bd7f05Smrg } 482a3bd7f05Smrg } 483a3bd7f05Smrg next = &(*next)->next; 484444c061aSmrg } 485444c061aSmrg} 486444c061aSmrg 487a3bd7f05Smrgstatic void 488a3bd7f05SmrgDestroyPassiveList(XtServerGrabPtr *passiveListPtr) 489444c061aSmrg{ 490a3bd7f05Smrg XtServerGrabPtr next, grab; 491444c061aSmrg 492a3bd7f05Smrg for (next = *passiveListPtr; next;) { 493a3bd7f05Smrg grab = next; 494a3bd7f05Smrg next = grab->next; 495444c061aSmrg 496a3bd7f05Smrg /* not necessary to explicitly ungrab key or button; 497a3bd7f05Smrg * window is being destroyed so server will take care of it. 498a3bd7f05Smrg */ 499444c061aSmrg 500a3bd7f05Smrg FreeGrab(grab); 501444c061aSmrg } 502444c061aSmrg} 503444c061aSmrg 504444c061aSmrg/* 505444c061aSmrg * This function is called at widget destroy time to clean up 506444c061aSmrg */ 507a3bd7f05Smrgvoid 508a3bd7f05Smrg_XtDestroyServerGrabs(Widget w, 509a3bd7f05Smrg XtPointer closure, 510a3bd7f05Smrg XtPointer call_data _X_UNUSED) 511444c061aSmrg{ 512a3bd7f05Smrg XtPerWidgetInput pwi = (XtPerWidgetInput) closure; 513a3bd7f05Smrg XtPerDisplayInput pdi; 514444c061aSmrg 515444c061aSmrg LOCK_PROCESS; 516444c061aSmrg pdi = _XtGetPerDisplayInput(XtDisplay(w)); 517444c061aSmrg _XtClearAncestorCache(w); 518444c061aSmrg UNLOCK_PROCESS; 519444c061aSmrg 520444c061aSmrg /* Remove the active grab, if necessary */ 521444c061aSmrg if ((pdi->keyboard.grabType != XtNoServerGrab) && 522a3bd7f05Smrg (pdi->keyboard.grab.widget == w)) { 523a3bd7f05Smrg pdi->keyboard.grabType = XtNoServerGrab; 524a3bd7f05Smrg pdi->activatingKey = (KeyCode) 0; 525444c061aSmrg } 526444c061aSmrg if ((pdi->pointer.grabType != XtNoServerGrab) && 527a3bd7f05Smrg (pdi->pointer.grab.widget == w)) 528a3bd7f05Smrg pdi->pointer.grabType = XtNoServerGrab; 529444c061aSmrg 530444c061aSmrg DestroyPassiveList(&pwi->keyList); 531444c061aSmrg DestroyPassiveList(&pwi->ptrList); 532444c061aSmrg 533444c061aSmrg _XtFreePerWidgetInput(w, pwi); 534444c061aSmrg} 535444c061aSmrg 536444c061aSmrg/* 537444c061aSmrg * If the incoming event is on the passive grab list, then activate 538444c061aSmrg * the grab. The grab will remain in effect until the key is released. 539444c061aSmrg */ 540444c061aSmrg 541a3bd7f05SmrgXtServerGrabPtr 542a3bd7f05Smrg_XtCheckServerGrabsOnWidget(XEvent *event, Widget widget, _XtBoolean isKeyboard) 543444c061aSmrg{ 544444c061aSmrg register XtServerGrabPtr grab; 545a3bd7f05Smrg XtServerGrabRec tempGrab; 546a3bd7f05Smrg XtServerGrabPtr *passiveListPtr; 547a3bd7f05Smrg XtPerWidgetInput pwi; 548444c061aSmrg 549444c061aSmrg LOCK_PROCESS; 550444c061aSmrg pwi = _XtGetPerWidgetInput(widget, FALSE); 551444c061aSmrg UNLOCK_PROCESS; 552444c061aSmrg if (!pwi) 553a3bd7f05Smrg return (XtServerGrabPtr) NULL; 554444c061aSmrg if (isKeyboard) 555a3bd7f05Smrg passiveListPtr = &pwi->keyList; 556444c061aSmrg else 557a3bd7f05Smrg passiveListPtr = &pwi->ptrList; 558444c061aSmrg 559444c061aSmrg /* 560444c061aSmrg * if either there is no entry in the context manager or the entry 561444c061aSmrg * is empty, or the keyboard is grabed, then no work to be done 562444c061aSmrg */ 563444c061aSmrg if (!*passiveListPtr) 564a3bd7f05Smrg return (XtServerGrabPtr) NULL; 565444c061aSmrg 566444c061aSmrg /* Take only the lower thirteen bits as modifier state. The X Keyboard 567444c061aSmrg * Extension may be representing keyboard group state in two upper bits. 568444c061aSmrg */ 569444c061aSmrg tempGrab.widget = widget; 570a3bd7f05Smrg tempGrab.keybut = (KeyCode) event->xkey.keycode; /* also xbutton.button */ 571a3bd7f05Smrg tempGrab.modifiers = event->xkey.state & 0x1FFF; /*also xbutton.state */ 572444c061aSmrg tempGrab.hasExt = False; 573444c061aSmrg 574444c061aSmrg for (grab = *passiveListPtr; grab; grab = grab->next) { 575a3bd7f05Smrg if (GrabMatchesSecond(&tempGrab, grab)) 576a3bd7f05Smrg return (grab); 577444c061aSmrg } 578a3bd7f05Smrg return (XtServerGrabPtr) NULL; 579444c061aSmrg} 580444c061aSmrg 581444c061aSmrg/* 582444c061aSmrg * This handler is needed to guarantee that we see releases on passive 583444c061aSmrg * button grabs for widgets that haven't selected for button release. 584444c061aSmrg */ 585444c061aSmrg 586a3bd7f05Smrgstatic void 587a3bd7f05SmrgActiveHandler(Widget widget _X_UNUSED, 588a3bd7f05Smrg XtPointer pdi _X_UNUSED, 589a3bd7f05Smrg XEvent *event _X_UNUSED, 590a3bd7f05Smrg Boolean *cont _X_UNUSED) 591444c061aSmrg{ 592444c061aSmrg /* nothing */ 593444c061aSmrg} 594444c061aSmrg 595444c061aSmrg/* 596a3bd7f05Smrg * MakeGrab 597444c061aSmrg */ 598a3bd7f05Smrgstatic void 599a3bd7f05SmrgMakeGrab(XtServerGrabPtr grab, 600a3bd7f05Smrg XtServerGrabPtr *passiveListPtr, 601a3bd7f05Smrg Boolean isKeyboard, 602a3bd7f05Smrg XtPerDisplayInput pdi, 603a3bd7f05Smrg XtPerWidgetInput pwi) 604444c061aSmrg{ 605444c061aSmrg if (!isKeyboard && !pwi->active_handler_added) { 606a3bd7f05Smrg XtAddEventHandler(grab->widget, ButtonReleaseMask, FALSE, 607a3bd7f05Smrg ActiveHandler, (XtPointer) pdi); 608a3bd7f05Smrg pwi->active_handler_added = TRUE; 609444c061aSmrg } 610444c061aSmrg 611444c061aSmrg if (isKeyboard) { 612a3bd7f05Smrg XGrabKey(pDisplay(grab), 613a3bd7f05Smrg grab->keybut, grab->modifiers, 614a3bd7f05Smrg pWindow(grab), grab->ownerEvents, 615a3bd7f05Smrg grab->pointerMode, grab->keyboardMode); 616a3bd7f05Smrg } 617a3bd7f05Smrg else { 618a3bd7f05Smrg Window confineTo = None; 619a3bd7f05Smrg Cursor cursor = None; 620a3bd7f05Smrg 621a3bd7f05Smrg if (grab->hasExt) { 622a3bd7f05Smrg if (grab->confineToIsWidgetWin) 623a3bd7f05Smrg confineTo = XtWindow(grab->widget); 624a3bd7f05Smrg else 625a3bd7f05Smrg confineTo = GRABEXT(grab)->confineTo; 626a3bd7f05Smrg cursor = GRABEXT(grab)->cursor; 627a3bd7f05Smrg } 628a3bd7f05Smrg XGrabButton(pDisplay(grab), 629a3bd7f05Smrg grab->keybut, grab->modifiers, 630a3bd7f05Smrg pWindow(grab), grab->ownerEvents, grab->eventMask, 631a3bd7f05Smrg grab->pointerMode, grab->keyboardMode, confineTo, cursor); 632444c061aSmrg } 633444c061aSmrg 634444c061aSmrg /* Add the new grab entry to the passive key grab list */ 635444c061aSmrg grab->next = *passiveListPtr; 636444c061aSmrg *passiveListPtr = grab; 637444c061aSmrg} 638444c061aSmrg 639a3bd7f05Smrgstatic void 640a3bd7f05SmrgMakeGrabs(XtServerGrabPtr *passiveListPtr, 641a3bd7f05Smrg Boolean isKeyboard, 642a3bd7f05Smrg XtPerDisplayInput pdi) 643444c061aSmrg{ 644a3bd7f05Smrg XtServerGrabPtr next = *passiveListPtr; 645a3bd7f05Smrg 646444c061aSmrg /* 647444c061aSmrg * make MakeGrab build a new list that has had the merge 648444c061aSmrg * processing done on it. Start with an empty list 649444c061aSmrg * (passiveListPtr). 650444c061aSmrg */ 651444c061aSmrg LOCK_PROCESS; 652444c061aSmrg *passiveListPtr = NULL; 653a3bd7f05Smrg while (next) { 654a3bd7f05Smrg XtServerGrabPtr grab; 655a3bd7f05Smrg XtPerWidgetInput pwi; 656a3bd7f05Smrg 657a3bd7f05Smrg grab = next; 658a3bd7f05Smrg next = grab->next; 659a3bd7f05Smrg pwi = _XtGetPerWidgetInput(grab->widget, FALSE); 660a3bd7f05Smrg MakeGrab(grab, passiveListPtr, isKeyboard, pdi, pwi); 661a3bd7f05Smrg } 662444c061aSmrg UNLOCK_PROCESS; 663444c061aSmrg} 664444c061aSmrg 665444c061aSmrg/* 666444c061aSmrg * This function is the event handler attached to the associated widget 667444c061aSmrg * when grabs need to be added, but the widget is not yet realized. When 668444c061aSmrg * it is first mapped, this handler will be invoked, and it will add all 669444c061aSmrg * needed grabs. 670444c061aSmrg */ 671444c061aSmrg 672a3bd7f05Smrgstatic void 673a3bd7f05SmrgRealizeHandler(Widget widget, 674a3bd7f05Smrg XtPointer closure, 675a3bd7f05Smrg XEvent *event _X_UNUSED, 676a3bd7f05Smrg Boolean *cont _X_UNUSED) 677444c061aSmrg{ 678a3bd7f05Smrg XtPerWidgetInput pwi = (XtPerWidgetInput) closure; 679a3bd7f05Smrg XtPerDisplayInput pdi; 680444c061aSmrg 681444c061aSmrg LOCK_PROCESS; 682444c061aSmrg pdi = _XtGetPerDisplayInput(XtDisplay(widget)); 683444c061aSmrg UNLOCK_PROCESS; 684444c061aSmrg MakeGrabs(&pwi->keyList, KEYBOARD, pdi); 685444c061aSmrg MakeGrabs(&pwi->ptrList, POINTER, pdi); 686444c061aSmrg 687444c061aSmrg XtRemoveEventHandler(widget, XtAllEvents, True, 688a3bd7f05Smrg RealizeHandler, (XtPointer) pwi); 689444c061aSmrg pwi->realize_handler_added = FALSE; 690444c061aSmrg} 691444c061aSmrg 692444c061aSmrg/***************************************************************************/ 693444c061aSmrg/**************************** Global Routines ******************************/ 694444c061aSmrg/***************************************************************************/ 695444c061aSmrg 696444c061aSmrg/* 697444c061aSmrg * Routine used by an application to set up a passive grab for a key/modifier 698444c061aSmrg * combination. 699444c061aSmrg */ 700444c061aSmrg 701a3bd7f05Smrgstatic void 702a3bd7f05SmrgGrabKeyOrButton(Widget widget, 703a3bd7f05Smrg KeyCode keyOrButton, 704a3bd7f05Smrg Modifiers modifiers, 705a3bd7f05Smrg Boolean owner_events, 706a3bd7f05Smrg int pointer_mode, 707a3bd7f05Smrg int keyboard_mode, 708a3bd7f05Smrg Mask event_mask, 709a3bd7f05Smrg Window confine_to, 710a3bd7f05Smrg Cursor cursor, 711a3bd7f05Smrg Boolean isKeyboard) 712444c061aSmrg{ 713a3bd7f05Smrg XtServerGrabPtr *passiveListPtr; 714a3bd7f05Smrg XtServerGrabPtr newGrab; 715a3bd7f05Smrg XtPerWidgetInput pwi; 716a3bd7f05Smrg XtPerDisplayInput pdi; 717444c061aSmrg 718444c061aSmrg XtCheckSubclass(widget, coreWidgetClass, "in XtGrabKey or XtGrabButton"); 719444c061aSmrg LOCK_PROCESS; 720444c061aSmrg pwi = _XtGetPerWidgetInput(widget, TRUE); 721444c061aSmrg if (isKeyboard) 722a3bd7f05Smrg passiveListPtr = &pwi->keyList; 723444c061aSmrg else 724a3bd7f05Smrg passiveListPtr = &pwi->ptrList; 725444c061aSmrg pdi = _XtGetPerDisplayInput(XtDisplay(widget)); 726444c061aSmrg UNLOCK_PROCESS; 727444c061aSmrg newGrab = CreateGrab(widget, owner_events, modifiers, 728a3bd7f05Smrg keyOrButton, pointer_mode, keyboard_mode, 729a3bd7f05Smrg event_mask, confine_to, cursor, False); 730444c061aSmrg /* 731444c061aSmrg * if the widget is realized then process the entry into the grab 732444c061aSmrg * list. else if the list is empty (i.e. first time) then add the 733444c061aSmrg * event handler. then add the raw entry to the list for processing 734444c061aSmrg * in the handler at realize time. 735444c061aSmrg */ 736444c061aSmrg if (XtIsRealized(widget)) 737a3bd7f05Smrg MakeGrab(newGrab, passiveListPtr, isKeyboard, pdi, pwi); 738444c061aSmrg else { 739a3bd7f05Smrg if (!pwi->realize_handler_added) { 740a3bd7f05Smrg XtAddEventHandler(widget, StructureNotifyMask, FALSE, 741a3bd7f05Smrg RealizeHandler, (XtPointer) pwi); 742a3bd7f05Smrg pwi->realize_handler_added = TRUE; 743a3bd7f05Smrg } 744a3bd7f05Smrg 745a3bd7f05Smrg while (*passiveListPtr) 746a3bd7f05Smrg passiveListPtr = &(*passiveListPtr)->next; 747a3bd7f05Smrg *passiveListPtr = newGrab; 748444c061aSmrg } 749444c061aSmrg} 750444c061aSmrg 751a3bd7f05Smrgstatic void 752a3bd7f05SmrgUngrabKeyOrButton(Widget widget, 753a3bd7f05Smrg int keyOrButton, 754a3bd7f05Smrg Modifiers modifiers, 755a3bd7f05Smrg Boolean isKeyboard) 756444c061aSmrg{ 757a3bd7f05Smrg XtServerGrabRec tempGrab; 758a3bd7f05Smrg XtPerWidgetInput pwi; 759444c061aSmrg 760444c061aSmrg XtCheckSubclass(widget, coreWidgetClass, 761a3bd7f05Smrg "in XtUngrabKey or XtUngrabButton"); 762444c061aSmrg 763444c061aSmrg /* Build a temporary grab list entry */ 764444c061aSmrg tempGrab.widget = widget; 7650568f49bSmrg tempGrab.modifiers = (unsigned short) modifiers; 7660568f49bSmrg tempGrab.keybut = (KeyCode) keyOrButton; 767444c061aSmrg tempGrab.hasExt = False; 768444c061aSmrg 769444c061aSmrg LOCK_PROCESS; 770444c061aSmrg pwi = _XtGetPerWidgetInput(widget, FALSE); 771444c061aSmrg UNLOCK_PROCESS; 772444c061aSmrg /* 773444c061aSmrg * if there is no entry in the context manager then somethings wrong 774444c061aSmrg */ 775a3bd7f05Smrg if (!pwi) { 776a3bd7f05Smrg XtAppWarningMsg(XtWidgetToApplicationContext(widget), 777a3bd7f05Smrg "invalidGrab", "ungrabKeyOrButton", XtCXtToolkitError, 778a3bd7f05Smrg "Attempt to remove nonexistent passive grab", 779a3bd7f05Smrg NULL, NULL); 780a3bd7f05Smrg return; 781a3bd7f05Smrg } 782444c061aSmrg 783a3bd7f05Smrg if (XtIsRealized(widget)) { 784a3bd7f05Smrg if (isKeyboard) 785a3bd7f05Smrg XUngrabKey(widget->core.screen->display, 786a3bd7f05Smrg keyOrButton, (unsigned int) modifiers, 787a3bd7f05Smrg widget->core.window); 788a3bd7f05Smrg else 789a3bd7f05Smrg XUngrabButton(widget->core.screen->display, 790a3bd7f05Smrg (unsigned) keyOrButton, (unsigned int) modifiers, 791a3bd7f05Smrg widget->core.window); 792a3bd7f05Smrg } 793444c061aSmrg 794444c061aSmrg /* Delete all entries which are encompassed by the specified grab. */ 795444c061aSmrg DeleteServerGrabFromList(isKeyboard ? &pwi->keyList : &pwi->ptrList, 796a3bd7f05Smrg &tempGrab); 797444c061aSmrg} 798444c061aSmrg 799a3bd7f05Smrgvoid 800a3bd7f05SmrgXtGrabKey(Widget widget, 801a3bd7f05Smrg _XtKeyCode keycode, 802a3bd7f05Smrg Modifiers modifiers, 803a3bd7f05Smrg _XtBoolean owner_events, 804a3bd7f05Smrg int pointer_mode, 805a3bd7f05Smrg int keyboard_mode) 806444c061aSmrg{ 807444c061aSmrg WIDGET_TO_APPCON(widget); 808444c061aSmrg 809444c061aSmrg LOCK_APP(app); 810a3bd7f05Smrg GrabKeyOrButton(widget, (KeyCode) keycode, modifiers, 811a3bd7f05Smrg (Boolean) owner_events, pointer_mode, keyboard_mode, 812a3bd7f05Smrg (Mask) 0, (Window) None, (Cursor) None, KEYBOARD); 813444c061aSmrg UNLOCK_APP(app); 814444c061aSmrg} 815444c061aSmrg 816a3bd7f05Smrgvoid 817a3bd7f05SmrgXtGrabButton(Widget widget, 818a3bd7f05Smrg int button, 819a3bd7f05Smrg Modifiers modifiers, 820a3bd7f05Smrg _XtBoolean owner_events, 821a3bd7f05Smrg unsigned int event_mask, 822a3bd7f05Smrg int pointer_mode, 823a3bd7f05Smrg int keyboard_mode, 824a3bd7f05Smrg Window confine_to, 825a3bd7f05Smrg Cursor cursor) 826444c061aSmrg{ 827444c061aSmrg WIDGET_TO_APPCON(widget); 828444c061aSmrg 829444c061aSmrg LOCK_APP(app); 830a3bd7f05Smrg GrabKeyOrButton(widget, (KeyCode) button, modifiers, (Boolean) owner_events, 831a3bd7f05Smrg pointer_mode, keyboard_mode, 832a3bd7f05Smrg (Mask) event_mask, confine_to, cursor, POINTER); 833444c061aSmrg UNLOCK_APP(app); 834444c061aSmrg} 835444c061aSmrg 836444c061aSmrg/* 837444c061aSmrg * Routine used by an application to clear a passive grab for a key/modifier 838444c061aSmrg * combination. 839444c061aSmrg */ 840444c061aSmrg 841a3bd7f05Smrgvoid 842a3bd7f05SmrgXtUngrabKey(Widget widget, _XtKeyCode keycode, Modifiers modifiers) 843444c061aSmrg{ 844444c061aSmrg WIDGET_TO_APPCON(widget); 845444c061aSmrg 846444c061aSmrg LOCK_APP(app); 847a3bd7f05Smrg UngrabKeyOrButton(widget, (int) keycode, modifiers, KEYBOARD); 848444c061aSmrg UNLOCK_APP(app); 849444c061aSmrg} 850444c061aSmrg 851a3bd7f05Smrgvoid 852a3bd7f05SmrgXtUngrabButton(Widget widget, unsigned int button, Modifiers modifiers) 853444c061aSmrg{ 854444c061aSmrg WIDGET_TO_APPCON(widget); 855444c061aSmrg 856444c061aSmrg LOCK_APP(app); 857a3bd7f05Smrg UngrabKeyOrButton(widget, (KeyCode) button, modifiers, POINTER); 858444c061aSmrg UNLOCK_APP(app); 859444c061aSmrg} 860444c061aSmrg 861444c061aSmrg/* 862444c061aSmrg * Active grab of Device. clear any client side grabs so we dont lock 863444c061aSmrg */ 864a3bd7f05Smrgstatic int 865a3bd7f05SmrgGrabDevice(Widget widget, 866a3bd7f05Smrg Boolean owner_events, 867a3bd7f05Smrg int pointer_mode, 868a3bd7f05Smrg int keyboard_mode, 869a3bd7f05Smrg Mask event_mask, 870a3bd7f05Smrg Window confine_to, 871a3bd7f05Smrg Cursor cursor, 872a3bd7f05Smrg Time time, 873a3bd7f05Smrg Boolean isKeyboard) 874444c061aSmrg{ 875a3bd7f05Smrg XtPerDisplayInput pdi; 876a3bd7f05Smrg int returnVal; 877444c061aSmrg 878444c061aSmrg XtCheckSubclass(widget, coreWidgetClass, 879a3bd7f05Smrg "in XtGrabKeyboard or XtGrabPointer"); 880444c061aSmrg if (!XtIsRealized(widget)) 881a3bd7f05Smrg return GrabNotViewable; 882444c061aSmrg LOCK_PROCESS; 883444c061aSmrg pdi = _XtGetPerDisplayInput(XtDisplay(widget)); 884444c061aSmrg UNLOCK_PROCESS; 885444c061aSmrg if (!isKeyboard) 886a3bd7f05Smrg returnVal = XGrabPointer(XtDisplay(widget), XtWindow(widget), 887a3bd7f05Smrg owner_events, (unsigned) event_mask, 888a3bd7f05Smrg pointer_mode, keyboard_mode, 889a3bd7f05Smrg confine_to, cursor, time); 890444c061aSmrg else 891a3bd7f05Smrg returnVal = XGrabKeyboard(XtDisplay(widget), XtWindow(widget), 892a3bd7f05Smrg owner_events, pointer_mode, 893a3bd7f05Smrg keyboard_mode, time); 894444c061aSmrg 895444c061aSmrg if (returnVal == GrabSuccess) { 896a3bd7f05Smrg XtDevice device; 897a3bd7f05Smrg 898a3bd7f05Smrg device = isKeyboard ? &pdi->keyboard : &pdi->pointer; 899a3bd7f05Smrg 900a3bd7f05Smrg /* fill in the server grab rec */ 901a3bd7f05Smrg device->grab.widget = widget; 902a3bd7f05Smrg device->grab.modifiers = 0; 903a3bd7f05Smrg device->grab.keybut = 0; 904a3bd7f05Smrg XtSetBit(device->grab.ownerEvents, owner_events); 905a3bd7f05Smrg XtSetBit(device->grab.pointerMode, pointer_mode); 906a3bd7f05Smrg XtSetBit(device->grab.keyboardMode, keyboard_mode); 907a3bd7f05Smrg device->grab.hasExt = False; 908a3bd7f05Smrg device->grabType = XtActiveServerGrab; 909a3bd7f05Smrg pdi->activatingKey = (KeyCode) 0; 910a3bd7f05Smrg } 911444c061aSmrg return returnVal; 912444c061aSmrg} 913444c061aSmrg 914a3bd7f05Smrgstatic void 915a3bd7f05SmrgUngrabDevice(Widget widget, Time time, Boolean isKeyboard) 916444c061aSmrg{ 917444c061aSmrg XtPerDisplayInput pdi; 918444c061aSmrg XtDevice device; 919444c061aSmrg 920444c061aSmrg LOCK_PROCESS; 921444c061aSmrg pdi = _XtGetPerDisplayInput(XtDisplay(widget)); 922444c061aSmrg UNLOCK_PROCESS; 923444c061aSmrg device = isKeyboard ? &pdi->keyboard : &pdi->pointer; 924a3bd7f05Smrg 925444c061aSmrg XtCheckSubclass(widget, coreWidgetClass, 926a3bd7f05Smrg "in XtUngrabKeyboard or XtUngrabPointer"); 927444c061aSmrg 928444c061aSmrg if (device->grabType != XtNoServerGrab) { 929444c061aSmrg 930a3bd7f05Smrg if (device->grabType != XtPseudoPassiveServerGrab 931a3bd7f05Smrg && XtIsRealized(widget)) { 932a3bd7f05Smrg if (isKeyboard) 933a3bd7f05Smrg XUngrabKeyboard(XtDisplay(widget), time); 934a3bd7f05Smrg else 935a3bd7f05Smrg XUngrabPointer(XtDisplay(widget), time); 936a3bd7f05Smrg } 937a3bd7f05Smrg device->grabType = XtNoServerGrab; 938a3bd7f05Smrg pdi->activatingKey = (KeyCode) 0; 939444c061aSmrg } 940444c061aSmrg} 941444c061aSmrg 942444c061aSmrg/* 943444c061aSmrg * Active grab of keyboard. clear any client side grabs so we dont lock 944444c061aSmrg */ 945a3bd7f05Smrgint 946a3bd7f05SmrgXtGrabKeyboard(Widget widget, 947a3bd7f05Smrg _XtBoolean owner_events, 948a3bd7f05Smrg int pointer_mode, 949a3bd7f05Smrg int keyboard_mode, 950a3bd7f05Smrg Time time) 951444c061aSmrg{ 952444c061aSmrg int retval; 953a3bd7f05Smrg 954444c061aSmrg WIDGET_TO_APPCON(widget); 955444c061aSmrg 956444c061aSmrg LOCK_APP(app); 957a3bd7f05Smrg retval = GrabDevice(widget, (Boolean) owner_events, 958a3bd7f05Smrg pointer_mode, keyboard_mode, 959a3bd7f05Smrg (Mask) 0, (Window) None, (Cursor) None, time, KEYBOARD); 960444c061aSmrg UNLOCK_APP(app); 961444c061aSmrg return retval; 962444c061aSmrg} 963444c061aSmrg 964444c061aSmrg/* 965444c061aSmrg * Ungrab the keyboard 966444c061aSmrg */ 967444c061aSmrg 968a3bd7f05Smrgvoid 969a3bd7f05SmrgXtUngrabKeyboard(Widget widget, Time time) 970444c061aSmrg{ 971444c061aSmrg WIDGET_TO_APPCON(widget); 972444c061aSmrg 973444c061aSmrg LOCK_APP(app); 974444c061aSmrg UngrabDevice(widget, time, KEYBOARD); 975444c061aSmrg UNLOCK_APP(app); 976444c061aSmrg} 977444c061aSmrg 978444c061aSmrg/* 979444c061aSmrg * grab the pointer 980444c061aSmrg */ 981a3bd7f05Smrgint 982a3bd7f05SmrgXtGrabPointer(Widget widget, 983a3bd7f05Smrg _XtBoolean owner_events, 984a3bd7f05Smrg unsigned int event_mask, 985a3bd7f05Smrg int pointer_mode, 986a3bd7f05Smrg int keyboard_mode, 987a3bd7f05Smrg Window confine_to, 988a3bd7f05Smrg Cursor cursor, 989a3bd7f05Smrg Time time) 990444c061aSmrg{ 991444c061aSmrg int retval; 992a3bd7f05Smrg 993444c061aSmrg WIDGET_TO_APPCON(widget); 994444c061aSmrg 995444c061aSmrg LOCK_APP(app); 996a3bd7f05Smrg retval = GrabDevice(widget, (Boolean) owner_events, 997a3bd7f05Smrg pointer_mode, keyboard_mode, 998a3bd7f05Smrg (Mask) event_mask, confine_to, cursor, time, POINTER); 999444c061aSmrg UNLOCK_APP(app); 1000444c061aSmrg return retval; 1001444c061aSmrg} 1002444c061aSmrg 1003444c061aSmrg/* 1004444c061aSmrg * Ungrab the pointer 1005444c061aSmrg */ 1006444c061aSmrg 1007a3bd7f05Smrgvoid 1008a3bd7f05SmrgXtUngrabPointer(Widget widget, Time time) 1009444c061aSmrg{ 1010444c061aSmrg WIDGET_TO_APPCON(widget); 1011444c061aSmrg 1012444c061aSmrg LOCK_APP(app); 1013444c061aSmrg UngrabDevice(widget, time, POINTER); 1014444c061aSmrg UNLOCK_APP(app); 1015444c061aSmrg} 1016444c061aSmrg 1017a3bd7f05Smrgvoid 1018a3bd7f05Smrg_XtRegisterPassiveGrabs(Widget widget) 1019444c061aSmrg{ 1020a3bd7f05Smrg XtPerWidgetInput pwi = _XtGetPerWidgetInput(widget, FALSE); 1021444c061aSmrg 1022444c061aSmrg if (pwi != NULL && !pwi->realize_handler_added) { 1023a3bd7f05Smrg XtAddEventHandler(widget, StructureNotifyMask, FALSE, 1024a3bd7f05Smrg RealizeHandler, (XtPointer) pwi); 1025a3bd7f05Smrg pwi->realize_handler_added = TRUE; 1026444c061aSmrg } 1027444c061aSmrg} 1028