xref: /vim-8.2.3635/src/gui_gtk_f.c (revision 2bf24176)
1 /* vi:set ts=8 sts=4 sw=4:
2  *
3  * VIM - Vi IMproved		by Bram Moolenaar
4  *
5  * Do ":help uganda"  in Vim to read copying and usage conditions.
6  * Do ":help credits" in Vim to see a list of people who contributed.
7  * See README.txt for an overview of the Vim source code.
8  */
9 
10 /*
11  * (C) 1998,1999 by Marcin Dalecki <[email protected]>
12  *
13  * Support for GTK+ 2 was added by:
14  *
15  * (C) 2002,2003  Jason Hildebrand  <[email protected]>
16  *		  Daniel Elstner  <[email protected]>
17  *
18  * This is a special purpose container widget, which manages arbitrary
19  * children at arbitrary positions width arbitrary sizes.  This finally puts
20  * an end on our resize problems with which we where struggling for such a
21  * long time.
22  */
23 
24 #include "vim.h"
25 #include <gtk/gtk.h>	/* without this it compiles, but gives errors at
26 			   runtime! */
27 #include "gui_gtk_f.h"
28 #include <gtk/gtksignal.h>
29 #ifdef WIN3264
30 # include <gdk/gdkwin32.h>
31 #else
32 # include <gdk/gdkx.h>
33 #endif
34 
35 typedef struct _GtkFormChild GtkFormChild;
36 
37 struct _GtkFormChild
38 {
39     GtkWidget *widget;
40     GdkWindow *window;
41     gint x;		/* relative subwidget x position */
42     gint y;		/* relative subwidget y position */
43     gint mapped;
44 };
45 
46 
47 static void gtk_form_class_init(GtkFormClass *klass);
48 static void gtk_form_init(GtkForm *form);
49 
50 static void gtk_form_realize(GtkWidget *widget);
51 static void gtk_form_unrealize(GtkWidget *widget);
52 static void gtk_form_map(GtkWidget *widget);
53 static void gtk_form_size_request(GtkWidget *widget,
54 				  GtkRequisition *requisition);
55 static void gtk_form_size_allocate(GtkWidget *widget,
56 				   GtkAllocation *allocation);
57 static gint gtk_form_expose(GtkWidget *widget,
58 			    GdkEventExpose *event);
59 
60 static void gtk_form_remove(GtkContainer *container,
61 			    GtkWidget *widget);
62 static void gtk_form_forall(GtkContainer *container,
63 			    gboolean include_internals,
64 			    GtkCallback callback,
65 			    gpointer callback_data);
66 
67 static void gtk_form_attach_child_window(GtkForm *form,
68 					 GtkFormChild *child);
69 static void gtk_form_realize_child(GtkForm *form,
70 				   GtkFormChild *child);
71 static void gtk_form_position_child(GtkForm *form,
72 				    GtkFormChild *child,
73 				    gboolean force_allocate);
74 static void gtk_form_position_children(GtkForm *form);
75 
76 static GdkFilterReturn gtk_form_filter(GdkXEvent *gdk_xevent,
77 				       GdkEvent *event,
78 				       gpointer data);
79 static GdkFilterReturn gtk_form_main_filter(GdkXEvent *gdk_xevent,
80 					    GdkEvent *event,
81 					    gpointer data);
82 
83 static void gtk_form_set_static_gravity(GdkWindow *window,
84 					gboolean use_static);
85 
86 static void gtk_form_send_configure(GtkForm *form);
87 
88 static void gtk_form_child_map(GtkWidget *widget, gpointer user_data);
89 static void gtk_form_child_unmap(GtkWidget *widget, gpointer user_data);
90 
91 static GtkWidgetClass *parent_class = NULL;
92 
93 /* Public interface
94  */
95 
96     GtkWidget *
97 gtk_form_new(void)
98 {
99     GtkForm *form;
100 
101     form = gtk_type_new(gtk_form_get_type());
102 
103     return GTK_WIDGET(form);
104 }
105 
106     void
107 gtk_form_put(GtkForm	*form,
108 	     GtkWidget	*child_widget,
109 	     gint	x,
110 	     gint	y)
111 {
112     GtkFormChild *child;
113 
114     g_return_if_fail(GTK_IS_FORM(form));
115 
116     /* LINTED: avoid warning: conversion to 'unsigned long' */
117     child = g_new(GtkFormChild, 1);
118 
119     child->widget = child_widget;
120     child->window = NULL;
121     child->x = x;
122     child->y = y;
123     child->widget->requisition.width = 0;
124     child->widget->requisition.height = 0;
125     child->mapped = FALSE;
126 
127     form->children = g_list_append(form->children, child);
128 
129     /* child->window must be created and attached to the widget _before_
130      * it has been realized, or else things will break with GTK2.  Note
131      * that gtk_widget_set_parent() realizes the widget if it's visible
132      * and its parent is mapped.
133      */
134     if (GTK_WIDGET_REALIZED(form))
135 	gtk_form_attach_child_window(form, child);
136 
137     gtk_widget_set_parent(child_widget, GTK_WIDGET(form));
138     gtk_widget_size_request(child->widget, NULL);
139 
140     if (GTK_WIDGET_REALIZED(form) && !GTK_WIDGET_REALIZED(child_widget))
141 	gtk_form_realize_child(form, child);
142 
143     gtk_form_position_child(form, child, TRUE);
144 }
145 
146     void
147 gtk_form_move(GtkForm	*form,
148 	      GtkWidget	*child_widget,
149 	      gint	x,
150 	      gint	y)
151 {
152     GList *tmp_list;
153     GtkFormChild *child;
154 
155     g_return_if_fail(GTK_IS_FORM(form));
156 
157     for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next)
158     {
159 	child = tmp_list->data;
160 	if (child->widget == child_widget)
161 	{
162 	    child->x = x;
163 	    child->y = y;
164 
165 	    gtk_form_position_child(form, child, TRUE);
166 	    return;
167 	}
168     }
169 }
170 
171     void
172 gtk_form_freeze(GtkForm *form)
173 {
174     g_return_if_fail(GTK_IS_FORM(form));
175 
176     ++form->freeze_count;
177 }
178 
179     void
180 gtk_form_thaw(GtkForm *form)
181 {
182     g_return_if_fail(GTK_IS_FORM(form));
183 
184     if (form->freeze_count)
185     {
186 	if (!(--form->freeze_count))
187 	{
188 	    gtk_form_position_children(form);
189 	    gtk_widget_queue_draw(GTK_WIDGET(form));
190 	}
191     }
192 }
193 
194 /* Basic Object handling procedures
195  */
196     GtkType
197 gtk_form_get_type(void)
198 {
199     static GtkType form_type = 0;
200 
201     if (!form_type)
202     {
203 	GtkTypeInfo form_info;
204 
205 	vim_memset(&form_info, 0, sizeof(form_info));
206 	form_info.type_name = "GtkForm";
207 	form_info.object_size = sizeof(GtkForm);
208 	form_info.class_size = sizeof(GtkFormClass);
209 	form_info.class_init_func = (GtkClassInitFunc)gtk_form_class_init;
210 	form_info.object_init_func = (GtkObjectInitFunc)gtk_form_init;
211 
212 	form_type = gtk_type_unique(GTK_TYPE_CONTAINER, &form_info);
213     }
214     return form_type;
215 }
216 
217     static void
218 gtk_form_class_init(GtkFormClass *klass)
219 {
220     GtkWidgetClass *widget_class;
221     GtkContainerClass *container_class;
222 
223     widget_class = (GtkWidgetClass *) klass;
224     container_class = (GtkContainerClass *) klass;
225 
226     parent_class = gtk_type_class(gtk_container_get_type());
227 
228     widget_class->realize = gtk_form_realize;
229     widget_class->unrealize = gtk_form_unrealize;
230     widget_class->map = gtk_form_map;
231     widget_class->size_request = gtk_form_size_request;
232     widget_class->size_allocate = gtk_form_size_allocate;
233     widget_class->expose_event = gtk_form_expose;
234 
235     container_class->remove = gtk_form_remove;
236     container_class->forall = gtk_form_forall;
237 }
238 
239     static void
240 gtk_form_init(GtkForm *form)
241 {
242     form->children = NULL;
243 
244     form->width = 1;
245     form->height = 1;
246 
247     form->bin_window = NULL;
248 
249     form->configure_serial = 0;
250     form->visibility = GDK_VISIBILITY_PARTIAL;
251 
252     form->freeze_count = 0;
253 }
254 
255 /*
256  * Widget methods
257  */
258 
259     static void
260 gtk_form_realize(GtkWidget *widget)
261 {
262     GList *tmp_list;
263     GtkForm *form;
264     GdkWindowAttr attributes;
265     gint attributes_mask;
266 
267     g_return_if_fail(GTK_IS_FORM(widget));
268 
269     form = GTK_FORM(widget);
270     GTK_WIDGET_SET_FLAGS(form, GTK_REALIZED);
271 
272     attributes.window_type = GDK_WINDOW_CHILD;
273     attributes.x = widget->allocation.x;
274     attributes.y = widget->allocation.y;
275     attributes.width = widget->allocation.width;
276     attributes.height = widget->allocation.height;
277     attributes.wclass = GDK_INPUT_OUTPUT;
278     attributes.visual = gtk_widget_get_visual(widget);
279     attributes.colormap = gtk_widget_get_colormap(widget);
280     attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
281 
282     attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
283 
284     widget->window = gdk_window_new(gtk_widget_get_parent_window(widget),
285 				    &attributes, attributes_mask);
286     gdk_window_set_user_data(widget->window, widget);
287 
288     attributes.x = 0;
289     attributes.y = 0;
290     attributes.event_mask = gtk_widget_get_events(widget);
291 
292     form->bin_window = gdk_window_new(widget->window,
293 				      &attributes, attributes_mask);
294     gdk_window_set_user_data(form->bin_window, widget);
295 
296     gtk_form_set_static_gravity(form->bin_window, TRUE);
297 
298     widget->style = gtk_style_attach(widget->style, widget->window);
299     gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL);
300     gtk_style_set_background(widget->style, form->bin_window, GTK_STATE_NORMAL);
301 
302     gdk_window_add_filter(widget->window, gtk_form_main_filter, form);
303     gdk_window_add_filter(form->bin_window, gtk_form_filter, form);
304 
305     for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next)
306     {
307 	GtkFormChild *child = tmp_list->data;
308 
309 	gtk_form_attach_child_window(form, child);
310 
311 	if (GTK_WIDGET_VISIBLE(child->widget))
312 	    gtk_form_realize_child(form, child);
313     }
314 }
315 
316 
317 /* After reading the documentation at
318  * http://developer.gnome.org/doc/API/2.0/gtk/gtk-changes-2-0.html
319  * I think it should be possible to remove this function when compiling
320  * against gtk-2.0.  It doesn't seem to cause problems, though.
321  *
322  * Well, I reckon at least the gdk_window_show(form->bin_window)
323  * is necessary.  GtkForm is anything but a usual container widget.
324  */
325     static void
326 gtk_form_map(GtkWidget *widget)
327 {
328     GList *tmp_list;
329     GtkForm *form;
330 
331     g_return_if_fail(GTK_IS_FORM(widget));
332 
333     form = GTK_FORM(widget);
334 
335     GTK_WIDGET_SET_FLAGS(widget, GTK_MAPPED);
336 
337     gdk_window_show(widget->window);
338     gdk_window_show(form->bin_window);
339 
340     for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next)
341     {
342 	GtkFormChild *child = tmp_list->data;
343 
344 	if (GTK_WIDGET_VISIBLE(child->widget)
345 		&& !GTK_WIDGET_MAPPED(child->widget))
346 	    gtk_widget_map(child->widget);
347     }
348 }
349 
350     static void
351 gtk_form_unrealize(GtkWidget *widget)
352 {
353     GList *tmp_list;
354     GtkForm *form;
355 
356     g_return_if_fail(GTK_IS_FORM(widget));
357 
358     form = GTK_FORM(widget);
359 
360     tmp_list = form->children;
361 
362     gdk_window_set_user_data(form->bin_window, NULL);
363     gdk_window_destroy(form->bin_window);
364     form->bin_window = NULL;
365 
366     while (tmp_list)
367     {
368 	GtkFormChild *child = tmp_list->data;
369 
370 	if (child->window != NULL)
371 	{
372 	    gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget),
373 					  GTK_SIGNAL_FUNC(gtk_form_child_map),
374 					  child);
375 	    gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget),
376 					  GTK_SIGNAL_FUNC(gtk_form_child_unmap),
377 					  child);
378 
379 	    gdk_window_set_user_data(child->window, NULL);
380 	    gdk_window_destroy(child->window);
381 
382 	    child->window = NULL;
383 	}
384 
385 	tmp_list = tmp_list->next;
386     }
387 
388     if (GTK_WIDGET_CLASS (parent_class)->unrealize)
389 	 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
390 }
391 
392     static void
393 gtk_form_size_request(GtkWidget *widget, GtkRequisition *requisition)
394 {
395     GList *tmp_list;
396     GtkForm *form;
397 
398     g_return_if_fail(GTK_IS_FORM(widget));
399 
400     form = GTK_FORM(widget);
401 
402     requisition->width = form->width;
403     requisition->height = form->height;
404 
405     tmp_list = form->children;
406 
407     while (tmp_list)
408     {
409 	GtkFormChild *child = tmp_list->data;
410 	gtk_widget_size_request(child->widget, NULL);
411 	tmp_list = tmp_list->next;
412     }
413 }
414 
415     static void
416 gtk_form_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
417 {
418     GList *tmp_list;
419     GtkForm *form;
420     gboolean need_reposition;
421 
422     g_return_if_fail(GTK_IS_FORM(widget));
423 
424     if (widget->allocation.x == allocation->x
425 	    && widget->allocation.y == allocation->y
426 	    && widget->allocation.width == allocation->width
427 	    && widget->allocation.height == allocation->height)
428 	return;
429 
430     need_reposition = widget->allocation.width != allocation->width
431 		   || widget->allocation.height != allocation->height;
432     form = GTK_FORM(widget);
433 
434     if (need_reposition)
435     {
436 	tmp_list = form->children;
437 
438 	while (tmp_list)
439 	{
440 	    GtkFormChild *child = tmp_list->data;
441 	    gtk_form_position_child(form, child, TRUE);
442 
443 	    tmp_list = tmp_list->next;
444 	}
445     }
446 
447     if (GTK_WIDGET_REALIZED(widget))
448     {
449 	gdk_window_move_resize(widget->window,
450 			       allocation->x, allocation->y,
451 			       allocation->width, allocation->height);
452 	gdk_window_move_resize(GTK_FORM(widget)->bin_window,
453 			       0, 0,
454 			       allocation->width, allocation->height);
455     }
456     widget->allocation = *allocation;
457     if (need_reposition)
458 	gtk_form_send_configure(form);
459 }
460 
461     static gint
462 gtk_form_expose(GtkWidget *widget, GdkEventExpose *event)
463 {
464     GList   *tmp_list;
465     GtkForm *form;
466 
467     g_return_val_if_fail(GTK_IS_FORM(widget), FALSE);
468 
469     form = GTK_FORM(widget);
470 
471     if (event->window == form->bin_window)
472 	return FALSE;
473 
474     for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next)
475     {
476 	GtkFormChild	*formchild = tmp_list->data;
477 	GtkWidget	*child	   = formchild->widget;
478 	/*
479 	 * The following chunk of code is taken from gtkcontainer.c.  The
480 	 * gtk1.x code synthesized expose events directly on the child widgets,
481 	 * which can't be done in gtk2
482 	 */
483 	if (GTK_WIDGET_DRAWABLE(child) && GTK_WIDGET_NO_WINDOW(child)
484 		&& child->window == event->window)
485 	{
486 	    GdkEventExpose child_event;
487 	    child_event = *event;
488 
489 	    child_event.region = gtk_widget_region_intersect(child, event->region);
490 	    if (!gdk_region_empty(child_event.region))
491 	    {
492 		gdk_region_get_clipbox(child_event.region, &child_event.area);
493 		gtk_widget_send_expose(child, (GdkEvent *)&child_event);
494 	    }
495 	}
496     }
497 
498     return FALSE;
499 }
500 
501 /* Container method
502  */
503     static void
504 gtk_form_remove(GtkContainer *container, GtkWidget *widget)
505 {
506     GList *tmp_list;
507     GtkForm *form;
508     GtkFormChild *child = NULL;	    /* init for gcc */
509 
510     g_return_if_fail(GTK_IS_FORM(container));
511 
512     form = GTK_FORM(container);
513 
514     tmp_list = form->children;
515     while (tmp_list)
516     {
517 	child = tmp_list->data;
518 	if (child->widget == widget)
519 	    break;
520 	tmp_list = tmp_list->next;
521     }
522 
523     if (tmp_list)
524     {
525 	if (child->window)
526 	{
527 	    gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget),
528 					  GTK_SIGNAL_FUNC(&gtk_form_child_map), child);
529 	    gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget),
530 					  GTK_SIGNAL_FUNC(&gtk_form_child_unmap), child);
531 
532 	    /* FIXME: This will cause problems for reparenting NO_WINDOW
533 	     * widgets out of a GtkForm
534 	     */
535 	    gdk_window_set_user_data(child->window, NULL);
536 	    gdk_window_destroy(child->window);
537 	}
538 	gtk_widget_unparent(widget);
539 
540 	form->children = g_list_remove_link(form->children, tmp_list);
541 	g_list_free_1(tmp_list);
542 	g_free(child);
543     }
544 }
545 
546     static void
547 gtk_form_forall(GtkContainer	*container,
548 		gboolean	include_internals UNUSED,
549 		GtkCallback	callback,
550 		gpointer	callback_data)
551 {
552     GtkForm *form;
553     GtkFormChild *child;
554     GList *tmp_list;
555 
556     g_return_if_fail(GTK_IS_FORM(container));
557     g_return_if_fail(callback != NULL);
558 
559     form = GTK_FORM(container);
560 
561     tmp_list = form->children;
562     while (tmp_list)
563     {
564 	child = tmp_list->data;
565 	tmp_list = tmp_list->next;
566 
567 	(*callback) (child->widget, callback_data);
568     }
569 }
570 
571 /* Operations on children
572  */
573 
574     static void
575 gtk_form_attach_child_window(GtkForm *form, GtkFormChild *child)
576 {
577     if (child->window != NULL)
578 	return; /* been there, done that */
579 
580     if (GTK_WIDGET_NO_WINDOW(child->widget))
581     {
582 	GtkWidget	*widget;
583 	GdkWindowAttr	attributes;
584 	gint		attributes_mask;
585 
586 	widget = GTK_WIDGET(form);
587 
588 	attributes.window_type = GDK_WINDOW_CHILD;
589 	attributes.x = child->x;
590 	attributes.y = child->y;
591 	attributes.width = child->widget->requisition.width;
592 	attributes.height = child->widget->requisition.height;
593 	attributes.wclass = GDK_INPUT_OUTPUT;
594 	attributes.visual = gtk_widget_get_visual(widget);
595 	attributes.colormap = gtk_widget_get_colormap(widget);
596 	attributes.event_mask = GDK_EXPOSURE_MASK;
597 
598 	attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
599 	child->window = gdk_window_new(form->bin_window,
600 				       &attributes, attributes_mask);
601 	gdk_window_set_user_data(child->window, widget);
602 
603 	gtk_style_set_background(widget->style,
604 				 child->window,
605 				 GTK_STATE_NORMAL);
606 
607 	gtk_widget_set_parent_window(child->widget, child->window);
608 	gtk_form_set_static_gravity(child->window, TRUE);
609 	/*
610 	 * Install signal handlers to map/unmap child->window
611 	 * alongside with the actual widget.
612 	 */
613 	gtk_signal_connect(GTK_OBJECT(child->widget), "map",
614 			   GTK_SIGNAL_FUNC(&gtk_form_child_map), child);
615 	gtk_signal_connect(GTK_OBJECT(child->widget), "unmap",
616 			   GTK_SIGNAL_FUNC(&gtk_form_child_unmap), child);
617     }
618     else if (!GTK_WIDGET_REALIZED(child->widget))
619     {
620 	gtk_widget_set_parent_window(child->widget, form->bin_window);
621     }
622 }
623 
624     static void
625 gtk_form_realize_child(GtkForm *form, GtkFormChild *child)
626 {
627     gtk_form_attach_child_window(form, child);
628     gtk_widget_realize(child->widget);
629 
630     if (child->window == NULL) /* might be already set, see above */
631 	gtk_form_set_static_gravity(child->widget->window, TRUE);
632 }
633 
634     static void
635 gtk_form_position_child(GtkForm *form, GtkFormChild *child,
636 			gboolean force_allocate)
637 {
638     gint x;
639     gint y;
640 
641     x = child->x;
642     y = child->y;
643 
644     if ((x >= G_MINSHORT) && (x <= G_MAXSHORT) &&
645 	(y >= G_MINSHORT) && (y <= G_MAXSHORT))
646     {
647 	if (!child->mapped)
648 	{
649 	    if (GTK_WIDGET_MAPPED(form) && GTK_WIDGET_VISIBLE(child->widget))
650 	    {
651 		if (!GTK_WIDGET_MAPPED(child->widget))
652 		    gtk_widget_map(child->widget);
653 
654 		child->mapped = TRUE;
655 		force_allocate = TRUE;
656 	    }
657 	}
658 
659 	if (force_allocate)
660 	{
661 	    GtkAllocation allocation;
662 
663 	    if (GTK_WIDGET_NO_WINDOW(child->widget))
664 	    {
665 		if (child->window)
666 		{
667 		    gdk_window_move_resize(child->window,
668 			    x, y,
669 			    child->widget->requisition.width,
670 			    child->widget->requisition.height);
671 		}
672 
673 		allocation.x = 0;
674 		allocation.y = 0;
675 	    }
676 	    else
677 	    {
678 		allocation.x = x;
679 		allocation.y = y;
680 	    }
681 
682 	    allocation.width = child->widget->requisition.width;
683 	    allocation.height = child->widget->requisition.height;
684 
685 	    gtk_widget_size_allocate(child->widget, &allocation);
686 	}
687     }
688     else
689     {
690 	if (child->mapped)
691 	{
692 	    child->mapped = FALSE;
693 
694 	    if (GTK_WIDGET_MAPPED(child->widget))
695 		gtk_widget_unmap(child->widget);
696 	}
697     }
698 }
699 
700     static void
701 gtk_form_position_children(GtkForm *form)
702 {
703     GList *tmp_list;
704 
705     for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next)
706 	gtk_form_position_child(form, tmp_list->data, FALSE);
707 }
708 
709 /* Callbacks */
710 
711 /* The main event filter. Actually, we probably don't really need
712  * to install this as a filter at all, since we are calling it
713  * directly above in the expose-handling hack.
714  *
715  * This routine identifies expose events that are generated when
716  * we've temporarily moved the bin_window_origin, and translates
717  * them or discards them, depending on whether we are obscured
718  * or not.
719  */
720     static GdkFilterReturn
721 gtk_form_filter(GdkXEvent *gdk_xevent, GdkEvent *event UNUSED, gpointer data)
722 {
723     XEvent *xevent;
724     GtkForm *form;
725 
726     xevent = (XEvent *) gdk_xevent;
727     form = GTK_FORM(data);
728 
729     switch (xevent->type)
730     {
731     case Expose:
732 	if (xevent->xexpose.serial == form->configure_serial)
733 	{
734 	    if (form->visibility == GDK_VISIBILITY_UNOBSCURED)
735 		return GDK_FILTER_REMOVE;
736 	    else
737 		break;
738 	}
739 	break;
740 
741     case ConfigureNotify:
742 	if ((xevent->xconfigure.x != 0) || (xevent->xconfigure.y != 0))
743 	    form->configure_serial = xevent->xconfigure.serial;
744 	break;
745     }
746 
747     return GDK_FILTER_CONTINUE;
748 }
749 
750 /* Although GDK does have a GDK_VISIBILITY_NOTIFY event,
751  * there is no corresponding event in GTK, so we have
752  * to get the events from a filter
753  */
754     static GdkFilterReturn
755 gtk_form_main_filter(GdkXEvent *gdk_xevent,
756 		     GdkEvent *event UNUSED,
757 		     gpointer data)
758 {
759     XEvent *xevent;
760     GtkForm *form;
761 
762     xevent = (XEvent *) gdk_xevent;
763     form = GTK_FORM(data);
764 
765     if (xevent->type == VisibilityNotify)
766     {
767 	switch (xevent->xvisibility.state)
768 	{
769 	case VisibilityFullyObscured:
770 	    form->visibility = GDK_VISIBILITY_FULLY_OBSCURED;
771 	    break;
772 
773 	case VisibilityPartiallyObscured:
774 	    form->visibility = GDK_VISIBILITY_PARTIAL;
775 	    break;
776 
777 	case VisibilityUnobscured:
778 	    form->visibility = GDK_VISIBILITY_UNOBSCURED;
779 	    break;
780 	}
781 
782 	return GDK_FILTER_REMOVE;
783     }
784     return GDK_FILTER_CONTINUE;
785 }
786 
787     static void
788 gtk_form_set_static_gravity(GdkWindow *window, gboolean use_static)
789 {
790     /* We don't check if static gravity is actually supported, because it
791      * results in an annoying assertion error message. */
792     gdk_window_set_static_gravities(window, use_static);
793 }
794 
795     void
796 gtk_form_move_resize(GtkForm *form, GtkWidget *widget,
797 		     gint x, gint y, gint w, gint h)
798 {
799     widget->requisition.width  = w;
800     widget->requisition.height = h;
801 
802     gtk_form_move(form, widget, x, y);
803 }
804 
805     static void
806 gtk_form_send_configure(GtkForm *form)
807 {
808     GtkWidget *widget;
809     GdkEventConfigure event;
810 
811     widget = GTK_WIDGET(form);
812 
813     event.type = GDK_CONFIGURE;
814     event.window = widget->window;
815     event.x = widget->allocation.x;
816     event.y = widget->allocation.y;
817     event.width = widget->allocation.width;
818     event.height = widget->allocation.height;
819 
820     gtk_main_do_event((GdkEvent*)&event);
821 }
822 
823     static void
824 gtk_form_child_map(GtkWidget *widget UNUSED, gpointer user_data)
825 {
826     GtkFormChild *child;
827 
828     child = (GtkFormChild *)user_data;
829 
830     child->mapped = TRUE;
831     gdk_window_show(child->window);
832 }
833 
834     static void
835 gtk_form_child_unmap(GtkWidget *widget UNUSED, gpointer user_data)
836 {
837     GtkFormChild *child;
838 
839     child = (GtkFormChild *)user_data;
840 
841     child->mapped = FALSE;
842     gdk_window_hide(child->window);
843 }
844 
845