1 /*
2 * This file is part of the XForms library package.
3 *
4 * XForms is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as
6 * published by the Free Software Foundation; either version 2.1, or
7 * (at your option) any later version.
8 *
9 * XForms is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with XForms. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18
19 /**
20 * \file appwin.c
21 *.
22 * This file is part of the XForms library package.
23 * Copyright (c) 1996-2002 T.C. Zhao
24 * All rights reserved.
25 *
26 * Manage application windows
27 */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include "include/forms.h"
34 #include "flinternal.h"
35
36
37 /*****************************************************************
38 * Application window management. Data structure is grossly wrong
39 * ****TODO******
40 **************************************************************{**/
41
42 /* some constant handlers */
43
44 static int
handle_mapping_notify(XEvent * xev,void * user_data FL_UNUSED_ARG)45 handle_mapping_notify( XEvent * xev,
46 void * user_data FL_UNUSED_ARG )
47 {
48 XRefreshKeyboardMapping( ( XMappingEvent * ) xev );
49 return 0;
50 }
51
52
53 /***************************************
54 ***************************************/
55
56 static void
remove_app_win(FLI_WIN * appwin)57 remove_app_win( FLI_WIN * appwin )
58 {
59 #if FL_DEBUG >= ML_DEBUG
60 M_info( "remove_app_win", "deleting window %ld", appwin->win );
61 #endif
62
63 if ( fli_app_win == appwin )
64 fli_app_win = appwin->next;
65 else
66 {
67 FLI_WIN *fwin = fli_app_win;
68
69 while ( fwin && fwin->next != appwin )
70 fwin = fwin->next;
71
72 if ( fwin )
73 fwin->next = fwin->next->next;
74 else
75 {
76 M_err( "remove_app_win", "Invalid argument" );
77 return;
78 }
79 }
80
81 fl_free( appwin );
82 }
83
84
85 /***************************************
86 * Given a window find the correct structure or create one
87 ***************************************/
88
89 static FLI_WIN *
get_fl_win_struct(Window win)90 get_fl_win_struct( Window win )
91 {
92 FLI_WIN *fwin = fli_app_win,
93 *lwin = fli_app_win;
94 size_t i;
95
96 for ( ; fwin && fwin->win != win; lwin = fwin, fwin = fwin->next )
97 /* empty */ ;
98
99 /* If we found it we're done */
100
101 if ( fwin )
102 return fwin;
103
104 /* Otherwise create a new structure and append it to the end */
105
106 #if FL_DEBUG >= ML_DEBUG
107 M_info( "get_fl_win_struct", "Creating FLI_WIN struct for %ld", win );
108 #endif
109
110 if ( ( fwin = fl_malloc( sizeof *fwin ) ) == NULL )
111 return NULL;
112
113 fwin->next = NULL;
114 fwin->win = win;
115 fwin->pre_emptive = NULL;
116 fwin->pre_emptive_data = NULL;
117 for ( i = 0; i < LASTEvent; i++ )
118 {
119 fwin->callback[ i ] = NULL;
120 fwin->user_data[ i ] = NULL;
121 }
122
123 /* Default handlers */
124
125 fwin->callback[ MappingNotify ] = handle_mapping_notify;
126
127 fwin->default_callback = NULL;
128 fwin->mask = 0;
129
130 if ( ! fli_app_win )
131 fli_app_win = fwin;
132 else
133 lwin->next = fwin;
134
135 return fwin;
136 }
137
138
139 /***************************************
140 ***************************************/
141
142 FL_APPEVENT_CB
fli_set_preemptive_callback(Window win,FL_APPEVENT_CB pcb,void * data)143 fli_set_preemptive_callback( Window win,
144 FL_APPEVENT_CB pcb,
145 void * data )
146 {
147 FLI_WIN *fwin;
148 FL_APPEVENT_CB old = NULL;
149
150 if ( ! ( fwin = get_fl_win_struct( win ) ) )
151 {
152 M_err( "fli_set_preemptive_callback", "Memory allocation failure" );
153 return NULL;
154 }
155
156 old = fwin->pre_emptive;
157
158 fwin->pre_emptive = pcb;
159 fwin->pre_emptive_data = data;
160
161 return old;
162 }
163
164
165 /***************************************
166 * Add an event handler for a window
167 ***************************************/
168
169 FL_APPEVENT_CB
fl_add_event_callback(Window win,int ev,FL_APPEVENT_CB wincb,void * user_data)170 fl_add_event_callback( Window win,
171 int ev,
172 FL_APPEVENT_CB wincb,
173 void * user_data )
174 {
175 FLI_WIN *fwin;
176 int i,
177 nev;
178 FL_APPEVENT_CB old = NULL;
179
180 if ( ev < 0 || ev >= LASTEvent )
181 return NULL;
182
183 if ( ! ( fwin = get_fl_win_struct( win ) ) )
184 {
185 M_err( "fl_add_event_callback", "Memory allocation failure" );
186 return NULL;
187 }
188
189 /* ev < KeyPress means all events */
190
191 nev = ev;
192 if ( ev < KeyPress )
193 {
194 ev = KeyPress;
195 nev = LASTEvent - 1;
196 }
197
198 for ( i = ev; i <= nev; i++ )
199 {
200 old = fwin->callback[ i ];
201 fwin->callback[ i ] = wincb;
202 fwin->user_data[ i ] = user_data;
203 }
204
205 return old;
206 }
207
208
209 /***************************************
210 * Removes one or all event callbacks for a window. Might be
211 * called for a window for which no event callbacks have been
212 * set, so handle also that case gracefully.
213 ***************************************/
214
215 void
fl_remove_event_callback(Window win,int ev)216 fl_remove_event_callback( Window win,
217 int ev )
218 {
219 FLI_WIN *fwin = fli_app_win;
220
221 if ( ev < 0 || ev >= LASTEvent )
222 return;
223
224 while ( fwin && fwin->win != win )
225 fwin = fwin->next;
226
227 if ( ! fwin )
228 return;
229
230 if ( ev >= KeyPress )
231 {
232 fwin->callback[ ev ] = NULL;
233 fwin->user_data[ ev ] = NULL;
234 }
235 else /* ev < KeyPress means all events */
236 remove_app_win( fwin );
237 }
238
239
240 typedef struct
241 {
242 int event;
243 unsigned long mask;
244 } EMS;
245
246 static EMS ems[ ] =
247 {
248 { CirculateNotify, StructureNotifyMask },
249 { ConfigureNotify, StructureNotifyMask },
250 { DestroyNotify, StructureNotifyMask },
251 { CreateNotify, StructureNotifyMask },
252 { GravityNotify, StructureNotifyMask },
253 { MapNotify, StructureNotifyMask },
254 { ReparentNotify, StructureNotifyMask },
255 { UnmapNotify, StructureNotifyMask },
256 { CirculateRequest, SubstructureRedirectMask },
257 { ConfigureRequest, SubstructureRedirectMask },
258 { MapRequest, SubstructureRedirectMask },
259 { ResizeRequest, ResizeRedirectMask },
260 { Expose, ExposureMask },
261 { EnterNotify, EnterWindowMask },
262 { LeaveNotify, LeaveWindowMask },
263 { KeyPress, KeyPressMask },
264 { KeyRelease, KeyReleaseMask} ,
265 { ButtonPress, ButtonPressMask
266 /* | OwnerGrabButtonMask */ },
267 { ButtonRelease, ButtonReleaseMask
268 /* | OwnerGrabButtonMask */ },
269 { MotionNotify, PointerMotionMask
270 | ButtonMotionMask
271 | PointerMotionHintMask },
272 { FocusIn, FocusChangeMask },
273 { FocusOut, FocusChangeMask },
274 { KeymapNotify, KeymapStateMask },
275 { PropertyNotify, PropertyChangeMask },
276 { VisibilityNotify, VisibilityChangeMask },
277 { ColormapNotify, ColormapChangeMask },
278 /* non-maskable events */
279 { MappingNotify, 0 },
280 { SelectionNotify, 0 },
281 { SelectionRequest, 0 },
282 { SelectionClear, 0 },
283 { ClientMessage, 0 },
284 { GraphicsExpose, 0 },
285 { NoExpose, 0 }
286 };
287
288
289 /***************************************
290 ***************************************/
291
292 unsigned long
fli_xevent_to_mask(int event)293 fli_xevent_to_mask( int event )
294 {
295 EMS *em = ems,
296 *eme = ems + sizeof ems / sizeof *ems;
297
298 for ( ; em < eme; em++ )
299 if ( em->event == event )
300 return em->mask;
301
302 return 0;
303 }
304
305
306 /***************************************
307 ***************************************/
308
309 void
fl_activate_event_callbacks(Window win)310 fl_activate_event_callbacks( Window win )
311 {
312 FLI_WIN *fwin = fli_app_win;
313 int i;
314 unsigned long mask;
315
316 while ( fwin && fwin->win != win )
317 fwin = fwin->next;
318
319 if ( ! fwin )
320 {
321 M_err( "fl_activate_event_callbacks", "Unknown window %ld", win );
322 return;
323 }
324
325 /* Solicit all registered events */
326
327 for ( mask = i = 0; i < LASTEvent; i++ )
328 if ( fwin->callback[ i ] )
329 mask |= fli_xevent_to_mask( i );
330
331 XSelectInput( flx->display, win, mask );
332 }
333
334
335 /***************************************
336 ***************************************/
337
338 void
fl_winclose(Window win)339 fl_winclose( Window win )
340 {
341 XEvent xev;
342
343 XUnmapWindow( flx->display, win );
344 XDestroyWindow( flx->display, win );
345
346 XSync( flx->display, 0 );
347
348 while ( XCheckWindowEvent( flx->display, win, AllEventsMask, &xev ) )
349 fli_xevent_name( "Eaten", &xev );
350
351 fl_remove_event_callback( win, 0 );
352 }
353
354
355 /*
356 * Local variables:
357 * tab-width: 4
358 * indent-tabs-mode: nil
359 * End:
360 */
361