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