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