Commit | Line | Data |
---|---|---|
07bf635f RS |
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 | |
3b7ad313 EN |
18 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
19 | Boston, MA 02111-1307, USA. */ | |
07bf635f RS |
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 | ||
0f0912e6 PE |
30 | #ifdef HAVE_CONFIG_H |
31 | #include <config.h> | |
32 | #endif | |
33 | ||
07bf635f RS |
34 | #include <IntrinsicI.h> /* Don't change this: see comments in Imakefile. */ |
35 | #include <X11/Xatom.h> | |
36 | #include "dispatch.h" | |
37 | ||
15c909ba RS |
38 | #include <X11/Xlib.h> |
39 | #include <X11/cursorfont.h> | |
40 | #include <X11/Xutil.h> | |
07bf635f | 41 | |
15c909ba RS |
42 | #ifdef XlibSpecificationRelease |
43 | #if XlibSpecificationRelease >= 5 | |
44 | #define HAVE_X11R5 | |
07bf635f | 45 | #endif |
07bf635f RS |
46 | #endif |
47 | ||
07bf635f RS |
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. | |
51 | */ | |
52 | ||
53 | #if __STDC__ | |
54 | #define Const const | |
55 | #else | |
56 | #define Const /**/ | |
57 | #endif | |
58 | ||
59 | #define NonMaskableMask ((EventMask)0x80000000L) | |
60 | ||
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) | |
66 | ||
67 | ||
68 | /* -- lots of stuff we don't need to copy, omitted -- */ | |
69 | ||
70 | ||
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 */ | |
115 | }; | |
116 | ||
15c909ba | 117 | #ifndef HAVE_X11R5 |
07bf635f RS |
118 | |
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; | |
122 | { | |
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; | |
128 | } | |
129 | ||
15c909ba | 130 | #endif /* not HAVE_X11R5 */ |
07bf635f RS |
131 | |
132 | /* -- _XtOnGrabList() omitted -- */ | |
133 | ||
134 | ||
135 | static Widget LookupSpringLoaded(grabList) | |
136 | XtGrabList grabList; | |
137 | { | |
138 | XtGrabList gl; | |
139 | ||
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; | |
147 | } | |
148 | return NULL; | |
149 | } | |
150 | ||
151 | ||
152 | \f | |
153 | /* This function is new. */ | |
154 | ||
155 | static Boolean WouldDispatchEvent(event, widget, mask, pd) | |
156 | register XEvent *event; | |
157 | Widget widget; | |
158 | EventMask mask; | |
159 | XtPerDisplay pd; | |
160 | { | |
161 | XtEventRec *p; | |
162 | Boolean would_dispatched = False; | |
163 | ||
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; | |
169 | ||
170 | ||
171 | if ((mask == VisibilityChangeMask) && | |
172 | XtClass(widget)->core_class.visible_interest) | |
173 | return True; | |
174 | ||
175 | for (p=widget->core.event_table; p != NULL; p = p->next) | |
176 | if ((mask & p->mask) != 0 | |
15c909ba | 177 | #ifndef HAVE_X11R5 |
07bf635f RS |
178 | || (mask == 0 && p->non_filter) |
179 | #endif | |
180 | ) | |
181 | return True; | |
182 | ||
183 | return False; | |
184 | } | |
185 | ||
186 | ||
187 | /* #### This function is mostly copied from DecideToDispatch(). | |
188 | */ | |
189 | ||
190 | typedef enum _GrabType {pass, ignore, remap} GrabType; | |
191 | ||
192 | Widget | |
193 | XtWidgetToDispatchTo (XEvent* event) | |
194 | { | |
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; | |
203 | ||
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); | |
208 | ||
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; | |
223 | } | |
224 | ||
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; | |
232 | } | |
233 | ||
234 | switch(grabType) { | |
235 | case pass: | |
236 | return widget; | |
237 | ||
238 | case ignore: | |
239 | if ((grabList == NULL || _XtOnGrabList(widget,grabList)) | |
240 | && XtIsSensitive(widget)) { | |
241 | return widget; | |
242 | } | |
243 | return NULL; | |
244 | ||
245 | case remap: | |
246 | ||
247 | { | |
248 | Widget was_dispatched_to= NULL; | |
249 | extern Widget _XtFindRemapWidget(); | |
250 | extern void _XtUngrabBadGrabs(); | |
251 | ||
252 | dspWidget = _XtFindRemapWidget(event, widget, mask, pdi); | |
253 | ||
254 | if ((grabList == NULL || | |
255 | _XtOnGrabList(dspWidget, grabList)) && | |
256 | XtIsSensitive(dspWidget)) { | |
257 | if (WouldDispatchEvent (event, dspWidget, mask, pd)) | |
258 | was_dispatched_to = dspWidget; | |
259 | } | |
260 | ||
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; | |
268 | } | |
269 | ||
270 | return was_dispatched_to; | |
271 | } | |
272 | } | |
273 | /* should never reach here */ | |
274 | return NULL; | |
275 | } |