Line data Source code
1 : /* Copyright (C) 2000-2012 by George Williams */
2 : /*
3 : * Redistribution and use in source and binary forms, with or without
4 : * modification, are permitted provided that the following conditions are met:
5 :
6 : * Redistributions of source code must retain the above copyright notice, this
7 : * list of conditions and the following disclaimer.
8 :
9 : * Redistributions in binary form must reproduce the above copyright notice,
10 : * this list of conditions and the following disclaimer in the documentation
11 : * and/or other materials provided with the distribution.
12 :
13 : * The name of the author may not be used to endorse or promote products
14 : * derived from this software without specific prior written permission.
15 :
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 : * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 : * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 : #include "gwidgetP.h"
28 : #include "ggadgetP.h"
29 : #include "../gdraw/gdrawP.h"
30 : #include <ggadget.h>
31 : #include <gkeysym.h>
32 : #include <utype.h>
33 : #include <gresource.h>
34 : #include <string.h>
35 :
36 : static GWindow current_focus_window, previous_focus_window, last_input_window;
37 : /* in focus follows pointer mode, the current focus doesn't really count */
38 : /* until the window gets input (otherwise moving the mouse across a wind */
39 : /* would set the previous_focus_window to something inappropriate) */
40 : /* So... we set current focus window when a window gains the focus, and */
41 : /* at the same time we set the previous focus window to the last window */
42 : /* that got input. NOT to the old current_focus_window (which might be junk) */
43 : static GWindow last_paletted_focus_window = NULL;
44 :
45 : static int broken_palettes = true;
46 : static int widgets_initted = false;
47 :
48 0 : static void gwidget_init(void) {
49 0 : broken_palettes = GResourceFindBool("GWidget.BrokenPalettes",broken_palettes);
50 0 : widgets_initted = true;
51 0 : }
52 :
53 0 : GWindow GWindowGetCurrentFocusTopWindow(void) {
54 0 : return( current_focus_window );
55 : }
56 :
57 0 : GWindow GWidgetGetPreviousFocusTopWindow(void) {
58 0 : return( previous_focus_window );
59 : }
60 :
61 0 : GGadget *GWindowGetCurrentFocusGadget(void) {
62 : GTopLevelD *td;
63 0 : if ( current_focus_window==NULL )
64 0 : return( NULL );
65 0 : td = (GTopLevelD *) (current_focus_window->widget_data);
66 0 : return( td->gfocus );
67 : }
68 :
69 0 : void GWindowClearFocusGadgetOfWindow(GWindow gw) {
70 : GTopLevelD *td;
71 0 : if ( gw==NULL )
72 0 : return;
73 0 : while ( gw->parent!=NULL && !gw->is_toplevel ) gw=gw->parent;
74 0 : td = (GTopLevelD *) (gw->widget_data);
75 0 : if ( gw == current_focus_window && td->gfocus!=NULL &&
76 0 : td->gfocus->funcs->handle_focus!=NULL ) {
77 : GEvent e;
78 0 : e.type = et_focus;
79 0 : e.w = gw;
80 0 : e.u.focus.gained_focus = false;
81 0 : e.u.focus.mnemonic_focus = mf_normal;
82 0 : (td->gfocus->funcs->handle_focus)(td->gfocus,&e);
83 : }
84 0 : td->gfocus = NULL;
85 : }
86 :
87 0 : GGadget *GWindowGetFocusGadgetOfWindow(GWindow gw) {
88 : GTopLevelD *td;
89 0 : if ( gw==NULL )
90 0 : return( NULL );
91 0 : while ( gw->parent!=NULL && !gw->is_toplevel ) gw=gw->parent;
92 0 : td = (GTopLevelD *) (gw->widget_data);
93 0 : return( td->gfocus );
94 : }
95 :
96 0 : int GGadgetActiveGadgetEditCmd(GWindow gw,enum editor_commands cmd) {
97 0 : GGadget *g = GWindowGetFocusGadgetOfWindow(gw);
98 :
99 0 : if ( g==NULL )
100 0 : return( false );
101 0 : return( GGadgetEditCmd(g,cmd));
102 : }
103 :
104 0 : GWindow GWidgetGetCurrentFocusWindow(void) {
105 : GTopLevelD *td;
106 0 : if ( current_focus_window==NULL )
107 0 : return( NULL );
108 0 : td = (GTopLevelD *) (current_focus_window->widget_data);
109 0 : if ( td->gfocus!=NULL )
110 0 : return( td->gfocus->base );
111 0 : return( td->wfocus );
112 : }
113 :
114 : struct gfuncs *last_indicatedfocus_funcs; /* !!!! Debug code */
115 : GGadget *last_indicatedfocus_gadget;
116 : struct gwindow *last_indicatedfocus_widget;
117 :
118 0 : static void _GWidget_IndicateFocusGadget(GGadget *g, enum mnemonic_focus mf) {
119 : GWindow top;
120 : GTopLevelD *td;
121 : GEvent e;
122 :
123 0 : last_indicatedfocus_funcs = g->funcs;
124 0 : last_indicatedfocus_gadget = g;
125 0 : last_indicatedfocus_widget = g->base;
126 :
127 0 : if ( g->funcs==NULL ) {
128 0 : fprintf( stderr, "Bad focus attempt\n" );
129 0 : return;
130 : }
131 :
132 : // We recurse and find the top-level gadget.
133 0 : for ( top=g->base; top->parent!=NULL && !top->is_toplevel ; top=top->parent );
134 0 : td = (GTopLevelD *) (top->widget_data);
135 :
136 : // We check whether the gadget in question has focus.
137 0 : if ( td->gfocus!=g ) {
138 : // If not, we try to deal with the lack of focus.
139 : /* Hmm. KDE doesn't give us a focus out event when we make a window invisible */
140 : /* So to be on the save side lets send local focus out events even when not */
141 : /* strictly needed */
142 0 : if ( /*top == current_focus_window &&*/ td->gfocus!=NULL &&
143 0 : td->gfocus->funcs->handle_focus!=NULL ) {
144 : // We use the focus handler provided by the presently focussed gadget and process a loss-of-focus event for the currently focused object.
145 0 : memset(&e, 0, sizeof(GEvent));
146 0 : e.type = et_focus;
147 0 : e.w = top;
148 0 : e.u.focus.gained_focus = false;
149 0 : e.u.focus.mnemonic_focus = mf_normal;
150 0 : (td->gfocus->funcs->handle_focus)(td->gfocus,&e);
151 : }
152 : }
153 : // We give focus to the desired gadget.
154 0 : td->gfocus = g; td->wfocus = NULL;
155 0 : if ( top == current_focus_window && g->funcs->handle_focus!=NULL ) {
156 : // If the desired gadget has a focus handler, we construct an event and run it.
157 0 : memset(&e, 0, sizeof(GEvent));
158 0 : e.u.focus.gained_focus = true;
159 0 : e.u.focus.mnemonic_focus = mf;
160 0 : (g->funcs->handle_focus)(g,&e);
161 : }
162 : }
163 :
164 0 : void GWidgetIndicateFocusGadget(GGadget *g) {
165 0 : _GWidget_IndicateFocusGadget(g,mf_normal);
166 0 : }
167 :
168 0 : static GGadget *_GWidget_FindPost(GContainerD *cd,GGadget *oldfocus,GGadget **last) {
169 : GGadget *g;
170 : GWidgetD *w;
171 :
172 0 : if ( cd==NULL || !cd->iscontainer )
173 0 : return( false );
174 0 : for ( g=cd->gadgets; g!=NULL; g=g->prev ) {
175 0 : if ( g==oldfocus )
176 0 : return( *last );
177 0 : if ( g->focusable && g->state!=gs_invisible && g->state!=gs_disabled )
178 0 : *last = g;
179 : }
180 0 : for ( w=cd->widgets; w!=NULL; w=w->next ) {
181 0 : if (( g = _GWidget_FindPost((GContainerD *) w,oldfocus,last))!=NULL )
182 0 : return( g );
183 : }
184 0 : return( NULL );
185 : }
186 :
187 0 : void GWidgetNextFocus(GWindow top) {
188 : GTopLevelD *topd;
189 0 : GGadget *focus, *last=NULL;
190 :
191 0 : while ( top->parent!=NULL && !top->is_toplevel ) top = top->parent;
192 0 : topd = (GTopLevelD *) (top->widget_data);
193 0 : if ( topd==NULL || topd->gfocus == NULL )
194 0 : return;
195 0 : if ( (focus = _GWidget_FindPost((GContainerD *) topd,topd->gfocus,&last))== NULL ) {
196 : /* if we didn't find a Next Gadget, it's either because: */
197 : /* 1) the focus gadget is first in the chain, in which case we want */
198 : /* the last thing in the chain */
199 : /* 2) our data structures are screwed up */
200 0 : _GWidget_FindPost((GContainerD *) topd,NULL,&last);
201 0 : focus = last;
202 : }
203 0 : _GWidget_IndicateFocusGadget(focus,mf_tab);
204 : }
205 :
206 0 : static GGadget *_GWidget_FindPrev(GContainerD *cd,GGadget *oldfocus,GGadget **first, int *found) {
207 : GGadget *g;
208 : GWidgetD *w;
209 :
210 0 : if ( cd==NULL || !cd->iscontainer )
211 0 : return( false );
212 0 : for ( g=cd->gadgets; g!=NULL; g=g->prev ) {
213 0 : if ( g->focusable && g->state!=gs_invisible && g->state!=gs_disabled ) {
214 0 : if ( *first==NULL )
215 0 : *first = g;
216 0 : if ( *found )
217 0 : return( g );
218 : }
219 0 : if ( g==oldfocus )
220 0 : *found = true;
221 : }
222 0 : for ( w=cd->widgets; w!=NULL; w=w->next ) {
223 0 : if (( g = _GWidget_FindPrev((GContainerD *) w,oldfocus,first,found))!=NULL )
224 0 : return( g );
225 : }
226 0 : return( NULL );
227 : }
228 :
229 0 : void GWidgetPrevFocus(GWindow top) {
230 : GTopLevelD *topd;
231 : GGadget *focus;
232 :
233 0 : while ( top->parent!=NULL && !top->is_toplevel ) top = top->parent;
234 0 : topd = (GTopLevelD *) (top->widget_data);
235 0 : if ( topd==NULL || topd->gfocus == NULL )
236 0 : return;
237 0 : for ( focus = topd->gfocus->prev;
238 0 : focus!=NULL && (!focus->focusable || focus->state==gs_invisible || focus->state==gs_disabled);
239 0 : focus = focus->prev );
240 0 : if ( focus==NULL ) {
241 0 : GGadget *first = NULL; int found = false;
242 0 : if ( (focus = _GWidget_FindPrev((GContainerD *) topd,topd->gfocus,&first,&found))== NULL )
243 0 : focus = first;
244 : }
245 0 : _GWidget_IndicateFocusGadget(focus,mf_tab);
246 : }
247 :
248 0 : static int _GWidget_Container_eh(GWindow gw, GEvent *event) {
249 : /* Gadgets can get mouse, char and expose events */
250 : /* Widgets might need char events redirected to them */
251 : /* If a gadget doesn't want an event it returns false from its eh */
252 : /* If a subwidget doesn't want an event it may send it up to us */
253 0 : int handled = false;
254 : GGadget *gadget;
255 0 : GContainerD *gd = (GContainerD *) (gw->widget_data);
256 : GWindow pixmap;
257 : GWindow parent;
258 : GTopLevelD *topd;
259 :
260 0 : if ( gd==NULL ) /* dying */
261 0 : return(true);
262 :
263 0 : for ( parent = gw; parent->parent!=NULL && parent->parent->widget_data!=NULL &&
264 0 : !parent->is_toplevel; parent = parent->parent );
265 0 : topd = (GTopLevelD *) (parent->widget_data);
266 0 : if ( topd==NULL )
267 0 : fprintf( stderr, "No top level window found\n" );
268 :
269 0 : GGadgetPopupExternalEvent(event);
270 0 : if ( event->type == et_expose ) {
271 : GRect old;
272 :
273 0 : pixmap = _GWidget_GetPixmap(gw,&event->u.expose.rect);
274 0 : pixmap->ggc->bg = gw->ggc->bg;
275 0 : GDrawPushClip(pixmap,&event->u.expose.rect,&old);
276 0 : pixmap->user_data = gw->user_data;
277 :
278 0 : if ( gd->e_h!=NULL ) {
279 0 : (gd->e_h)(pixmap,event);
280 : }
281 0 : for ( gadget = gd->gadgets; gadget!=NULL ; gadget=gadget->prev )
282 0 : if ( ! ( gadget->r.x>event->u.expose.rect.x+event->u.expose.rect.width ||
283 0 : gadget->r.y>event->u.expose.rect.y+event->u.expose.rect.height ||
284 0 : gadget->r.x+gadget->r.width<event->u.expose.rect.x ||
285 0 : gadget->r.y+gadget->r.height<event->u.expose.rect.y ) &&
286 0 : gadget->state!=gs_invisible )
287 0 : (gadget->funcs->handle_expose)(pixmap,gadget,event);
288 :
289 0 : GDrawPopClip(pixmap,&old);
290 0 : _GWidget_RestorePixmap(gw,pixmap,&event->u.expose.rect);
291 :
292 0 : return( true );
293 0 : } else if ( event->type >= et_mousemove && event->type <= et_crossing ) {
294 0 : if ( topd!=NULL && topd->popupowner!=NULL ) {
295 0 : handled = (topd->popupowner->funcs->handle_mouse)(topd->popupowner,event);
296 0 : return( handled );
297 : }
298 0 : if ( gd->grabgadget && event->type==et_mousedown &&
299 0 : (event->u.mouse.state&ksm_buttons)==0 )
300 0 : gd->grabgadget = NULL; /* Happens if a gadget invokes a popup menu. Gadget remains grabbed because menu gets the mouse up */
301 0 : if ( gd->grabgadget!=NULL ) {
302 0 : handled = (gd->grabgadget->funcs->handle_mouse)(gd->grabgadget,event);
303 0 : if ( !GDrawNativeWindowExists(NULL,event->native_window) ||
304 0 : gw->is_dying || gw->widget_data==NULL )
305 0 : return( true );
306 0 : if ( event->type==et_mouseup )
307 0 : gd->grabgadget = NULL;
308 0 : } else if ( event->type==et_mousedown ) {
309 0 : if ( !parent->is_popup )
310 0 : last_input_window = parent;
311 0 : for ( gadget = gd->gadgets; gadget!=NULL && !handled ; gadget=gadget->prev ) {
312 0 : if ( gadget->state!=gs_disabled && gadget->state!=gs_invisible &&
313 0 : gadget->takes_input &&
314 0 : GGadgetWithin(gadget,event->u.mouse.x,event->u.mouse.y)) {
315 0 : handled = (gadget->funcs->handle_mouse)(gadget,event);
316 0 : if ( !GDrawNativeWindowExists(NULL,event->native_window) ||
317 0 : gw->is_dying || gw->widget_data==NULL )
318 0 : return( true );
319 0 : gd->grabgadget = gadget;
320 0 : if ( gadget->focusable && handled )
321 0 : GWidgetIndicateFocusGadget(gadget);
322 : }
323 : }
324 : } else {
325 0 : for ( gadget = gd->gadgets; gadget!=NULL && !handled ; gadget=gadget->prev ) {
326 0 : if ( !gadget->state!=gs_disabled && gadget->state!=gs_invisible &&
327 : /*gadget->takes_input &&*/ /* everybody needs mouse moves for popups, even labels */
328 0 : GGadgetWithin(gadget,event->u.mouse.x,event->u.mouse.y)) {
329 0 : if ( gd->lastwiggle!=NULL && gd->lastwiggle!=gadget )
330 0 : (gd->lastwiggle->funcs->handle_mouse)(gd->lastwiggle,event);
331 0 : handled = (gadget->funcs->handle_mouse)(gadget,event);
332 0 : if ( !GDrawNativeWindowExists(NULL,event->native_window) ||
333 0 : gw->is_dying || gw->widget_data==NULL )
334 0 : return( true );
335 0 : gd->lastwiggle = gadget;
336 : }
337 : }
338 0 : if ( !handled && gd->lastwiggle!=NULL ) {
339 0 : (gd->lastwiggle->funcs->handle_mouse)(gd->lastwiggle,event);
340 0 : if ( !GDrawNativeWindowExists(NULL,event->native_window) ||
341 : gw->is_dying )
342 0 : return( true );
343 : }
344 : }
345 0 : } else if ( event->type == et_char || event->type == et_charup ) {
346 0 : if ( topd!=NULL ) {
347 0 : handled = (topd->handle_key)(parent,gw,event);
348 : }
349 0 : } else if ( event->type == et_drag || event->type == et_dragout || event->type==et_drop ) {
350 0 : GGadget *lastdd = NULL;
351 : GEvent e;
352 0 : for ( gadget = gd->gadgets; gadget!=NULL && !handled ; gadget=gadget->prev ) {
353 0 : if ( gadget->funcs->handle_sel &&
354 0 : GGadgetWithin(gadget,event->u.drag_drop.x,event->u.drag_drop.y))
355 0 : if (( handled = (gadget->funcs->handle_sel)(gadget,event) )) {
356 0 : lastdd = gadget;
357 0 : if ( !GDrawNativeWindowExists(NULL,event->native_window) ||
358 : gw->is_dying )
359 0 : return( true );
360 : }
361 : }
362 0 : if ( !handled && gd->e_h!=NULL ) {
363 0 : handled = (gd->e_h)(gw,event);
364 0 : if ( !GDrawNativeWindowExists(NULL,event->native_window) ||
365 : gw->is_dying )
366 0 : return( true );
367 0 : lastdd = (GGadget *) -1;
368 : }
369 0 : e.type = et_dragout;
370 0 : e.w = gw;
371 0 : if ( lastdd!=gd->lastddgadget ) {
372 0 : if ( gd->lastddgadget==(GGadget *) -1 )
373 0 : (gd->e_h)(gw,&e);
374 0 : else if ( gd->lastddgadget!=NULL )
375 0 : (gd->lastddgadget->funcs->handle_sel)(gd->lastddgadget,&e);
376 0 : if ( !GDrawNativeWindowExists(NULL,event->native_window) ||
377 : gw->is_dying )
378 0 : return( true );
379 : }
380 0 : if ( event->type==et_drag )
381 0 : gd->lastddgadget = lastdd;
382 : else
383 0 : gd->lastddgadget = NULL;
384 0 : return( handled );
385 0 : } else if ( event->type == et_selclear ) {
386 0 : for ( gadget = gd->gadgets; gadget!=NULL && !handled ; gadget=gadget->prev ) {
387 0 : if ( gadget->funcs->handle_sel ) {
388 0 : if ( (handled = (gadget->funcs->handle_sel)(gadget,event)) )
389 0 : break;
390 : }
391 : }
392 0 : } else if ( event->type == et_timer ) {
393 0 : for ( gadget = gd->gadgets; gadget!=NULL && !handled ; gadget=gadget->prev ) {
394 0 : if ( gadget->funcs->handle_timer ) {
395 0 : if ( (handled = (gadget->funcs->handle_timer)(gadget,event)) )
396 0 : break;
397 : }
398 : }
399 0 : } else if ( event->type == et_resize ) {
400 0 : GWidgetFlowGadgets(gw);
401 : }
402 0 : if ( gd->e_h!=NULL && (!handled || event->type==et_mousemove ))
403 0 : handled = (gd->e_h)(gw,event);
404 0 : if ( event->type == et_destroy ) {
405 : GGadget *prev;
406 0 : for ( gadget = gd->gadgets; gadget!=NULL ; gadget=prev ) {
407 0 : prev = gadget->prev;
408 0 : if ( !gadget->contained )
409 0 : (gadget->funcs->destroy)(gadget);
410 : /* contained ggadgets will be destroyed when their owner is destroyed */
411 : }
412 : /* Widgets are windows and should get their own destroy events and free themselves */
413 : /* remove us from our parent */
414 0 : parent = gw->parent;
415 0 : if ( parent!=NULL && parent->widget_data!=NULL ) {
416 0 : GContainerD *pgd = (GContainerD *) (parent->widget_data);
417 : struct gwidgetdata *wd, *pwd;
418 0 : for ( pwd=NULL, wd=pgd->widgets; wd!=NULL && wd!=(struct gwidgetdata *) gd; pwd = wd, wd = wd->next );
419 0 : if ( pwd==NULL )
420 0 : pgd->widgets = gd->next;
421 : else
422 0 : pwd->next = gd->next;
423 : }
424 0 : free(gd);
425 0 : gw->widget_data = NULL;
426 : }
427 0 : return( handled );
428 : }
429 :
430 0 : static int GWidgetCheckMn(GContainerD *gd,GEvent *event) {
431 0 : int handled = false;
432 : GGadget *gadget, *last;
433 : struct gwidgetdata *widget;
434 0 : unichar_t keysym = event->u.chr.keysym;
435 0 : int mask = GMenuMask() & (ksm_control|ksm_cmdmacosx);
436 :
437 0 : if ( (mask&ksm_cmdmacosx) && keysym>0x7f &&
438 0 : (event->u.chr.state&ksm_meta) && !(event->u.chr.state&mask) )
439 0 : keysym = GGadgetUndoMacEnglishOptionCombinations(event);
440 :
441 0 : if ( islower(keysym)) keysym = toupper(keysym);
442 0 : for ( gadget = gd->gadgets; gadget!=NULL && !handled ; gadget=gadget->prev ) {
443 0 : if ( (event->u.chr.state&ksm_meta) && !(event->u.chr.state&mask) &&
444 0 : gadget->mnemonic==keysym &&
445 0 : gadget->state != gs_invisible && gadget->state != gs_disabled ) {
446 0 : if ( gadget->focusable ) { /* labels may have a mnemonic */
447 : /* (ie. because textfields can't display mnemonics) */
448 : /* but they don't act on it */
449 0 : _GWidget_IndicateFocusGadget(gadget,mf_mnemonic);
450 0 : handled = true;
451 0 : } else if ( last!=NULL && last->mnemonic=='\0' ) {
452 : /* So if we get a label with a mnemonic, and the next gadget */
453 : /* is focusable and doesn't have a mnemoic itself, give it */
454 : /* the label's focus */
455 0 : _GWidget_IndicateFocusGadget(last,mf_mnemonic);
456 0 : handled = true;
457 : }
458 0 : } else if ( gadget->shortcut == keysym &&
459 0 : (gadget->short_mask&event->u.chr.state)==gadget->short_mask ) {
460 0 : _GWidget_IndicateFocusGadget(gadget,mf_shortcut);
461 0 : handled = true;
462 0 : } else if ( gadget->state != gs_invisible &&
463 0 : gadget->state != gs_disabled &&
464 : gadget->focusable ) {
465 0 : last = gadget;
466 : }
467 : }
468 0 : for ( widget = gd->widgets; widget!=NULL && !handled ; widget=widget->next ) {
469 0 : if ( widget->iscontainer )
470 0 : handled = GWidgetCheckMn((GContainerD *) widget,event);
471 : }
472 0 : return( handled );
473 : }
474 :
475 0 : static int _GWidget_TopLevel_Key(GWindow top, GWindow ew, GEvent *event) {
476 0 : GTopLevelD *topd = (GTopLevelD *) (top->widget_data);
477 0 : int handled=0;
478 : GEvent sub;
479 :
480 0 : if ( !top->is_popup )
481 0 : last_input_window = top;
482 :
483 : /* If the palette has the focus, and it usually will under kde, then */
484 : /* give the event to the main window if the cursor is outside of the palette */
485 0 : if ( topd->ispalette ) {
486 0 : if ( event->u.chr.x<-2 || event->u.chr.x>top->pos.width+2 ||
487 0 : event->u.chr.y<-2 || event->u.chr.y>top->pos.height+2 ) {
488 : GPoint p;
489 0 : topd = topd->owner;
490 0 : p.x = event->u.chr.x; p.y = event->u.chr.y;
491 0 : GDrawTranslateCoordinates(ew,topd->w,&p);
492 0 : event->u.chr.x = p.x; event->u.chr.y = p.y;
493 0 : ew = top = topd->w;
494 0 : event->w = top;
495 : }
496 : }
497 : /* Check for mnemonics and shortcuts */
498 0 : if ( event->type == et_char && !GKeysymIsModifier(event->u.chr.keysym) ) {
499 0 : handled = GMenuPopupCheckKey(event);
500 0 : if ( topd->ispalette ) {
501 0 : if ( !(handled = GMenuBarCheckKey(top,topd->owner->gmenubar,event)) )
502 0 : handled = GWidgetCheckMn((GContainerD *) topd->owner,event);
503 : }
504 0 : if ( !handled )
505 0 : if ( !(handled = GMenuBarCheckKey(top,topd->gmenubar,event)) )
506 0 : handled = GWidgetCheckMn((GContainerD *) topd,event);
507 : }
508 0 : if ( handled )
509 : /* No op */;
510 0 : else if ( topd->popupowner!=NULL ) {
511 : /* When we've got an active popup (menu, list, etc.) all key events */
512 : /* go to the popups owner (which, presumably sends them to the popup)*/
513 0 : if ( topd->popupowner->funcs->handle_key !=NULL )
514 0 : handled = (topd->popupowner->funcs->handle_key)(topd->popupowner,event);
515 0 : } else if ( topd->gfocus!=NULL && topd->gfocus->funcs->handle_key )
516 0 : handled = (topd->gfocus->funcs->handle_key)(topd->gfocus,event);
517 0 : else if ( topd->wfocus!=NULL ) {
518 0 : if ( topd->wfocus->widget_data==NULL ) {
519 0 : if ( topd->wfocus->eh!=NULL )
520 0 : handled = (topd->wfocus->eh)(topd->wfocus,event);
521 0 : } else if ( topd->wfocus->widget_data->e_h!=NULL )
522 0 : handled = (topd->wfocus->widget_data->e_h)(topd->wfocus,event);
523 : }
524 0 : if ( !handled ) {
525 0 : if ( ew->widget_data==NULL ) {
526 0 : if ( ew->eh!=NULL )
527 0 : handled = (ew->eh)(ew,event);
528 0 : } else if ( ew->widget_data->e_h!=NULL )
529 0 : handled = (ew->widget_data->e_h)(ew,event);
530 : }
531 :
532 0 : if ( event->type==et_charup )
533 0 : return( handled );
534 : /* If no one wanted it then try keyboard navigation */
535 : /* Tab or back tab cycles the focus through our widgets/gadgets */
536 0 : if ( !handled && (event->u.chr.keysym==GK_Tab || event->u.chr.keysym==GK_BackTab )) {
537 0 : if ( event->u.chr.keysym==GK_BackTab || (event->u.chr.state&ksm_shift) )
538 0 : GWidgetPrevFocus(ew);
539 : else
540 0 : GWidgetNextFocus(ew);
541 0 : handled = true;
542 : }
543 : /* Return activates the default button (if there is one) */
544 0 : else if ( !handled && (event->u.chr.keysym==GK_Return || event->u.chr.keysym==GK_KP_Enter) &&
545 0 : topd->gdef!=NULL ) {
546 0 : sub.type = et_controlevent;
547 0 : sub.w = topd->gdef->base;
548 0 : sub.u.control.subtype = et_buttonactivate;
549 0 : sub.u.control.g = topd->gdef;
550 0 : sub.u.control.u.button.clicks = 0;
551 0 : if ( topd->gdef->handle_controlevent != NULL )
552 0 : (topd->gdef->handle_controlevent)(topd->gdef,&sub);
553 : else
554 0 : GDrawPostEvent(&sub);
555 : }
556 : /* Escape activates the cancel button (if there is one) */
557 : /* (On the mac, Command-. has that meaning) */
558 0 : else if ( !handled && topd->gcancel!=NULL &&
559 0 : (event->u.chr.keysym==GK_Escape ||
560 0 : ((GMenuMask()&ksm_cmdmacosx) &&
561 0 : (event->u.chr.state&GMenuMask())==ksm_cmdmacosx &&
562 0 : event->u.chr.keysym=='.'))) {
563 0 : sub.type = et_controlevent;
564 0 : sub.w = topd->gcancel->base;
565 0 : sub.u.control.subtype = et_buttonactivate;
566 0 : sub.u.control.g = topd->gcancel;
567 0 : sub.u.control.u.button.clicks = 0;
568 0 : if ( topd->gcancel->handle_controlevent != NULL )
569 0 : (topd->gcancel->handle_controlevent)(topd->gcancel,&sub);
570 : else
571 0 : GDrawPostEvent(&sub);
572 : }
573 0 : return( handled );
574 : }
575 :
576 0 : static int GiveToAll(GContainerD *wd, GEvent *event) {
577 : GGadget *g;
578 : GContainerD *sub;
579 :
580 0 : if ( wd!=NULL && wd->iscontainer ) {
581 0 : for ( g=wd->gadgets; g!=NULL; g=g->prev )
582 0 : if ( g->funcs->handle_mouse!=NULL )
583 0 : (g->funcs->handle_mouse)(g,event);
584 0 : for ( sub = (GContainerD *) (wd->widgets); sub!=NULL;
585 0 : sub=(GContainerD *) (sub->next) )
586 0 : GiveToAll(sub,event);
587 : }
588 0 : if ( wd!=NULL ) {
589 0 : if ( wd->e_h!=NULL )
590 0 : (wd->e_h)(wd->w,event);
591 : } else {
592 0 : if ( wd->w->eh!=NULL )
593 0 : (wd->w->eh)(wd->w,event);
594 : }
595 0 : return( true );
596 : }
597 :
598 0 : static void ManagePalettesVis(GTopLevelD *td, int is_visible ) {
599 : GTopLevelD *palette;
600 :
601 0 : if ( td->w!=last_paletted_focus_window )
602 0 : return;
603 0 : for ( palette=td->palettes; palette!=NULL; palette = palette->nextp ) {
604 0 : if ( is_visible && palette->w->visible_request )
605 0 : GDrawSetVisible(palette->w,true);
606 0 : else if ( !is_visible && palette->w->visible_request ) {
607 0 : GDrawSetVisible(palette->w,false);
608 0 : palette->w->visible_request = true;
609 : }
610 : }
611 : }
612 :
613 : static GTopLevelD *oldtd = NULL;
614 : static GGadget *oldgfocus = NULL;
615 :
616 0 : static int _GWidget_TopLevel_eh(GWindow gw, GEvent *event) {
617 : GTopLevelD *td;
618 : int ret;
619 :
620 0 : if ( !GDrawNativeWindowExists(NULL,event->native_window) )
621 0 : return( true );
622 :
623 0 : td = (GTopLevelD *) (gw->widget_data);
624 0 : if ( td==NULL ) /* Dying */
625 0 : return( true );
626 :
627 0 : GGadgetPopupExternalEvent(event);
628 0 : if ( event->type==et_focus ) {
629 :
630 0 : if ( event->u.focus.gained_focus ) {
631 0 : if ( gw->is_toplevel && !gw->is_popup && !gw->is_dying ) {
632 0 : if ( last_input_window!=gw )
633 0 : previous_focus_window = last_input_window;
634 0 : current_focus_window = gw;
635 : }
636 0 : } else if ( current_focus_window==gw ) {
637 0 : current_focus_window = NULL;
638 : }
639 0 : if ( !td->ispalette && gw->is_visible && event->u.focus.gained_focus && !gw->is_dying ) {
640 0 : GWindow dlg = GDrawGetRedirectWindow(NULL);
641 0 : if ( dlg==NULL || dlg==gw ) {
642 : /* If top level window loses the focus all its palettes go invisible */
643 : /* if it gains focus then all palettes that are supposed to be vis */
644 : /* become visible */
645 : /* But not if we've got an active dialog */
646 : GTopLevelD *palette;
647 0 : if ( last_paletted_focus_window!=NULL && !last_paletted_focus_window->is_dying ) {
648 0 : GTopLevelD *lpfw_td = (GTopLevelD *) (last_paletted_focus_window->widget_data);
649 0 : for ( palette=lpfw_td->palettes; palette!=NULL; palette = palette->nextp ) {
650 0 : if ( !palette->w->is_visible && palette->w->visible_request ) {
651 0 : GDrawSetVisible(palette->w,false);
652 0 : palette->w->visible_request = true;
653 : }
654 : }
655 : }
656 0 : for ( palette=td->palettes; palette!=NULL; palette = palette->nextp ) {
657 0 : if ( !palette->w->is_visible && palette->w->visible_request )
658 0 : GDrawSetVisible(palette->w,true);
659 : }
660 0 : last_paletted_focus_window = gw;
661 : }
662 : }
663 0 : if ( !gw->is_dying && td->gfocus!=NULL && td->gfocus->funcs->handle_focus!=NULL ) {
664 0 : { oldtd = td; oldgfocus = td->gfocus; } /* Debug!!!! */
665 0 : (td->gfocus->funcs->handle_focus)(td->gfocus,event);
666 0 : } else if ( !gw->is_dying && td->wfocus!=NULL ) {
667 0 : if ( td->wfocus->widget_data!=NULL ) {
668 0 : if ( td->wfocus->widget_data->e_h!=NULL )
669 0 : (td->wfocus->widget_data->e_h)(td->wfocus,event);
670 0 : } else if ( td->wfocus->eh!=NULL )
671 0 : (td->wfocus->eh)(td->wfocus,event);
672 : }
673 0 : if ( !gw->is_dying && td->e_h!=NULL )
674 0 : (td->e_h)(gw,event);
675 0 : return( true );
676 0 : } else if ( !gw->is_dying && event->type == et_crossing ) {
677 0 : GiveToAll((GContainerD *) td,event);
678 0 : return( true );
679 0 : } else if ( event->type == et_char || event->type == et_charup ) {
680 0 : return( _GWidget_TopLevel_Key(gw,gw,event));
681 0 : } else if ( !gw->is_dying && event->type == et_resize ) {
682 : GRect r;
683 0 : if ( td->gmenubar!=NULL ) {
684 0 : GGadgetGetSize(td->gmenubar,&r);
685 0 : GGadgetResize(td->gmenubar,event->u.resize.size.width,r.height);
686 0 : GGadgetRedraw(td->gmenubar);
687 : } /* status line, toolbar, etc. */
688 0 : if ( td->palettes!=NULL && event->u.resize.moved ) {
689 : GTopLevelD *palette;
690 0 : for ( palette=td->palettes; palette!=NULL; palette = palette->nextp ) {
691 0 : if ( !broken_palettes || !palette->positioned_yet ) {
692 0 : int x = gw->pos.x + palette->owner_off_x,
693 0 : y = gw->pos.y + palette->owner_off_y;
694 0 : if ( x<0 ) x=0;
695 0 : if ( y<0 ) y=0;
696 0 : if ( x+palette->w->pos.width>GDrawGetRoot(NULL)->pos.width )
697 0 : x = GDrawGetRoot(NULL)->pos.width-palette->w->pos.width;
698 0 : if ( y+palette->w->pos.height>GDrawGetRoot(NULL)->pos.height )
699 0 : y = GDrawGetRoot(NULL)->pos.height-palette->w->pos.height;
700 0 : ++palette->programmove;
701 0 : if ( gw->is_visible )
702 0 : GDrawTrueMove(palette->w, x, y);
703 : else
704 0 : GDrawMove(palette->w, x, y);
705 0 : palette->positioned_yet = true;
706 : }
707 : }
708 : }
709 0 : if ( td->ispalette ) {
710 0 : if ( td->programmove>0 )
711 0 : --td->programmove;
712 : else {
713 0 : td->owner_off_x = gw->pos.x - td->owner->w->pos.x;
714 0 : td->owner_off_y = gw->pos.y - td->owner->w->pos.y;
715 : }
716 : }
717 0 : } else if ( event->type == et_close && td->ispalette ) {
718 0 : GDrawSetVisible(gw,false);
719 0 : return( true );
720 0 : } else if ( !gw->is_dying && event->type == et_visibility ) {
721 0 : if ( broken_palettes )
722 : /* Do Nothing */;
723 0 : else if ( td->ispalette && event->u.visibility.state!=vs_unobscured ) {
724 0 : if ( !GDrawIsAbove(gw,td->owner->w))
725 0 : GDrawRaiseAbove(gw,td->owner->w);
726 : }
727 0 : } else if ( !gw->is_dying && event->type == et_map && !td->ispalette ) {
728 : /* If top level window goes invisible all its palettes follow */
729 : /* if it goes visible then all palettes that are supposed to be vis */
730 : /* follow */
731 0 : ManagePalettesVis(td, event->u.map.is_visible );
732 : }
733 0 : if ( event->type == et_destroy ) {
734 0 : if ( td->palettes!=NULL ) {
735 : struct gtopleveldata *palettes, *next;
736 0 : for ( palettes=td->palettes; palettes!=NULL; palettes = next ) {
737 0 : next = palettes->nextp;
738 0 : GDrawDestroyWindow(palettes->w);
739 : }
740 : /* Palettes must die before our widget data are freed */
741 0 : GDrawSync(GDrawGetDisplayOfWindow(gw));
742 0 : GDrawProcessPendingEvents(GDrawGetDisplayOfWindow(gw));
743 : }
744 : }
745 0 : ret = _GWidget_Container_eh(gw,event);
746 0 : if ( event->type == et_destroy ) {
747 0 : if ( gw==current_focus_window )
748 0 : current_focus_window = NULL;
749 0 : if ( gw==previous_focus_window )
750 0 : previous_focus_window = NULL;
751 0 : if ( gw==last_input_window )
752 0 : last_input_window = NULL;
753 0 : if ( gw==last_paletted_focus_window )
754 0 : last_paletted_focus_window = NULL;
755 0 : ret = true;
756 : }
757 0 : return( ret );
758 : }
759 :
760 : static struct wfuncs _gwidget_container_funcs;
761 : static struct wfuncs _gwidget_toplevel_funcs;
762 :
763 0 : static void MakeContainerWidget(GWindow gw) {
764 : struct gwidgetcontainerdata *gd;
765 :
766 0 : if ( gw->widget_data!=NULL )
767 0 : GDrawIError( "Attempt to make a window into a widget twice");
768 0 : if ( !widgets_initted )
769 0 : gwidget_init();
770 0 : if ( gw->parent==NULL || gw->is_toplevel )
771 0 : gd = calloc(1,sizeof(struct gtopleveldata));
772 : else
773 0 : gd = calloc(1,sizeof(struct gwidgetcontainerdata));
774 0 : gw->widget_data = (struct gwidgetdata *) gd;
775 0 : gd->w = gw;
776 0 : gd->e_h = gw->eh;
777 0 : gw->eh = _GWidget_Container_eh;
778 0 : gd->enabled = true;
779 0 : gd->iscontainer = true;
780 0 : gd->funcs = &_gwidget_container_funcs;
781 0 : if ( gw->parent!=NULL && !gw->is_toplevel ) {
782 0 : if ( gw->parent->widget_data==NULL )
783 0 : MakeContainerWidget(gw->parent);
784 0 : if ( !gw->parent->widget_data->iscontainer )
785 0 : GDrawIError( "Attempt to add a widget to something which is not a container");
786 0 : gd->next = ((struct gwidgetcontainerdata *) (gw->parent->widget_data))->widgets;
787 0 : ((struct gwidgetcontainerdata *) (gw->parent->widget_data))->widgets =
788 : (struct gwidgetdata *) gd;
789 : } else {
790 : struct gtopleveldata *topd;
791 0 : topd = (struct gtopleveldata *) gd;
792 0 : gd->funcs = &_gwidget_toplevel_funcs;
793 0 : gw->eh = _GWidget_TopLevel_eh;
794 0 : topd->handle_key = _GWidget_TopLevel_Key;
795 0 : topd->istoplevel = true;
796 : }
797 0 : }
798 :
799 0 : void _GWidget_AddGGadget(GWindow gw,GGadget *g) {
800 : struct gwidgetcontainerdata *gd;
801 :
802 0 : if ( gw->widget_data==NULL )
803 0 : MakeContainerWidget(gw);
804 0 : gd = (struct gwidgetcontainerdata *) (gw->widget_data);
805 0 : if ( !gd->iscontainer )
806 0 : GDrawIError( "Attempt to add a gadget to something which is not a container");
807 0 : g->prev = gd->gadgets;
808 0 : gd->gadgets = g;
809 0 : if ( g->base!=NULL )
810 0 : GDrawIError( "Attempt to add a gadget to two widgets" );
811 0 : g->base = gw;
812 0 : }
813 :
814 0 : void _GWidget_RemoveGadget(GGadget *g) {
815 : struct gwidgetcontainerdata *gd;
816 : GTopLevelD *td;
817 0 : GWindow gw = g->base;
818 : GGadget *next;
819 :
820 0 : if ( gw==NULL )
821 0 : return;
822 :
823 0 : gd = (struct gwidgetcontainerdata *) (gw->widget_data);
824 0 : if ( gd==NULL || !gd->iscontainer )
825 0 : GDrawIError( "Attempt to remove a gadget to something which is not a container");
826 0 : if ( gd->gadgets==g )
827 0 : gd->gadgets = g->prev;
828 : else {
829 0 : for ( next = gd->gadgets; next!=NULL && next->prev!=g; next = next->prev );
830 0 : if ( next==NULL )
831 0 : GDrawIError( "Attempt to remove a gadget which is not in the gadget list" );
832 : else
833 0 : next->prev = g->prev;
834 : }
835 0 : if ( gd->grabgadget == g ) gd->grabgadget = NULL;
836 0 : g->prev = NULL;
837 0 : g->base = NULL;
838 :
839 0 : while ( gw->parent!=NULL && !gw->is_toplevel ) gw = gw->parent;
840 0 : td = (GTopLevelD *) (gw->widget_data);
841 0 : if ( td->gdef == g ) td->gdef = NULL;
842 0 : if ( td->gcancel == g ) td->gcancel = NULL;
843 0 : if ( td->gfocus == g ) td->gfocus = NULL;
844 : }
845 :
846 0 : void _GWidget_SetDefaultButton(GGadget *g) {
847 0 : struct gtopleveldata *gd=NULL;
848 0 : GWindow gw = g->base;
849 :
850 0 : if ( gw!=NULL ) while ( gw->parent != NULL && !gw->is_toplevel ) gw = gw->parent;
851 0 : if ( gw!=NULL )
852 0 : gd = (struct gtopleveldata *) (gw->widget_data);
853 0 : if ( gd==NULL || !gd->istoplevel )
854 0 : GDrawIError( "This gadget isn't in a top level widget, can't be a default button" );
855 : else
856 0 : gd->gdef = g;
857 0 : }
858 :
859 : /* The previous function assumes everything is set up properly. This one doesn't */
860 : /* it's for when you've got two buttons which might be default and you toggle */
861 : /* between them. It lets each button know if it's default, and then redraws */
862 : /* both */
863 0 : void _GWidget_MakeDefaultButton(GGadget *g) {
864 0 : struct gtopleveldata *gd=NULL;
865 0 : GWindow gw = g->base;
866 :
867 0 : if ( gw!=NULL ) while ( gw->parent != NULL && !gw->is_toplevel ) gw = gw->parent;
868 0 : if ( gw!=NULL )
869 0 : gd = (struct gtopleveldata *) (gw->widget_data);
870 0 : if ( gd==NULL || !gd->istoplevel )
871 0 : GDrawIError( "This gadget isn't in a top level widget, can't be a default button" );
872 0 : else if ( gd->gdef!=g ) {
873 0 : _GButton_SetDefault(gd->gdef,false);
874 0 : gd->gdef = g;
875 0 : _GButton_SetDefault(g,true);
876 : }
877 0 : }
878 :
879 0 : void _GWidget_SetCancelButton(GGadget *g) {
880 0 : struct gtopleveldata *gd=NULL;
881 0 : GWindow gw = g->base;
882 :
883 0 : if ( gw!=NULL ) while ( gw->parent != NULL && !gw->is_toplevel ) gw = gw->parent;
884 0 : if ( gw!=NULL )
885 0 : gd = (struct gtopleveldata *) (gw->widget_data);
886 0 : if ( gd==NULL || !gd->istoplevel )
887 0 : GDrawIError( "This gadget isn't in a top level widget, can't be a cancel button" );
888 : else
889 0 : gd->gcancel = g;
890 0 : }
891 :
892 0 : void _GWidget_SetMenuBar(GGadget *g) {
893 0 : struct gtopleveldata *gd=NULL;
894 0 : GWindow gw = g->base;
895 :
896 0 : if ( gw!=NULL ) while ( gw->parent != NULL && !gw->is_toplevel ) gw = gw->parent;
897 0 : if ( gw!=NULL )
898 0 : gd = (struct gtopleveldata *) (gw->widget_data);
899 0 : if ( gd==NULL || !gd->istoplevel )
900 0 : GDrawIError( "This gadget isn't in a top level widget, can't be a menubar" );
901 : else
902 0 : gd->gmenubar = g;
903 0 : }
904 :
905 0 : void _GWidget_SetPopupOwner(GGadget *g) {
906 0 : struct gtopleveldata *gd=NULL;
907 0 : GWindow gw = g->base;
908 :
909 0 : if ( gw!=NULL ) while ( gw->parent != NULL && !gw->is_toplevel ) gw = gw->parent;
910 0 : if ( gw!=NULL )
911 0 : gd = (struct gtopleveldata *) (gw->widget_data);
912 0 : if ( gd==NULL || !gd->istoplevel )
913 0 : GDrawIError( "This gadget isn't in a top level widget, can't have a popup" );
914 : else
915 0 : gd->popupowner = g;
916 0 : }
917 :
918 0 : void _GWidget_ClearPopupOwner(GGadget *g) {
919 0 : struct gtopleveldata *gd=NULL;
920 0 : GWindow gw = g->base;
921 :
922 0 : if ( gw!=NULL ) while ( gw->parent != NULL && !gw->is_toplevel ) gw = gw->parent;
923 0 : if ( gw!=NULL )
924 0 : gd = (struct gtopleveldata *) (gw->widget_data);
925 0 : if ( gd==NULL || !gd->istoplevel )
926 0 : GDrawIError( "This gadget isn't in a top level widget, can't have a popup" );
927 : else
928 0 : gd->popupowner = NULL;
929 0 : }
930 :
931 0 : void _GWidget_SetGrabGadget(GGadget *g) {
932 0 : struct gwidgetcontainerdata *gd=NULL;
933 0 : GWindow gw = g->base;
934 :
935 0 : if ( gw!=NULL )
936 0 : gd = (struct gwidgetcontainerdata *) (gw->widget_data);
937 0 : if ( gd==NULL || !gd->iscontainer )
938 0 : GDrawIError( "This gadget isn't in a container, can't be a grab gadget" );
939 : else
940 0 : gd->grabgadget = g;
941 0 : }
942 :
943 0 : void _GWidget_ClearGrabGadget(GGadget *g) {
944 0 : struct gwidgetcontainerdata *gd=NULL;
945 0 : GWindow gw = g->base;
946 :
947 0 : if ( gw!=NULL )
948 0 : gd = (struct gwidgetcontainerdata *) (gw->widget_data);
949 0 : if ( gd==NULL || !gd->iscontainer )
950 0 : GDrawIError( "This gadget isn't in a container, can't be a grab gadget" );
951 : else
952 0 : gd->grabgadget = NULL;
953 0 : }
954 :
955 0 : GWindow GWidgetCreateTopWindow(GDisplay *gdisp, GRect *pos, int (*eh)(GWindow,GEvent *), void *user_data, GWindowAttrs *wattrs) {
956 0 : GWindow gw = GDrawCreateTopWindow(gdisp,pos,eh,user_data,wattrs);
957 0 : MakeContainerWidget(gw);
958 0 : return( gw );
959 : }
960 :
961 0 : GWindow GWidgetCreateSubWindow(GWindow w, GRect *pos, int (*eh)(GWindow,GEvent *), void *user_data, GWindowAttrs *wattrs) {
962 0 : GWindow gw = GDrawCreateSubWindow(w,pos,eh,user_data,wattrs);
963 0 : MakeContainerWidget(gw);
964 0 : return( gw );
965 : }
966 :
967 : /* Palettes follow their owners when the owner moves around the screen */
968 : /* Palettes go invisible when the owner does, and become visible again when it does */
969 : /* Palettes are always on top of their owner */
970 : /* Palettes go invisible when the owner loses focus, and become visible when it gains focus */
971 0 : GWindow GWidgetCreatePalette(GWindow w, GRect *pos, int (*eh)(GWindow,GEvent *), void *user_data, GWindowAttrs *wattrs) {
972 : GWindow gw;
973 : GPoint pt, base;
974 : GRect newpos, ownerpos, screensize;
975 : struct gtopleveldata *gd, *od;
976 : GWindow root;
977 :
978 0 : if ( !w->is_toplevel )
979 0 : return( false );
980 :
981 0 : pt.x = pos->x; pt.y = pos->y;
982 0 : root = GDrawGetRoot(w->display);
983 0 : GDrawGetSize(w,&ownerpos);
984 0 : GDrawGetSize(root,&screensize);
985 0 : GDrawTranslateCoordinates(w,root,&pt);
986 0 : base.x = base.y = 0;
987 0 : GDrawTranslateCoordinates(w,root,&base);
988 0 : if ( pt.x<0 ) {
989 0 : if ( base.x+ownerpos.width+20+pos->width+20 > screensize.width )
990 0 : pt.x=0;
991 : else
992 0 : pt.x = base.x+ownerpos.width+20;
993 : }
994 0 : if ( pt.y<0 ) pt.y=0;
995 0 : if ( pt.x+pos->width>root->pos.width )
996 0 : pt.x = root->pos.width-pos->width;
997 0 : if ( pt.y+pos->height>root->pos.height )
998 0 : pt.y = root->pos.height-pos->height;
999 :
1000 0 : newpos.x = pt.x; newpos.y = pt.y; newpos.width = pos->width; newpos.height = pos->height;
1001 0 : wattrs->event_masks |= (1<<et_visibility);
1002 0 : if ( !(wattrs->mask&wam_transient)) {
1003 0 : wattrs->mask |= wam_transient;
1004 0 : wattrs->transient = GWidgetGetTopWidget(w);
1005 : }
1006 0 : if ( broken_palettes ) {
1007 0 : wattrs->mask |= wam_positioned;
1008 0 : wattrs->positioned = true;
1009 : }
1010 0 : gw = GDrawCreateTopWindow(w->display,&newpos,eh,user_data,wattrs);
1011 0 : MakeContainerWidget(gw);
1012 0 : if ( w->widget_data==NULL )
1013 0 : MakeContainerWidget(w);
1014 0 : od = (struct gtopleveldata *) (w->widget_data);
1015 0 : gd = (struct gtopleveldata *) (gw->widget_data);
1016 0 : gd->nextp = od->palettes;
1017 0 : gd->owner = od;
1018 0 : od->palettes = gd;
1019 0 : gd->ispalette = true;
1020 0 : gd->owner_off_x = pos->x; gd->owner_off_y = pos->y;
1021 0 : return( gw );
1022 : }
1023 :
1024 0 : void GWidgetRequestVisiblePalette(GWindow palette,int visible) {
1025 0 : GTopLevelD *td = (GTopLevelD *) (palette->widget_data);
1026 :
1027 0 : if ( td->owner!=NULL ) {
1028 0 : palette->visible_request = visible;
1029 0 : if ( td->owner->w == last_paletted_focus_window )
1030 0 : GDrawSetVisible(palette,visible);
1031 : }
1032 0 : }
1033 :
1034 0 : GGadget *GWidgetGetControl(GWindow gw, int cid) {
1035 : GGadget *gadget;
1036 0 : GContainerD *gd = (GContainerD *) (gw->widget_data);
1037 : GWidgetD *widg;
1038 :
1039 0 : if ( gd==NULL || !gd->iscontainer )
1040 0 : return( NULL );
1041 0 : for ( gadget = gd->gadgets; gadget!=NULL ; gadget=gadget->prev ) {
1042 0 : if ( gadget->cid == cid )
1043 0 : return( gadget );
1044 : }
1045 0 : for ( widg = gd->widgets; widg!=NULL; widg = widg->next ) {
1046 0 : if ( widg->iscontainer ) {
1047 0 : gadget = GWidgetGetControl(widg->w,cid);
1048 0 : if ( gadget!=NULL )
1049 0 : return( gadget );
1050 : }
1051 : }
1052 0 : return( NULL );
1053 : }
1054 :
1055 0 : GGadget *_GWidgetGetGadgets(GWindow gw) {
1056 : GContainerD *gd;
1057 :
1058 0 : if ( gw==NULL )
1059 0 : return( NULL );
1060 :
1061 0 : gd = (GContainerD *) (gw->widget_data);
1062 :
1063 0 : if ( gd==NULL || !gd->iscontainer )
1064 0 : return( NULL );
1065 :
1066 0 : return( gd->gadgets );
1067 : }
1068 :
1069 0 : GWindow GWidgetGetParent(GWindow gw) {
1070 :
1071 0 : return( gw->parent );
1072 : }
1073 :
1074 0 : GWindow GWidgetGetTopWidget(GWindow gw) {
1075 :
1076 0 : for ( ; gw->parent!=NULL && !gw->is_toplevel; gw = gw->parent );
1077 0 : return( gw );
1078 : }
1079 :
1080 0 : GDrawEH GWidgetGetEH(GWindow gw) {
1081 0 : if ( gw->widget_data==NULL )
1082 0 : return( gw->eh );
1083 : else
1084 0 : return( gw->widget_data->e_h );
1085 : }
1086 :
1087 0 : void GWidgetSetEH(GWindow gw, GDrawEH e_h ) {
1088 0 : if ( gw->widget_data==NULL )
1089 0 : gw->eh = e_h;
1090 : else
1091 0 : gw->widget_data->e_h = e_h;
1092 0 : }
1093 :
1094 0 : void GWidgetHidePalettes(void) {
1095 : GTopLevelD *td, *palette;
1096 :
1097 0 : if ( last_paletted_focus_window==NULL )
1098 0 : return;
1099 0 : td = (GTopLevelD *) (last_paletted_focus_window->widget_data);
1100 0 : for ( palette=td->palettes; palette!=NULL; palette = palette->nextp ) {
1101 0 : if ( palette->w->visible_request ) {
1102 0 : GDrawSetVisible(palette->w,false);
1103 0 : palette->w->visible_request = true;
1104 : }
1105 : }
1106 : }
1107 :
1108 0 : void GWidgetReparentWindow(GWindow child,GWindow newparent, int x,int y) {
1109 0 : if ( !child->is_toplevel ) {
1110 : GWindow oldparent, gadgetparent;
1111 0 : for ( oldparent = child; oldparent->parent!=NULL && !oldparent->is_toplevel; oldparent=oldparent->parent );
1112 0 : if ( oldparent!=child ) {
1113 0 : GTopLevelD *td = (GTopLevelD *) (oldparent->widget_data);
1114 0 : if ( td->gfocus!=NULL ) {
1115 0 : for ( gadgetparent = td->gfocus->base;
1116 0 : gadgetparent!=child &&
1117 0 : gadgetparent!=NULL; gadgetparent = gadgetparent->parent );
1118 0 : if ( gadgetparent==child )
1119 0 : td->gfocus = NULL;
1120 : }
1121 : }
1122 : }
1123 0 : GDrawReparentWindow(child,newparent,x,y);
1124 0 : }
1125 :
1126 0 : GIC *GWidgetCreateInputContext(GWindow w,enum gic_style def_style) {
1127 0 : GWidgetD *wd = (GWidgetD *) (w->widget_data);
1128 :
1129 0 : if ( wd->gic==NULL )
1130 0 : wd->gic = GDrawCreateInputContext(w,def_style);
1131 0 : return( wd->gic );
1132 : }
1133 :
1134 0 : GIC *GWidgetGetInputContext(GWindow w) {
1135 0 : GWidgetD *wd = (GWidgetD *) (w->widget_data);
1136 0 : return( wd->gic );
1137 : }
1138 :
1139 0 : void GWidgetFlowGadgets(GWindow gw) {
1140 : GGadget *gadget;
1141 0 : GContainerD *gd = (GContainerD *) (gw->widget_data);
1142 :
1143 0 : if ( gd==NULL )
1144 0 : return;
1145 :
1146 0 : gadget = gd->gadgets;
1147 0 : if ( gadget!=NULL ) {
1148 0 : while ( gadget->prev!=NULL )
1149 0 : gadget=gadget->prev;
1150 : }
1151 0 : if ( gadget != NULL && GGadgetFillsWindow(gadget)) {
1152 : GRect wsize;
1153 0 : GDrawGetSize(gw, &wsize);
1154 :
1155 : /* Make any offset simmetrical */
1156 0 : if (wsize.width >= 2*gadget->r.x) wsize.width -= 2*gadget->r.x;
1157 0 : else wsize.width = 0;
1158 :
1159 0 : if (wsize.height >= 2*gadget->r.y) wsize.height -= 2*gadget->r.y;
1160 0 : else wsize.height = 0;
1161 :
1162 0 : GGadgetResize(gadget,wsize.width,wsize.height);
1163 0 : GDrawRequestExpose(gw,NULL,false);
1164 : }
1165 : }
1166 :
1167 0 : void GWidgetToDesiredSize(GWindow gw) {
1168 : GGadget *gadget;
1169 0 : GContainerD *gd = (GContainerD *) (gw->widget_data);
1170 :
1171 0 : if ( gd==NULL )
1172 0 : return;
1173 :
1174 0 : gadget = gd->gadgets;
1175 0 : if ( gadget!=NULL ) {
1176 0 : while ( gadget->prev!=NULL )
1177 0 : gadget=gadget->prev;
1178 : }
1179 0 : if ( gadget != NULL && GGadgetFillsWindow(gadget))
1180 0 : GHVBoxFitWindow(gadget);
1181 : }
|