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