Update FSF's address in the preamble.
[bpt/emacs.git] / lwlib / dispatch.c
1 /* Defines a function to find the Widget that XtDispatchEvent() would use.
2 Copyright (C) 1992 Lucid, Inc.
3
4 This file is part of the Lucid Widget Library.
5
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.
10
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.
15
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. */
20
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.
28 */
29
30 #include <IntrinsicI.h> /* Don't change this: see comments in Imakefile. */
31 #include <X11/Xatom.h>
32 #include "dispatch.h"
33
34 #include <X11/Xlib.h>
35 #include <X11/cursorfont.h>
36 #include <X11/Xutil.h>
37
38 #ifdef XlibSpecificationRelease
39 #if XlibSpecificationRelease >= 5
40 #define HAVE_X11R5
41 #endif
42 #endif
43
44 /* ## All of the code on this page was copied from the X11R5 lib/Xt/Event.c,
45 ## but is compatible with X11R4; the code in Event.c is different, but
46 ## functionally equivalent for our purposes.
47 */
48
49 #if __STDC__
50 #define Const const
51 #else
52 #define Const /**/
53 #endif
54
55 #define NonMaskableMask ((EventMask)0x80000000L)
56
57 #define COMP_EXPOSE (widget->core.widget_class->core_class.compress_exposure)
58 #define COMP_EXPOSE_TYPE (COMP_EXPOSE & 0x0f)
59 #define GRAPHICS_EXPOSE ((XtExposeGraphicsExpose & COMP_EXPOSE) || \
60 (XtExposeGraphicsExposeMerged & COMP_EXPOSE))
61 #define NO_EXPOSE (XtExposeNoExpose & COMP_EXPOSE)
62
63
64 /* -- lots of stuff we don't need to copy, omitted -- */
65
66
67 static EventMask Const masks[] = {
68 0, /* Error, should never see */
69 0, /* Reply, should never see */
70 KeyPressMask, /* KeyPress */
71 KeyReleaseMask, /* KeyRelease */
72 ButtonPressMask, /* ButtonPress */
73 ButtonReleaseMask, /* ButtonRelease */
74 PointerMotionMask /* MotionNotify */
75 | ButtonMotionMask,
76 EnterWindowMask, /* EnterNotify */
77 LeaveWindowMask, /* LeaveNotify */
78 FocusChangeMask, /* FocusIn */
79 FocusChangeMask, /* FocusOut */
80 KeymapStateMask, /* KeymapNotify */
81 ExposureMask, /* Expose */
82 NonMaskableMask, /* GraphicsExpose, in GC */
83 NonMaskableMask, /* NoExpose, in GC */
84 VisibilityChangeMask, /* VisibilityNotify */
85 SubstructureNotifyMask, /* CreateNotify */
86 StructureNotifyMask /* DestroyNotify */
87 | SubstructureNotifyMask,
88 StructureNotifyMask /* UnmapNotify */
89 | SubstructureNotifyMask,
90 StructureNotifyMask /* MapNotify */
91 | SubstructureNotifyMask,
92 SubstructureRedirectMask, /* MapRequest */
93 StructureNotifyMask /* ReparentNotify */
94 | SubstructureNotifyMask,
95 StructureNotifyMask /* ConfigureNotify */
96 | SubstructureNotifyMask,
97 SubstructureRedirectMask, /* ConfigureRequest */
98 StructureNotifyMask /* GravityNotify */
99 | SubstructureNotifyMask,
100 ResizeRedirectMask, /* ResizeRequest */
101 StructureNotifyMask /* CirculateNotify */
102 | SubstructureNotifyMask,
103 SubstructureRedirectMask, /* CirculateRequest */
104 PropertyChangeMask, /* PropertyNotify */
105 NonMaskableMask, /* SelectionClear */
106 NonMaskableMask, /* SelectionRequest */
107 NonMaskableMask, /* SelectionNotify */
108 ColormapChangeMask, /* ColormapNotify */
109 NonMaskableMask, /* ClientMessage */
110 NonMaskableMask /* MappingNotify */
111 };
112
113 #ifndef HAVE_X11R5
114
115 static /* in R5, this is not static, so we don't need to define it at all */
116 EventMask _XtConvertTypeToMask (eventType)
117 int eventType;
118 {
119 eventType &= 0x7f; /* Events sent with XSendEvent have high bit set. */
120 if (eventType < XtNumber(masks))
121 return masks[eventType];
122 else
123 return 0;
124 }
125
126 #endif /* not HAVE_X11R5 */
127
128 /* -- _XtOnGrabList() omitted -- */
129
130
131 static Widget LookupSpringLoaded(grabList)
132 XtGrabList grabList;
133 {
134 XtGrabList gl;
135
136 for (gl = grabList; gl != NULL; gl = gl->next) {
137 if (gl->spring_loaded)
138 if (XtIsSensitive(gl->widget))
139 return gl->widget;
140 else
141 return NULL;
142 if (gl->exclusive) break;
143 }
144 return NULL;
145 }
146
147
148 \f
149 /* This function is new. */
150
151 static Boolean WouldDispatchEvent(event, widget, mask, pd)
152 register XEvent *event;
153 Widget widget;
154 EventMask mask;
155 XtPerDisplay pd;
156 {
157 XtEventRec *p;
158 Boolean would_dispatched = False;
159
160 if ((mask == ExposureMask) ||
161 ((event->type == NoExpose) && NO_EXPOSE) ||
162 ((event->type == GraphicsExpose) && GRAPHICS_EXPOSE) )
163 if (widget->core.widget_class->core_class.expose != NULL )
164 return True;
165
166
167 if ((mask == VisibilityChangeMask) &&
168 XtClass(widget)->core_class.visible_interest)
169 return True;
170
171 for (p=widget->core.event_table; p != NULL; p = p->next)
172 if ((mask & p->mask) != 0
173 #ifndef HAVE_X11R5
174 || (mask == 0 && p->non_filter)
175 #endif
176 )
177 return True;
178
179 return False;
180 }
181
182
183 /* #### This function is mostly copied from DecideToDispatch().
184 */
185
186 typedef enum _GrabType {pass, ignore, remap} GrabType;
187
188 Widget
189 XtWidgetToDispatchTo (XEvent* event)
190 {
191 register Widget widget;
192 EventMask mask;
193 GrabType grabType;
194 Widget dspWidget;
195 Time time = 0;
196 XtPerDisplay pd;
197 XtPerDisplayInput pdi;
198 XtGrabList grabList;
199
200 widget = XtWindowToWidget (event->xany.display, event->xany.window);
201 pd = _XtGetPerDisplay(event->xany.display);
202 pdi = _XtGetPerDisplayInput(event->xany.display);
203 grabList = *_XtGetGrabList(pdi);
204
205 mask = _XtConvertTypeToMask(event->xany.type);
206 grabType = pass;
207 switch (event->xany.type & 0x7f) {
208 case KeyPress:
209 case KeyRelease: grabType = remap; break;
210 case ButtonPress:
211 case ButtonRelease: grabType = remap; break;
212 case MotionNotify: grabType = ignore;
213 #define XKnownButtons (Button1MotionMask|Button2MotionMask|Button3MotionMask|\
214 Button4MotionMask|Button5MotionMask)
215 mask |= (event->xmotion.state & XKnownButtons);
216 #undef XKnownButtons
217 break;
218 case EnterNotify: grabType = ignore; break;
219 }
220
221 if (widget == NULL) {
222 if (grabType != remap) return False;
223 /* event occurred in a non-widget window, but we've promised also
224 to dispatch it to the nearest accessible spring_loaded widget */
225 else if ((widget = LookupSpringLoaded(grabList)) != NULL)
226 return widget;
227 return False;
228 }
229
230 switch(grabType) {
231 case pass:
232 return widget;
233
234 case ignore:
235 if ((grabList == NULL || _XtOnGrabList(widget,grabList))
236 && XtIsSensitive(widget)) {
237 return widget;
238 }
239 return NULL;
240
241 case remap:
242
243 {
244 Widget was_dispatched_to= NULL;
245 extern Widget _XtFindRemapWidget();
246 extern void _XtUngrabBadGrabs();
247
248 dspWidget = _XtFindRemapWidget(event, widget, mask, pdi);
249
250 if ((grabList == NULL ||
251 _XtOnGrabList(dspWidget, grabList)) &&
252 XtIsSensitive(dspWidget)) {
253 if (WouldDispatchEvent (event, dspWidget, mask, pd))
254 was_dispatched_to = dspWidget;
255 }
256
257 /* Also dispatch to nearest accessible spring_loaded. */
258 /* Fetch this afterward to reflect modal list changes */
259 grabList = *_XtGetGrabList(pdi);
260 widget = LookupSpringLoaded(grabList);
261 if (widget != NULL && widget != dspWidget) {
262 if (!was_dispatched_to)
263 was_dispatched_to = widget;
264 }
265
266 return was_dispatched_to;
267 }
268 }
269 /* should never reach here */
270 return NULL;
271 }