1 /* 2 3 Copyright (c) 1993, Oracle and/or its affiliates. 4 5 Permission is hereby granted, free of charge, to any person obtaining a 6 copy of this software and associated documentation files (the "Software"), 7 to deal in the Software without restriction, including without limitation 8 the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 and/or sell copies of the Software, and to permit persons to whom the 10 Software is furnished to do so, subject to the following conditions: 11 12 The above copyright notice and this permission notice (including the next 13 paragraph) shall be included in all copies or substantial portions of the 14 Software. 15 16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 DEALINGS IN THE SOFTWARE. 23 24 */ 25 /******************************************************** 26 27 Copyright 1988 by Hewlett-Packard Company 28 Copyright 1987, 1988, 1989 by Digital Equipment Corporation, Maynard, Massachusetts 29 30 Permission to use, copy, modify, and distribute this software 31 and its documentation for any purpose and without fee is hereby 32 granted, provided that the above copyright notice appear in all 33 copies and that both that copyright notice and this permission 34 notice appear in supporting documentation, and that the names of 35 Hewlett-Packard or Digital not be used in advertising or 36 publicity pertaining to distribution of the software without specific, 37 written prior permission. 38 39 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 40 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 41 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 42 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 43 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 44 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 45 SOFTWARE. 46 47 ********************************************************/ 48 49 /* 50 51 Copyright 1987, 1988, 1989, 1998 The Open Group 52 53 Permission to use, copy, modify, distribute, and sell this software and its 54 documentation for any purpose is hereby granted without fee, provided that 55 the above copyright notice appear in all copies and that both that 56 copyright notice and this permission notice appear in supporting 57 documentation. 58 59 The above copyright notice and this permission notice shall be included in 60 all copies or substantial portions of the Software. 61 62 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 63 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 64 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 65 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 66 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 67 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 68 69 Except as contained in this notice, the name of The Open Group shall not be 70 used in advertising or otherwise to promote the sale, use or other dealings 71 in 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 83 static XContext perWidgetInputContext = 0; 84 85 void 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 */ 99 XtPerWidgetInput 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 135 void 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 173 Widget 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 195 void 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