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