aboutsummaryrefslogtreecommitdiff
path: root/libXt/src/PassivGrab.c
diff options
context:
space:
mode:
Diffstat (limited to 'libXt/src/PassivGrab.c')
-rw-r--r--libXt/src/PassivGrab.c2130
1 files changed, 1064 insertions, 1066 deletions
diff --git a/libXt/src/PassivGrab.c b/libXt/src/PassivGrab.c
index b7648d1a6..d97ada27f 100644
--- a/libXt/src/PassivGrab.c
+++ b/libXt/src/PassivGrab.c
@@ -1,1066 +1,1064 @@
-/* $Xorg: PassivGrab.c,v 1.5 2001/02/09 02:03:56 xorgcvs Exp $ */
-/*
-
-Copyright 1993 Sun Microsystems, Inc. All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
-
-*/
-/********************************************************
-
-Copyright 1988 by Hewlett-Packard Company
-Copyright 1987, 1988, 1989,1990 by Digital Equipment Corporation, Maynard, Massachusetts
-
-Permission to use, copy, modify, and distribute this software
-and its documentation for any purpose and without fee is hereby
-granted, provided that the above copyright notice appear in all
-copies and that both that copyright notice and this permission
-notice appear in supporting documentation, and that the names of
-Hewlett-Packard or Digital not be used in advertising or
-publicity pertaining to distribution of the software without specific,
-written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-********************************************************/
-/* $XFree86$ */
-
-/*
-
-Copyright 1987, 1988, 1989, 1990, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "IntrinsicI.h"
-#include "StringDefs.h"
-#include "PassivGraI.h"
-
-/* typedef unsigned long Mask; */
-#define BITMASK(i) (((Mask)1) << ((i) & 31))
-#define MASKIDX(i) ((i) >> 5)
-#define MASKWORD(buf, i) buf[MASKIDX(i)]
-#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
-#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
-#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
-#define MasksPerDetailMask 8
-
-#define pDisplay(grabPtr) (((grabPtr)->widget)->core.screen->display)
-#define pWindow(grabPtr) (((grabPtr)->widget)->core.window)
-
-
-/***************************************************************************/
-/*********************** Internal Support Routines *************************/
-/***************************************************************************/
-
-/*
- * Turn off (clear) the bit in the specified detail mask which is associated
- * with the detail.
- */
-
-static void DeleteDetailFromMask(
- Mask **ppDetailMask,
- unsigned short detail)
-{
- Mask *pDetailMask = *ppDetailMask;
-
- if (!pDetailMask) {
- int i;
- pDetailMask = (Mask *)__XtMalloc(sizeof(Mask) * MasksPerDetailMask);
- for (i = MasksPerDetailMask; --i >= 0; )
- pDetailMask[i] = ~0;
- *ppDetailMask = pDetailMask;
- }
- BITCLEAR((pDetailMask), detail);
-}
-
-
-/*
- * Make an exact copy of the specified detail mask.
- */
-
-static Mask *CopyDetailMask(
- Mask *pOriginalDetailMask)
-{
- Mask *pTempMask;
- int i;
-
- if (!pOriginalDetailMask)
- return NULL;
-
- pTempMask = (Mask *)__XtMalloc(sizeof(Mask) * MasksPerDetailMask);
-
- for ( i = 0; i < MasksPerDetailMask; i++)
- pTempMask[i]= pOriginalDetailMask[i];
-
- return pTempMask;
-}
-
-
-/*
- * Allocate a new grab entry, and fill in all of the fields using the
- * specified parameters.
- */
-
-static XtServerGrabPtr CreateGrab(
- Widget widget,
- Boolean ownerEvents,
- Modifiers modifiers,
- KeyCode keybut,
- int pointer_mode,
- int keyboard_mode,
- Mask event_mask,
- Window confine_to,
- Cursor cursor,
- Boolean need_ext)
-{
- XtServerGrabPtr grab;
-
- if (confine_to || cursor)
- need_ext = True;
- grab = (XtServerGrabPtr)__XtMalloc(sizeof(XtServerGrabRec) +
- (need_ext ? sizeof(XtServerGrabExtRec)
- : 0));
- grab->next = NULL;
- grab->widget = widget;
- grab->ownerEvents = ownerEvents;
- grab->pointerMode = pointer_mode;
- grab->keyboardMode = keyboard_mode;
- grab->eventMask = event_mask;
- grab->hasExt = need_ext;
- grab->confineToIsWidgetWin = (XtWindow (widget) == confine_to);
- grab->modifiers = modifiers;
- grab->keybut = keybut;
- if (need_ext) {
- XtServerGrabExtPtr ext = GRABEXT(grab);
- ext->pModifiersMask = NULL;
- ext->pKeyButMask = NULL;
- ext->confineTo = confine_to;
- ext->cursor = cursor;
- }
- return grab;
-}
-
-
-/*
- * Free up the space occupied by a grab entry.
- */
-
-static void FreeGrab(
- XtServerGrabPtr pGrab)
-{
- if (pGrab->hasExt) {
- XtServerGrabExtPtr ext = GRABEXT(pGrab);
- if (ext->pModifiersMask)
- XtFree((char *)ext->pModifiersMask);
- if (ext->pKeyButMask)
- XtFree((char *)ext->pKeyButMask);
- }
- XtFree((char *)pGrab);
-}
-
-typedef struct _DetailRec {
- unsigned short exact;
- Mask *pMask;
-} DetailRec, *DetailPtr;
-
-/*
- * If the first detail is set to 'exception' and the second detail
- * is contained in the mask of the first, then TRUE is returned.
- */
-
-static Bool IsInGrabMask(
- register DetailPtr firstDetail,
- register DetailPtr secondDetail,
- unsigned short exception)
-{
- if (firstDetail->exact == exception) {
- if (!firstDetail->pMask)
- return TRUE;
-
- /* (at present) never called with two non-null pMasks */
- if (secondDetail->exact == exception)
- return FALSE;
-
- if (GETBIT(firstDetail->pMask, secondDetail->exact))
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-/*
- * If neither of the details is set to 'exception', and they match
- * exactly, then TRUE is returned.
- */
-
-static Bool IdenticalExactDetails(
- unsigned short firstExact,
- unsigned short secondExact,
- unsigned short exception)
-{
- if ((firstExact == exception) || (secondExact == exception))
- return FALSE;
-
- if (firstExact == secondExact)
- return TRUE;
-
- return FALSE;
-}
-
-
-/*
- * If the first detail is set to 'exception', and its mask has the bit
- * enabled which corresponds to the second detail, OR if neither of the
- * details is set to 'exception' and the details match exactly, then
- * TRUE is returned.
- */
-
-static Bool DetailSupersedesSecond(
- register DetailPtr firstDetail,
- register DetailPtr secondDetail,
- unsigned short exception)
-{
- if (IsInGrabMask(firstDetail, secondDetail, exception))
- return TRUE;
-
- if (IdenticalExactDetails(firstDetail->exact, secondDetail->exact,
- exception))
- return TRUE;
-
- return FALSE;
-}
-
-
-/*
- * If the two grab events match exactly, or if the first grab entry
- * 'encompasses' the second grab entry, then TRUE is returned.
- */
-
-static Bool GrabSupersedesSecond(
- register XtServerGrabPtr pFirstGrab,
- register XtServerGrabPtr pSecondGrab)
-{
- DetailRec first, second;
-
- first.exact = pFirstGrab->modifiers;
- if (pFirstGrab->hasExt)
- first.pMask = GRABEXT(pFirstGrab)->pModifiersMask;
- else
- first.pMask = NULL;
- second.exact = pSecondGrab->modifiers;
- if (pSecondGrab->hasExt)
- second.pMask = GRABEXT(pSecondGrab)->pModifiersMask;
- else
- second.pMask = NULL;
- if (!DetailSupersedesSecond(&first, &second, (unsigned short)AnyModifier))
- return FALSE;
-
- first.exact = pFirstGrab->keybut;
- if (pFirstGrab->hasExt)
- first.pMask = GRABEXT(pFirstGrab)->pKeyButMask;
- else
- first.pMask = NULL;
- second.exact = pSecondGrab->keybut;
- if (pSecondGrab->hasExt)
- second.pMask = GRABEXT(pSecondGrab)->pKeyButMask;
- else
- second.pMask = NULL;
- if (DetailSupersedesSecond(&first, &second, (unsigned short)AnyKey))
- return TRUE;
-
- return FALSE;
-}
-
-
-/*
- * Two grabs are considered to be matching if either of the following are true:
- *
- * 1) The two grab entries match exactly, or the first grab entry
- * encompasses the second grab entry.
- * 2) The second grab entry encompasses the first grab entry.
- * 3) The keycodes match exactly, and one entry's modifiers encompasses
- * the others.
- * 4) The keycode for one entry encompasses the other, and the detail
- * for the other entry encompasses the first.
- */
-
-static Bool GrabMatchesSecond(
- register XtServerGrabPtr pFirstGrab,
- register XtServerGrabPtr pSecondGrab)
-{
- DetailRec firstD, firstM, secondD, secondM;
-
- if (pDisplay(pFirstGrab) != pDisplay(pSecondGrab))
- return FALSE;
-
- if (GrabSupersedesSecond(pFirstGrab, pSecondGrab))
- return TRUE;
-
- if (GrabSupersedesSecond(pSecondGrab, pFirstGrab))
- return TRUE;
-
- firstD.exact = pFirstGrab->keybut;
- firstM.exact = pFirstGrab->modifiers;
- if (pFirstGrab->hasExt) {
- firstD.pMask = GRABEXT(pFirstGrab)->pKeyButMask;
- firstM.pMask = GRABEXT(pFirstGrab)->pModifiersMask;
- } else {
- firstD.pMask = NULL;
- firstM.pMask = NULL;
- }
- secondD.exact = pSecondGrab->keybut;
- secondM.exact = pSecondGrab->modifiers;
- if (pSecondGrab->hasExt) {
- secondD.pMask = GRABEXT(pSecondGrab)->pKeyButMask;
- secondM.pMask = GRABEXT(pSecondGrab)->pModifiersMask;
- } else {
- secondD.pMask = NULL;
- secondM.pMask = NULL;
- }
-
- if (DetailSupersedesSecond(&secondD, &firstD, (unsigned short)AnyKey) &&
- DetailSupersedesSecond(&firstM, &secondM, (unsigned short)AnyModifier))
- return TRUE;
-
- if (DetailSupersedesSecond(&firstD, &secondD, (unsigned short)AnyKey) &&
- DetailSupersedesSecond(&secondM, &firstM, (unsigned short)AnyModifier))
- return TRUE;
-
- return FALSE;
-}
-
-
-/*
- * Delete a grab combination from the passive grab list. Each entry will
- * be checked to see if it is affected by the grab being deleted. This
- * may result in multiple entries being modified/deleted.
- */
-
-static void DeleteServerGrabFromList(
- XtServerGrabPtr *passiveListPtr,
- XtServerGrabPtr pMinuendGrab)
-{
- register XtServerGrabPtr *next;
- register XtServerGrabPtr grab;
- register XtServerGrabExtPtr ext;
-
- for (next = passiveListPtr; (grab = *next); )
- {
- if (GrabMatchesSecond(grab, pMinuendGrab) &&
- (pDisplay(grab) == pDisplay(pMinuendGrab)))
- {
- if (GrabSupersedesSecond(pMinuendGrab, grab))
- {
- /*
- * The entry being deleted encompasses the list entry,
- * so delete the list entry.
- */
- *next = grab->next;
- FreeGrab(grab);
- continue;
- }
-
- if (!grab->hasExt) {
- grab = (XtServerGrabPtr)
- XtRealloc((char *)grab, (sizeof(XtServerGrabRec) +
- sizeof(XtServerGrabExtRec)));
- *next = grab;
- grab->hasExt = True;
- ext = GRABEXT(grab);
- ext->pKeyButMask = NULL;
- ext->pModifiersMask = NULL;
- ext->confineTo = None;
- ext->cursor = None;
- } else
- ext = GRABEXT(grab);
- if ((grab->keybut == AnyKey) && (grab->modifiers != AnyModifier))
- {
- /*
- * If the list entry has the key detail of AnyKey, and
- * a modifier detail not set to AnyModifier, then we
- * simply need to turn off the key detail bit in the
- * list entry's key detail mask.
- */
- DeleteDetailFromMask(&ext->pKeyButMask, pMinuendGrab->keybut);
- } else if ((grab->modifiers == AnyModifier) &&
- (grab->keybut != AnyKey)) {
- /*
- * The list entry has a specific key detail, but its
- * modifier detail is set to AnyModifier; so, we only
- * need to turn off the specified modifier combination
- * in the list entry's modifier mask.
- */
- DeleteDetailFromMask(&ext->pModifiersMask,
- pMinuendGrab->modifiers);
- } else if ((pMinuendGrab->keybut != AnyKey) &&
- (pMinuendGrab->modifiers != AnyModifier)) {
- /*
- * The list entry has a key detail of AnyKey and a
- * modifier detail of AnyModifier; the entry being
- * deleted has a specific key and a specific modifier
- * combination. Therefore, we need to mask off the
- * keycode from the list entry, and also create a
- * new entry for this keycode, which has a modifier
- * mask set to AnyModifier & ~(deleted modifiers).
- */
- XtServerGrabPtr pNewGrab;
-
- DeleteDetailFromMask(&ext->pKeyButMask, pMinuendGrab->keybut);
- pNewGrab = CreateGrab(grab->widget,
- (Boolean)grab->ownerEvents,
- (Modifiers)AnyModifier,
- pMinuendGrab->keybut,
- (int)grab->pointerMode,
- (int)grab->keyboardMode,
- (Mask)0, (Window)0, (Cursor)0, True);
- GRABEXT(pNewGrab)->pModifiersMask =
- CopyDetailMask(ext->pModifiersMask);
-
- DeleteDetailFromMask(&GRABEXT(pNewGrab)->pModifiersMask,
- pMinuendGrab->modifiers);
-
- pNewGrab->next = *passiveListPtr;
- *passiveListPtr = pNewGrab;
- } else if (pMinuendGrab->keybut == AnyKey) {
- /*
- * The list entry has keycode AnyKey and modifier
- * AnyModifier; the entry being deleted has
- * keycode AnyKey and specific modifiers. So we
- * simply need to mask off the specified modifier
- * combination.
- */
- DeleteDetailFromMask(&ext->pModifiersMask,
- pMinuendGrab->modifiers);
- } else {
- /*
- * The list entry has keycode AnyKey and modifier
- * AnyModifier; the entry being deleted has a
- * specific keycode and modifier AnyModifier. So
- * we simply need to mask off the specified
- * keycode.
- */
- DeleteDetailFromMask(&ext->pKeyButMask, pMinuendGrab->keybut);
- }
- }
- next = &(*next)->next;
- }
-}
-
-static void DestroyPassiveList(
- XtServerGrabPtr *passiveListPtr)
-{
- XtServerGrabPtr next, grab;
-
- for (next = *passiveListPtr; next; ) {
- grab = next;
- next = grab->next;
-
- /* not necessary to explicitly ungrab key or button;
- * window is being destroyed so server will take care of it.
- */
-
- FreeGrab(grab);
- }
-}
-
-
-/*
- * This function is called at widget destroy time to clean up
- */
-/*ARGSUSED*/
-void _XtDestroyServerGrabs(
- Widget w,
- XtPointer closure,
- XtPointer call_data) /* unused */
-{
- XtPerWidgetInput pwi = (XtPerWidgetInput)closure;
- XtPerDisplayInput pdi;
-
- LOCK_PROCESS;
- pdi = _XtGetPerDisplayInput(XtDisplay(w));
- _XtClearAncestorCache(w);
- UNLOCK_PROCESS;
-
- /* Remove the active grab, if necessary */
- if ((pdi->keyboard.grabType != XtNoServerGrab) &&
- (pdi->keyboard.grab.widget == w)) {
- pdi->keyboard.grabType = XtNoServerGrab;
- pdi->activatingKey = (KeyCode)0;
- }
- if ((pdi->pointer.grabType != XtNoServerGrab) &&
- (pdi->pointer.grab.widget == w))
- pdi->pointer.grabType = XtNoServerGrab;
-
- DestroyPassiveList(&pwi->keyList);
- DestroyPassiveList(&pwi->ptrList);
-
- _XtFreePerWidgetInput(w, pwi);
-}
-
-/*
- * If the incoming event is on the passive grab list, then activate
- * the grab. The grab will remain in effect until the key is released.
- */
-
-XtServerGrabPtr _XtCheckServerGrabsOnWidget (
- XEvent *event,
- Widget widget,
- _XtBoolean isKeyboard)
-{
- register XtServerGrabPtr grab;
- XtServerGrabRec tempGrab;
- XtServerGrabPtr *passiveListPtr;
- XtPerWidgetInput pwi;
-
- LOCK_PROCESS;
- pwi = _XtGetPerWidgetInput(widget, FALSE);
- UNLOCK_PROCESS;
- if (!pwi)
- return (XtServerGrabPtr)NULL;
- if (isKeyboard)
- passiveListPtr = &pwi->keyList;
- else
- passiveListPtr = &pwi->ptrList;
-
- /*
- * if either there is no entry in the context manager or the entry
- * is empty, or the keyboard is grabed, then no work to be done
- */
- if (!*passiveListPtr)
- return (XtServerGrabPtr)NULL;
-
- /* Take only the lower thirteen bits as modifier state. The X Keyboard
- * Extension may be representing keyboard group state in two upper bits.
- */
- tempGrab.widget = widget;
- tempGrab.keybut = event->xkey.keycode; /* also xbutton.button */
- tempGrab.modifiers = event->xkey.state & 0x1FFF; /*also xbutton.state*/
- tempGrab.hasExt = False;
-
- for (grab = *passiveListPtr; grab; grab = grab->next) {
- if (GrabMatchesSecond(&tempGrab, grab))
- return (grab);
- }
- return (XtServerGrabPtr)NULL;
-}
-
-/*
- * This handler is needed to guarantee that we see releases on passive
- * button grabs for widgets that haven't selected for button release.
- */
-
-/*ARGSUSED*/
-static void ActiveHandler (
- Widget widget,
- XtPointer pdi,
- XEvent *event,
- Boolean *cont)
-{
- /* nothing */
-}
-
-
-/*
- * MakeGrab
- */
-static void MakeGrab(
- XtServerGrabPtr grab,
- XtServerGrabPtr *passiveListPtr,
- Boolean isKeyboard,
- XtPerDisplayInput pdi,
- XtPerWidgetInput pwi)
-{
- if (!isKeyboard && !pwi->active_handler_added) {
- XtAddEventHandler(grab->widget, ButtonReleaseMask, FALSE,
- ActiveHandler, (XtPointer)pdi);
- pwi->active_handler_added = TRUE;
- }
-
- if (isKeyboard) {
- XGrabKey(pDisplay(grab),
- grab->keybut, grab->modifiers,
- pWindow(grab), grab->ownerEvents,
- grab->pointerMode, grab->keyboardMode);
- } else {
- Window confineTo = None;
- Cursor cursor = None;
-
- if (grab->hasExt) {
- if (grab->confineToIsWidgetWin)
- confineTo = XtWindow (grab->widget);
- else
- confineTo = GRABEXT(grab)->confineTo;
- cursor = GRABEXT(grab)->cursor;
- }
- XGrabButton(pDisplay(grab),
- grab->keybut, grab->modifiers,
- pWindow(grab), grab->ownerEvents, grab->eventMask,
- grab->pointerMode, grab->keyboardMode,
- confineTo, cursor);
- }
-
- /* Add the new grab entry to the passive key grab list */
- grab->next = *passiveListPtr;
- *passiveListPtr = grab;
-}
-
-static void MakeGrabs(
- XtServerGrabPtr *passiveListPtr,
- Boolean isKeyboard,
- XtPerDisplayInput pdi)
-{
- XtServerGrabPtr next = *passiveListPtr;
- XtServerGrabPtr grab;
- XtPerWidgetInput pwi;
- /*
- * make MakeGrab build a new list that has had the merge
- * processing done on it. Start with an empty list
- * (passiveListPtr).
- */
- LOCK_PROCESS;
- *passiveListPtr = NULL;
- while (next)
- {
- grab = next;
- next = grab->next;
- pwi = _XtGetPerWidgetInput(grab->widget, FALSE);
- MakeGrab(grab, passiveListPtr, isKeyboard, pdi, pwi);
- }
- UNLOCK_PROCESS;
-}
-
-/*
- * This function is the event handler attached to the associated widget
- * when grabs need to be added, but the widget is not yet realized. When
- * it is first mapped, this handler will be invoked, and it will add all
- * needed grabs.
- */
-
-/*ARGSUSED*/
-static void RealizeHandler (
- Widget widget,
- XtPointer closure,
- XEvent *event, /* unused */
- Boolean *cont) /* unused */
-{
- XtPerWidgetInput pwi = (XtPerWidgetInput)closure;
- XtPerDisplayInput pdi;
-
- LOCK_PROCESS;
- pdi = _XtGetPerDisplayInput(XtDisplay(widget));
- UNLOCK_PROCESS;
- MakeGrabs(&pwi->keyList, KEYBOARD, pdi);
- MakeGrabs(&pwi->ptrList, POINTER, pdi);
-
- XtRemoveEventHandler(widget, XtAllEvents, True,
- RealizeHandler, (XtPointer)pwi);
- pwi->realize_handler_added = FALSE;
-}
-
-/***************************************************************************/
-/**************************** Global Routines ******************************/
-/***************************************************************************/
-
-
-/*
- * Routine used by an application to set up a passive grab for a key/modifier
- * combination.
- */
-
-static
-void GrabKeyOrButton (
- Widget widget,
- KeyCode keyOrButton,
- Modifiers modifiers,
- Boolean owner_events,
- int pointer_mode,
- int keyboard_mode,
- Mask event_mask,
- Window confine_to,
- Cursor cursor,
- Boolean isKeyboard)
-{
- XtServerGrabPtr *passiveListPtr;
- XtServerGrabPtr newGrab;
- XtPerWidgetInput pwi;
- XtPerDisplayInput pdi;
-
-
- XtCheckSubclass(widget, coreWidgetClass, "in XtGrabKey or XtGrabButton");
- LOCK_PROCESS;
- pwi = _XtGetPerWidgetInput(widget, TRUE);
- if (isKeyboard)
- passiveListPtr = &pwi->keyList;
- else
- passiveListPtr = &pwi->ptrList;
- pdi = _XtGetPerDisplayInput(XtDisplay(widget));
- UNLOCK_PROCESS;
- newGrab = CreateGrab(widget, owner_events, modifiers,
- keyOrButton, pointer_mode, keyboard_mode,
- event_mask, confine_to, cursor, False);
- /*
- * if the widget is realized then process the entry into the grab
- * list. else if the list is empty (i.e. first time) then add the
- * event handler. then add the raw entry to the list for processing
- * in the handler at realize time.
- */
- if (XtIsRealized(widget))
- MakeGrab(newGrab, passiveListPtr, isKeyboard, pdi, pwi);
- else {
- if (!pwi->realize_handler_added)
- {
- XtAddEventHandler(widget, StructureNotifyMask, FALSE,
- RealizeHandler,
- (XtPointer)pwi);
- pwi->realize_handler_added = TRUE;
- }
-
- while (*passiveListPtr)
- passiveListPtr = &(*passiveListPtr)->next;
- *passiveListPtr = newGrab;
- }
-}
-
-
-static
-void UngrabKeyOrButton (
- Widget widget,
- int keyOrButton,
- Modifiers modifiers,
- Boolean isKeyboard)
-{
- XtServerGrabRec tempGrab;
- XtPerWidgetInput pwi;
-
- XtCheckSubclass(widget, coreWidgetClass,
- "in XtUngrabKey or XtUngrabButton");
-
- /* Build a temporary grab list entry */
- tempGrab.widget = widget;
- tempGrab.modifiers = modifiers;
- tempGrab.keybut = keyOrButton;
- tempGrab.hasExt = False;
-
- LOCK_PROCESS;
- pwi = _XtGetPerWidgetInput(widget, FALSE);
- UNLOCK_PROCESS;
- /*
- * if there is no entry in the context manager then somethings wrong
- */
- if (!pwi)
- {
- XtAppWarningMsg(XtWidgetToApplicationContext(widget),
- "invalidGrab", "ungrabKeyOrButton", XtCXtToolkitError,
- "Attempt to remove nonexistent passive grab",
- (String *)NULL, (Cardinal *)NULL);
- return;
- }
-
- if (XtIsRealized(widget))
- {
- if (isKeyboard)
- XUngrabKey(widget->core.screen->display,
- keyOrButton, (unsigned int)modifiers,
- widget->core.window);
- else
- XUngrabButton(widget->core.screen->display,
- keyOrButton, (unsigned int)modifiers,
- widget->core.window);
- }
-
-
- /* Delete all entries which are encompassed by the specified grab. */
- DeleteServerGrabFromList(isKeyboard ? &pwi->keyList : &pwi->ptrList,
- &tempGrab);
-}
-
-void XtGrabKey (
- Widget widget,
- _XtKeyCode keycode,
- Modifiers modifiers,
- _XtBoolean owner_events,
- int pointer_mode,
- int keyboard_mode)
-{
- WIDGET_TO_APPCON(widget);
-
- LOCK_APP(app);
- GrabKeyOrButton(widget, (KeyCode)keycode, modifiers, owner_events,
- pointer_mode, keyboard_mode,
- (Mask)0, (Window)None, (Cursor)None, KEYBOARD);
- UNLOCK_APP(app);
-}
-
-void XtGrabButton(
- Widget widget,
- int button,
- Modifiers modifiers,
- _XtBoolean owner_events,
- unsigned int event_mask,
- int pointer_mode,
- int keyboard_mode,
- Window confine_to,
- Cursor cursor)
-{
- WIDGET_TO_APPCON(widget);
-
- LOCK_APP(app);
- GrabKeyOrButton(widget, (KeyCode)button, modifiers, owner_events,
- pointer_mode, keyboard_mode,
- (Mask)event_mask, confine_to, cursor, POINTER);
- UNLOCK_APP(app);
-}
-
-
-/*
- * Routine used by an application to clear a passive grab for a key/modifier
- * combination.
- */
-
-void XtUngrabKey (
- Widget widget,
- _XtKeyCode keycode,
- Modifiers modifiers)
-{
- WIDGET_TO_APPCON(widget);
-
- LOCK_APP(app);
- UngrabKeyOrButton(widget, (int)keycode, modifiers, KEYBOARD);
- UNLOCK_APP(app);
-}
-
-void XtUngrabButton (
- Widget widget,
- unsigned int button,
- Modifiers modifiers)
-{
- WIDGET_TO_APPCON(widget);
-
- LOCK_APP(app);
- UngrabKeyOrButton(widget, (KeyCode)button, modifiers, POINTER);
- UNLOCK_APP(app);
-}
-
-/*
- * Active grab of Device. clear any client side grabs so we dont lock
- */
-static int GrabDevice (
- Widget widget,
- Boolean owner_events,
- int pointer_mode,
- int keyboard_mode,
- Mask event_mask,
- Window confine_to,
- Cursor cursor,
- Time time,
- Boolean isKeyboard)
-{
- XtPerDisplayInput pdi;
- int returnVal;
-
- XtCheckSubclass(widget, coreWidgetClass,
- "in XtGrabKeyboard or XtGrabPointer");
- if (!XtIsRealized(widget))
- return GrabNotViewable;
- LOCK_PROCESS;
- pdi = _XtGetPerDisplayInput(XtDisplay(widget));
- UNLOCK_PROCESS;
- if (!isKeyboard)
- returnVal = XGrabPointer(XtDisplay(widget), XtWindow(widget),
- owner_events, event_mask,
- pointer_mode, keyboard_mode,
- confine_to, cursor, time);
- else
- returnVal = XGrabKeyboard(XtDisplay(widget), XtWindow(widget),
- owner_events, pointer_mode,
- keyboard_mode, time);
-
- if (returnVal == GrabSuccess) {
- XtDevice device;
-
- device = isKeyboard ? &pdi->keyboard : &pdi->pointer;
- /* fill in the server grab rec */
- device->grab.widget = widget;
- device->grab.modifiers = 0;
- device->grab.keybut = 0;
- device->grab.ownerEvents = owner_events;
- device->grab.pointerMode = pointer_mode;
- device->grab.keyboardMode = keyboard_mode;
- device->grab.hasExt = False;
- device->grabType = XtActiveServerGrab;
- pdi->activatingKey = (KeyCode)0;
- }
- return returnVal;
-}
-
-static void UngrabDevice(
- Widget widget,
- Time time,
- Boolean isKeyboard)
-{
- XtPerDisplayInput pdi;
- XtDevice device;
-
- LOCK_PROCESS;
- pdi = _XtGetPerDisplayInput(XtDisplay(widget));
- UNLOCK_PROCESS;
- device = isKeyboard ? &pdi->keyboard : &pdi->pointer;
- XtCheckSubclass(widget, coreWidgetClass,
- "in XtUngrabKeyboard or XtUngrabPointer");
-
- if (device->grabType != XtNoServerGrab) {
-
- if (device->grabType != XtPseudoPassiveServerGrab
- && XtIsRealized(widget)) {
- if (isKeyboard)
- XUngrabKeyboard(XtDisplay(widget), time);
- else
- XUngrabPointer(XtDisplay(widget), time);
- }
- device->grabType = XtNoServerGrab;
- pdi->activatingKey = (KeyCode)0;
- }
-}
-
-
-/*
- * Active grab of keyboard. clear any client side grabs so we dont lock
- */
-int XtGrabKeyboard (
- Widget widget,
- _XtBoolean owner_events,
- int pointer_mode,
- int keyboard_mode,
- Time time)
-{
- int retval;
- WIDGET_TO_APPCON(widget);
-
- LOCK_APP(app);
- retval = GrabDevice (widget, owner_events,
- pointer_mode, keyboard_mode,
- (Mask)0, (Window)None, (Cursor)None, time, KEYBOARD);
- UNLOCK_APP(app);
- return retval;
-}
-
-
-/*
- * Ungrab the keyboard
- */
-
-void XtUngrabKeyboard(
- Widget widget,
- Time time)
-{
- WIDGET_TO_APPCON(widget);
-
- LOCK_APP(app);
- UngrabDevice(widget, time, KEYBOARD);
- UNLOCK_APP(app);
-}
-
-
-
-
-/*
- * grab the pointer
- */
-int XtGrabPointer (
- Widget widget,
- _XtBoolean owner_events,
- unsigned int event_mask,
- int pointer_mode,
- int keyboard_mode,
- Window confine_to,
- Cursor cursor,
- Time time)
-{
- int retval;
- WIDGET_TO_APPCON(widget);
-
- LOCK_APP(app);
- retval = GrabDevice (widget, owner_events,
- pointer_mode, keyboard_mode,
- (Mask)event_mask, confine_to,
- cursor, time, POINTER);
- UNLOCK_APP(app);
- return retval;
-}
-
-
-/*
- * Ungrab the pointer
- */
-
-void XtUngrabPointer(
- Widget widget,
- Time time)
-{
- WIDGET_TO_APPCON(widget);
-
- LOCK_APP(app);
- UngrabDevice(widget, time, POINTER);
- UNLOCK_APP(app);
-}
-
-
-void _XtRegisterPassiveGrabs (
- Widget widget)
-{
- XtPerWidgetInput pwi = _XtGetPerWidgetInput (widget, FALSE);
-
- if (pwi != NULL && !pwi->realize_handler_added) {
- XtAddEventHandler(widget, StructureNotifyMask, FALSE,
- RealizeHandler,
- (XtPointer)pwi);
- pwi->realize_handler_added = TRUE;
- }
-}
+/*
+
+Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+/********************************************************
+
+Copyright 1988 by Hewlett-Packard Company
+Copyright 1987, 1988, 1989,1990 by Digital Equipment Corporation, Maynard, Massachusetts
+
+Permission to use, copy, modify, and distribute this software
+and its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that copyright notice and this permission
+notice appear in supporting documentation, and that the names of
+Hewlett-Packard or Digital not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+********************************************************/
+
+/*
+
+Copyright 1987, 1988, 1989, 1990, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "IntrinsicI.h"
+#include "StringDefs.h"
+#include "PassivGraI.h"
+
+/* typedef unsigned long Mask; */
+#define BITMASK(i) (((Mask)1) << ((i) & 31))
+#define MASKIDX(i) ((i) >> 5)
+#define MASKWORD(buf, i) buf[MASKIDX(i)]
+#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
+#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
+#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
+#define MasksPerDetailMask 8
+
+#define pDisplay(grabPtr) (((grabPtr)->widget)->core.screen->display)
+#define pWindow(grabPtr) (((grabPtr)->widget)->core.window)
+
+
+/***************************************************************************/
+/*********************** Internal Support Routines *************************/
+/***************************************************************************/
+
+/*
+ * Turn off (clear) the bit in the specified detail mask which is associated
+ * with the detail.
+ */
+
+static void DeleteDetailFromMask(
+ Mask **ppDetailMask,
+ unsigned short detail)
+{
+ Mask *pDetailMask = *ppDetailMask;
+
+ if (!pDetailMask) {
+ int i;
+ pDetailMask = (Mask *)__XtMalloc(sizeof(Mask) * MasksPerDetailMask);
+ for (i = MasksPerDetailMask; --i >= 0; )
+ pDetailMask[i] = ~0;
+ *ppDetailMask = pDetailMask;
+ }
+ BITCLEAR((pDetailMask), detail);
+}
+
+
+/*
+ * Make an exact copy of the specified detail mask.
+ */
+
+static Mask *CopyDetailMask(
+ Mask *pOriginalDetailMask)
+{
+ Mask *pTempMask;
+ int i;
+
+ if (!pOriginalDetailMask)
+ return NULL;
+
+ pTempMask = (Mask *)__XtMalloc(sizeof(Mask) * MasksPerDetailMask);
+
+ for ( i = 0; i < MasksPerDetailMask; i++)
+ pTempMask[i]= pOriginalDetailMask[i];
+
+ return pTempMask;
+}
+
+
+/*
+ * Allocate a new grab entry, and fill in all of the fields using the
+ * specified parameters.
+ */
+
+static XtServerGrabPtr CreateGrab(
+ Widget widget,
+ Boolean ownerEvents,
+ Modifiers modifiers,
+ KeyCode keybut,
+ int pointer_mode,
+ int keyboard_mode,
+ Mask event_mask,
+ Window confine_to,
+ Cursor cursor,
+ Boolean need_ext)
+{
+ XtServerGrabPtr grab;
+
+ if (confine_to || cursor)
+ need_ext = True;
+ grab = (XtServerGrabPtr)__XtMalloc(sizeof(XtServerGrabRec) +
+ (need_ext ? sizeof(XtServerGrabExtRec)
+ : 0));
+ grab->next = NULL;
+ grab->widget = widget;
+ grab->ownerEvents = ownerEvents;
+ grab->pointerMode = pointer_mode;
+ grab->keyboardMode = keyboard_mode;
+ grab->eventMask = event_mask;
+ grab->hasExt = need_ext;
+ grab->confineToIsWidgetWin = (XtWindow (widget) == confine_to);
+ grab->modifiers = modifiers;
+ grab->keybut = keybut;
+ if (need_ext) {
+ XtServerGrabExtPtr ext = GRABEXT(grab);
+ ext->pModifiersMask = NULL;
+ ext->pKeyButMask = NULL;
+ ext->confineTo = confine_to;
+ ext->cursor = cursor;
+ }
+ return grab;
+}
+
+
+/*
+ * Free up the space occupied by a grab entry.
+ */
+
+static void FreeGrab(
+ XtServerGrabPtr pGrab)
+{
+ if (pGrab->hasExt) {
+ XtServerGrabExtPtr ext = GRABEXT(pGrab);
+ if (ext->pModifiersMask)
+ XtFree((char *)ext->pModifiersMask);
+ if (ext->pKeyButMask)
+ XtFree((char *)ext->pKeyButMask);
+ }
+ XtFree((char *)pGrab);
+}
+
+typedef struct _DetailRec {
+ unsigned short exact;
+ Mask *pMask;
+} DetailRec, *DetailPtr;
+
+/*
+ * If the first detail is set to 'exception' and the second detail
+ * is contained in the mask of the first, then TRUE is returned.
+ */
+
+static Bool IsInGrabMask(
+ register DetailPtr firstDetail,
+ register DetailPtr secondDetail,
+ unsigned short exception)
+{
+ if (firstDetail->exact == exception) {
+ if (!firstDetail->pMask)
+ return TRUE;
+
+ /* (at present) never called with two non-null pMasks */
+ if (secondDetail->exact == exception)
+ return FALSE;
+
+ if (GETBIT(firstDetail->pMask, secondDetail->exact))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * If neither of the details is set to 'exception', and they match
+ * exactly, then TRUE is returned.
+ */
+
+static Bool IdenticalExactDetails(
+ unsigned short firstExact,
+ unsigned short secondExact,
+ unsigned short exception)
+{
+ if ((firstExact == exception) || (secondExact == exception))
+ return FALSE;
+
+ if (firstExact == secondExact)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/*
+ * If the first detail is set to 'exception', and its mask has the bit
+ * enabled which corresponds to the second detail, OR if neither of the
+ * details is set to 'exception' and the details match exactly, then
+ * TRUE is returned.
+ */
+
+static Bool DetailSupersedesSecond(
+ register DetailPtr firstDetail,
+ register DetailPtr secondDetail,
+ unsigned short exception)
+{
+ if (IsInGrabMask(firstDetail, secondDetail, exception))
+ return TRUE;
+
+ if (IdenticalExactDetails(firstDetail->exact, secondDetail->exact,
+ exception))
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/*
+ * If the two grab events match exactly, or if the first grab entry
+ * 'encompasses' the second grab entry, then TRUE is returned.
+ */
+
+static Bool GrabSupersedesSecond(
+ register XtServerGrabPtr pFirstGrab,
+ register XtServerGrabPtr pSecondGrab)
+{
+ DetailRec first, second;
+
+ first.exact = pFirstGrab->modifiers;
+ if (pFirstGrab->hasExt)
+ first.pMask = GRABEXT(pFirstGrab)->pModifiersMask;
+ else
+ first.pMask = NULL;
+ second.exact = pSecondGrab->modifiers;
+ if (pSecondGrab->hasExt)
+ second.pMask = GRABEXT(pSecondGrab)->pModifiersMask;
+ else
+ second.pMask = NULL;
+ if (!DetailSupersedesSecond(&first, &second, (unsigned short)AnyModifier))
+ return FALSE;
+
+ first.exact = pFirstGrab->keybut;
+ if (pFirstGrab->hasExt)
+ first.pMask = GRABEXT(pFirstGrab)->pKeyButMask;
+ else
+ first.pMask = NULL;
+ second.exact = pSecondGrab->keybut;
+ if (pSecondGrab->hasExt)
+ second.pMask = GRABEXT(pSecondGrab)->pKeyButMask;
+ else
+ second.pMask = NULL;
+ if (DetailSupersedesSecond(&first, &second, (unsigned short)AnyKey))
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/*
+ * Two grabs are considered to be matching if either of the following are true:
+ *
+ * 1) The two grab entries match exactly, or the first grab entry
+ * encompasses the second grab entry.
+ * 2) The second grab entry encompasses the first grab entry.
+ * 3) The keycodes match exactly, and one entry's modifiers encompasses
+ * the others.
+ * 4) The keycode for one entry encompasses the other, and the detail
+ * for the other entry encompasses the first.
+ */
+
+static Bool GrabMatchesSecond(
+ register XtServerGrabPtr pFirstGrab,
+ register XtServerGrabPtr pSecondGrab)
+{
+ DetailRec firstD, firstM, secondD, secondM;
+
+ if (pDisplay(pFirstGrab) != pDisplay(pSecondGrab))
+ return FALSE;
+
+ if (GrabSupersedesSecond(pFirstGrab, pSecondGrab))
+ return TRUE;
+
+ if (GrabSupersedesSecond(pSecondGrab, pFirstGrab))
+ return TRUE;
+
+ firstD.exact = pFirstGrab->keybut;
+ firstM.exact = pFirstGrab->modifiers;
+ if (pFirstGrab->hasExt) {
+ firstD.pMask = GRABEXT(pFirstGrab)->pKeyButMask;
+ firstM.pMask = GRABEXT(pFirstGrab)->pModifiersMask;
+ } else {
+ firstD.pMask = NULL;
+ firstM.pMask = NULL;
+ }
+ secondD.exact = pSecondGrab->keybut;
+ secondM.exact = pSecondGrab->modifiers;
+ if (pSecondGrab->hasExt) {
+ secondD.pMask = GRABEXT(pSecondGrab)->pKeyButMask;
+ secondM.pMask = GRABEXT(pSecondGrab)->pModifiersMask;
+ } else {
+ secondD.pMask = NULL;
+ secondM.pMask = NULL;
+ }
+
+ if (DetailSupersedesSecond(&secondD, &firstD, (unsigned short)AnyKey) &&
+ DetailSupersedesSecond(&firstM, &secondM, (unsigned short)AnyModifier))
+ return TRUE;
+
+ if (DetailSupersedesSecond(&firstD, &secondD, (unsigned short)AnyKey) &&
+ DetailSupersedesSecond(&secondM, &firstM, (unsigned short)AnyModifier))
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/*
+ * Delete a grab combination from the passive grab list. Each entry will
+ * be checked to see if it is affected by the grab being deleted. This
+ * may result in multiple entries being modified/deleted.
+ */
+
+static void DeleteServerGrabFromList(
+ XtServerGrabPtr *passiveListPtr,
+ XtServerGrabPtr pMinuendGrab)
+{
+ register XtServerGrabPtr *next;
+ register XtServerGrabPtr grab;
+ register XtServerGrabExtPtr ext;
+
+ for (next = passiveListPtr; (grab = *next); )
+ {
+ if (GrabMatchesSecond(grab, pMinuendGrab) &&
+ (pDisplay(grab) == pDisplay(pMinuendGrab)))
+ {
+ if (GrabSupersedesSecond(pMinuendGrab, grab))
+ {
+ /*
+ * The entry being deleted encompasses the list entry,
+ * so delete the list entry.
+ */
+ *next = grab->next;
+ FreeGrab(grab);
+ continue;
+ }
+
+ if (!grab->hasExt) {
+ grab = (XtServerGrabPtr)
+ XtRealloc((char *)grab, (sizeof(XtServerGrabRec) +
+ sizeof(XtServerGrabExtRec)));
+ *next = grab;
+ grab->hasExt = True;
+ ext = GRABEXT(grab);
+ ext->pKeyButMask = NULL;
+ ext->pModifiersMask = NULL;
+ ext->confineTo = None;
+ ext->cursor = None;
+ } else
+ ext = GRABEXT(grab);
+ if ((grab->keybut == AnyKey) && (grab->modifiers != AnyModifier))
+ {
+ /*
+ * If the list entry has the key detail of AnyKey, and
+ * a modifier detail not set to AnyModifier, then we
+ * simply need to turn off the key detail bit in the
+ * list entry's key detail mask.
+ */
+ DeleteDetailFromMask(&ext->pKeyButMask, pMinuendGrab->keybut);
+ } else if ((grab->modifiers == AnyModifier) &&
+ (grab->keybut != AnyKey)) {
+ /*
+ * The list entry has a specific key detail, but its
+ * modifier detail is set to AnyModifier; so, we only
+ * need to turn off the specified modifier combination
+ * in the list entry's modifier mask.
+ */
+ DeleteDetailFromMask(&ext->pModifiersMask,
+ pMinuendGrab->modifiers);
+ } else if ((pMinuendGrab->keybut != AnyKey) &&
+ (pMinuendGrab->modifiers != AnyModifier)) {
+ /*
+ * The list entry has a key detail of AnyKey and a
+ * modifier detail of AnyModifier; the entry being
+ * deleted has a specific key and a specific modifier
+ * combination. Therefore, we need to mask off the
+ * keycode from the list entry, and also create a
+ * new entry for this keycode, which has a modifier
+ * mask set to AnyModifier & ~(deleted modifiers).
+ */
+ XtServerGrabPtr pNewGrab;
+
+ DeleteDetailFromMask(&ext->pKeyButMask, pMinuendGrab->keybut);
+ pNewGrab = CreateGrab(grab->widget,
+ (Boolean)grab->ownerEvents,
+ (Modifiers)AnyModifier,
+ pMinuendGrab->keybut,
+ (int)grab->pointerMode,
+ (int)grab->keyboardMode,
+ (Mask)0, (Window)0, (Cursor)0, True);
+ GRABEXT(pNewGrab)->pModifiersMask =
+ CopyDetailMask(ext->pModifiersMask);
+
+ DeleteDetailFromMask(&GRABEXT(pNewGrab)->pModifiersMask,
+ pMinuendGrab->modifiers);
+
+ pNewGrab->next = *passiveListPtr;
+ *passiveListPtr = pNewGrab;
+ } else if (pMinuendGrab->keybut == AnyKey) {
+ /*
+ * The list entry has keycode AnyKey and modifier
+ * AnyModifier; the entry being deleted has
+ * keycode AnyKey and specific modifiers. So we
+ * simply need to mask off the specified modifier
+ * combination.
+ */
+ DeleteDetailFromMask(&ext->pModifiersMask,
+ pMinuendGrab->modifiers);
+ } else {
+ /*
+ * The list entry has keycode AnyKey and modifier
+ * AnyModifier; the entry being deleted has a
+ * specific keycode and modifier AnyModifier. So
+ * we simply need to mask off the specified
+ * keycode.
+ */
+ DeleteDetailFromMask(&ext->pKeyButMask, pMinuendGrab->keybut);
+ }
+ }
+ next = &(*next)->next;
+ }
+}
+
+static void DestroyPassiveList(
+ XtServerGrabPtr *passiveListPtr)
+{
+ XtServerGrabPtr next, grab;
+
+ for (next = *passiveListPtr; next; ) {
+ grab = next;
+ next = grab->next;
+
+ /* not necessary to explicitly ungrab key or button;
+ * window is being destroyed so server will take care of it.
+ */
+
+ FreeGrab(grab);
+ }
+}
+
+
+/*
+ * This function is called at widget destroy time to clean up
+ */
+/*ARGSUSED*/
+void _XtDestroyServerGrabs(
+ Widget w,
+ XtPointer closure,
+ XtPointer call_data) /* unused */
+{
+ XtPerWidgetInput pwi = (XtPerWidgetInput)closure;
+ XtPerDisplayInput pdi;
+
+ LOCK_PROCESS;
+ pdi = _XtGetPerDisplayInput(XtDisplay(w));
+ _XtClearAncestorCache(w);
+ UNLOCK_PROCESS;
+
+ /* Remove the active grab, if necessary */
+ if ((pdi->keyboard.grabType != XtNoServerGrab) &&
+ (pdi->keyboard.grab.widget == w)) {
+ pdi->keyboard.grabType = XtNoServerGrab;
+ pdi->activatingKey = (KeyCode)0;
+ }
+ if ((pdi->pointer.grabType != XtNoServerGrab) &&
+ (pdi->pointer.grab.widget == w))
+ pdi->pointer.grabType = XtNoServerGrab;
+
+ DestroyPassiveList(&pwi->keyList);
+ DestroyPassiveList(&pwi->ptrList);
+
+ _XtFreePerWidgetInput(w, pwi);
+}
+
+/*
+ * If the incoming event is on the passive grab list, then activate
+ * the grab. The grab will remain in effect until the key is released.
+ */
+
+XtServerGrabPtr _XtCheckServerGrabsOnWidget (
+ XEvent *event,
+ Widget widget,
+ _XtBoolean isKeyboard)
+{
+ register XtServerGrabPtr grab;
+ XtServerGrabRec tempGrab;
+ XtServerGrabPtr *passiveListPtr;
+ XtPerWidgetInput pwi;
+
+ LOCK_PROCESS;
+ pwi = _XtGetPerWidgetInput(widget, FALSE);
+ UNLOCK_PROCESS;
+ if (!pwi)
+ return (XtServerGrabPtr)NULL;
+ if (isKeyboard)
+ passiveListPtr = &pwi->keyList;
+ else
+ passiveListPtr = &pwi->ptrList;
+
+ /*
+ * if either there is no entry in the context manager or the entry
+ * is empty, or the keyboard is grabed, then no work to be done
+ */
+ if (!*passiveListPtr)
+ return (XtServerGrabPtr)NULL;
+
+ /* Take only the lower thirteen bits as modifier state. The X Keyboard
+ * Extension may be representing keyboard group state in two upper bits.
+ */
+ tempGrab.widget = widget;
+ tempGrab.keybut = event->xkey.keycode; /* also xbutton.button */
+ tempGrab.modifiers = event->xkey.state & 0x1FFF; /*also xbutton.state*/
+ tempGrab.hasExt = False;
+
+ for (grab = *passiveListPtr; grab; grab = grab->next) {
+ if (GrabMatchesSecond(&tempGrab, grab))
+ return (grab);
+ }
+ return (XtServerGrabPtr)NULL;
+}
+
+/*
+ * This handler is needed to guarantee that we see releases on passive
+ * button grabs for widgets that haven't selected for button release.
+ */
+
+/*ARGSUSED*/
+static void ActiveHandler (
+ Widget widget,
+ XtPointer pdi,
+ XEvent *event,
+ Boolean *cont)
+{
+ /* nothing */
+}
+
+
+/*
+ * MakeGrab
+ */
+static void MakeGrab(
+ XtServerGrabPtr grab,
+ XtServerGrabPtr *passiveListPtr,
+ Boolean isKeyboard,
+ XtPerDisplayInput pdi,
+ XtPerWidgetInput pwi)
+{
+ if (!isKeyboard && !pwi->active_handler_added) {
+ XtAddEventHandler(grab->widget, ButtonReleaseMask, FALSE,
+ ActiveHandler, (XtPointer)pdi);
+ pwi->active_handler_added = TRUE;
+ }
+
+ if (isKeyboard) {
+ XGrabKey(pDisplay(grab),
+ grab->keybut, grab->modifiers,
+ pWindow(grab), grab->ownerEvents,
+ grab->pointerMode, grab->keyboardMode);
+ } else {
+ Window confineTo = None;
+ Cursor cursor = None;
+
+ if (grab->hasExt) {
+ if (grab->confineToIsWidgetWin)
+ confineTo = XtWindow (grab->widget);
+ else
+ confineTo = GRABEXT(grab)->confineTo;
+ cursor = GRABEXT(grab)->cursor;
+ }
+ XGrabButton(pDisplay(grab),
+ grab->keybut, grab->modifiers,
+ pWindow(grab), grab->ownerEvents, grab->eventMask,
+ grab->pointerMode, grab->keyboardMode,
+ confineTo, cursor);
+ }
+
+ /* Add the new grab entry to the passive key grab list */
+ grab->next = *passiveListPtr;
+ *passiveListPtr = grab;
+}
+
+static void MakeGrabs(
+ XtServerGrabPtr *passiveListPtr,
+ Boolean isKeyboard,
+ XtPerDisplayInput pdi)
+{
+ XtServerGrabPtr next = *passiveListPtr;
+ XtServerGrabPtr grab;
+ XtPerWidgetInput pwi;
+ /*
+ * make MakeGrab build a new list that has had the merge
+ * processing done on it. Start with an empty list
+ * (passiveListPtr).
+ */
+ LOCK_PROCESS;
+ *passiveListPtr = NULL;
+ while (next)
+ {
+ grab = next;
+ next = grab->next;
+ pwi = _XtGetPerWidgetInput(grab->widget, FALSE);
+ MakeGrab(grab, passiveListPtr, isKeyboard, pdi, pwi);
+ }
+ UNLOCK_PROCESS;
+}
+
+/*
+ * This function is the event handler attached to the associated widget
+ * when grabs need to be added, but the widget is not yet realized. When
+ * it is first mapped, this handler will be invoked, and it will add all
+ * needed grabs.
+ */
+
+/*ARGSUSED*/
+static void RealizeHandler (
+ Widget widget,
+ XtPointer closure,
+ XEvent *event, /* unused */
+ Boolean *cont) /* unused */
+{
+ XtPerWidgetInput pwi = (XtPerWidgetInput)closure;
+ XtPerDisplayInput pdi;
+
+ LOCK_PROCESS;
+ pdi = _XtGetPerDisplayInput(XtDisplay(widget));
+ UNLOCK_PROCESS;
+ MakeGrabs(&pwi->keyList, KEYBOARD, pdi);
+ MakeGrabs(&pwi->ptrList, POINTER, pdi);
+
+ XtRemoveEventHandler(widget, XtAllEvents, True,
+ RealizeHandler, (XtPointer)pwi);
+ pwi->realize_handler_added = FALSE;
+}
+
+/***************************************************************************/
+/**************************** Global Routines ******************************/
+/***************************************************************************/
+
+
+/*
+ * Routine used by an application to set up a passive grab for a key/modifier
+ * combination.
+ */
+
+static
+void GrabKeyOrButton (
+ Widget widget,
+ KeyCode keyOrButton,
+ Modifiers modifiers,
+ Boolean owner_events,
+ int pointer_mode,
+ int keyboard_mode,
+ Mask event_mask,
+ Window confine_to,
+ Cursor cursor,
+ Boolean isKeyboard)
+{
+ XtServerGrabPtr *passiveListPtr;
+ XtServerGrabPtr newGrab;
+ XtPerWidgetInput pwi;
+ XtPerDisplayInput pdi;
+
+
+ XtCheckSubclass(widget, coreWidgetClass, "in XtGrabKey or XtGrabButton");
+ LOCK_PROCESS;
+ pwi = _XtGetPerWidgetInput(widget, TRUE);
+ if (isKeyboard)
+ passiveListPtr = &pwi->keyList;
+ else
+ passiveListPtr = &pwi->ptrList;
+ pdi = _XtGetPerDisplayInput(XtDisplay(widget));
+ UNLOCK_PROCESS;
+ newGrab = CreateGrab(widget, owner_events, modifiers,
+ keyOrButton, pointer_mode, keyboard_mode,
+ event_mask, confine_to, cursor, False);
+ /*
+ * if the widget is realized then process the entry into the grab
+ * list. else if the list is empty (i.e. first time) then add the
+ * event handler. then add the raw entry to the list for processing
+ * in the handler at realize time.
+ */
+ if (XtIsRealized(widget))
+ MakeGrab(newGrab, passiveListPtr, isKeyboard, pdi, pwi);
+ else {
+ if (!pwi->realize_handler_added)
+ {
+ XtAddEventHandler(widget, StructureNotifyMask, FALSE,
+ RealizeHandler,
+ (XtPointer)pwi);
+ pwi->realize_handler_added = TRUE;
+ }
+
+ while (*passiveListPtr)
+ passiveListPtr = &(*passiveListPtr)->next;
+ *passiveListPtr = newGrab;
+ }
+}
+
+
+static
+void UngrabKeyOrButton (
+ Widget widget,
+ int keyOrButton,
+ Modifiers modifiers,
+ Boolean isKeyboard)
+{
+ XtServerGrabRec tempGrab;
+ XtPerWidgetInput pwi;
+
+ XtCheckSubclass(widget, coreWidgetClass,
+ "in XtUngrabKey or XtUngrabButton");
+
+ /* Build a temporary grab list entry */
+ tempGrab.widget = widget;
+ tempGrab.modifiers = modifiers;
+ tempGrab.keybut = keyOrButton;
+ tempGrab.hasExt = False;
+
+ LOCK_PROCESS;
+ pwi = _XtGetPerWidgetInput(widget, FALSE);
+ UNLOCK_PROCESS;
+ /*
+ * if there is no entry in the context manager then somethings wrong
+ */
+ if (!pwi)
+ {
+ XtAppWarningMsg(XtWidgetToApplicationContext(widget),
+ "invalidGrab", "ungrabKeyOrButton", XtCXtToolkitError,
+ "Attempt to remove nonexistent passive grab",
+ (String *)NULL, (Cardinal *)NULL);
+ return;
+ }
+
+ if (XtIsRealized(widget))
+ {
+ if (isKeyboard)
+ XUngrabKey(widget->core.screen->display,
+ keyOrButton, (unsigned int)modifiers,
+ widget->core.window);
+ else
+ XUngrabButton(widget->core.screen->display,
+ keyOrButton, (unsigned int)modifiers,
+ widget->core.window);
+ }
+
+
+ /* Delete all entries which are encompassed by the specified grab. */
+ DeleteServerGrabFromList(isKeyboard ? &pwi->keyList : &pwi->ptrList,
+ &tempGrab);
+}
+
+void XtGrabKey (
+ Widget widget,
+ _XtKeyCode keycode,
+ Modifiers modifiers,
+ _XtBoolean owner_events,
+ int pointer_mode,
+ int keyboard_mode)
+{
+ WIDGET_TO_APPCON(widget);
+
+ LOCK_APP(app);
+ GrabKeyOrButton(widget, (KeyCode)keycode, modifiers, owner_events,
+ pointer_mode, keyboard_mode,
+ (Mask)0, (Window)None, (Cursor)None, KEYBOARD);
+ UNLOCK_APP(app);
+}
+
+void XtGrabButton(
+ Widget widget,
+ int button,
+ Modifiers modifiers,
+ _XtBoolean owner_events,
+ unsigned int event_mask,
+ int pointer_mode,
+ int keyboard_mode,
+ Window confine_to,
+ Cursor cursor)
+{
+ WIDGET_TO_APPCON(widget);
+
+ LOCK_APP(app);
+ GrabKeyOrButton(widget, (KeyCode)button, modifiers, owner_events,
+ pointer_mode, keyboard_mode,
+ (Mask)event_mask, confine_to, cursor, POINTER);
+ UNLOCK_APP(app);
+}
+
+
+/*
+ * Routine used by an application to clear a passive grab for a key/modifier
+ * combination.
+ */
+
+void XtUngrabKey (
+ Widget widget,
+ _XtKeyCode keycode,
+ Modifiers modifiers)
+{
+ WIDGET_TO_APPCON(widget);
+
+ LOCK_APP(app);
+ UngrabKeyOrButton(widget, (int)keycode, modifiers, KEYBOARD);
+ UNLOCK_APP(app);
+}
+
+void XtUngrabButton (
+ Widget widget,
+ unsigned int button,
+ Modifiers modifiers)
+{
+ WIDGET_TO_APPCON(widget);
+
+ LOCK_APP(app);
+ UngrabKeyOrButton(widget, (KeyCode)button, modifiers, POINTER);
+ UNLOCK_APP(app);
+}
+
+/*
+ * Active grab of Device. clear any client side grabs so we dont lock
+ */
+static int GrabDevice (
+ Widget widget,
+ Boolean owner_events,
+ int pointer_mode,
+ int keyboard_mode,
+ Mask event_mask,
+ Window confine_to,
+ Cursor cursor,
+ Time time,
+ Boolean isKeyboard)
+{
+ XtPerDisplayInput pdi;
+ int returnVal;
+
+ XtCheckSubclass(widget, coreWidgetClass,
+ "in XtGrabKeyboard or XtGrabPointer");
+ if (!XtIsRealized(widget))
+ return GrabNotViewable;
+ LOCK_PROCESS;
+ pdi = _XtGetPerDisplayInput(XtDisplay(widget));
+ UNLOCK_PROCESS;
+ if (!isKeyboard)
+ returnVal = XGrabPointer(XtDisplay(widget), XtWindow(widget),
+ owner_events, event_mask,
+ pointer_mode, keyboard_mode,
+ confine_to, cursor, time);
+ else
+ returnVal = XGrabKeyboard(XtDisplay(widget), XtWindow(widget),
+ owner_events, pointer_mode,
+ keyboard_mode, time);
+
+ if (returnVal == GrabSuccess) {
+ XtDevice device;
+
+ device = isKeyboard ? &pdi->keyboard : &pdi->pointer;
+ /* fill in the server grab rec */
+ device->grab.widget = widget;
+ device->grab.modifiers = 0;
+ device->grab.keybut = 0;
+ device->grab.ownerEvents = owner_events;
+ device->grab.pointerMode = pointer_mode;
+ device->grab.keyboardMode = keyboard_mode;
+ device->grab.hasExt = False;
+ device->grabType = XtActiveServerGrab;
+ pdi->activatingKey = (KeyCode)0;
+ }
+ return returnVal;
+}
+
+static void UngrabDevice(
+ Widget widget,
+ Time time,
+ Boolean isKeyboard)
+{
+ XtPerDisplayInput pdi;
+ XtDevice device;
+
+ LOCK_PROCESS;
+ pdi = _XtGetPerDisplayInput(XtDisplay(widget));
+ UNLOCK_PROCESS;
+ device = isKeyboard ? &pdi->keyboard : &pdi->pointer;
+ XtCheckSubclass(widget, coreWidgetClass,
+ "in XtUngrabKeyboard or XtUngrabPointer");
+
+ if (device->grabType != XtNoServerGrab) {
+
+ if (device->grabType != XtPseudoPassiveServerGrab
+ && XtIsRealized(widget)) {
+ if (isKeyboard)
+ XUngrabKeyboard(XtDisplay(widget), time);
+ else
+ XUngrabPointer(XtDisplay(widget), time);
+ }
+ device->grabType = XtNoServerGrab;
+ pdi->activatingKey = (KeyCode)0;
+ }
+}
+
+
+/*
+ * Active grab of keyboard. clear any client side grabs so we dont lock
+ */
+int XtGrabKeyboard (
+ Widget widget,
+ _XtBoolean owner_events,
+ int pointer_mode,
+ int keyboard_mode,
+ Time time)
+{
+ int retval;
+ WIDGET_TO_APPCON(widget);
+
+ LOCK_APP(app);
+ retval = GrabDevice (widget, owner_events,
+ pointer_mode, keyboard_mode,
+ (Mask)0, (Window)None, (Cursor)None, time, KEYBOARD);
+ UNLOCK_APP(app);
+ return retval;
+}
+
+
+/*
+ * Ungrab the keyboard
+ */
+
+void XtUngrabKeyboard(
+ Widget widget,
+ Time time)
+{
+ WIDGET_TO_APPCON(widget);
+
+ LOCK_APP(app);
+ UngrabDevice(widget, time, KEYBOARD);
+ UNLOCK_APP(app);
+}
+
+
+
+
+/*
+ * grab the pointer
+ */
+int XtGrabPointer (
+ Widget widget,
+ _XtBoolean owner_events,
+ unsigned int event_mask,
+ int pointer_mode,
+ int keyboard_mode,
+ Window confine_to,
+ Cursor cursor,
+ Time time)
+{
+ int retval;
+ WIDGET_TO_APPCON(widget);
+
+ LOCK_APP(app);
+ retval = GrabDevice (widget, owner_events,
+ pointer_mode, keyboard_mode,
+ (Mask)event_mask, confine_to,
+ cursor, time, POINTER);
+ UNLOCK_APP(app);
+ return retval;
+}
+
+
+/*
+ * Ungrab the pointer
+ */
+
+void XtUngrabPointer(
+ Widget widget,
+ Time time)
+{
+ WIDGET_TO_APPCON(widget);
+
+ LOCK_APP(app);
+ UngrabDevice(widget, time, POINTER);
+ UNLOCK_APP(app);
+}
+
+
+void _XtRegisterPassiveGrabs (
+ Widget widget)
+{
+ XtPerWidgetInput pwi = _XtGetPerWidgetInput (widget, FALSE);
+
+ if (pwi != NULL && !pwi->realize_handler_added) {
+ XtAddEventHandler(widget, StructureNotifyMask, FALSE,
+ RealizeHandler,
+ (XtPointer)pwi);
+ pwi->realize_handler_added = TRUE;
+ }
+}