Event.c revision 1477040f
1444c061aSmrg/* $Xorg: Event.c,v 1.5 2001/02/09 02:03:54 xorgcvs Exp $ */
2444c061aSmrg
3444c061aSmrg/***********************************************************
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.
161477040fSmrg
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
251477040fSmrgCopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
26444c061aSmrg
27444c061aSmrg                        All Rights Reserved
28444c061aSmrg
29444c061aSmrgPermission to use, copy, modify, and distribute this software and its
30444c061aSmrgdocumentation for any purpose and without fee is hereby granted,
31444c061aSmrgprovided that the above copyright notice appear in all copies and that
32444c061aSmrgboth that copyright notice and this permission notice appear in
331477040fSmrgsupporting documentation, and that the name of Digital not be
34444c061aSmrgused in advertising or publicity pertaining to distribution of the
35444c061aSmrgsoftware without specific, written prior permission.
36444c061aSmrg
37444c061aSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38444c061aSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39444c061aSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40444c061aSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41444c061aSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42444c061aSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43444c061aSmrgSOFTWARE.
44444c061aSmrg
45444c061aSmrg******************************************************************/
46444c061aSmrg
47444c061aSmrg/*
48444c061aSmrg
49444c061aSmrgCopyright 1987, 1988, 1998  The Open Group
50444c061aSmrg
51444c061aSmrgPermission to use, copy, modify, distribute, and sell this software and its
52444c061aSmrgdocumentation for any purpose is hereby granted without fee, provided that
53444c061aSmrgthe above copyright notice appear in all copies and that both that
54444c061aSmrgcopyright notice and this permission notice appear in supporting
55444c061aSmrgdocumentation.
56444c061aSmrg
57444c061aSmrgThe above copyright notice and this permission notice shall be included in
58444c061aSmrgall copies or substantial portions of the Software.
59444c061aSmrg
60444c061aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
61444c061aSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
62444c061aSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
63444c061aSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
64444c061aSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
65444c061aSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
66444c061aSmrg
67444c061aSmrgExcept as contained in this notice, the name of The Open Group shall not be
68444c061aSmrgused in advertising or otherwise to promote the sale, use or other dealings
69444c061aSmrgin this Software without prior written authorization from The Open Group.
70444c061aSmrg
71444c061aSmrg*/
72444c061aSmrg/* $XFree86: xc/lib/Xt/Event.c,v 3.10 2001/12/14 19:56:11 dawes Exp $ */
73444c061aSmrg
74444c061aSmrg#ifdef HAVE_CONFIG_H
75444c061aSmrg#include <config.h>
76444c061aSmrg#endif
77444c061aSmrg#include "IntrinsicI.h"
78444c061aSmrg#include "Shell.h"
79444c061aSmrg#include "StringDefs.h"
80444c061aSmrg
81444c061aSmrgtypedef struct _XtEventRecExt {
82444c061aSmrg    int type;
83444c061aSmrg    XtPointer select_data[1]; /* actual dimension is [mask] */
84444c061aSmrg} XtEventRecExt;
85444c061aSmrg
86444c061aSmrg#define EXT_TYPE(p) (((XtEventRecExt*) ((p)+1))->type)
87444c061aSmrg#define EXT_SELECT_DATA(p,n) (((XtEventRecExt*) ((p)+1))->select_data[n])
88444c061aSmrg
89444c061aSmrg#define NonMaskableMask ((EventMask)0x80000000L)
90444c061aSmrg
91444c061aSmrg/*
92444c061aSmrg * These are definitions to make the code that handles exposure compresssion
93444c061aSmrg * easier to read.
94444c061aSmrg *
95444c061aSmrg * COMP_EXPOSE      - The compression exposure field of "widget"
96444c061aSmrg * COMP_EXPOSE_TYPE - The type of compression (lower 4 bits of COMP_EXPOSE.
97444c061aSmrg * GRAPHICS_EXPOSE  - TRUE if the widget wants graphics expose events
98444c061aSmrg *                    dispatched.
99444c061aSmrg * NO_EXPOSE        - TRUE if the widget wants No expose events dispatched.
100444c061aSmrg */
101444c061aSmrg
102444c061aSmrg#define COMP_EXPOSE   (widget->core.widget_class->core_class.compress_exposure)
103444c061aSmrg#define COMP_EXPOSE_TYPE (COMP_EXPOSE & 0x0f)
104444c061aSmrg#define GRAPHICS_EXPOSE  ((XtExposeGraphicsExpose & COMP_EXPOSE) || \
105444c061aSmrg			  (XtExposeGraphicsExposeMerged & COMP_EXPOSE))
106444c061aSmrg#define NO_EXPOSE        (XtExposeNoExpose & COMP_EXPOSE)
107444c061aSmrg
108444c061aSmrgEventMask XtBuildEventMask(
109444c061aSmrg    Widget widget)
110444c061aSmrg{
111444c061aSmrg    XtEventTable ev;
112444c061aSmrg    EventMask	mask = 0L;
113444c061aSmrg    WIDGET_TO_APPCON(widget);
114444c061aSmrg
115444c061aSmrg    LOCK_APP(app);
116444c061aSmrg    for (ev = widget->core.event_table; ev != NULL; ev = ev->next)
117444c061aSmrg	if (ev->select) {
118444c061aSmrg	    if (!ev->has_type_specifier)
119444c061aSmrg		mask |= ev->mask;
120444c061aSmrg	    else {
121444c061aSmrg		if (EXT_TYPE(ev) < LASTEvent) {
122444c061aSmrg		    Cardinal i;
123444c061aSmrg		    for (i = 0; i < ev->mask; i++)
124444c061aSmrg			if (EXT_SELECT_DATA(ev, i))
125444c061aSmrg			    mask |= *(EventMask*)EXT_SELECT_DATA(ev, i);
126444c061aSmrg		}
127444c061aSmrg	    }
128444c061aSmrg	}
129444c061aSmrg    LOCK_PROCESS;
130444c061aSmrg    if (widget->core.widget_class->core_class.expose != NULL)
131444c061aSmrg	mask |= ExposureMask;
132444c061aSmrg    if (widget->core.widget_class->core_class.visible_interest)
133444c061aSmrg	mask |= VisibilityChangeMask;
134444c061aSmrg    UNLOCK_PROCESS;
135444c061aSmrg    if (widget->core.tm.translations)
136444c061aSmrg	mask |= widget->core.tm.translations->eventMask;
137444c061aSmrg
138444c061aSmrg    mask =  mask & ~NonMaskableMask;
139444c061aSmrg    UNLOCK_APP(app);
140444c061aSmrg    return mask;
141444c061aSmrg}
142444c061aSmrg
143444c061aSmrgstatic void CallExtensionSelector(
144444c061aSmrg    Widget widget,
145444c061aSmrg    ExtSelectRec* rec,
146444c061aSmrg    Boolean forceCall)
147444c061aSmrg{
148444c061aSmrg    XtEventRec* p;
149444c061aSmrg    XtPointer* data;
150444c061aSmrg    int* types;
151444c061aSmrg    Cardinal i, count = 0;
152444c061aSmrg
153444c061aSmrg    for (p = widget->core.event_table; p != NULL; p = p->next)
154444c061aSmrg	if (p->has_type_specifier &&
155444c061aSmrg	    EXT_TYPE(p) >= rec->min && EXT_TYPE(p) <= rec->max)
156444c061aSmrg	    count += p->mask;
157444c061aSmrg
158444c061aSmrg    if (count == 0 && !forceCall) return;
159444c061aSmrg
160444c061aSmrg    data = (XtPointer *) ALLOCATE_LOCAL(count * sizeof (XtPointer));
161444c061aSmrg    types = (int *) ALLOCATE_LOCAL(count * sizeof (int));
162444c061aSmrg    count = 0;
163444c061aSmrg
164444c061aSmrg    for (p = widget->core.event_table; p != NULL; p = p->next)
165444c061aSmrg	if (p->has_type_specifier &&
166444c061aSmrg	    EXT_TYPE(p) >= rec->min && EXT_TYPE(p) <= rec->max)
167444c061aSmrg	    for (i =0; i < p->mask; i++) {
168444c061aSmrg		types[count] = EXT_TYPE(p);
169444c061aSmrg		data[count++] = EXT_SELECT_DATA(p, i);
170444c061aSmrg	    }
171444c061aSmrg
172444c061aSmrg    (*rec->proc)(widget, types, data, count, rec->client_data);
173444c061aSmrg    DEALLOCATE_LOCAL((char*) types);
174444c061aSmrg    DEALLOCATE_LOCAL((char*) data);
175444c061aSmrg}
176444c061aSmrg
177444c061aSmrgstatic void
178444c061aSmrgRemoveEventHandler(
179444c061aSmrg    Widget widget,
180444c061aSmrg    XtPointer select_data,
181444c061aSmrg    int type,
182444c061aSmrg    Boolean has_type_specifier,
183444c061aSmrg    Boolean other,
184444c061aSmrg    XtEventHandler proc,
185444c061aSmrg    XtPointer closure,
186444c061aSmrg    Boolean raw)
187444c061aSmrg{
188444c061aSmrg    XtEventRec *p, **pp;
189444c061aSmrg    EventMask eventMask, oldMask = XtBuildEventMask(widget);
190444c061aSmrg
191444c061aSmrg    if (raw) raw = 1;
192444c061aSmrg    pp = &widget->core.event_table;
193444c061aSmrg    while ((p = *pp) &&
194444c061aSmrg	   (p->proc != proc || p->closure != closure || p->select == raw ||
195444c061aSmrg	    has_type_specifier != p->has_type_specifier ||
196444c061aSmrg	    (has_type_specifier && EXT_TYPE(p) != type)))
197444c061aSmrg	pp = &p->next;
198444c061aSmrg    if (!p) return;
199444c061aSmrg
200444c061aSmrg    /* un-register it */
201444c061aSmrg    if (!has_type_specifier) {
202444c061aSmrg	eventMask = *(EventMask*)select_data;
203444c061aSmrg	eventMask &= ~NonMaskableMask;
204444c061aSmrg	if (other)
205444c061aSmrg	    eventMask |= NonMaskableMask;
206444c061aSmrg	p->mask &= ~eventMask;
207444c061aSmrg    } else {
208444c061aSmrg	Cardinal i;
209444c061aSmrg	/* p->mask specifies count of EXT_SELECT_DATA(p,i)
210444c061aSmrg	 * search through the list of selection data, if not found
211444c061aSmrg	 * dont remove this handler
212444c061aSmrg	 */
213444c061aSmrg	for (i = 0; i < p->mask && select_data != EXT_SELECT_DATA(p,i);) i++;
214444c061aSmrg	if (i == p->mask) return;
215444c061aSmrg	if (p->mask == 1) p->mask = 0;
216444c061aSmrg	else {
217444c061aSmrg	    p->mask--;
218444c061aSmrg	    while (i < p->mask) {
219444c061aSmrg		EXT_SELECT_DATA(p,i) = EXT_SELECT_DATA(p, i+1);
220444c061aSmrg		i++;
221444c061aSmrg	    }
222444c061aSmrg	}
223444c061aSmrg    }
224444c061aSmrg
225444c061aSmrg    if (!p->mask) {        /* delete it entirely */
226444c061aSmrg        *pp = p->next;
227444c061aSmrg	XtFree((char *)p);
228444c061aSmrg    }
229444c061aSmrg
230444c061aSmrg    /* Reset select mask if realized and not raw. */
231444c061aSmrg    if ( !raw && XtIsRealized(widget) && !widget->core.being_destroyed) {
232444c061aSmrg	EventMask mask = XtBuildEventMask(widget);
233444c061aSmrg	Display* dpy = XtDisplay (widget);
234444c061aSmrg
235444c061aSmrg	if (oldMask != mask)
236444c061aSmrg	    XSelectInput(dpy, XtWindow(widget), mask);
237444c061aSmrg
238444c061aSmrg	if (has_type_specifier) {
239444c061aSmrg	    XtPerDisplay pd = _XtGetPerDisplay(dpy);
240444c061aSmrg	    int i;
241444c061aSmrg	    for (i = 0; i < pd->ext_select_count; i++) {
242444c061aSmrg		if (type >= pd->ext_select_list[i].min &&
243444c061aSmrg		    type <= pd->ext_select_list[i].max) {
244444c061aSmrg		    CallExtensionSelector(widget, pd->ext_select_list+i, TRUE);
245444c061aSmrg		    break;
246444c061aSmrg		}
247444c061aSmrg		if (type < pd->ext_select_list[i].min) break;
248444c061aSmrg	    }
249444c061aSmrg	}
250444c061aSmrg    }
251444c061aSmrg}
252444c061aSmrg
253444c061aSmrg/*	Function Name: AddEventHandler
254444c061aSmrg *	Description: An Internal routine that does the actual work of
255444c061aSmrg *                   adding the event handlers.
256444c061aSmrg *	Arguments: widget - widget to register an event handler for.
257444c061aSmrg *                 eventMask - events to mask for.
258444c061aSmrg *                 other - pass non maskable events to this proceedure.
259444c061aSmrg *                 proc - proceedure to register.
260444c061aSmrg *                 closure - data to pass to the event hander.
261444c061aSmrg *                 position - where to add this event handler.
262444c061aSmrg *                 force_new_position - If the element is already in the
263444c061aSmrg *                                      list, this will force it to the
264444c061aSmrg *                                      beginning or end depending on position.
265444c061aSmrg *                 raw - If FALSE call XSelectInput for events in mask.
266444c061aSmrg *	Returns: none
267444c061aSmrg */
268444c061aSmrg
269444c061aSmrgstatic void
270444c061aSmrgAddEventHandler(
271444c061aSmrg    Widget widget,
272444c061aSmrg    XtPointer select_data,
273444c061aSmrg    int type,
274444c061aSmrg    Boolean         has_type_specifier,
275444c061aSmrg    Boolean         other,
276444c061aSmrg    XtEventHandler  proc,
277444c061aSmrg    XtPointer	closure,
278444c061aSmrg    XtListPosition  position,
279444c061aSmrg    Boolean         force_new_position,
280444c061aSmrg    Boolean         raw)
281444c061aSmrg{
282444c061aSmrg    register XtEventRec *p, **pp;
283444c061aSmrg    EventMask oldMask = 0, eventMask = 0;
284444c061aSmrg
285444c061aSmrg    if (!has_type_specifier) {
286444c061aSmrg	eventMask = *(EventMask*)select_data & ~NonMaskableMask;
287444c061aSmrg	if (other) eventMask |= NonMaskableMask;
288444c061aSmrg	if (!eventMask) return;
289444c061aSmrg    } else if (!type) return;
290444c061aSmrg
291444c061aSmrg    if (XtIsRealized(widget) && !raw) oldMask = XtBuildEventMask(widget);
292444c061aSmrg
293444c061aSmrg    if (raw) raw = 1;
294444c061aSmrg    pp = &widget->core.event_table;
295444c061aSmrg    while ((p = *pp) &&
296444c061aSmrg	   (p->proc != proc || p->closure != closure || p->select == raw ||
297444c061aSmrg	    has_type_specifier != p->has_type_specifier ||
298444c061aSmrg	    (has_type_specifier && EXT_TYPE(p) != type)))
299444c061aSmrg	pp = &p->next;
300444c061aSmrg
301444c061aSmrg    if (!p) {		                /* New proc to add to list */
302444c061aSmrg	if (has_type_specifier) {
303444c061aSmrg	    p = (XtEventRec*) __XtMalloc(sizeof(XtEventRec) +
304444c061aSmrg				       sizeof(XtEventRecExt));
305444c061aSmrg	    EXT_TYPE(p) = type;
306444c061aSmrg	    EXT_SELECT_DATA(p,0) = select_data;
307444c061aSmrg	    p->mask = 1;
308444c061aSmrg	    p->has_type_specifier = True;
309444c061aSmrg	} else {
310444c061aSmrg	    p = (XtEventRec*) __XtMalloc(sizeof(XtEventRec));
311444c061aSmrg	    p->mask = eventMask;
312444c061aSmrg	    p->has_type_specifier = False;
313444c061aSmrg	}
314444c061aSmrg	p->proc = proc;
315444c061aSmrg	p->closure = closure;
316444c061aSmrg	p->select = ! raw;
317444c061aSmrg
318444c061aSmrg	if (position == XtListHead) {
319444c061aSmrg	    p->next = widget->core.event_table;
320444c061aSmrg	    widget->core.event_table = p;
321444c061aSmrg	    pp = &widget->core.event_table;
322444c061aSmrg	} else {
323444c061aSmrg	    *pp = p;
324444c061aSmrg	    p->next = NULL;
325444c061aSmrg	}
326444c061aSmrg    }
327444c061aSmrg    else {
328444c061aSmrg	if (force_new_position) {
329444c061aSmrg	    *pp = p->next;
330444c061aSmrg
331444c061aSmrg	    if (position == XtListHead) {
332444c061aSmrg		p->next = widget->core.event_table;
333444c061aSmrg		widget->core.event_table = p;
334444c061aSmrg	    } else {
335444c061aSmrg	       	/*
336444c061aSmrg		 * Find the last element in the list.
337444c061aSmrg		 */
338444c061aSmrg		while (*pp)
339444c061aSmrg		    pp = &(*pp)->next;
340444c061aSmrg		*pp = p;
341444c061aSmrg		p->next = NULL;
342444c061aSmrg	    }
343444c061aSmrg	}
344444c061aSmrg
345444c061aSmrg	if (!has_type_specifier)
346444c061aSmrg	    p->mask |= eventMask;
347444c061aSmrg	else {
348444c061aSmrg	    Cardinal i;
349444c061aSmrg	    /* p->mask specifies count of EXT_SELECT_DATA(p,i) */
350444c061aSmrg	    for (i = 0; i < p->mask && select_data != EXT_SELECT_DATA(p,i); )
351444c061aSmrg		i++;
352444c061aSmrg	    if (i == p->mask) {
353444c061aSmrg		p = (XtEventRec*) XtRealloc((char*)p,
354444c061aSmrg					    sizeof(XtEventRec) +
355444c061aSmrg					    sizeof(XtEventRecExt) +
356444c061aSmrg					    p->mask * sizeof(XtPointer));
357444c061aSmrg		EXT_SELECT_DATA(p,i) = select_data;
358444c061aSmrg		p->mask++;
359444c061aSmrg		*pp = p;
360444c061aSmrg	    }
361444c061aSmrg	}
362444c061aSmrg    }
363444c061aSmrg
364444c061aSmrg    if (XtIsRealized(widget) && !raw) {
365444c061aSmrg	EventMask mask = XtBuildEventMask(widget);
366444c061aSmrg	Display* dpy = XtDisplay (widget);
367444c061aSmrg
368444c061aSmrg	if (oldMask != mask)
369444c061aSmrg	    XSelectInput(dpy, XtWindow(widget), mask);
370444c061aSmrg
371444c061aSmrg	if (has_type_specifier) {
372444c061aSmrg	    XtPerDisplay pd = _XtGetPerDisplay (dpy);
373444c061aSmrg	    int i;
374444c061aSmrg	    for (i = 0; i < pd->ext_select_count; i++) {
375444c061aSmrg		if (type >= pd->ext_select_list[i].min &&
376444c061aSmrg		    type <= pd->ext_select_list[i].max) {
377444c061aSmrg		    CallExtensionSelector(widget, pd->ext_select_list+i, FALSE);
378444c061aSmrg		    break;
379444c061aSmrg		}
380444c061aSmrg		if (type < pd->ext_select_list[i].min) break;
381444c061aSmrg	    }
382444c061aSmrg	}
383444c061aSmrg    }
384444c061aSmrg}
385444c061aSmrg
386444c061aSmrgvoid XtRemoveEventHandler(
387444c061aSmrg    Widget	    widget,
388444c061aSmrg    EventMask       eventMask,
389444c061aSmrg    _XtBoolean	    other,
390444c061aSmrg    XtEventHandler  proc,
391444c061aSmrg    XtPointer	    closure)
392444c061aSmrg{
393444c061aSmrg    WIDGET_TO_APPCON(widget);
394444c061aSmrg    LOCK_APP(app);
395444c061aSmrg    RemoveEventHandler(widget, (XtPointer) &eventMask, 0, FALSE,
396444c061aSmrg		       other, proc, closure, FALSE);
397444c061aSmrg    UNLOCK_APP(app);
398444c061aSmrg}
399444c061aSmrg
400444c061aSmrgvoid XtAddEventHandler(
401444c061aSmrg    Widget	    widget,
402444c061aSmrg    EventMask       eventMask,
403444c061aSmrg    _XtBoolean      other,
404444c061aSmrg    XtEventHandler  proc,
405444c061aSmrg    XtPointer	    closure)
406444c061aSmrg{
407444c061aSmrg    WIDGET_TO_APPCON(widget);
408444c061aSmrg    LOCK_APP(app);
409444c061aSmrg    AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other,
410444c061aSmrg		    proc, closure, XtListTail, FALSE, FALSE);
411444c061aSmrg    UNLOCK_APP(app);
412444c061aSmrg}
413444c061aSmrg
414444c061aSmrgvoid XtInsertEventHandler(
415444c061aSmrg    Widget	    widget,
416444c061aSmrg    EventMask       eventMask,
417444c061aSmrg    _XtBoolean      other,
418444c061aSmrg    XtEventHandler  proc,
419444c061aSmrg    XtPointer	    closure,
420444c061aSmrg    XtListPosition  position)
421444c061aSmrg{
422444c061aSmrg    WIDGET_TO_APPCON(widget);
423444c061aSmrg    LOCK_APP(app);
424444c061aSmrg    AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other,
425444c061aSmrg		    proc, closure, position, TRUE, FALSE);
426444c061aSmrg    UNLOCK_APP(app);
427444c061aSmrg}
428444c061aSmrg
429444c061aSmrgvoid XtRemoveRawEventHandler(
430444c061aSmrg    Widget	    widget,
431444c061aSmrg    EventMask       eventMask,
432444c061aSmrg    _XtBoolean	    other,
433444c061aSmrg    XtEventHandler  proc,
434444c061aSmrg    XtPointer	    closure)
435444c061aSmrg{
436444c061aSmrg    WIDGET_TO_APPCON(widget);
437444c061aSmrg    LOCK_APP(app);
438444c061aSmrg    RemoveEventHandler(widget, (XtPointer) &eventMask, 0, FALSE,
439444c061aSmrg		       other, proc, closure, TRUE);
440444c061aSmrg    UNLOCK_APP(app);
441444c061aSmrg}
442444c061aSmrg
443444c061aSmrgvoid XtInsertRawEventHandler(
444444c061aSmrg    Widget	    widget,
445444c061aSmrg    EventMask       eventMask,
446444c061aSmrg    _XtBoolean	    other,
447444c061aSmrg    XtEventHandler  proc,
448444c061aSmrg    XtPointer	    closure,
449444c061aSmrg    XtListPosition  position)
450444c061aSmrg{
451444c061aSmrg    WIDGET_TO_APPCON(widget);
452444c061aSmrg    LOCK_APP(app);
453444c061aSmrg    AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other,
454444c061aSmrg		    proc, closure, position, TRUE, TRUE);
455444c061aSmrg    UNLOCK_APP(app);
456444c061aSmrg}
457444c061aSmrg
458444c061aSmrgvoid XtAddRawEventHandler(
459444c061aSmrg    Widget	    widget,
460444c061aSmrg    EventMask       eventMask,
461444c061aSmrg    _XtBoolean      other,
462444c061aSmrg    XtEventHandler  proc,
463444c061aSmrg    XtPointer	    closure)
464444c061aSmrg{
465444c061aSmrg    WIDGET_TO_APPCON(widget);
466444c061aSmrg    LOCK_APP(app);
467444c061aSmrg    AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other,
468444c061aSmrg		    proc, closure, XtListTail, FALSE, TRUE);
469444c061aSmrg    UNLOCK_APP(app);
470444c061aSmrg}
471444c061aSmrg
472444c061aSmrgvoid XtRemoveEventTypeHandler(
473444c061aSmrg    Widget	    widget,
474444c061aSmrg    int		    type,
475444c061aSmrg    XtPointer	    select_data,
476444c061aSmrg    XtEventHandler  proc,
477444c061aSmrg    XtPointer	    closure)
478444c061aSmrg{
479444c061aSmrg    WIDGET_TO_APPCON(widget);
480444c061aSmrg    LOCK_APP(app);
481444c061aSmrg    RemoveEventHandler(widget, select_data, type, TRUE,
482444c061aSmrg		       FALSE, proc, closure, FALSE);
483444c061aSmrg    UNLOCK_APP(app);
484444c061aSmrg}
485444c061aSmrg
486444c061aSmrgvoid XtInsertEventTypeHandler(
487444c061aSmrg    Widget	    widget,
488444c061aSmrg    int		    type,
489444c061aSmrg    XtPointer	    select_data,
490444c061aSmrg    XtEventHandler  proc,
491444c061aSmrg    XtPointer	    closure,
492444c061aSmrg    XtListPosition  position)
493444c061aSmrg{
494444c061aSmrg    WIDGET_TO_APPCON(widget);
495444c061aSmrg    LOCK_APP(app);
496444c061aSmrg    AddEventHandler(widget, select_data, type, TRUE, FALSE,
497444c061aSmrg		    proc, closure, position, TRUE, FALSE);
498444c061aSmrg    UNLOCK_APP(app);
499444c061aSmrg}
500444c061aSmrg
501444c061aSmrgtypedef struct _WWPair {
502444c061aSmrg    struct _WWPair *next;
503444c061aSmrg    Window window;
504444c061aSmrg    Widget widget;
505444c061aSmrg} *WWPair;
506444c061aSmrg
507444c061aSmrgtypedef struct _WWTable {
508444c061aSmrg    unsigned int mask;		/* size of hash table - 1 */
509444c061aSmrg    unsigned int rehash;	/* mask - 2 */
510444c061aSmrg    unsigned int occupied;	/* number of occupied entries */
511444c061aSmrg    unsigned int fakes;		/* number occupied by WWfake */
512444c061aSmrg    Widget *entries;		/* the entries */
513444c061aSmrg    WWPair pairs;		/* bogus entries */
514444c061aSmrg} *WWTable;
515444c061aSmrg
516444c061aSmrgstatic const WidgetRec WWfake;	/* placeholder for deletions */
517444c061aSmrg
518444c061aSmrg#define WWHASH(tab,win) ((win) & tab->mask)
519444c061aSmrg#define WWREHASHVAL(tab,win) ((((win) % tab->rehash) + 2) | 1)
520444c061aSmrg#define WWREHASH(tab,idx,rehash) ((idx + rehash) & tab->mask)
521444c061aSmrg#define WWTABLE(display) (_XtGetPerDisplay(display)->WWtable)
522444c061aSmrg
523444c061aSmrgstatic void ExpandWWTable(WWTable);
524444c061aSmrg
525444c061aSmrgvoid XtRegisterDrawable(
526444c061aSmrg    Display* display,
527444c061aSmrg    Drawable drawable,
528444c061aSmrg    Widget widget)
529444c061aSmrg{
530444c061aSmrg    WWTable tab;
531444c061aSmrg    int idx, rehash;
532444c061aSmrg    Widget entry;
533444c061aSmrg    Window window = (Window) drawable;
534444c061aSmrg    WIDGET_TO_APPCON(widget);
535444c061aSmrg
536444c061aSmrg    LOCK_APP(app);
537444c061aSmrg    LOCK_PROCESS;
538444c061aSmrg    tab = WWTABLE(display);
539444c061aSmrg    if (window != XtWindow(widget)) {
540444c061aSmrg	WWPair pair;
541444c061aSmrg	pair = XtNew(struct _WWPair);
542444c061aSmrg	pair->next = tab->pairs;
543444c061aSmrg	pair->window = window;
544444c061aSmrg	pair->widget = widget;
545444c061aSmrg	tab->pairs = pair;
546444c061aSmrg	UNLOCK_PROCESS;
547444c061aSmrg	UNLOCK_APP(app);
548444c061aSmrg	return;
549444c061aSmrg    }
550444c061aSmrg    if ((tab->occupied + (tab->occupied >> 2)) > tab->mask)
551444c061aSmrg	ExpandWWTable(tab);
552444c061aSmrg
553444c061aSmrg    idx = WWHASH(tab, window);
554444c061aSmrg    if ((entry = tab->entries[idx]) && entry != &WWfake) {
555444c061aSmrg	rehash = WWREHASHVAL(tab, window);
556444c061aSmrg	do {
557444c061aSmrg	    idx = WWREHASH(tab, idx, rehash);
558444c061aSmrg	} while ((entry = tab->entries[idx]) && entry != &WWfake);
559444c061aSmrg    }
560444c061aSmrg    if (!entry)
561444c061aSmrg	tab->occupied++;
562444c061aSmrg    else if (entry == &WWfake)
563444c061aSmrg	tab->fakes--;
564444c061aSmrg    tab->entries[idx] = widget;
565444c061aSmrg    UNLOCK_PROCESS;
566444c061aSmrg    UNLOCK_APP(app);
567444c061aSmrg}
568444c061aSmrg
569444c061aSmrgvoid XtUnregisterDrawable(
570444c061aSmrg    Display* display,
571444c061aSmrg    Drawable drawable)
572444c061aSmrg{
573444c061aSmrg    WWTable tab;
574444c061aSmrg    int idx, rehash;
575444c061aSmrg    Widget entry;
576444c061aSmrg    Window window = (Window) drawable;
577444c061aSmrg    Widget widget = XtWindowToWidget (display, window);
578444c061aSmrg    DPY_TO_APPCON(display);
579444c061aSmrg
580444c061aSmrg    if (widget == NULL) return;
581444c061aSmrg
582444c061aSmrg    LOCK_APP(app);
583444c061aSmrg    LOCK_PROCESS;
584444c061aSmrg    tab = WWTABLE(display);
585444c061aSmrg    if (window != XtWindow(widget)) {
586444c061aSmrg	WWPair *prev, pair;
587444c061aSmrg
588444c061aSmrg	prev = &tab->pairs;
589444c061aSmrg	while ((pair = *prev) && pair->window != window)
590444c061aSmrg	    prev = &pair->next;
591444c061aSmrg	if (pair) {
592444c061aSmrg	    *prev = pair->next;
593444c061aSmrg	    XtFree((char *)pair);
594444c061aSmrg	}
595444c061aSmrg	UNLOCK_PROCESS;
596444c061aSmrg	UNLOCK_APP(app);
597444c061aSmrg	return;
598444c061aSmrg    }
599444c061aSmrg    idx = WWHASH(tab, window);
600444c061aSmrg    if ((entry = tab->entries[idx])) {
601444c061aSmrg	if (entry != widget) {
602444c061aSmrg	    rehash = WWREHASHVAL(tab, window);
603444c061aSmrg	    do {
604444c061aSmrg		idx = WWREHASH(tab, idx, rehash);
605444c061aSmrg		if (!(entry = tab->entries[idx])) {
606444c061aSmrg		    UNLOCK_PROCESS;
607444c061aSmrg		    UNLOCK_APP(app);
608444c061aSmrg		    return;
609444c061aSmrg		}
610444c061aSmrg	    } while (entry != widget);
611444c061aSmrg	}
612444c061aSmrg	tab->entries[idx] = (Widget)&WWfake;
613444c061aSmrg	tab->fakes++;
614444c061aSmrg    }
615444c061aSmrg    UNLOCK_PROCESS;
616444c061aSmrg    UNLOCK_APP(app);
617444c061aSmrg}
618444c061aSmrg
619444c061aSmrgstatic void ExpandWWTable(
620444c061aSmrg    register WWTable tab)
621444c061aSmrg{
622444c061aSmrg    unsigned int oldmask;
623444c061aSmrg    register Widget *oldentries, *entries;
624444c061aSmrg    register Cardinal oldidx, newidx, rehash;
625444c061aSmrg    register Widget entry;
626444c061aSmrg
627444c061aSmrg    LOCK_PROCESS;
628444c061aSmrg    oldmask = tab->mask;
629444c061aSmrg    oldentries = tab->entries;
630444c061aSmrg    tab->occupied -= tab->fakes;
631444c061aSmrg    tab->fakes = 0;
632444c061aSmrg    if ((tab->occupied + (tab->occupied >> 2)) > tab->mask) {
633444c061aSmrg	tab->mask = (tab->mask << 1) + 1;
634444c061aSmrg	tab->rehash = tab->mask - 2;
635444c061aSmrg    }
636444c061aSmrg    entries = tab->entries = (Widget *) __XtCalloc(tab->mask+1, sizeof(Widget));
637444c061aSmrg    for (oldidx = 0; oldidx <= oldmask; oldidx++) {
638444c061aSmrg	if ((entry = oldentries[oldidx]) && entry != &WWfake) {
639444c061aSmrg	    newidx = WWHASH(tab, XtWindow(entry));
640444c061aSmrg	    if (entries[newidx]) {
641444c061aSmrg		rehash = WWREHASHVAL(tab, XtWindow(entry));
642444c061aSmrg		do {
643444c061aSmrg		    newidx = WWREHASH(tab, newidx, rehash);
644444c061aSmrg		} while (entries[newidx]);
645444c061aSmrg	    }
646444c061aSmrg	    entries[newidx] = entry;
647444c061aSmrg	}
648444c061aSmrg    }
649444c061aSmrg    XtFree((char *)oldentries);
650444c061aSmrg    UNLOCK_PROCESS;
651444c061aSmrg}
652444c061aSmrg
653444c061aSmrgWidget XtWindowToWidget(
654444c061aSmrg    register Display *display,
655444c061aSmrg    register Window window)
656444c061aSmrg{
657444c061aSmrg    register WWTable tab;
658444c061aSmrg    register int idx, rehash;
659444c061aSmrg    register Widget entry;
660444c061aSmrg    WWPair pair;
661444c061aSmrg    DPY_TO_APPCON(display);
662444c061aSmrg
663444c061aSmrg    if (!window) return NULL;
664444c061aSmrg
665444c061aSmrg    LOCK_APP(app);
666444c061aSmrg    LOCK_PROCESS;
667444c061aSmrg    tab = WWTABLE(display);
668444c061aSmrg    idx = WWHASH(tab, window);
669444c061aSmrg    if ((entry = tab->entries[idx]) && XtWindow(entry) != window) {
670444c061aSmrg	rehash = WWREHASHVAL(tab, window);
671444c061aSmrg	do {
672444c061aSmrg	    idx = WWREHASH(tab, idx, rehash);
673444c061aSmrg	} while ((entry = tab->entries[idx]) && XtWindow(entry) != window);
674444c061aSmrg    }
675444c061aSmrg    if (entry) {
676444c061aSmrg    	UNLOCK_PROCESS;
677444c061aSmrg    	UNLOCK_APP(app);
678444c061aSmrg	return entry;
679444c061aSmrg    }
680444c061aSmrg    for (pair = tab->pairs; pair; pair = pair->next) {
681444c061aSmrg	if (pair->window == window) {
682444c061aSmrg	    entry = pair->widget;
683444c061aSmrg	    UNLOCK_PROCESS;
684444c061aSmrg    	    UNLOCK_APP(app);
685444c061aSmrg	    return entry;
686444c061aSmrg	}
687444c061aSmrg    }
688444c061aSmrg    UNLOCK_PROCESS;
689444c061aSmrg    UNLOCK_APP(app);
690444c061aSmrg    return NULL;
691444c061aSmrg}
692444c061aSmrg
693444c061aSmrgvoid _XtAllocWWTable(
694444c061aSmrg    XtPerDisplay pd)
695444c061aSmrg{
696444c061aSmrg    register WWTable tab;
697444c061aSmrg
698444c061aSmrg    tab = (WWTable) __XtMalloc(sizeof(struct _WWTable));
699444c061aSmrg    tab->mask = 0x7f;
700444c061aSmrg    tab->rehash = tab->mask - 2;
701444c061aSmrg    tab->entries = (Widget *) __XtCalloc(tab->mask+1, sizeof(Widget));
702444c061aSmrg    tab->occupied = 0;
703444c061aSmrg    tab->fakes = 0;
704444c061aSmrg    tab->pairs = NULL;
705444c061aSmrg    pd->WWtable = tab;
706444c061aSmrg}
707444c061aSmrg
708444c061aSmrgvoid _XtFreeWWTable(
709444c061aSmrg    register XtPerDisplay pd)
710444c061aSmrg{
711444c061aSmrg    register WWPair pair, next;
712444c061aSmrg
713444c061aSmrg    for (pair = pd->WWtable->pairs; pair; pair = next) {
714444c061aSmrg	next = pair->next;
715444c061aSmrg	XtFree((char *)pair);
716444c061aSmrg    }
717444c061aSmrg    XtFree((char *)pd->WWtable->entries);
718444c061aSmrg    XtFree((char *)pd->WWtable);
719444c061aSmrg}
720444c061aSmrg
721444c061aSmrg#define EHMAXSIZE 25 /* do not make whopping big */
722444c061aSmrg
723444c061aSmrgstatic Boolean CallEventHandlers(
724444c061aSmrg    Widget     widget,
725444c061aSmrg    XEvent    *event,
726444c061aSmrg    EventMask  mask)
727444c061aSmrg{
728444c061aSmrg    register XtEventRec *p;
729444c061aSmrg    XtEventHandler *proc;
730444c061aSmrg    XtPointer *closure;
731444c061aSmrg    XtEventHandler procs[EHMAXSIZE];
732444c061aSmrg    XtPointer closures[EHMAXSIZE];
733444c061aSmrg    Boolean cont_to_disp = True;
734444c061aSmrg    int i, numprocs;
735444c061aSmrg
736444c061aSmrg    /* Have to copy the procs into an array, because one of them might
737444c061aSmrg     * call XtRemoveEventHandler, which would break our linked list. */
738444c061aSmrg
739444c061aSmrg    numprocs = 0;
740444c061aSmrg    for (p=widget->core.event_table; p; p = p->next) {
741444c061aSmrg	if ((!p->has_type_specifier && (mask & p->mask)) ||
742444c061aSmrg	    (p->has_type_specifier && event->type == EXT_TYPE(p)))
743444c061aSmrg	    numprocs++;
744444c061aSmrg    }
745444c061aSmrg    if (numprocs > EHMAXSIZE) {
746444c061aSmrg	proc = (XtEventHandler *)__XtMalloc(numprocs * (sizeof(XtEventHandler) +
747444c061aSmrg						      sizeof(XtPointer)));
748444c061aSmrg	closure = (XtPointer *)(proc + numprocs);
749444c061aSmrg    } else {
750444c061aSmrg	proc = procs;
751444c061aSmrg	closure = closures;
752444c061aSmrg    }
753444c061aSmrg    numprocs = 0;
754444c061aSmrg    for (p=widget->core.event_table; p; p = p->next) {
755444c061aSmrg	if ((!p->has_type_specifier && (mask & p->mask)) ||
756444c061aSmrg	    (p->has_type_specifier && event->type == EXT_TYPE(p))) {
757444c061aSmrg	    proc[numprocs] = p->proc;
758444c061aSmrg	    closure[numprocs] = p->closure;
759444c061aSmrg	    numprocs++;
760444c061aSmrg	}
761444c061aSmrg    }
762444c061aSmrg/* FUNCTIONS CALLED THROUGH POINTER proc:
763444c061aSmrg		Selection.c:ReqCleanup,
764444c061aSmrg		"Shell.c":EventHandler,
765444c061aSmrg		PassivGrab.c:ActiveHandler,
766444c061aSmrg		PassivGrab.c:RealizeHandler,
767444c061aSmrg		Keyboard.c:QueryEventMask,
768444c061aSmrg		_XtHandleFocus,
769444c061aSmrg		Selection.c:HandleSelectionReplies,
770444c061aSmrg		Selection.c:HandleGetIncrement,
771444c061aSmrg		Selection.c:HandleIncremental,
772444c061aSmrg		Selection.c:HandlePropertyGone,
773444c061aSmrg		Selection.c:HandleSelectionEvents
774444c061aSmrg		*/
775444c061aSmrg    for (i = 0; i < numprocs && cont_to_disp; i++)
776444c061aSmrg	(*(proc[i]))(widget, closure[i], event, &cont_to_disp);
777444c061aSmrg    if (numprocs > EHMAXSIZE)
778444c061aSmrg	XtFree((char *)proc);
779444c061aSmrg    return cont_to_disp;
780444c061aSmrg}
781444c061aSmrg
782444c061aSmrgstatic void CompressExposures(XEvent *, Widget);
783444c061aSmrg
784444c061aSmrg#define KnownButtons (Button1MotionMask|Button2MotionMask|Button3MotionMask|\
785444c061aSmrg		      Button4MotionMask|Button5MotionMask)
786444c061aSmrg
787444c061aSmrg/* keep this SMALL to avoid blowing stack cache! */
788444c061aSmrg/* because some compilers allocate all local locals on procedure entry */
789444c061aSmrg#define EHSIZE 4
790444c061aSmrg
791444c061aSmrgBoolean XtDispatchEventToWidget(
792444c061aSmrg    Widget widget,
793444c061aSmrg    XEvent* event)
794444c061aSmrg{
795444c061aSmrg    register XtEventRec *p;
796444c061aSmrg    Boolean was_dispatched = False;
797444c061aSmrg    Boolean call_tm = False;
798444c061aSmrg    Boolean cont_to_disp;
799444c061aSmrg    EventMask mask;
800444c061aSmrg    WIDGET_TO_APPCON(widget);
801444c061aSmrg
802444c061aSmrg    LOCK_APP(app);
803444c061aSmrg
804444c061aSmrg    mask = _XtConvertTypeToMask(event->type);
805444c061aSmrg    if (event->type == MotionNotify)
806444c061aSmrg	mask |= (event->xmotion.state & KnownButtons);
807444c061aSmrg
808444c061aSmrg    LOCK_PROCESS;
809444c061aSmrg    if ( (mask == ExposureMask) ||
810444c061aSmrg	 ((event->type == NoExpose) && NO_EXPOSE) ||
811444c061aSmrg	 ((event->type == GraphicsExpose) && GRAPHICS_EXPOSE) ) {
812444c061aSmrg
813444c061aSmrg	if (widget->core.widget_class->core_class.expose != NULL ) {
814444c061aSmrg
815444c061aSmrg	    /* We need to mask off the bits that could contain the information
816444c061aSmrg	     * about whether or not we desire Graphics and NoExpose events.  */
817444c061aSmrg
818444c061aSmrg	    if ( (COMP_EXPOSE_TYPE == XtExposeNoCompress) ||
819444c061aSmrg		 (event->type == NoExpose) )
820444c061aSmrg
821444c061aSmrg		(*widget->core.widget_class->core_class.expose)
822444c061aSmrg		    (widget, event, (Region)NULL);
823444c061aSmrg	    else {
824444c061aSmrg		CompressExposures(event, widget);
825444c061aSmrg	    }
826444c061aSmrg	    was_dispatched = True;
827444c061aSmrg	}
828444c061aSmrg    }
829444c061aSmrg
830444c061aSmrg    if ((mask == VisibilityChangeMask) &&
831444c061aSmrg        XtClass(widget)->core_class.visible_interest) {
832444c061aSmrg	    was_dispatched = True;
833444c061aSmrg	    /* our visibility just changed... */
834444c061aSmrg	    switch (((XVisibilityEvent *)event)->state) {
835444c061aSmrg		case VisibilityUnobscured:
836444c061aSmrg		    widget->core.visible = TRUE;
837444c061aSmrg		    break;
838444c061aSmrg
839444c061aSmrg		case VisibilityPartiallyObscured:
840444c061aSmrg		    /* what do we want to say here? */
841444c061aSmrg		    /* well... some of us is visible */
842444c061aSmrg		    widget->core.visible = TRUE;
843444c061aSmrg		    break;
844444c061aSmrg
845444c061aSmrg		case VisibilityFullyObscured:
846444c061aSmrg		    widget->core.visible = FALSE;
847444c061aSmrg		    /* do we want to mark our children obscured? */
848444c061aSmrg		    break;
849444c061aSmrg	    }
850444c061aSmrg	}
851444c061aSmrg    UNLOCK_PROCESS;
852444c061aSmrg
853444c061aSmrg    /* to maintain "copy" semantics we check TM now but call later */
854444c061aSmrg    if (widget->core.tm.translations &&
855444c061aSmrg	(mask & widget->core.tm.translations->eventMask))
856444c061aSmrg	call_tm = True;
857444c061aSmrg
858444c061aSmrg    cont_to_disp = True;
859444c061aSmrg    p=widget->core.event_table;
860444c061aSmrg    if (p) {
861444c061aSmrg	if (p->next) {
862444c061aSmrg	    XtEventHandler proc[EHSIZE];
863444c061aSmrg	    XtPointer closure[EHSIZE];
864444c061aSmrg	    int numprocs = 0;
865444c061aSmrg
866444c061aSmrg	    /* Have to copy the procs into an array, because one of them might
867444c061aSmrg	     * call XtRemoveEventHandler, which would break our linked list. */
868444c061aSmrg
869444c061aSmrg	    for (; p; p = p->next) {
870444c061aSmrg		if ((!p->has_type_specifier && (mask & p->mask)) ||
871444c061aSmrg		    (p->has_type_specifier && event->type == EXT_TYPE(p))) {
872444c061aSmrg		    if (numprocs >= EHSIZE)
873444c061aSmrg			break;
874444c061aSmrg		    proc[numprocs] = p->proc;
875444c061aSmrg		    closure[numprocs] = p->closure;
876444c061aSmrg		    numprocs++;
877444c061aSmrg		}
878444c061aSmrg	    }
879444c061aSmrg	    if (numprocs) {
880444c061aSmrg		if (p) {
881444c061aSmrg		    cont_to_disp = CallEventHandlers(widget, event, mask);
882444c061aSmrg		} else {
883444c061aSmrg		    int i;
884444c061aSmrg		    for (i = 0; i < numprocs && cont_to_disp; i++)
885444c061aSmrg			(*(proc[i]))(widget, closure[i], event, &cont_to_disp);
886444c061aSmrg/* FUNCTIONS CALLED THROUGH POINTER proc:
887444c061aSmrg		Selection.c:ReqCleanup,
888444c061aSmrg		"Shell.c":EventHandler,
889444c061aSmrg		PassivGrab.c:ActiveHandler,
890444c061aSmrg		PassivGrab.c:RealizeHandler,
891444c061aSmrg		Keyboard.c:QueryEventMask,
892444c061aSmrg		_XtHandleFocus,
893444c061aSmrg		Selection.c:HandleSelectionReplies,
894444c061aSmrg		Selection.c:HandleGetIncrement,
895444c061aSmrg		Selection.c:HandleIncremental,
896444c061aSmrg		Selection.c:HandlePropertyGone,
897444c061aSmrg		Selection.c:HandleSelectionEvents
898444c061aSmrg		*/
899444c061aSmrg		}
900444c061aSmrg		was_dispatched = True;
901444c061aSmrg	    }
902444c061aSmrg	} else if ((!p->has_type_specifier && (mask & p->mask)) ||
903444c061aSmrg		   (p->has_type_specifier && event->type == EXT_TYPE(p))) {
904444c061aSmrg	    (*p->proc)(widget, p->closure, event, &cont_to_disp);
905444c061aSmrg	    was_dispatched = True;
906444c061aSmrg	}
907444c061aSmrg    }
908444c061aSmrg    if (call_tm && cont_to_disp)
909444c061aSmrg	_XtTranslateEvent(widget, event);
910444c061aSmrg    UNLOCK_APP(app);
911444c061aSmrg    return (was_dispatched|call_tm);
912444c061aSmrg}
913444c061aSmrg
914444c061aSmrg/*
915444c061aSmrg * This structure is passed into the check exposure proc.
916444c061aSmrg */
917444c061aSmrg
918444c061aSmrgtypedef struct _CheckExposeInfo {
919444c061aSmrg    int type1, type2;		/* Types of events to check for. */
920444c061aSmrg    Boolean maximal;		/* Ignore non-exposure events? */
921444c061aSmrg    Boolean non_matching;	/* Was there an event that did not
922444c061aSmrg				   match either type? */
923444c061aSmrg    Window window;		/* Window to match. */
924444c061aSmrg} CheckExposeInfo;
925444c061aSmrg
926444c061aSmrg#define GetCount(ev) (((XExposeEvent *)(ev))->count)
927444c061aSmrg
928444c061aSmrgstatic void SendExposureEvent(XEvent *, Widget, XtPerDisplay);
929444c061aSmrgstatic Bool CheckExposureEvent(Display *, XEvent *, char *);
930444c061aSmrgstatic void AddExposureToRectangularRegion(XEvent *, Region);
931444c061aSmrg
932444c061aSmrg/*	Function Name: CompressExposures
933444c061aSmrg *	Description: Handles all exposure compression
934444c061aSmrg *	Arguments: event - the xevent that is to be dispatched
935444c061aSmrg *                 widget - the widget that this event occured in.
936444c061aSmrg *	Returns: none.
937444c061aSmrg *
938444c061aSmrg *      NOTE: Event must be of type Expose or GraphicsExpose.
939444c061aSmrg */
940444c061aSmrg
941444c061aSmrgstatic void
942444c061aSmrgCompressExposures(
943444c061aSmrgXEvent * event,
944444c061aSmrgWidget widget)
945444c061aSmrg{
946444c061aSmrg    CheckExposeInfo info;
947444c061aSmrg    int count;
948444c061aSmrg    Display* dpy = XtDisplay (widget);
949444c061aSmrg    XtPerDisplay pd = _XtGetPerDisplay(dpy);
950444c061aSmrg    XtEnum comp_expose;
951444c061aSmrg    XtEnum comp_expose_type;
952444c061aSmrg    Boolean no_region;
953444c061aSmrg
954444c061aSmrg    LOCK_PROCESS;
955444c061aSmrg    comp_expose = COMP_EXPOSE;
956444c061aSmrg    UNLOCK_PROCESS;
957444c061aSmrg    comp_expose_type = comp_expose & 0x0f;
958444c061aSmrg    no_region = ((comp_expose & XtExposeNoRegion) ? True : False);
959444c061aSmrg
960444c061aSmrg    if (no_region)
961444c061aSmrg	AddExposureToRectangularRegion(event, pd->region);
962444c061aSmrg    else
963444c061aSmrg	XtAddExposureToRegion(event, pd->region);
964444c061aSmrg
965444c061aSmrg    if ( GetCount(event) != 0 )
966444c061aSmrg 	return;
967444c061aSmrg
968444c061aSmrg    if ((comp_expose_type == XtExposeCompressSeries) ||
969444c061aSmrg	(XEventsQueued(dpy, QueuedAfterReading) == 0)) {
970444c061aSmrg	SendExposureEvent(event, widget, pd);
971444c061aSmrg	return;
972444c061aSmrg    }
973444c061aSmrg
974444c061aSmrg    if (comp_expose & XtExposeGraphicsExposeMerged) {
975444c061aSmrg	info.type1 = Expose;
976444c061aSmrg	info.type2 = GraphicsExpose;
977444c061aSmrg    }
978444c061aSmrg    else {
979444c061aSmrg	info.type1 = event->type;
980444c061aSmrg	info.type2 = 0;
981444c061aSmrg    }
982444c061aSmrg    info.maximal = (comp_expose_type == XtExposeCompressMaximal);
983444c061aSmrg    info.non_matching = FALSE;
984444c061aSmrg    info.window = XtWindow(widget);
985444c061aSmrg
986444c061aSmrg/*
987444c061aSmrg * We have to be very careful here not to hose down the processor
988444c061aSmrg * when blocking until count gets to zero.
989444c061aSmrg *
990444c061aSmrg * First, check to see if there are any events in the queue for this
991444c061aSmrg * widget, and of the correct type.
992444c061aSmrg *
993444c061aSmrg * Once we cannot find any more events, check to see that count is zero.
994444c061aSmrg * If it is not then block until we get another exposure event.
995444c061aSmrg *
996444c061aSmrg * If we find no more events, and count on the last one we saw was zero we
997444c061aSmrg * we can be sure that all events have been processed.
998444c061aSmrg *
999444c061aSmrg * Unfortunately, we wind up having to look at the entire queue
1000444c061aSmrg * event if we're not doing Maximal compression, due to the
1001444c061aSmrg * semantics of XCheckIfEvent (we can't abort without re-ordering
1002444c061aSmrg * the event queue as a side-effect).
1003444c061aSmrg */
1004444c061aSmrg
1005444c061aSmrg    count = 0;
1006444c061aSmrg    while (TRUE) {
1007444c061aSmrg	XEvent event_return;
1008444c061aSmrg
1009444c061aSmrg	if (XCheckIfEvent(dpy, &event_return,
1010444c061aSmrg			  CheckExposureEvent, (char *) &info)) {
1011444c061aSmrg
1012444c061aSmrg	    count = GetCount(&event_return);
1013444c061aSmrg 	    if (no_region)
1014444c061aSmrg		AddExposureToRectangularRegion(&event_return, pd->region);
1015444c061aSmrg 	    else
1016444c061aSmrg		XtAddExposureToRegion(&event_return, pd->region);
1017444c061aSmrg	}
1018444c061aSmrg	else if (count != 0) {
1019444c061aSmrg	    XIfEvent(dpy, &event_return,
1020444c061aSmrg		     CheckExposureEvent, (char *) &info);
1021444c061aSmrg	    count = GetCount(&event_return);
1022444c061aSmrg 	    if (no_region)
1023444c061aSmrg		AddExposureToRectangularRegion(&event_return, pd->region);
1024444c061aSmrg 	    else
1025444c061aSmrg		XtAddExposureToRegion(&event_return, pd->region);
1026444c061aSmrg	}
1027444c061aSmrg	else /* count == 0 && XCheckIfEvent Failed. */
1028444c061aSmrg	    break;
1029444c061aSmrg    }
1030444c061aSmrg
1031444c061aSmrg    SendExposureEvent(event, widget, pd);
1032444c061aSmrg}
1033444c061aSmrg
1034444c061aSmrgvoid XtAddExposureToRegion(
1035444c061aSmrg    XEvent   *event,
1036444c061aSmrg    Region   region)
1037444c061aSmrg{
1038444c061aSmrg    XRectangle rect;
1039444c061aSmrg    XExposeEvent *ev = (XExposeEvent *) event;
1040444c061aSmrg    /* These Expose and GraphicsExpose fields are at identical offsets */
1041444c061aSmrg
1042444c061aSmrg    if (event->type == Expose || event->type == GraphicsExpose) {
1043444c061aSmrg	rect.x = ev->x;
1044444c061aSmrg	rect.y = ev->y;
1045444c061aSmrg	rect.width = ev->width;
1046444c061aSmrg	rect.height = ev->height;
1047444c061aSmrg	XUnionRectWithRegion(&rect, region, region);
1048444c061aSmrg    }
1049444c061aSmrg}
1050444c061aSmrg
1051444c061aSmrg#ifndef MAX
1052444c061aSmrg#define MAX(a,b) (((a) > (b)) ? (a) : (b))
1053444c061aSmrg#endif
1054444c061aSmrg
1055444c061aSmrg#ifndef MIN
1056444c061aSmrg#define MIN(a,b) (((a) < (b)) ? (a) : (b))
1057444c061aSmrg#endif
1058444c061aSmrg
1059444c061aSmrgstatic void AddExposureToRectangularRegion(
1060444c061aSmrg     XEvent *event, /* when called internally, type is always appropriate */
1061444c061aSmrg     Region  region)
1062444c061aSmrg{
1063444c061aSmrg    XRectangle rect;
1064444c061aSmrg    XExposeEvent *ev = (XExposeEvent *) event;
1065444c061aSmrg    /* These Expose and GraphicsExpose fields are at identical offsets */
1066444c061aSmrg
1067444c061aSmrg    rect.x = ev->x;
1068444c061aSmrg    rect.y = ev->y;
1069444c061aSmrg    rect.width = ev->width;
1070444c061aSmrg    rect.height = ev->height;
1071444c061aSmrg
1072444c061aSmrg    if (XEmptyRegion(region)) {
1073444c061aSmrg	XUnionRectWithRegion(&rect, region, region);
1074444c061aSmrg    } else {
1075444c061aSmrg	XRectangle merged, bbox;
1076444c061aSmrg
1077444c061aSmrg	XClipBox(region, &bbox);
1078444c061aSmrg	merged.x = MIN(rect.x, bbox.x);
1079444c061aSmrg	merged.y = MIN(rect.y, bbox.y);
1080444c061aSmrg	merged.width = MAX(rect.x + rect.width,
1081444c061aSmrg			   bbox.x + bbox.width) - merged.x;
1082444c061aSmrg	merged.height = MAX(rect.y + rect.height,
1083444c061aSmrg			    bbox.y + bbox.height) - merged.y;
1084444c061aSmrg	XUnionRectWithRegion(&merged, region, region);
1085444c061aSmrg    }
1086444c061aSmrg}
1087444c061aSmrg
1088444c061aSmrgstatic Region nullRegion;
1089444c061aSmrg/* READ-ONLY VARIABLES: nullRegion */
1090444c061aSmrg
1091444c061aSmrgvoid _XtEventInitialize(void)
1092444c061aSmrg{
1093444c061aSmrg#ifndef __lock_lint
1094444c061aSmrg    nullRegion = XCreateRegion();
1095444c061aSmrg#endif
1096444c061aSmrg}
1097444c061aSmrg
1098444c061aSmrg/*	Function Name: SendExposureEvent
1099444c061aSmrg *	Description: Sets the x, y, width, and height of the event
1100444c061aSmrg *                   to be the clip box of Expose Region.
1101444c061aSmrg *	Arguments: event  - the X Event to mangle; Expose or GraphicsExpose.
1102444c061aSmrg *                 widget - the widget that this event occured in.
1103444c061aSmrg *                 pd     - the per display information for this widget.
1104444c061aSmrg *	Returns: none.
1105444c061aSmrg */
1106444c061aSmrg
1107444c061aSmrgstatic void
1108444c061aSmrgSendExposureEvent(
1109444c061aSmrgXEvent * event,
1110444c061aSmrgWidget widget,
1111444c061aSmrgXtPerDisplay pd)
1112444c061aSmrg{
1113444c061aSmrg    XtExposeProc expose;
1114444c061aSmrg    XRectangle rect;
1115444c061aSmrg    XtEnum comp_expose;
1116444c061aSmrg    XExposeEvent *ev = (XExposeEvent *) event;
1117444c061aSmrg
1118444c061aSmrg    XClipBox(pd->region, &rect);
1119444c061aSmrg    ev->x = rect.x;
1120444c061aSmrg    ev->y = rect.y;
1121444c061aSmrg    ev->width = rect.width;
1122444c061aSmrg    ev->height = rect.height;
1123444c061aSmrg
1124444c061aSmrg    LOCK_PROCESS;
1125444c061aSmrg    comp_expose = COMP_EXPOSE;
1126444c061aSmrg    expose = widget->core.widget_class->core_class.expose;
1127444c061aSmrg    UNLOCK_PROCESS;
1128444c061aSmrg    if (comp_expose & XtExposeNoRegion)
1129444c061aSmrg	(*expose)(widget, event, NULL);
1130444c061aSmrg    else
1131444c061aSmrg	(*expose)(widget, event, pd->region);
1132444c061aSmrg    (void) XIntersectRegion(nullRegion, pd->region, pd->region);
1133444c061aSmrg}
1134444c061aSmrg
1135444c061aSmrg/*	Function Name: CheckExposureEvent
1136444c061aSmrg *	Description: Checks the event queue for an expose event
1137444c061aSmrg *	Arguments: display - the display connection.
1138444c061aSmrg *                 event - the event to check.
1139444c061aSmrg *                 arg - a pointer to the exposure info structure.
1140444c061aSmrg *	Returns: TRUE if we found an event of the correct type
1141444c061aSmrg *               with the right window.
1142444c061aSmrg *
1143444c061aSmrg * NOTE: The only valid types (info.type1 and info.type2) are Expose
1144444c061aSmrg *       and GraphicsExpose.
1145444c061aSmrg */
1146444c061aSmrg
1147444c061aSmrg/* ARGSUSED */
1148444c061aSmrgstatic Bool
1149444c061aSmrgCheckExposureEvent(
1150444c061aSmrgDisplay * disp,
1151444c061aSmrgXEvent * event,
1152444c061aSmrgchar * arg)
1153444c061aSmrg{
1154444c061aSmrg    CheckExposeInfo * info = ((CheckExposeInfo *) arg);
1155444c061aSmrg
1156444c061aSmrg    if ( (info->type1 == event->type) || (info->type2 == event->type)) {
1157444c061aSmrg	if (!info->maximal && info->non_matching) return FALSE;
1158444c061aSmrg	if (event->type == GraphicsExpose)
1159444c061aSmrg	    return(event->xgraphicsexpose.drawable == info->window);
1160444c061aSmrg	return(event->xexpose.window == info->window);
1161444c061aSmrg    }
1162444c061aSmrg    info->non_matching = TRUE;
1163444c061aSmrg    return(FALSE);
1164444c061aSmrg}
1165444c061aSmrg
1166444c061aSmrgstatic EventMask const masks[] = {
1167444c061aSmrg	0,			    /* Error, should never see  */
1168444c061aSmrg	0,			    /* Reply, should never see  */
1169444c061aSmrg	KeyPressMask,		    /* KeyPress			*/
1170444c061aSmrg	KeyReleaseMask,		    /* KeyRelease		*/
1171444c061aSmrg	ButtonPressMask,	    /* ButtonPress		*/
1172444c061aSmrg	ButtonReleaseMask,	    /* ButtonRelease		*/
1173444c061aSmrg	PointerMotionMask	    /* MotionNotify		*/
1174444c061aSmrg		| ButtonMotionMask,
1175444c061aSmrg	EnterWindowMask,	    /* EnterNotify		*/
1176444c061aSmrg	LeaveWindowMask,	    /* LeaveNotify		*/
1177444c061aSmrg	FocusChangeMask,	    /* FocusIn			*/
1178444c061aSmrg	FocusChangeMask,	    /* FocusOut			*/
1179444c061aSmrg	KeymapStateMask,	    /* KeymapNotify		*/
1180444c061aSmrg	ExposureMask,		    /* Expose			*/
1181444c061aSmrg	NonMaskableMask,	    /* GraphicsExpose, in GC    */
1182444c061aSmrg	NonMaskableMask,	    /* NoExpose, in GC		*/
1183444c061aSmrg	VisibilityChangeMask,       /* VisibilityNotify		*/
1184444c061aSmrg	SubstructureNotifyMask,     /* CreateNotify		*/
1185444c061aSmrg	StructureNotifyMask	    /* DestroyNotify		*/
1186444c061aSmrg		| SubstructureNotifyMask,
1187444c061aSmrg	StructureNotifyMask	    /* UnmapNotify		*/
1188444c061aSmrg		| SubstructureNotifyMask,
1189444c061aSmrg	StructureNotifyMask	    /* MapNotify		*/
1190444c061aSmrg		| SubstructureNotifyMask,
1191444c061aSmrg	SubstructureRedirectMask,   /* MapRequest		*/
1192444c061aSmrg	StructureNotifyMask	    /* ReparentNotify		*/
1193444c061aSmrg		| SubstructureNotifyMask,
1194444c061aSmrg	StructureNotifyMask	    /* ConfigureNotify		*/
1195444c061aSmrg		| SubstructureNotifyMask,
1196444c061aSmrg	SubstructureRedirectMask,   /* ConfigureRequest		*/
1197444c061aSmrg	StructureNotifyMask	    /* GravityNotify		*/
1198444c061aSmrg		| SubstructureNotifyMask,
1199444c061aSmrg	ResizeRedirectMask,	    /* ResizeRequest		*/
1200444c061aSmrg	StructureNotifyMask	    /* CirculateNotify		*/
1201444c061aSmrg		| SubstructureNotifyMask,
1202444c061aSmrg	SubstructureRedirectMask,   /* CirculateRequest		*/
1203444c061aSmrg	PropertyChangeMask,	    /* PropertyNotify		*/
1204444c061aSmrg	NonMaskableMask,	    /* SelectionClear		*/
1205444c061aSmrg	NonMaskableMask,	    /* SelectionRequest		*/
1206444c061aSmrg	NonMaskableMask,	    /* SelectionNotify		*/
1207444c061aSmrg	ColormapChangeMask,	    /* ColormapNotify		*/
1208444c061aSmrg	NonMaskableMask,	    /* ClientMessage		*/
1209444c061aSmrg	NonMaskableMask		    /* MappingNotify		*/
1210444c061aSmrg};
1211444c061aSmrg
1212444c061aSmrgEventMask _XtConvertTypeToMask (
1213444c061aSmrg    int		eventType)
1214444c061aSmrg{
1215444c061aSmrg    if ((Cardinal) eventType < XtNumber(masks))
1216444c061aSmrg	return masks[eventType];
1217444c061aSmrg    else
1218444c061aSmrg	return NoEventMask;
1219444c061aSmrg}
1220444c061aSmrg
1221444c061aSmrgBoolean _XtOnGrabList(
1222444c061aSmrg    register Widget widget,
1223444c061aSmrg    XtGrabRec  *grabList)
1224444c061aSmrg{
1225444c061aSmrg    register XtGrabRec* gl;
1226444c061aSmrg    for (; widget != NULL; widget = (Widget)widget->core.parent) {
1227444c061aSmrg	for (gl = grabList; gl != NULL; gl = gl->next) {
1228444c061aSmrg	    if (gl->widget == widget) return TRUE;
1229444c061aSmrg	    if (gl->exclusive) break;
1230444c061aSmrg	}
1231444c061aSmrg    }
1232444c061aSmrg    return FALSE;
1233444c061aSmrg}
1234444c061aSmrg
1235444c061aSmrgstatic Widget LookupSpringLoaded(
1236444c061aSmrg    XtGrabList	grabList)
1237444c061aSmrg{
1238444c061aSmrg    XtGrabList	gl;
1239444c061aSmrg
1240444c061aSmrg    for (gl = grabList; gl != NULL; gl = gl->next) {
1241444c061aSmrg	if (gl->spring_loaded) {
1242444c061aSmrg	  if (XtIsSensitive(gl->widget))
1243444c061aSmrg	    return gl->widget;
1244444c061aSmrg	  else
1245444c061aSmrg	    return NULL;
1246444c061aSmrg	}
1247444c061aSmrg	if (gl->exclusive) break;
1248444c061aSmrg    }
1249444c061aSmrg    return NULL;
1250444c061aSmrg}
1251444c061aSmrg
1252444c061aSmrgstatic Boolean DispatchEvent(
1253444c061aSmrg    XEvent* event,
1254444c061aSmrg    Widget widget)
1255444c061aSmrg{
1256444c061aSmrg
1257444c061aSmrg    if (event->type == EnterNotify &&
1258444c061aSmrg	event->xcrossing.mode == NotifyNormal &&
1259444c061aSmrg	widget->core.widget_class->core_class.compress_enterleave) {
1260444c061aSmrg	if (XPending(event->xcrossing.display)) {
1261444c061aSmrg	    XEvent nextEvent;
1262444c061aSmrg	    XPeekEvent(event->xcrossing.display, &nextEvent);
1263444c061aSmrg	    if (nextEvent.type == LeaveNotify &&
1264444c061aSmrg		event->xcrossing.window == nextEvent.xcrossing.window &&
1265444c061aSmrg		nextEvent.xcrossing.mode == NotifyNormal &&
1266444c061aSmrg		((event->xcrossing.detail != NotifyInferior &&
1267444c061aSmrg		 nextEvent.xcrossing.detail != NotifyInferior) ||
1268444c061aSmrg		 (event->xcrossing.detail == NotifyInferior &&
1269444c061aSmrg		 nextEvent.xcrossing.detail == NotifyInferior))) {
1270444c061aSmrg		/* skip the enter/leave pair */
1271444c061aSmrg		XNextEvent(event->xcrossing.display, &nextEvent);
1272444c061aSmrg		return False;
1273444c061aSmrg	    }
1274444c061aSmrg	}
1275444c061aSmrg    }
1276444c061aSmrg
1277444c061aSmrg    if (event->type == MotionNotify &&
1278444c061aSmrg	    widget->core.widget_class->core_class.compress_motion) {
1279444c061aSmrg	while (XPending(event->xmotion.display)) {
1280444c061aSmrg	    XEvent nextEvent;
1281444c061aSmrg	    XPeekEvent(event->xmotion.display, &nextEvent);
1282444c061aSmrg	    if (nextEvent.type == MotionNotify &&
1283444c061aSmrg		    event->xmotion.window == nextEvent.xmotion.window &&
1284444c061aSmrg		    event->xmotion.subwindow == nextEvent.xmotion.subwindow) {
1285444c061aSmrg		/* replace the current event with the next one */
1286444c061aSmrg		XNextEvent(event->xmotion.display, event);
1287444c061aSmrg	    } else break;
1288444c061aSmrg	}
1289444c061aSmrg    }
1290444c061aSmrg
1291444c061aSmrg    return XtDispatchEventToWidget(widget, event);
1292444c061aSmrg}
1293444c061aSmrg
1294444c061aSmrgtypedef enum _GrabType {pass, ignore, remap} GrabType;
1295444c061aSmrg
1296444c061aSmrg#if !defined(AIXV3) || !defined(AIXSHLIB)
1297444c061aSmrgstatic /* AIX shared libraries are broken */
1298444c061aSmrg#endif
1299444c061aSmrgBoolean _XtDefaultDispatcher(
1300444c061aSmrg    XEvent  *event)
1301444c061aSmrg{
1302444c061aSmrg    register    Widget widget;
1303444c061aSmrg    GrabType    grabType;
1304444c061aSmrg    XtPerDisplayInput pdi;
1305444c061aSmrg    XtGrabList  grabList;
1306444c061aSmrg    Boolean	was_dispatched = False;
1307444c061aSmrg    DPY_TO_APPCON(event->xany.display);
1308444c061aSmrg
1309444c061aSmrg    /* the default dispatcher discards all extension events */
1310444c061aSmrg    if (event->type >= LASTEvent)
1311444c061aSmrg	return False;
1312444c061aSmrg
1313444c061aSmrg    LOCK_APP(app);
1314444c061aSmrg
1315444c061aSmrg    switch (event->type) {
1316444c061aSmrg      case KeyPress:
1317444c061aSmrg      case KeyRelease:
1318444c061aSmrg      case ButtonPress:
1319444c061aSmrg      case ButtonRelease:	grabType = remap;	break;
1320444c061aSmrg      case MotionNotify:
1321444c061aSmrg      case EnterNotify:		grabType = ignore;	break;
1322444c061aSmrg      default:			grabType = pass;	break;
1323444c061aSmrg    }
1324444c061aSmrg
1325444c061aSmrg    widget = XtWindowToWidget (event->xany.display, event->xany.window);
1326444c061aSmrg    pdi = _XtGetPerDisplayInput(event->xany.display);
1327444c061aSmrg    grabList = *_XtGetGrabList(pdi);
1328444c061aSmrg
1329444c061aSmrg    if (widget == NULL) {
1330444c061aSmrg	if (grabType == remap
1331444c061aSmrg	    && (widget = LookupSpringLoaded(grabList)) != NULL) {
1332444c061aSmrg	    /* event occurred in a non-widget window, but we've promised also
1333444c061aSmrg	       to dispatch it to the nearest accessible spring_loaded widget */
1334444c061aSmrg	    was_dispatched = (XFilterEvent(event, XtWindow(widget))
1335444c061aSmrg			      || XtDispatchEventToWidget(widget, event));
1336444c061aSmrg	}
1337444c061aSmrg	else was_dispatched = XFilterEvent(event, None);
1338444c061aSmrg    }
1339444c061aSmrg    else if (grabType == pass) {
1340444c061aSmrg	if (event->type == LeaveNotify ||
1341444c061aSmrg	    event->type == FocusIn ||
1342444c061aSmrg	    event->type == FocusOut) {
1343444c061aSmrg		if (XtIsSensitive (widget))
1344444c061aSmrg		    was_dispatched = (XFilterEvent(event, XtWindow(widget)) ||
1345444c061aSmrg				      XtDispatchEventToWidget(widget, event));
1346444c061aSmrg	    } else was_dispatched = (XFilterEvent(event, XtWindow(widget)) ||
1347444c061aSmrg				     XtDispatchEventToWidget(widget, event));
1348444c061aSmrg    }
1349444c061aSmrg    else if (grabType == ignore) {
1350444c061aSmrg	if ((grabList == NULL || _XtOnGrabList(widget, grabList))
1351444c061aSmrg	    && XtIsSensitive(widget)) {
1352444c061aSmrg	    was_dispatched = (XFilterEvent(event, XtWindow(widget))
1353444c061aSmrg			      || DispatchEvent(event, widget));
1354444c061aSmrg	}
1355444c061aSmrg    }
1356444c061aSmrg    else if (grabType == remap) {
1357444c061aSmrg	EventMask	mask = _XtConvertTypeToMask(event->type);
1358444c061aSmrg	Widget		dspWidget;
1359444c061aSmrg	Boolean		was_filtered = False;
1360444c061aSmrg
1361444c061aSmrg	dspWidget = _XtFindRemapWidget(event, widget, mask, pdi);
1362444c061aSmrg
1363444c061aSmrg	if ((grabList == NULL ||_XtOnGrabList(dspWidget, grabList))
1364444c061aSmrg	    && XtIsSensitive(dspWidget)) {
1365444c061aSmrg	    if ((was_filtered = XFilterEvent(event, XtWindow(dspWidget)))) {
1366444c061aSmrg		/* If this event activated a device grab, release it. */
1367444c061aSmrg		_XtUngrabBadGrabs(event, widget, mask, pdi);
1368444c061aSmrg		was_dispatched = True;
1369444c061aSmrg	    } else
1370444c061aSmrg		was_dispatched = XtDispatchEventToWidget(dspWidget, event);
1371444c061aSmrg	}
1372444c061aSmrg	else _XtUngrabBadGrabs(event, widget, mask, pdi);
1373444c061aSmrg
1374444c061aSmrg	if (!was_filtered) {
1375444c061aSmrg	    /* Also dispatch to nearest accessible spring_loaded. */
1376444c061aSmrg	    /* Fetch this afterward to reflect modal list changes */
1377444c061aSmrg	    grabList = *_XtGetGrabList(pdi);
1378444c061aSmrg	    widget = LookupSpringLoaded(grabList);
1379444c061aSmrg	    if (widget != NULL && widget != dspWidget) {
1380444c061aSmrg		was_dispatched = (XFilterEvent(event, XtWindow(widget))
1381444c061aSmrg				  || XtDispatchEventToWidget(widget, event)
1382444c061aSmrg				  || was_dispatched);
1383444c061aSmrg	    }
1384444c061aSmrg	}
1385444c061aSmrg    }
1386444c061aSmrg    UNLOCK_APP(app);
1387444c061aSmrg    return was_dispatched;
1388444c061aSmrg}
1389444c061aSmrg
1390444c061aSmrgBoolean XtDispatchEvent (
1391444c061aSmrg    XEvent  *event)
1392444c061aSmrg{
1393444c061aSmrg    Boolean was_dispatched, safe;
1394444c061aSmrg    int dispatch_level;
1395444c061aSmrg    int starting_count;
1396444c061aSmrg    XtPerDisplay pd;
1397444c061aSmrg    Time	time = 0;
1398444c061aSmrg    XtEventDispatchProc dispatch = _XtDefaultDispatcher;
1399444c061aSmrg    XtAppContext app = XtDisplayToApplicationContext(event->xany.display);
1400444c061aSmrg
1401444c061aSmrg    LOCK_APP(app);
1402444c061aSmrg    dispatch_level = ++app->dispatch_level;
1403444c061aSmrg    starting_count = app->destroy_count;
1404444c061aSmrg
1405444c061aSmrg    switch (event->type) {
1406444c061aSmrg      case KeyPress:
1407444c061aSmrg      case KeyRelease:	   time = event->xkey.time;		break;
1408444c061aSmrg      case ButtonPress:
1409444c061aSmrg      case ButtonRelease:  time = event->xbutton.time;		break;
1410444c061aSmrg      case MotionNotify:   time = event->xmotion.time;		break;
1411444c061aSmrg      case EnterNotify:
1412444c061aSmrg      case LeaveNotify:	   time = event->xcrossing.time;	break;
1413444c061aSmrg      case PropertyNotify: time = event->xproperty.time;	break;
1414444c061aSmrg      case SelectionClear: time = event->xselectionclear.time;	break;
1415444c061aSmrg
1416444c061aSmrg      case MappingNotify:  _XtRefreshMapping(event, True);	break;
1417444c061aSmrg    }
1418444c061aSmrg    pd = _XtGetPerDisplay(event->xany.display);
1419444c061aSmrg    if (time) pd->last_timestamp = time;
1420444c061aSmrg    pd->last_event = *event;
1421444c061aSmrg
1422444c061aSmrg    if (pd->dispatcher_list) {
1423444c061aSmrg	dispatch = pd->dispatcher_list[event->type];
1424444c061aSmrg	if (dispatch == NULL) dispatch = _XtDefaultDispatcher;
1425444c061aSmrg    }
1426444c061aSmrg    was_dispatched = (*dispatch)(event);
1427444c061aSmrg
1428444c061aSmrg    /*
1429444c061aSmrg     * To make recursive XtDispatchEvent work, we need to do phase 2 destroys
1430444c061aSmrg     * only on those widgets destroyed by this particular dispatch.
1431444c061aSmrg     *
1432444c061aSmrg     */
1433444c061aSmrg
1434444c061aSmrg    if (app->destroy_count > starting_count)
1435444c061aSmrg	_XtDoPhase2Destroy(app, dispatch_level);
1436444c061aSmrg
1437444c061aSmrg    app->dispatch_level = dispatch_level - 1;
1438444c061aSmrg
1439444c061aSmrg    if ((safe = _XtSafeToDestroy(app))) {
1440444c061aSmrg	if (app->dpy_destroy_count != 0) _XtCloseDisplays(app);
1441444c061aSmrg	if (app->free_bindings) _XtDoFreeBindings(app);
1442444c061aSmrg    }
1443444c061aSmrg    UNLOCK_APP(app);
1444444c061aSmrg    LOCK_PROCESS;
1445444c061aSmrg    if (_XtAppDestroyCount != 0 && safe) _XtDestroyAppContexts();
1446444c061aSmrg    UNLOCK_PROCESS;
1447444c061aSmrg    return was_dispatched;
1448444c061aSmrg}
1449444c061aSmrg
1450444c061aSmrg/* ARGSUSED */
1451444c061aSmrgstatic void GrabDestroyCallback(
1452444c061aSmrg    Widget  widget,
1453444c061aSmrg    XtPointer closure,
1454444c061aSmrg    XtPointer call_data)
1455444c061aSmrg{
1456444c061aSmrg    /* Remove widget from grab list if it destroyed */
1457444c061aSmrg    XtRemoveGrab(widget);
1458444c061aSmrg}
1459444c061aSmrg
1460444c061aSmrgstatic XtGrabRec *NewGrabRec(
1461444c061aSmrg    Widget  widget,
1462444c061aSmrg    Boolean exclusive,
1463444c061aSmrg    Boolean spring_loaded)
1464444c061aSmrg{
1465444c061aSmrg    register XtGrabList    gl;
1466444c061aSmrg
1467444c061aSmrg    gl		      = XtNew(XtGrabRec);
1468444c061aSmrg    gl->next	      = NULL;
1469444c061aSmrg    gl->widget        = widget;
1470444c061aSmrg    gl->exclusive     = exclusive;
1471444c061aSmrg    gl->spring_loaded = spring_loaded;
1472444c061aSmrg
1473444c061aSmrg    return gl;
1474444c061aSmrg}
1475444c061aSmrg
1476444c061aSmrgvoid XtAddGrab(
1477444c061aSmrg    Widget  widget,
1478444c061aSmrg    _XtBoolean exclusive,
1479444c061aSmrg    _XtBoolean spring_loaded)
1480444c061aSmrg{
1481444c061aSmrg    register    XtGrabList gl;
1482444c061aSmrg    XtGrabList	*grabListPtr;
1483444c061aSmrg    XtAppContext app = XtWidgetToApplicationContext(widget);
1484444c061aSmrg
1485444c061aSmrg    LOCK_APP(app);
1486444c061aSmrg    LOCK_PROCESS;
1487444c061aSmrg    grabListPtr = _XtGetGrabList(_XtGetPerDisplayInput(XtDisplay(widget)));
1488444c061aSmrg
1489444c061aSmrg    if (spring_loaded && !exclusive) {
1490444c061aSmrg	XtAppWarningMsg(app,
1491444c061aSmrg		"grabError", "xtAddGrab", XtCXtToolkitError,
1492444c061aSmrg		"XtAddGrab requires exclusive grab if spring_loaded is TRUE",
1493444c061aSmrg		(String *) NULL, (Cardinal *) NULL);
1494444c061aSmrg	exclusive = TRUE;
1495444c061aSmrg    }
1496444c061aSmrg
1497444c061aSmrg    gl = NewGrabRec(widget, exclusive, spring_loaded);
1498444c061aSmrg    gl->next = *grabListPtr;
1499444c061aSmrg    *grabListPtr = gl;
1500444c061aSmrg
1501444c061aSmrg    XtAddCallback (widget, XtNdestroyCallback,
1502444c061aSmrg	    GrabDestroyCallback, (XtPointer) NULL);
1503444c061aSmrg    UNLOCK_PROCESS;
1504444c061aSmrg    UNLOCK_APP(app);
1505444c061aSmrg}
1506444c061aSmrg
1507444c061aSmrgvoid XtRemoveGrab(
1508444c061aSmrg    Widget  widget)
1509444c061aSmrg{
1510444c061aSmrg    register XtGrabList gl;
1511444c061aSmrg    register Boolean done;
1512444c061aSmrg    XtGrabList	*grabListPtr;
1513444c061aSmrg    XtAppContext app = XtWidgetToApplicationContext(widget);
1514444c061aSmrg
1515444c061aSmrg    LOCK_APP(app);
1516444c061aSmrg    LOCK_PROCESS;
1517444c061aSmrg
1518444c061aSmrg    grabListPtr = _XtGetGrabList(_XtGetPerDisplayInput(XtDisplay(widget)));
1519444c061aSmrg
1520444c061aSmrg    for (gl = *grabListPtr; gl != NULL; gl = gl->next) {
1521444c061aSmrg	if (gl->widget == widget) break;
1522444c061aSmrg    }
1523444c061aSmrg
1524444c061aSmrg    if (gl == NULL) {
1525444c061aSmrg	    XtAppWarningMsg(app,
1526444c061aSmrg		       "grabError","xtRemoveGrab",XtCXtToolkitError,
1527444c061aSmrg		       "XtRemoveGrab asked to remove a widget not on the list",
1528444c061aSmrg		       (String *)NULL, (Cardinal *)NULL);
1529444c061aSmrg	    UNLOCK_PROCESS;
1530444c061aSmrg    	    UNLOCK_APP(app);
1531444c061aSmrg	    return;
1532444c061aSmrg	}
1533444c061aSmrg
1534444c061aSmrg    do {
1535444c061aSmrg	gl = *grabListPtr;
1536444c061aSmrg	done = (gl->widget == widget);
1537444c061aSmrg	*grabListPtr = gl->next;
1538444c061aSmrg	XtRemoveCallback(gl->widget, XtNdestroyCallback,
1539444c061aSmrg		GrabDestroyCallback, (XtPointer)NULL);
1540444c061aSmrg	XtFree((char *)gl);
1541444c061aSmrg    } while (! done);
1542444c061aSmrg    UNLOCK_PROCESS;
1543444c061aSmrg    UNLOCK_APP(app);
1544444c061aSmrg    return;
1545444c061aSmrg}
1546444c061aSmrg
1547444c061aSmrgvoid XtMainLoop(void)
1548444c061aSmrg{
1549444c061aSmrg	XtAppMainLoop(_XtDefaultAppContext());
1550444c061aSmrg}
1551444c061aSmrg
1552444c061aSmrgvoid XtAppMainLoop(
1553444c061aSmrg	XtAppContext app)
1554444c061aSmrg{
1555444c061aSmrg    XEvent event;
1556444c061aSmrg
1557444c061aSmrg    LOCK_APP(app);
1558444c061aSmrg    do {
1559444c061aSmrg    	XtAppNextEvent(app, &event);
1560444c061aSmrg#ifdef XTHREADS
1561444c061aSmrg	/* assert(app == XtDisplayToApplicationContext(event.xany.display)); */
1562444c061aSmrg#endif
1563444c061aSmrg	XtDispatchEvent(&event);
1564444c061aSmrg    } while(app->exit_flag == FALSE);
1565444c061aSmrg    UNLOCK_APP(app);
1566444c061aSmrg}
1567444c061aSmrg
1568444c061aSmrgvoid _XtFreeEventTable(
1569444c061aSmrg    XtEventTable *event_table)
1570444c061aSmrg{
1571444c061aSmrg    register XtEventTable event;
1572444c061aSmrg
1573444c061aSmrg    event = *event_table;
1574444c061aSmrg    while (event != NULL) {
1575444c061aSmrg	register XtEventTable next = event->next;
1576444c061aSmrg	XtFree((char *) event);
1577444c061aSmrg	event = next;
1578444c061aSmrg    }
1579444c061aSmrg}
1580444c061aSmrg
1581444c061aSmrgTime XtLastTimestampProcessed(
1582444c061aSmrg    Display *dpy)
1583444c061aSmrg{
1584444c061aSmrg    Time time;
1585444c061aSmrg    DPY_TO_APPCON(dpy);
1586444c061aSmrg
1587444c061aSmrg    LOCK_APP(app);
1588444c061aSmrg    LOCK_PROCESS;
1589444c061aSmrg    time =  _XtGetPerDisplay(dpy)->last_timestamp;
1590444c061aSmrg    UNLOCK_PROCESS;
1591444c061aSmrg    UNLOCK_APP(app);
1592444c061aSmrg    return(time);
1593444c061aSmrg}
1594444c061aSmrg
1595444c061aSmrgXEvent* XtLastEventProcessed(
1596444c061aSmrg    Display* dpy)
1597444c061aSmrg{
1598444c061aSmrg    XEvent* le = NULL;
1599444c061aSmrg    DPY_TO_APPCON(dpy);
1600444c061aSmrg
1601444c061aSmrg    LOCK_APP(app);
1602444c061aSmrg    le = &_XtGetPerDisplay(dpy)->last_event;
1603444c061aSmrg    if (!le->xany.serial)
1604444c061aSmrg	le =  NULL;
1605444c061aSmrg    UNLOCK_APP(app);
1606444c061aSmrg    return le;
1607444c061aSmrg}
1608444c061aSmrg
1609444c061aSmrgvoid _XtSendFocusEvent(
1610444c061aSmrg    Widget child,
1611444c061aSmrg    int type)
1612444c061aSmrg{
1613444c061aSmrg    child = XtIsWidget(child) ? child : _XtWindowedAncestor(child);
1614444c061aSmrg    if (XtIsSensitive(child) && !child->core.being_destroyed
1615444c061aSmrg	&& XtIsRealized(child)
1616444c061aSmrg	&& (XtBuildEventMask(child) & FocusChangeMask))
1617444c061aSmrg    {
1618444c061aSmrg	XFocusChangeEvent event;
1619444c061aSmrg	Display* dpy = XtDisplay (child);
1620444c061aSmrg
1621444c061aSmrg	event.type = type;
1622444c061aSmrg	event.serial = LastKnownRequestProcessed(dpy);
1623444c061aSmrg	event.send_event = True;
1624444c061aSmrg	event.display = dpy;
1625444c061aSmrg	event.window = XtWindow(child);
1626444c061aSmrg	event.mode = NotifyNormal;
1627444c061aSmrg	event.detail = NotifyAncestor;
1628444c061aSmrg	if (XFilterEvent((XEvent*)&event, XtWindow(child)))
1629444c061aSmrg	    return;
1630444c061aSmrg	XtDispatchEventToWidget(child, (XEvent*)&event);
1631444c061aSmrg    }
1632444c061aSmrg}
1633444c061aSmrg
1634444c061aSmrgstatic XtEventDispatchProc* NewDispatcherList(void)
1635444c061aSmrg{
1636444c061aSmrg    XtEventDispatchProc* l =
1637444c061aSmrg	(XtEventDispatchProc*) __XtCalloc((Cardinal) 128,
1638444c061aSmrg					(Cardinal)sizeof(XtEventDispatchProc));
1639444c061aSmrg    return l;
1640444c061aSmrg}
1641444c061aSmrg
1642444c061aSmrgXtEventDispatchProc XtSetEventDispatcher(
1643444c061aSmrg    Display		*dpy,
1644444c061aSmrg    int			event_type,
1645444c061aSmrg    XtEventDispatchProc	proc)
1646444c061aSmrg{
1647444c061aSmrg    XtEventDispatchProc *list;
1648444c061aSmrg    XtEventDispatchProc old_proc;
1649444c061aSmrg    register XtPerDisplay pd;
1650444c061aSmrg    DPY_TO_APPCON(dpy);
1651444c061aSmrg
1652444c061aSmrg    LOCK_APP(app);
1653444c061aSmrg    LOCK_PROCESS;
1654444c061aSmrg    pd = _XtGetPerDisplay(dpy);
1655444c061aSmrg
1656444c061aSmrg    list = pd->dispatcher_list;
1657444c061aSmrg    if (!list) {
1658444c061aSmrg	if (proc) list = pd->dispatcher_list = NewDispatcherList();
1659444c061aSmrg	else return _XtDefaultDispatcher;
1660444c061aSmrg    }
1661444c061aSmrg    old_proc = list[event_type];
1662444c061aSmrg    list[event_type] = proc;
1663444c061aSmrg    if (old_proc == NULL) old_proc = _XtDefaultDispatcher;
1664444c061aSmrg    UNLOCK_PROCESS;
1665444c061aSmrg    UNLOCK_APP(app);
1666444c061aSmrg    return old_proc;
1667444c061aSmrg}
1668444c061aSmrg
1669444c061aSmrgvoid XtRegisterExtensionSelector(
1670444c061aSmrg    Display		*dpy,
1671444c061aSmrg    int			min_event_type,
1672444c061aSmrg    int			max_event_type,
1673444c061aSmrg    XtExtensionSelectProc	proc,
1674444c061aSmrg    XtPointer 		client_data)
1675444c061aSmrg{
1676444c061aSmrg    ExtSelectRec *e;
1677444c061aSmrg    XtPerDisplay pd;
1678444c061aSmrg    int i;
1679444c061aSmrg    DPY_TO_APPCON(dpy);
1680444c061aSmrg
1681444c061aSmrg    if (dpy == NULL) XtErrorMsg("nullDisplay",
1682444c061aSmrg		"xtRegisterExtensionSelector", XtCXtToolkitError,
1683444c061aSmrg		"XtRegisterExtensionSelector requires a non-NULL display",
1684444c061aSmrg		(String *) NULL, (Cardinal *) NULL);
1685444c061aSmrg
1686444c061aSmrg    LOCK_APP(app);
1687444c061aSmrg    LOCK_PROCESS;
1688444c061aSmrg    pd = _XtGetPerDisplay(dpy);
1689444c061aSmrg
1690444c061aSmrg    for (i = 0; i < pd->ext_select_count; i++) {
1691444c061aSmrg	e = &pd->ext_select_list[i];
1692444c061aSmrg	if (e->min == min_event_type && e->max == max_event_type) {
1693444c061aSmrg	    e->proc = proc;
1694444c061aSmrg	    e->client_data = client_data;
1695444c061aSmrg	    return;
1696444c061aSmrg	}
1697444c061aSmrg	if ((min_event_type >= e->min && min_event_type <= e->max) ||
1698444c061aSmrg	    (max_event_type >= e->min && max_event_type <= e->max)) {
1699444c061aSmrg	    XtErrorMsg("rangeError", "xtRegisterExtensionSelector",
1700444c061aSmrg		       XtCXtToolkitError,
1701444c061aSmrg	"Attempt to register multiple selectors for one extension event type",
1702444c061aSmrg		       (String *) NULL, (Cardinal *) NULL);
1703444c061aSmrg	    UNLOCK_PROCESS;
1704444c061aSmrg	    UNLOCK_APP(app);
1705444c061aSmrg	    return;
1706444c061aSmrg	}
1707444c061aSmrg    }
1708444c061aSmrg    pd->ext_select_count++;
1709444c061aSmrg    pd->ext_select_list =
1710444c061aSmrg	    (ExtSelectRec *) XtRealloc((char *) pd->ext_select_list,
1711444c061aSmrg		       pd->ext_select_count * sizeof(ExtSelectRec));
1712444c061aSmrg    for (i = pd->ext_select_count - 1; i > 0; i--) {
1713444c061aSmrg	if (pd->ext_select_list[i-1].min > min_event_type) {
1714444c061aSmrg	    pd->ext_select_list[i] = pd->ext_select_list[i-1];
1715444c061aSmrg	} else break;
1716444c061aSmrg    }
1717444c061aSmrg    pd->ext_select_list[i].min = min_event_type;
1718444c061aSmrg    pd->ext_select_list[i].max = max_event_type;
1719444c061aSmrg    pd->ext_select_list[i].proc = proc;
1720444c061aSmrg    pd->ext_select_list[i].client_data = client_data;
1721444c061aSmrg    UNLOCK_PROCESS;
1722444c061aSmrg    UNLOCK_APP(app);
1723444c061aSmrg}
1724444c061aSmrg
1725444c061aSmrgvoid _XtExtensionSelect(
1726444c061aSmrg    Widget widget)
1727444c061aSmrg{
1728444c061aSmrg    int i;
1729444c061aSmrg    XtPerDisplay pd;
1730444c061aSmrg    WIDGET_TO_APPCON(widget);
1731444c061aSmrg
1732444c061aSmrg    LOCK_APP(app);
1733444c061aSmrg    LOCK_PROCESS;
1734444c061aSmrg
1735444c061aSmrg    pd = _XtGetPerDisplay(XtDisplay(widget));
1736444c061aSmrg
1737444c061aSmrg    for (i = 0; i < pd->ext_select_count; i++) {
1738444c061aSmrg	CallExtensionSelector(widget, pd->ext_select_list+i, FALSE);
1739444c061aSmrg    }
1740444c061aSmrg    UNLOCK_PROCESS;
1741444c061aSmrg    UNLOCK_APP(app);
1742444c061aSmrg}
1743