1/* 2 3Copyright (c) 1993, Oracle and/or its affiliates. 4 5Permission is hereby granted, free of charge, to any person obtaining a 6copy of this software and associated documentation files (the "Software"), 7to deal in the Software without restriction, including without limitation 8the rights to use, copy, modify, merge, publish, distribute, sublicense, 9and/or sell copies of the Software, and to permit persons to whom the 10Software is furnished to do so, subject to the following conditions: 11 12The above copyright notice and this permission notice (including the next 13paragraph) shall be included in all copies or substantial portions of the 14Software. 15 16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22DEALINGS IN THE SOFTWARE. 23 24*/ 25/******************************************************** 26 27Copyright 1988 by Hewlett-Packard Company 28Copyright 1987, 1988, 1989 by Digital Equipment Corporation, Maynard, Massachusetts 29 30Permission to use, copy, modify, and distribute this software 31and its documentation for any purpose and without fee is hereby 32granted, provided that the above copyright notice appear in all 33copies and that both that copyright notice and this permission 34notice appear in supporting documentation, and that the names of 35Hewlett-Packard or Digital not be used in advertising or 36publicity pertaining to distribution of the software without specific, 37written prior permission. 38 39DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 40ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 41DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 42ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 43WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 44ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 45SOFTWARE. 46 47********************************************************/ 48 49/* 50 51Copyright 1987, 1988, 1989, 1998 The Open Group 52 53Permission to use, copy, modify, distribute, and sell this software and its 54documentation for any purpose is hereby granted without fee, provided that 55the above copyright notice appear in all copies and that both that 56copyright notice and this permission notice appear in supporting 57documentation. 58 59The above copyright notice and this permission notice shall be included in 60all copies or substantial portions of the Software. 61 62THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 63IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 64FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 65OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 66AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 67CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 68 69Except as contained in this notice, the name of The Open Group shall not be 70used in advertising or otherwise to promote the sale, use or other dealings 71in this Software without prior written authorization from The Open Group. 72 73*/ 74 75#ifdef HAVE_CONFIG_H 76#include <config.h> 77#endif 78#include "IntrinsicI.h" 79#include "PassivGraI.h" 80#include "StringDefs.h" 81#include "EventI.h" 82 83static XContext perWidgetInputContext = 0; 84 85void 86_XtFreePerWidgetInput(Widget w, XtPerWidgetInput pwi) 87{ 88 LOCK_PROCESS; 89 XDeleteContext(XtDisplay(w), (Window) w, perWidgetInputContext); 90 91 XtFree((char *) pwi); 92 UNLOCK_PROCESS; 93} 94 95/* 96 * This routine gets the passive list associated with the widget 97 * from the context manager. 98 */ 99XtPerWidgetInput 100_XtGetPerWidgetInput(Widget widget, _XtBoolean create) 101{ 102 XtPerWidgetInput pwi = NULL; 103 Display *dpy = widget->core.screen->display; 104 105 LOCK_PROCESS; 106 if (!perWidgetInputContext) 107 perWidgetInputContext = XUniqueContext(); 108 109 if (XFindContext(dpy, 110 (Window) widget, 111 perWidgetInputContext, (XPointer *) &pwi) && create) { 112 pwi = (XtPerWidgetInput) 113 __XtMalloc((unsigned) sizeof(XtPerWidgetInputRec)); 114 115 pwi->focusKid = NULL; 116 pwi->queryEventDescendant = NULL; 117 pwi->focalPoint = XtUnrelated; 118 pwi->keyList = pwi->ptrList = NULL; 119 120 pwi->haveFocus = 121 pwi->map_handler_added = 122 pwi->realize_handler_added = pwi->active_handler_added = FALSE; 123 124 XtAddCallback(widget, XtNdestroyCallback, 125 _XtDestroyServerGrabs, (XtPointer) pwi); 126 127 (void) XSaveContext(dpy, 128 (Window) widget, 129 perWidgetInputContext, (char *) pwi); 130 } 131 UNLOCK_PROCESS; 132 return pwi; 133} 134 135void 136_XtFillAncestorList(Widget **listPtr, 137 int *maxElemsPtr, 138 int *numElemsPtr, 139 Widget start, 140 Widget breakWidget) 141{ 142#define CACHESIZE 16 143 Cardinal i; 144 Widget w; 145 Widget *trace = *listPtr; 146 147 /* First time in, allocate the ancestor list */ 148 if (trace == NULL) { 149 trace = XtMallocArray(CACHESIZE, (Cardinal) sizeof(Widget)); 150 *maxElemsPtr = CACHESIZE; 151 } 152 /* First fill in the ancestor list */ 153 154 trace[0] = start; 155 156 for (i = 1, w = XtParent(start); 157 w != NULL && !XtIsShell(trace[i - 1]) && trace[i - 1] != breakWidget; 158 w = XtParent(w), i++) { 159 if (i == (Cardinal) *maxElemsPtr) { 160 /* This should rarely happen, but if it does it'll probably 161 happen again, so grow the ancestor list */ 162 *maxElemsPtr += CACHESIZE; 163 trace = XtReallocArray(trace, (Cardinal) *maxElemsPtr, 164 (Cardinal) sizeof(Widget)); 165 } 166 trace[i] = w; 167 } 168 *listPtr = trace; 169 *numElemsPtr = (int) i; 170#undef CACHESIZE 171} 172 173Widget 174_XtFindRemapWidget(XEvent *event, 175 Widget widget, 176 EventMask mask, 177 XtPerDisplayInput pdi) 178{ 179 Widget dspWidget = widget; 180 181 if (!pdi->traceDepth || !(widget == pdi->trace[0])) { 182 _XtFillAncestorList(&pdi->trace, &pdi->traceMax, 183 &pdi->traceDepth, widget, NULL); 184 pdi->focusWidget = NULL; /* invalidate the focus 185 cache */ 186 } 187 if (mask & (KeyPressMask | KeyReleaseMask)) 188 dspWidget = _XtProcessKeyboardEvent((XKeyEvent *) event, widget, pdi); 189 else if (mask & (ButtonPressMask | ButtonReleaseMask)) 190 dspWidget = _XtProcessPointerEvent((XButtonEvent *) event, widget, pdi); 191 192 return dspWidget; 193} 194 195void 196_XtUngrabBadGrabs(XEvent *event, 197 Widget widget, 198 EventMask mask, 199 XtPerDisplayInput pdi) 200{ 201 XKeyEvent *ke = (XKeyEvent *) event; 202 203 if (mask & (KeyPressMask | KeyReleaseMask)) { 204 if (IsServerGrab(pdi->keyboard.grabType) && 205 !_XtOnGrabList(pdi->keyboard.grab.widget, pdi->grabList)) 206 XtUngrabKeyboard(widget, ke->time); 207 208 } 209 else { 210 if (IsServerGrab(pdi->pointer.grabType) && 211 !_XtOnGrabList(pdi->pointer.grab.widget, pdi->grabList)) 212 XtUngrabPointer(widget, ke->time); 213 } 214} 215