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