*** empty log message ***
[emacs.git] / lwlib / dispatch.c
blob7e70a43105ba8644a63e3bfcfa3b5c2c9647782d
1 /* Defines a function to find the Widget that XtDispatchEvent() would use.
2 Copyright (C) 1992 Lucid, Inc.
4 This file is part of the Lucid Widget Library.
6 The Lucid Widget Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
9 any later version.
11 The Lucid Widget Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /*
22 * The function XtWidgetToDispatchTo(), given an XEvent, returns the
23 * widget that XtDispatchEvent() would send that event to if called now.
24 * This file copies much code from the X11r4 Xt source, and is thus a
25 * portability problem. It also requires data structures defined in
26 * IntrinsicI.h, which is a non-exported Xt header file, so you can't
27 * compile this file unless you have the Xt sources online.
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
34 #include <IntrinsicI.h> /* Don't change this: see comments in Imakefile. */
35 #include <X11/Xatom.h>
36 #include "dispatch.h"
38 #include <X11/Xlib.h>
39 #include <X11/cursorfont.h>
40 #include <X11/Xutil.h>
42 #ifdef XlibSpecificationRelease
43 #if XlibSpecificationRelease >= 5
44 #define HAVE_X11R5
45 #endif
46 #endif
48 /* ## All of the code on this page was copied from the X11R5 lib/Xt/Event.c,
49 ## but is compatible with X11R4; the code in Event.c is different, but
50 ## functionally equivalent for our purposes.
53 #if __STDC__
54 #define Const const
55 #else
56 #define Const /**/
57 #endif
59 #define NonMaskableMask ((EventMask)0x80000000L)
61 #define COMP_EXPOSE (widget->core.widget_class->core_class.compress_exposure)
62 #define COMP_EXPOSE_TYPE (COMP_EXPOSE & 0x0f)
63 #define GRAPHICS_EXPOSE ((XtExposeGraphicsExpose & COMP_EXPOSE) || \
64 (XtExposeGraphicsExposeMerged & COMP_EXPOSE))
65 #define NO_EXPOSE (XtExposeNoExpose & COMP_EXPOSE)
68 /* -- lots of stuff we don't need to copy, omitted -- */
71 static EventMask Const masks[] = {
72 0, /* Error, should never see */
73 0, /* Reply, should never see */
74 KeyPressMask, /* KeyPress */
75 KeyReleaseMask, /* KeyRelease */
76 ButtonPressMask, /* ButtonPress */
77 ButtonReleaseMask, /* ButtonRelease */
78 PointerMotionMask /* MotionNotify */
79 | ButtonMotionMask,
80 EnterWindowMask, /* EnterNotify */
81 LeaveWindowMask, /* LeaveNotify */
82 FocusChangeMask, /* FocusIn */
83 FocusChangeMask, /* FocusOut */
84 KeymapStateMask, /* KeymapNotify */
85 ExposureMask, /* Expose */
86 NonMaskableMask, /* GraphicsExpose, in GC */
87 NonMaskableMask, /* NoExpose, in GC */
88 VisibilityChangeMask, /* VisibilityNotify */
89 SubstructureNotifyMask, /* CreateNotify */
90 StructureNotifyMask /* DestroyNotify */
91 | SubstructureNotifyMask,
92 StructureNotifyMask /* UnmapNotify */
93 | SubstructureNotifyMask,
94 StructureNotifyMask /* MapNotify */
95 | SubstructureNotifyMask,
96 SubstructureRedirectMask, /* MapRequest */
97 StructureNotifyMask /* ReparentNotify */
98 | SubstructureNotifyMask,
99 StructureNotifyMask /* ConfigureNotify */
100 | SubstructureNotifyMask,
101 SubstructureRedirectMask, /* ConfigureRequest */
102 StructureNotifyMask /* GravityNotify */
103 | SubstructureNotifyMask,
104 ResizeRedirectMask, /* ResizeRequest */
105 StructureNotifyMask /* CirculateNotify */
106 | SubstructureNotifyMask,
107 SubstructureRedirectMask, /* CirculateRequest */
108 PropertyChangeMask, /* PropertyNotify */
109 NonMaskableMask, /* SelectionClear */
110 NonMaskableMask, /* SelectionRequest */
111 NonMaskableMask, /* SelectionNotify */
112 ColormapChangeMask, /* ColormapNotify */
113 NonMaskableMask, /* ClientMessage */
114 NonMaskableMask /* MappingNotify */
117 #ifndef HAVE_X11R5
119 static /* in R5, this is not static, so we don't need to define it at all */
120 EventMask _XtConvertTypeToMask (eventType)
121 int eventType;
123 eventType &= 0x7f; /* Events sent with XSendEvent have high bit set. */
124 if (eventType < XtNumber(masks))
125 return masks[eventType];
126 else
127 return 0;
130 #endif /* not HAVE_X11R5 */
132 /* -- _XtOnGrabList() omitted -- */
135 static Widget LookupSpringLoaded(grabList)
136 XtGrabList grabList;
138 XtGrabList gl;
140 for (gl = grabList; gl != NULL; gl = gl->next) {
141 if (gl->spring_loaded)
142 if (XtIsSensitive(gl->widget))
143 return gl->widget;
144 else
145 return NULL;
146 if (gl->exclusive) break;
148 return NULL;
153 /* This function is new. */
155 static Boolean WouldDispatchEvent(event, widget, mask, pd)
156 register XEvent *event;
157 Widget widget;
158 EventMask mask;
159 XtPerDisplay pd;
161 XtEventRec *p;
162 Boolean would_dispatched = False;
164 if ((mask == ExposureMask) ||
165 ((event->type == NoExpose) && NO_EXPOSE) ||
166 ((event->type == GraphicsExpose) && GRAPHICS_EXPOSE) )
167 if (widget->core.widget_class->core_class.expose != NULL )
168 return True;
171 if ((mask == VisibilityChangeMask) &&
172 XtClass(widget)->core_class.visible_interest)
173 return True;
175 for (p=widget->core.event_table; p != NULL; p = p->next)
176 if ((mask & p->mask) != 0
177 #ifndef HAVE_X11R5
178 || (mask == 0 && p->non_filter)
179 #endif
181 return True;
183 return False;
187 /* #### This function is mostly copied from DecideToDispatch().
190 typedef enum _GrabType {pass, ignore, remap} GrabType;
192 Widget
193 XtWidgetToDispatchTo (XEvent* event)
195 register Widget widget;
196 EventMask mask;
197 GrabType grabType;
198 Widget dspWidget;
199 Time time = 0;
200 XtPerDisplay pd;
201 XtPerDisplayInput pdi;
202 XtGrabList grabList;
204 widget = XtWindowToWidget (event->xany.display, event->xany.window);
205 pd = _XtGetPerDisplay(event->xany.display);
206 pdi = _XtGetPerDisplayInput(event->xany.display);
207 grabList = *_XtGetGrabList(pdi);
209 mask = _XtConvertTypeToMask(event->xany.type);
210 grabType = pass;
211 switch (event->xany.type & 0x7f) {
212 case KeyPress:
213 case KeyRelease: grabType = remap; break;
214 case ButtonPress:
215 case ButtonRelease: grabType = remap; break;
216 case MotionNotify: grabType = ignore;
217 #define XKnownButtons (Button1MotionMask|Button2MotionMask|Button3MotionMask|\
218 Button4MotionMask|Button5MotionMask)
219 mask |= (event->xmotion.state & XKnownButtons);
220 #undef XKnownButtons
221 break;
222 case EnterNotify: grabType = ignore; break;
225 if (widget == NULL) {
226 if (grabType != remap) return False;
227 /* event occurred in a non-widget window, but we've promised also
228 to dispatch it to the nearest accessible spring_loaded widget */
229 else if ((widget = LookupSpringLoaded(grabList)) != NULL)
230 return widget;
231 return False;
234 switch(grabType) {
235 case pass:
236 return widget;
238 case ignore:
239 if ((grabList == NULL || _XtOnGrabList(widget,grabList))
240 && XtIsSensitive(widget)) {
241 return widget;
243 return NULL;
245 case remap:
248 Widget was_dispatched_to= NULL;
249 extern Widget _XtFindRemapWidget();
250 extern void _XtUngrabBadGrabs();
252 dspWidget = _XtFindRemapWidget(event, widget, mask, pdi);
254 if ((grabList == NULL ||
255 _XtOnGrabList(dspWidget, grabList)) &&
256 XtIsSensitive(dspWidget)) {
257 if (WouldDispatchEvent (event, dspWidget, mask, pd))
258 was_dispatched_to = dspWidget;
261 /* Also dispatch to nearest accessible spring_loaded. */
262 /* Fetch this afterward to reflect modal list changes */
263 grabList = *_XtGetGrabList(pdi);
264 widget = LookupSpringLoaded(grabList);
265 if (widget != NULL && widget != dspWidget) {
266 if (!was_dispatched_to)
267 was_dispatched_to = widget;
270 return was_dispatched_to;
273 /* should never reach here */
274 return NULL;