blob: 182fe82f96120a1bfb51e1789c36724cbbdfd7bd [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002 *
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/*
Bram Moolenaara0a83be2005-01-04 21:26:43 +000011 * (C) 1998,1999 by Marcin Dalecki <martin@dalecki.de>
Bram Moolenaar071d4272004-06-13 20:20:40 +000012 *
13 * Support for GTK+ 2 was added by:
14 *
15 * (C) 2002,2003 Jason Hildebrand <jason@peaceworks.ca>
16 * Daniel Elstner <daniel.elstner@gmx.net>
17 *
Bram Moolenaar933eb392007-05-10 17:52:45 +000018 * 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.
Bram Moolenaar98921892016-02-23 17:14:37 +010022 *
23 * Support for GTK+ 3 was added by:
24 *
25 * 2016 Kazunobu Kuriyama <kazunobu.kuriyama@gmail.com>
Bram Moolenaar071d4272004-06-13 20:20:40 +000026 */
27
28#include "vim.h"
29#include <gtk/gtk.h> /* without this it compiles, but gives errors at
30 runtime! */
31#include "gui_gtk_f.h"
Bram Moolenaar98921892016-02-23 17:14:37 +010032#if !GTK_CHECK_VERSION(3,0,0)
33# include <gtk/gtksignal.h>
34#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000035#ifdef WIN3264
36# include <gdk/gdkwin32.h>
37#else
38# include <gdk/gdkx.h>
39#endif
40
41typedef struct _GtkFormChild GtkFormChild;
42
43struct _GtkFormChild
44{
45 GtkWidget *widget;
46 GdkWindow *window;
47 gint x; /* relative subwidget x position */
48 gint y; /* relative subwidget y position */
49 gint mapped;
50};
51
52
53static void gtk_form_class_init(GtkFormClass *klass);
54static void gtk_form_init(GtkForm *form);
55
56static void gtk_form_realize(GtkWidget *widget);
57static void gtk_form_unrealize(GtkWidget *widget);
58static void gtk_form_map(GtkWidget *widget);
59static void gtk_form_size_request(GtkWidget *widget,
60 GtkRequisition *requisition);
Bram Moolenaar98921892016-02-23 17:14:37 +010061#if GTK_CHECK_VERSION(3,0,0)
62static void gtk_form_get_preferred_width(GtkWidget *widget,
63 gint *minimal_width,
64 gint *natural_width);
65static void gtk_form_get_preferred_height(GtkWidget *widget,
66 gint *minimal_height,
67 gint *natural_height);
68#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000069static void gtk_form_size_allocate(GtkWidget *widget,
70 GtkAllocation *allocation);
Bram Moolenaar98921892016-02-23 17:14:37 +010071#if GTK_CHECK_VERSION(3,0,0)
72static gboolean gtk_form_draw(GtkWidget *widget,
73 cairo_t *cr);
74#else
Bram Moolenaar071d4272004-06-13 20:20:40 +000075static gint gtk_form_expose(GtkWidget *widget,
76 GdkEventExpose *event);
Bram Moolenaar98921892016-02-23 17:14:37 +010077#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000078
79static void gtk_form_remove(GtkContainer *container,
80 GtkWidget *widget);
81static void gtk_form_forall(GtkContainer *container,
82 gboolean include_internals,
83 GtkCallback callback,
84 gpointer callback_data);
85
86static void gtk_form_attach_child_window(GtkForm *form,
87 GtkFormChild *child);
88static void gtk_form_realize_child(GtkForm *form,
89 GtkFormChild *child);
90static void gtk_form_position_child(GtkForm *form,
91 GtkFormChild *child,
92 gboolean force_allocate);
93static void gtk_form_position_children(GtkForm *form);
94
Bram Moolenaar98921892016-02-23 17:14:37 +010095#if !GTK_CHECK_VERSION(3,0,0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000096static GdkFilterReturn gtk_form_filter(GdkXEvent *gdk_xevent,
97 GdkEvent *event,
98 gpointer data);
99static GdkFilterReturn gtk_form_main_filter(GdkXEvent *gdk_xevent,
100 GdkEvent *event,
101 gpointer data);
Bram Moolenaar98921892016-02-23 17:14:37 +0100102#endif
103#if !GTK_CHECK_VERSION(3,16,0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000104static void gtk_form_set_static_gravity(GdkWindow *window,
105 gboolean use_static);
Bram Moolenaar98921892016-02-23 17:14:37 +0100106#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000107
108static void gtk_form_send_configure(GtkForm *form);
109
110static void gtk_form_child_map(GtkWidget *widget, gpointer user_data);
111static void gtk_form_child_unmap(GtkWidget *widget, gpointer user_data);
112
Bram Moolenaar98921892016-02-23 17:14:37 +0100113#if !GTK_CHECK_VERSION(3,0,0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000114static GtkWidgetClass *parent_class = NULL;
Bram Moolenaar98921892016-02-23 17:14:37 +0100115#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000116
117/* Public interface
118 */
119
120 GtkWidget *
121gtk_form_new(void)
122{
123 GtkForm *form;
124
Bram Moolenaar98921892016-02-23 17:14:37 +0100125#if GTK_CHECK_VERSION(3,0,0)
126 form = g_object_new(GTK_TYPE_FORM, NULL);
127#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000128 form = gtk_type_new(gtk_form_get_type());
Bram Moolenaar98921892016-02-23 17:14:37 +0100129#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000130
131 return GTK_WIDGET(form);
132}
133
134 void
135gtk_form_put(GtkForm *form,
136 GtkWidget *child_widget,
137 gint x,
138 gint y)
139{
140 GtkFormChild *child;
141
142 g_return_if_fail(GTK_IS_FORM(form));
143
Bram Moolenaar9d75c832005-01-25 21:57:23 +0000144 /* LINTED: avoid warning: conversion to 'unsigned long' */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000145 child = g_new(GtkFormChild, 1);
146
147 child->widget = child_widget;
148 child->window = NULL;
149 child->x = x;
150 child->y = y;
Bram Moolenaar98921892016-02-23 17:14:37 +0100151#if GTK_CHECK_VERSION(3,0,0)
152 gtk_widget_set_size_request(child->widget, -1, -1);
153#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000154 child->widget->requisition.width = 0;
155 child->widget->requisition.height = 0;
Bram Moolenaar98921892016-02-23 17:14:37 +0100156#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000157 child->mapped = FALSE;
158
159 form->children = g_list_append(form->children, child);
160
161 /* child->window must be created and attached to the widget _before_
162 * it has been realized, or else things will break with GTK2. Note
163 * that gtk_widget_set_parent() realizes the widget if it's visible
164 * and its parent is mapped.
165 */
Bram Moolenaar98921892016-02-23 17:14:37 +0100166#if GTK_CHECK_VERSION(3,0,0)
167 if (gtk_widget_get_realized(GTK_WIDGET(form)))
168#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000169 if (GTK_WIDGET_REALIZED(form))
Bram Moolenaar98921892016-02-23 17:14:37 +0100170#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000171 gtk_form_attach_child_window(form, child);
172
173 gtk_widget_set_parent(child_widget, GTK_WIDGET(form));
Bram Moolenaar98921892016-02-23 17:14:37 +0100174#if !GTK_CHECK_VERSION(3,0,0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000175 gtk_widget_size_request(child->widget, NULL);
Bram Moolenaar98921892016-02-23 17:14:37 +0100176#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000177
Bram Moolenaar98921892016-02-23 17:14:37 +0100178#if GTK_CHECK_VERSION(3,0,0)
179 if (gtk_widget_get_realized(GTK_WIDGET(form))
180 && !gtk_widget_get_realized(child_widget))
181#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000182 if (GTK_WIDGET_REALIZED(form) && !GTK_WIDGET_REALIZED(child_widget))
Bram Moolenaar98921892016-02-23 17:14:37 +0100183#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000184 gtk_form_realize_child(form, child);
185
186 gtk_form_position_child(form, child, TRUE);
187}
188
189 void
190gtk_form_move(GtkForm *form,
191 GtkWidget *child_widget,
192 gint x,
193 gint y)
194{
195 GList *tmp_list;
196 GtkFormChild *child;
197
198 g_return_if_fail(GTK_IS_FORM(form));
199
200 for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next)
201 {
202 child = tmp_list->data;
203 if (child->widget == child_widget)
204 {
205 child->x = x;
206 child->y = y;
207
208 gtk_form_position_child(form, child, TRUE);
209 return;
210 }
211 }
212}
213
Bram Moolenaar071d4272004-06-13 20:20:40 +0000214 void
215gtk_form_freeze(GtkForm *form)
216{
217 g_return_if_fail(GTK_IS_FORM(form));
218
219 ++form->freeze_count;
220}
221
222 void
223gtk_form_thaw(GtkForm *form)
224{
225 g_return_if_fail(GTK_IS_FORM(form));
226
227 if (form->freeze_count)
228 {
229 if (!(--form->freeze_count))
230 {
231 gtk_form_position_children(form);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000232 gtk_widget_queue_draw(GTK_WIDGET(form));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000233 }
234 }
235}
236
237/* Basic Object handling procedures
238 */
Bram Moolenaar98921892016-02-23 17:14:37 +0100239#if GTK_CHECK_VERSION(3,0,0)
240G_DEFINE_TYPE(GtkForm, gtk_form, GTK_TYPE_CONTAINER)
241#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000242 GtkType
243gtk_form_get_type(void)
244{
245 static GtkType form_type = 0;
246
247 if (!form_type)
248 {
Bram Moolenaarb85cb212009-05-17 14:24:23 +0000249 GtkTypeInfo form_info;
250
Bram Moolenaara9d45512009-05-17 21:25:42 +0000251 vim_memset(&form_info, 0, sizeof(form_info));
Bram Moolenaarb85cb212009-05-17 14:24:23 +0000252 form_info.type_name = "GtkForm";
253 form_info.object_size = sizeof(GtkForm);
254 form_info.class_size = sizeof(GtkFormClass);
255 form_info.class_init_func = (GtkClassInitFunc)gtk_form_class_init;
256 form_info.object_init_func = (GtkObjectInitFunc)gtk_form_init;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000257
258 form_type = gtk_type_unique(GTK_TYPE_CONTAINER, &form_info);
259 }
260 return form_type;
261}
Bram Moolenaar98921892016-02-23 17:14:37 +0100262#endif /* !GTK_CHECK_VERSION(3,0,0) */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000263
264 static void
265gtk_form_class_init(GtkFormClass *klass)
266{
267 GtkWidgetClass *widget_class;
268 GtkContainerClass *container_class;
269
270 widget_class = (GtkWidgetClass *) klass;
271 container_class = (GtkContainerClass *) klass;
272
Bram Moolenaar98921892016-02-23 17:14:37 +0100273#if !GTK_CHECK_VERSION(3,0,0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000274 parent_class = gtk_type_class(gtk_container_get_type());
Bram Moolenaar98921892016-02-23 17:14:37 +0100275#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000276
277 widget_class->realize = gtk_form_realize;
278 widget_class->unrealize = gtk_form_unrealize;
279 widget_class->map = gtk_form_map;
Bram Moolenaar98921892016-02-23 17:14:37 +0100280#if GTK_CHECK_VERSION(3,0,0)
281 widget_class->get_preferred_width = gtk_form_get_preferred_width;
282 widget_class->get_preferred_height = gtk_form_get_preferred_height;
283#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000284 widget_class->size_request = gtk_form_size_request;
Bram Moolenaar98921892016-02-23 17:14:37 +0100285#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000286 widget_class->size_allocate = gtk_form_size_allocate;
Bram Moolenaar98921892016-02-23 17:14:37 +0100287#if GTK_CHECK_VERSION(3,0,0)
288 widget_class->draw = gtk_form_draw;
289#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000290 widget_class->expose_event = gtk_form_expose;
Bram Moolenaar98921892016-02-23 17:14:37 +0100291#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000292
293 container_class->remove = gtk_form_remove;
294 container_class->forall = gtk_form_forall;
295}
296
297 static void
298gtk_form_init(GtkForm *form)
299{
Bram Moolenaar98921892016-02-23 17:14:37 +0100300#if GTK_CHECK_VERSION(3,0,0)
301 gtk_widget_set_has_window(GTK_WIDGET(form), TRUE);
302#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000303 form->children = NULL;
304
Bram Moolenaar98921892016-02-23 17:14:37 +0100305#if !GTK_CHECK_VERSION(3,0,0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000306 form->width = 1;
307 form->height = 1;
Bram Moolenaar98921892016-02-23 17:14:37 +0100308#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000309
310 form->bin_window = NULL;
311
Bram Moolenaar98921892016-02-23 17:14:37 +0100312#if !GTK_CHECK_VERSION(3,0,0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000313 form->configure_serial = 0;
314 form->visibility = GDK_VISIBILITY_PARTIAL;
Bram Moolenaar98921892016-02-23 17:14:37 +0100315#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000316
317 form->freeze_count = 0;
318}
319
320/*
321 * Widget methods
322 */
323
324 static void
325gtk_form_realize(GtkWidget *widget)
326{
327 GList *tmp_list;
328 GtkForm *form;
329 GdkWindowAttr attributes;
330 gint attributes_mask;
331
332 g_return_if_fail(GTK_IS_FORM(widget));
333
334 form = GTK_FORM(widget);
Bram Moolenaar98921892016-02-23 17:14:37 +0100335#if GTK_CHECK_VERSION(3,0,0)
336 gtk_widget_set_realized(widget, TRUE);
337#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000338 GTK_WIDGET_SET_FLAGS(form, GTK_REALIZED);
Bram Moolenaar98921892016-02-23 17:14:37 +0100339#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000340
341 attributes.window_type = GDK_WINDOW_CHILD;
Bram Moolenaar98921892016-02-23 17:14:37 +0100342#if GTK_CHECK_VERSION(3,0,0)
343 {
344 GtkAllocation allocation;
345 gtk_widget_get_allocation(widget, &allocation);
346 attributes.x = allocation.x;
347 attributes.y = allocation.y;
348 attributes.width = allocation.width;
349 attributes.height = allocation.height;
350 }
351#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000352 attributes.x = widget->allocation.x;
353 attributes.y = widget->allocation.y;
354 attributes.width = widget->allocation.width;
355 attributes.height = widget->allocation.height;
Bram Moolenaar98921892016-02-23 17:14:37 +0100356#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000357 attributes.wclass = GDK_INPUT_OUTPUT;
358 attributes.visual = gtk_widget_get_visual(widget);
Bram Moolenaar98921892016-02-23 17:14:37 +0100359#if GTK_CHECK_VERSION(3,0,0)
360 attributes.event_mask = GDK_EXPOSURE_MASK;
361#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000362 attributes.colormap = gtk_widget_get_colormap(widget);
363 attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
Bram Moolenaar98921892016-02-23 17:14:37 +0100364#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000365
Bram Moolenaar98921892016-02-23 17:14:37 +0100366#if GTK_CHECK_VERSION(3,0,0)
367 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
368#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000369 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
Bram Moolenaar98921892016-02-23 17:14:37 +0100370#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000371
Bram Moolenaar98921892016-02-23 17:14:37 +0100372#if GTK_CHECK_VERSION(3,0,0)
373 gtk_widget_set_window(widget,
374 gdk_window_new(gtk_widget_get_parent_window(widget),
375 &attributes, attributes_mask));
376 gdk_window_set_user_data(gtk_widget_get_window(widget), widget);
377#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000378 widget->window = gdk_window_new(gtk_widget_get_parent_window(widget),
379 &attributes, attributes_mask);
380 gdk_window_set_user_data(widget->window, widget);
Bram Moolenaar98921892016-02-23 17:14:37 +0100381#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000382
383 attributes.x = 0;
384 attributes.y = 0;
385 attributes.event_mask = gtk_widget_get_events(widget);
386
Bram Moolenaar98921892016-02-23 17:14:37 +0100387#if GTK_CHECK_VERSION(3,0,0)
388 form->bin_window = gdk_window_new(gtk_widget_get_window(widget),
389 &attributes, attributes_mask);
390#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000391 form->bin_window = gdk_window_new(widget->window,
392 &attributes, attributes_mask);
Bram Moolenaar98921892016-02-23 17:14:37 +0100393#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000394 gdk_window_set_user_data(form->bin_window, widget);
395
Bram Moolenaar98921892016-02-23 17:14:37 +0100396#if !GTK_CHECK_VERSION(3,16,0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000397 gtk_form_set_static_gravity(form->bin_window, TRUE);
Bram Moolenaar98921892016-02-23 17:14:37 +0100398#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000399
Bram Moolenaar98921892016-02-23 17:14:37 +0100400#if GTK_CHECK_VERSION(3,0,0)
401 {
402 GtkStyleContext * const sctx = gtk_widget_get_style_context(widget);
403
404 gtk_style_context_add_class(sctx, "gtk-form");
405 gtk_style_context_set_state(sctx, GTK_STATE_FLAG_NORMAL);
406# if !GTK_CHECK_VERSION(3,18,0)
407 gtk_style_context_set_background(sctx, gtk_widget_get_window(widget));
408 gtk_style_context_set_background(sctx, form->bin_window);
409# endif
410 }
411#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000412 widget->style = gtk_style_attach(widget->style, widget->window);
413 gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL);
414 gtk_style_set_background(widget->style, form->bin_window, GTK_STATE_NORMAL);
Bram Moolenaar98921892016-02-23 17:14:37 +0100415#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000416
Bram Moolenaar98921892016-02-23 17:14:37 +0100417#if !GTK_CHECK_VERSION(3,0,0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000418 gdk_window_add_filter(widget->window, gtk_form_main_filter, form);
419 gdk_window_add_filter(form->bin_window, gtk_form_filter, form);
Bram Moolenaar98921892016-02-23 17:14:37 +0100420#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000421
422 for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next)
423 {
424 GtkFormChild *child = tmp_list->data;
425
426 gtk_form_attach_child_window(form, child);
427
Bram Moolenaar98921892016-02-23 17:14:37 +0100428#if GTK_CHECK_VERSION(3,0,0)
429 if (gtk_widget_get_visible(child->widget))
430#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000431 if (GTK_WIDGET_VISIBLE(child->widget))
Bram Moolenaar98921892016-02-23 17:14:37 +0100432#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000433 gtk_form_realize_child(form, child);
434 }
435}
436
437
438/* After reading the documentation at
439 * http://developer.gnome.org/doc/API/2.0/gtk/gtk-changes-2-0.html
440 * I think it should be possible to remove this function when compiling
441 * against gtk-2.0. It doesn't seem to cause problems, though.
442 *
443 * Well, I reckon at least the gdk_window_show(form->bin_window)
444 * is necessary. GtkForm is anything but a usual container widget.
445 */
446 static void
447gtk_form_map(GtkWidget *widget)
448{
449 GList *tmp_list;
450 GtkForm *form;
451
452 g_return_if_fail(GTK_IS_FORM(widget));
453
454 form = GTK_FORM(widget);
455
Bram Moolenaar98921892016-02-23 17:14:37 +0100456#if GTK_CHECK_VERSION(3,0,0)
457 gtk_widget_set_mapped(widget, TRUE);
458#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000459 GTK_WIDGET_SET_FLAGS(widget, GTK_MAPPED);
Bram Moolenaar98921892016-02-23 17:14:37 +0100460#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000461
Bram Moolenaar98921892016-02-23 17:14:37 +0100462#if GTK_CHECK_VERSION(3,0,0)
463 gdk_window_show(gtk_widget_get_window(widget));
464#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000465 gdk_window_show(widget->window);
Bram Moolenaar98921892016-02-23 17:14:37 +0100466#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000467 gdk_window_show(form->bin_window);
468
469 for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next)
470 {
471 GtkFormChild *child = tmp_list->data;
472
Bram Moolenaar98921892016-02-23 17:14:37 +0100473#if GTK_CHECK_VERSION(3,0,0)
474 if (gtk_widget_get_visible(child->widget)
475 && !gtk_widget_get_mapped(child->widget))
476#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000477 if (GTK_WIDGET_VISIBLE(child->widget)
478 && !GTK_WIDGET_MAPPED(child->widget))
Bram Moolenaar98921892016-02-23 17:14:37 +0100479#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000480 gtk_widget_map(child->widget);
481 }
482}
483
484 static void
485gtk_form_unrealize(GtkWidget *widget)
486{
487 GList *tmp_list;
488 GtkForm *form;
489
490 g_return_if_fail(GTK_IS_FORM(widget));
491
492 form = GTK_FORM(widget);
493
494 tmp_list = form->children;
495
496 gdk_window_set_user_data(form->bin_window, NULL);
497 gdk_window_destroy(form->bin_window);
498 form->bin_window = NULL;
499
500 while (tmp_list)
501 {
502 GtkFormChild *child = tmp_list->data;
503
504 if (child->window != NULL)
505 {
Bram Moolenaar98921892016-02-23 17:14:37 +0100506#if GTK_CHECK_VERSION(3,0,0)
507 g_signal_handlers_disconnect_by_func(G_OBJECT(child->widget),
Bram Moolenaard47d8372016-09-09 22:13:24 +0200508 FUNC2GENERIC(gtk_form_child_map),
Bram Moolenaar98921892016-02-23 17:14:37 +0100509 child);
510 g_signal_handlers_disconnect_by_func(G_OBJECT(child->widget),
Bram Moolenaard47d8372016-09-09 22:13:24 +0200511 FUNC2GENERIC(gtk_form_child_unmap),
Bram Moolenaar98921892016-02-23 17:14:37 +0100512 child);
513#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000514 gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget),
Bram Moolenaard47d8372016-09-09 22:13:24 +0200515 GTK_SIGNAL_FUNC(gtk_form_child_map),
516 child);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000517 gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget),
Bram Moolenaard47d8372016-09-09 22:13:24 +0200518 GTK_SIGNAL_FUNC(gtk_form_child_unmap),
519 child);
Bram Moolenaar98921892016-02-23 17:14:37 +0100520#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000521
522 gdk_window_set_user_data(child->window, NULL);
523 gdk_window_destroy(child->window);
524
525 child->window = NULL;
526 }
527
528 tmp_list = tmp_list->next;
529 }
530
Bram Moolenaar98921892016-02-23 17:14:37 +0100531#if GTK_CHECK_VERSION(3,0,0)
532 if (GTK_WIDGET_CLASS (gtk_form_parent_class)->unrealize)
533 (* GTK_WIDGET_CLASS (gtk_form_parent_class)->unrealize) (widget);
534#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000535 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
536 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
Bram Moolenaar98921892016-02-23 17:14:37 +0100537#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000538}
539
Bram Moolenaar071d4272004-06-13 20:20:40 +0000540 static void
541gtk_form_size_request(GtkWidget *widget, GtkRequisition *requisition)
542{
Bram Moolenaar98921892016-02-23 17:14:37 +0100543#if !GTK_CHECK_VERSION(3,0,0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000544 GList *tmp_list;
545 GtkForm *form;
Bram Moolenaar98921892016-02-23 17:14:37 +0100546#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000547
548 g_return_if_fail(GTK_IS_FORM(widget));
549
Bram Moolenaar98921892016-02-23 17:14:37 +0100550#if !GTK_CHECK_VERSION(3,0,0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000551 form = GTK_FORM(widget);
Bram Moolenaar98921892016-02-23 17:14:37 +0100552#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000553
Bram Moolenaar98921892016-02-23 17:14:37 +0100554#if GTK_CHECK_VERSION(3,0,0)
555 requisition->width = 1;
556 requisition->height = 1;
557#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000558 requisition->width = form->width;
559 requisition->height = form->height;
560
561 tmp_list = form->children;
562
563 while (tmp_list)
564 {
565 GtkFormChild *child = tmp_list->data;
566 gtk_widget_size_request(child->widget, NULL);
567 tmp_list = tmp_list->next;
568 }
Bram Moolenaar98921892016-02-23 17:14:37 +0100569#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000570}
571
Bram Moolenaar98921892016-02-23 17:14:37 +0100572#if GTK_CHECK_VERSION(3,0,0)
573 static void
574gtk_form_get_preferred_width(GtkWidget *widget,
575 gint *minimal_width,
576 gint *natural_width)
577{
578 GtkRequisition requisition;
579
580 gtk_form_size_request(widget, &requisition);
581
582 *minimal_width = requisition.width;
583 *natural_width = requisition.width;
584}
585
586 static void
587gtk_form_get_preferred_height(GtkWidget *widget,
588 gint *minimal_height,
589 gint *natural_height)
590{
591 GtkRequisition requisition;
592
593 gtk_form_size_request(widget, &requisition);
594
595 *minimal_height = requisition.height;
596 *natural_height = requisition.height;
597}
598#endif /* GTK_CHECK_VERSION(3,0,0) */
599
Bram Moolenaar071d4272004-06-13 20:20:40 +0000600 static void
601gtk_form_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
602{
603 GList *tmp_list;
604 GtkForm *form;
605 gboolean need_reposition;
Bram Moolenaar98921892016-02-23 17:14:37 +0100606#if GTK_CHECK_VERSION(3,0,0)
607 GtkAllocation cur_alloc;
608#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000609
610 g_return_if_fail(GTK_IS_FORM(widget));
611
Bram Moolenaar98921892016-02-23 17:14:37 +0100612#if GTK_CHECK_VERSION(3,0,0)
613 gtk_widget_get_allocation(widget, &cur_alloc);
614
615 if (cur_alloc.x == allocation->x
616 && cur_alloc.y == allocation->y
617 && cur_alloc.width == allocation->width
618 && cur_alloc.height == allocation->height)
619#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000620 if (widget->allocation.x == allocation->x
621 && widget->allocation.y == allocation->y
622 && widget->allocation.width == allocation->width
623 && widget->allocation.height == allocation->height)
Bram Moolenaar98921892016-02-23 17:14:37 +0100624#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000625 return;
626
Bram Moolenaar98921892016-02-23 17:14:37 +0100627#if GTK_CHECK_VERSION(3,0,0)
628 need_reposition = cur_alloc.width != allocation->width
629 || cur_alloc.height != allocation->height;
630#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000631 need_reposition = widget->allocation.width != allocation->width
632 || widget->allocation.height != allocation->height;
Bram Moolenaar98921892016-02-23 17:14:37 +0100633#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000634 form = GTK_FORM(widget);
635
636 if (need_reposition)
637 {
638 tmp_list = form->children;
639
640 while (tmp_list)
641 {
642 GtkFormChild *child = tmp_list->data;
643 gtk_form_position_child(form, child, TRUE);
644
645 tmp_list = tmp_list->next;
646 }
647 }
648
Bram Moolenaar98921892016-02-23 17:14:37 +0100649#if GTK_CHECK_VERSION(3,0,0)
650 if (gtk_widget_get_realized(widget))
651#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000652 if (GTK_WIDGET_REALIZED(widget))
Bram Moolenaar98921892016-02-23 17:14:37 +0100653#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000654 {
Bram Moolenaar98921892016-02-23 17:14:37 +0100655#if GTK_CHECK_VERSION(3,0,0)
656 gdk_window_move_resize(gtk_widget_get_window(widget),
657 allocation->x, allocation->y,
658 allocation->width, allocation->height);
659#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000660 gdk_window_move_resize(widget->window,
661 allocation->x, allocation->y,
662 allocation->width, allocation->height);
Bram Moolenaar98921892016-02-23 17:14:37 +0100663#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000664 gdk_window_move_resize(GTK_FORM(widget)->bin_window,
665 0, 0,
666 allocation->width, allocation->height);
667 }
Bram Moolenaar98921892016-02-23 17:14:37 +0100668#if GTK_CHECK_VERSION(3,0,0)
669 gtk_widget_set_allocation(widget, allocation);
670#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000671 widget->allocation = *allocation;
Bram Moolenaar98921892016-02-23 17:14:37 +0100672#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000673 if (need_reposition)
674 gtk_form_send_configure(form);
675}
676
Bram Moolenaar98921892016-02-23 17:14:37 +0100677#if GTK_CHECK_VERSION(3,0,0)
678 static void
679gtk_form_render_background(GtkWidget *widget, cairo_t *cr)
680{
681 gtk_render_background(gtk_widget_get_style_context(widget), cr,
682 0, 0,
683 gtk_widget_get_allocated_width(widget),
684 gtk_widget_get_allocated_height(widget));
685}
686
687 static gboolean
688gtk_form_draw(GtkWidget *widget, cairo_t *cr)
689{
690 GList *tmp_list = NULL;
691 GtkForm *form = NULL;
692
693 g_return_val_if_fail(GTK_IS_FORM(widget), FALSE);
694
695 gtk_form_render_background(widget, cr);
696
697 form = GTK_FORM(widget);
698 for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next)
699 {
700 GtkFormChild * const formchild = tmp_list->data;
701
702 if (!gtk_widget_get_has_window(formchild->widget) &&
703 gtk_cairo_should_draw_window(cr, formchild->window))
704 {
705 /* To get gtk_widget_draw() to work, it is required to call
706 * gtk_widget_size_allocate() in advance with a well-posed
707 * allocation for a given child widget in order to set a
708 * certain private GtkWidget variable, called
709 * widget->priv->alloc_need, to the proper value; othewise,
710 * gtk_widget_draw() fails and the relevant scrollbar won't
711 * appear on the screen.
712 *
713 * Calling gtk_form_position_child() like this is one of ways
714 * to make sure of that. */
715 gtk_form_position_child(form, formchild, TRUE);
716
717 gtk_form_render_background(formchild->widget, cr);
718 }
719 }
720
721 return GTK_WIDGET_CLASS(gtk_form_parent_class)->draw(widget, cr);
722}
723#else /* !GTK_CHECK_VERSION(3,0,0) */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000724 static gint
725gtk_form_expose(GtkWidget *widget, GdkEventExpose *event)
726{
727 GList *tmp_list;
728 GtkForm *form;
729
730 g_return_val_if_fail(GTK_IS_FORM(widget), FALSE);
731
732 form = GTK_FORM(widget);
733
734 if (event->window == form->bin_window)
735 return FALSE;
736
737 for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next)
738 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000739 GtkFormChild *formchild = tmp_list->data;
740 GtkWidget *child = formchild->widget;
741 /*
742 * The following chunk of code is taken from gtkcontainer.c. The
743 * gtk1.x code synthesized expose events directly on the child widgets,
744 * which can't be done in gtk2
745 */
746 if (GTK_WIDGET_DRAWABLE(child) && GTK_WIDGET_NO_WINDOW(child)
747 && child->window == event->window)
748 {
749 GdkEventExpose child_event;
750 child_event = *event;
751
752 child_event.region = gtk_widget_region_intersect(child, event->region);
753 if (!gdk_region_empty(child_event.region))
754 {
755 gdk_region_get_clipbox(child_event.region, &child_event.area);
756 gtk_widget_send_expose(child, (GdkEvent *)&child_event);
757 }
758 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000759 }
760
761 return FALSE;
762}
Bram Moolenaar98921892016-02-23 17:14:37 +0100763#endif /* !GTK_CHECK_VERSION(3,0,0) */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000764
765/* Container method
766 */
767 static void
768gtk_form_remove(GtkContainer *container, GtkWidget *widget)
769{
770 GList *tmp_list;
771 GtkForm *form;
772 GtkFormChild *child = NULL; /* init for gcc */
773
774 g_return_if_fail(GTK_IS_FORM(container));
775
776 form = GTK_FORM(container);
777
778 tmp_list = form->children;
779 while (tmp_list)
780 {
781 child = tmp_list->data;
782 if (child->widget == widget)
783 break;
784 tmp_list = tmp_list->next;
785 }
786
787 if (tmp_list)
788 {
Bram Moolenaar98921892016-02-23 17:14:37 +0100789#if GTK_CHECK_VERSION(3,0,0)
790 const gboolean was_visible = gtk_widget_get_visible(widget);
791#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000792 if (child->window)
793 {
Bram Moolenaar98921892016-02-23 17:14:37 +0100794#if GTK_CHECK_VERSION(3,0,0)
795 g_signal_handlers_disconnect_by_func(G_OBJECT(child->widget),
Bram Moolenaard47d8372016-09-09 22:13:24 +0200796 FUNC2GENERIC(&gtk_form_child_map), child);
Bram Moolenaar98921892016-02-23 17:14:37 +0100797 g_signal_handlers_disconnect_by_func(G_OBJECT(child->widget),
Bram Moolenaard47d8372016-09-09 22:13:24 +0200798 FUNC2GENERIC(&gtk_form_child_unmap), child);
Bram Moolenaar98921892016-02-23 17:14:37 +0100799#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000800 gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget),
Bram Moolenaard47d8372016-09-09 22:13:24 +0200801 GTK_SIGNAL_FUNC(&gtk_form_child_map), child);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000802 gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget),
Bram Moolenaard47d8372016-09-09 22:13:24 +0200803 GTK_SIGNAL_FUNC(&gtk_form_child_unmap), child);
Bram Moolenaar98921892016-02-23 17:14:37 +0100804#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000805
806 /* FIXME: This will cause problems for reparenting NO_WINDOW
807 * widgets out of a GtkForm
808 */
809 gdk_window_set_user_data(child->window, NULL);
810 gdk_window_destroy(child->window);
811 }
812 gtk_widget_unparent(widget);
Bram Moolenaar98921892016-02-23 17:14:37 +0100813#if GTK_CHECK_VERSION(3,0,0)
814 if (was_visible)
815 gtk_widget_queue_resize(GTK_WIDGET(container));
816#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000817 form->children = g_list_remove_link(form->children, tmp_list);
818 g_list_free_1(tmp_list);
819 g_free(child);
820 }
821}
822
Bram Moolenaar071d4272004-06-13 20:20:40 +0000823 static void
824gtk_form_forall(GtkContainer *container,
Bram Moolenaarb85cb212009-05-17 14:24:23 +0000825 gboolean include_internals UNUSED,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000826 GtkCallback callback,
827 gpointer callback_data)
828{
829 GtkForm *form;
830 GtkFormChild *child;
831 GList *tmp_list;
832
833 g_return_if_fail(GTK_IS_FORM(container));
834 g_return_if_fail(callback != NULL);
835
836 form = GTK_FORM(container);
837
838 tmp_list = form->children;
839 while (tmp_list)
840 {
841 child = tmp_list->data;
842 tmp_list = tmp_list->next;
843
844 (*callback) (child->widget, callback_data);
845 }
846}
847
848/* Operations on children
849 */
850
851 static void
852gtk_form_attach_child_window(GtkForm *form, GtkFormChild *child)
853{
854 if (child->window != NULL)
855 return; /* been there, done that */
856
Bram Moolenaar98921892016-02-23 17:14:37 +0100857#if GTK_CHECK_VERSION(3,0,0)
858 if (!gtk_widget_get_has_window(child->widget))
859#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000860 if (GTK_WIDGET_NO_WINDOW(child->widget))
Bram Moolenaar98921892016-02-23 17:14:37 +0100861#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000862 {
863 GtkWidget *widget;
864 GdkWindowAttr attributes;
865 gint attributes_mask;
866
867 widget = GTK_WIDGET(form);
868
869 attributes.window_type = GDK_WINDOW_CHILD;
870 attributes.x = child->x;
871 attributes.y = child->y;
Bram Moolenaar98921892016-02-23 17:14:37 +0100872#if GTK_CHECK_VERSION(3,0,0)
873 {
874 GtkRequisition requisition;
875
876 gtk_widget_get_preferred_size(child->widget, &requisition, NULL);
877
878 attributes.width = requisition.width;
879 attributes.height = requisition.height;
880 }
881#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000882 attributes.width = child->widget->requisition.width;
883 attributes.height = child->widget->requisition.height;
Bram Moolenaar98921892016-02-23 17:14:37 +0100884#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000885 attributes.wclass = GDK_INPUT_OUTPUT;
886 attributes.visual = gtk_widget_get_visual(widget);
Bram Moolenaar98921892016-02-23 17:14:37 +0100887#if !GTK_CHECK_VERSION(3,0,0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000888 attributes.colormap = gtk_widget_get_colormap(widget);
Bram Moolenaar98921892016-02-23 17:14:37 +0100889#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000890 attributes.event_mask = GDK_EXPOSURE_MASK;
891
Bram Moolenaar98921892016-02-23 17:14:37 +0100892#if GTK_CHECK_VERSION(3,0,0)
893 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
894#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000895 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
Bram Moolenaar98921892016-02-23 17:14:37 +0100896#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000897 child->window = gdk_window_new(form->bin_window,
898 &attributes, attributes_mask);
899 gdk_window_set_user_data(child->window, widget);
900
Bram Moolenaar98921892016-02-23 17:14:37 +0100901#if GTK_CHECK_VERSION(3,0,0)
902 {
903 GtkStyleContext * const sctx = gtk_widget_get_style_context(widget);
904
905 gtk_style_context_set_state(sctx, GTK_STATE_FLAG_NORMAL);
906# if !GTK_CHECK_VERSION(3,18,0)
907 gtk_style_context_set_background(sctx, child->window);
908# endif
909 }
910#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000911 gtk_style_set_background(widget->style,
912 child->window,
913 GTK_STATE_NORMAL);
Bram Moolenaar98921892016-02-23 17:14:37 +0100914#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000915
916 gtk_widget_set_parent_window(child->widget, child->window);
Bram Moolenaar98921892016-02-23 17:14:37 +0100917#if !GTK_CHECK_VERSION(3,16,0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000918 gtk_form_set_static_gravity(child->window, TRUE);
Bram Moolenaar98921892016-02-23 17:14:37 +0100919#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000920 /*
921 * Install signal handlers to map/unmap child->window
922 * alongside with the actual widget.
923 */
Bram Moolenaar98921892016-02-23 17:14:37 +0100924#if GTK_CHECK_VERSION(3,0,0)
925 g_signal_connect(G_OBJECT(child->widget), "map",
926 G_CALLBACK(&gtk_form_child_map), child);
927 g_signal_connect(G_OBJECT(child->widget), "unmap",
928 G_CALLBACK(&gtk_form_child_unmap), child);
929#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000930 gtk_signal_connect(GTK_OBJECT(child->widget), "map",
931 GTK_SIGNAL_FUNC(&gtk_form_child_map), child);
932 gtk_signal_connect(GTK_OBJECT(child->widget), "unmap",
933 GTK_SIGNAL_FUNC(&gtk_form_child_unmap), child);
Bram Moolenaar98921892016-02-23 17:14:37 +0100934#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000935 }
Bram Moolenaar98921892016-02-23 17:14:37 +0100936#if GTK_CHECK_VERSION(3,0,0)
937 else if (!gtk_widget_get_realized(child->widget))
938#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000939 else if (!GTK_WIDGET_REALIZED(child->widget))
Bram Moolenaar98921892016-02-23 17:14:37 +0100940#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000941 {
942 gtk_widget_set_parent_window(child->widget, form->bin_window);
943 }
944}
945
946 static void
947gtk_form_realize_child(GtkForm *form, GtkFormChild *child)
948{
949 gtk_form_attach_child_window(form, child);
950 gtk_widget_realize(child->widget);
951
Bram Moolenaar98921892016-02-23 17:14:37 +0100952#if !GTK_CHECK_VERSION(3,16,0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000953 if (child->window == NULL) /* might be already set, see above */
Bram Moolenaar98921892016-02-23 17:14:37 +0100954# if GTK_CHECK_VERSION(3,0,0)
955 gtk_form_set_static_gravity(gtk_widget_get_window(child->widget), TRUE);
956# else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000957 gtk_form_set_static_gravity(child->widget->window, TRUE);
Bram Moolenaar98921892016-02-23 17:14:37 +0100958# endif
959#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000960}
961
962 static void
963gtk_form_position_child(GtkForm *form, GtkFormChild *child,
964 gboolean force_allocate)
965{
966 gint x;
967 gint y;
968
969 x = child->x;
970 y = child->y;
971
972 if ((x >= G_MINSHORT) && (x <= G_MAXSHORT) &&
973 (y >= G_MINSHORT) && (y <= G_MAXSHORT))
974 {
975 if (!child->mapped)
976 {
Bram Moolenaar98921892016-02-23 17:14:37 +0100977#if GTK_CHECK_VERSION(3,0,0)
978 if (gtk_widget_get_mapped(GTK_WIDGET(form))
979 && gtk_widget_get_visible(child->widget))
980#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000981 if (GTK_WIDGET_MAPPED(form) && GTK_WIDGET_VISIBLE(child->widget))
Bram Moolenaar98921892016-02-23 17:14:37 +0100982#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000983 {
Bram Moolenaar98921892016-02-23 17:14:37 +0100984#if GTK_CHECK_VERSION(3,0,0)
985 if (!gtk_widget_get_mapped(child->widget))
986#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000987 if (!GTK_WIDGET_MAPPED(child->widget))
Bram Moolenaar98921892016-02-23 17:14:37 +0100988#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000989 gtk_widget_map(child->widget);
990
991 child->mapped = TRUE;
992 force_allocate = TRUE;
993 }
994 }
995
996 if (force_allocate)
997 {
998 GtkAllocation allocation;
Bram Moolenaar98921892016-02-23 17:14:37 +0100999#if GTK_CHECK_VERSION(3,0,0)
1000 GtkRequisition requisition;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001001
Bram Moolenaar98921892016-02-23 17:14:37 +01001002 gtk_widget_get_preferred_size(child->widget, &requisition, NULL);
1003#endif
1004
1005#if GTK_CHECK_VERSION(3,0,0)
1006 if (!gtk_widget_get_has_window(child->widget))
1007#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001008 if (GTK_WIDGET_NO_WINDOW(child->widget))
Bram Moolenaar98921892016-02-23 17:14:37 +01001009#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001010 {
1011 if (child->window)
1012 {
Bram Moolenaar98921892016-02-23 17:14:37 +01001013#if GTK_CHECK_VERSION(3,0,0)
1014 gdk_window_move_resize(child->window,
1015 x, y,
1016 requisition.width,
1017 requisition.height);
1018#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001019 gdk_window_move_resize(child->window,
1020 x, y,
1021 child->widget->requisition.width,
1022 child->widget->requisition.height);
Bram Moolenaar98921892016-02-23 17:14:37 +01001023#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001024 }
1025
1026 allocation.x = 0;
1027 allocation.y = 0;
1028 }
1029 else
1030 {
1031 allocation.x = x;
1032 allocation.y = y;
1033 }
1034
Bram Moolenaar98921892016-02-23 17:14:37 +01001035#if GTK_CHECK_VERSION(3,0,0)
1036 allocation.width = requisition.width;
1037 allocation.height = requisition.height;
1038#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001039 allocation.width = child->widget->requisition.width;
1040 allocation.height = child->widget->requisition.height;
Bram Moolenaar98921892016-02-23 17:14:37 +01001041#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001042
1043 gtk_widget_size_allocate(child->widget, &allocation);
1044 }
1045 }
1046 else
1047 {
1048 if (child->mapped)
1049 {
1050 child->mapped = FALSE;
1051
Bram Moolenaar98921892016-02-23 17:14:37 +01001052#if GTK_CHECK_VERSION(3,0,0)
1053 if (gtk_widget_get_mapped(child->widget))
1054#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001055 if (GTK_WIDGET_MAPPED(child->widget))
Bram Moolenaar98921892016-02-23 17:14:37 +01001056#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001057 gtk_widget_unmap(child->widget);
1058 }
1059 }
1060}
1061
1062 static void
1063gtk_form_position_children(GtkForm *form)
1064{
1065 GList *tmp_list;
1066
1067 for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next)
1068 gtk_form_position_child(form, tmp_list->data, FALSE);
1069}
1070
1071/* Callbacks */
1072
1073/* The main event filter. Actually, we probably don't really need
1074 * to install this as a filter at all, since we are calling it
1075 * directly above in the expose-handling hack.
1076 *
1077 * This routine identifies expose events that are generated when
1078 * we've temporarily moved the bin_window_origin, and translates
1079 * them or discards them, depending on whether we are obscured
1080 * or not.
1081 */
Bram Moolenaar98921892016-02-23 17:14:37 +01001082#if !GTK_CHECK_VERSION(3,0,0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001083 static GdkFilterReturn
Bram Moolenaarb85cb212009-05-17 14:24:23 +00001084gtk_form_filter(GdkXEvent *gdk_xevent, GdkEvent *event UNUSED, gpointer data)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001085{
1086 XEvent *xevent;
1087 GtkForm *form;
1088
1089 xevent = (XEvent *) gdk_xevent;
1090 form = GTK_FORM(data);
1091
1092 switch (xevent->type)
1093 {
1094 case Expose:
1095 if (xevent->xexpose.serial == form->configure_serial)
1096 {
1097 if (form->visibility == GDK_VISIBILITY_UNOBSCURED)
1098 return GDK_FILTER_REMOVE;
1099 else
1100 break;
1101 }
1102 break;
1103
1104 case ConfigureNotify:
1105 if ((xevent->xconfigure.x != 0) || (xevent->xconfigure.y != 0))
1106 form->configure_serial = xevent->xconfigure.serial;
1107 break;
1108 }
1109
1110 return GDK_FILTER_CONTINUE;
1111}
1112
1113/* Although GDK does have a GDK_VISIBILITY_NOTIFY event,
1114 * there is no corresponding event in GTK, so we have
1115 * to get the events from a filter
1116 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001117 static GdkFilterReturn
Bram Moolenaarb85cb212009-05-17 14:24:23 +00001118gtk_form_main_filter(GdkXEvent *gdk_xevent,
1119 GdkEvent *event UNUSED,
1120 gpointer data)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001121{
1122 XEvent *xevent;
1123 GtkForm *form;
1124
1125 xevent = (XEvent *) gdk_xevent;
1126 form = GTK_FORM(data);
1127
1128 if (xevent->type == VisibilityNotify)
1129 {
1130 switch (xevent->xvisibility.state)
1131 {
1132 case VisibilityFullyObscured:
1133 form->visibility = GDK_VISIBILITY_FULLY_OBSCURED;
1134 break;
1135
1136 case VisibilityPartiallyObscured:
1137 form->visibility = GDK_VISIBILITY_PARTIAL;
1138 break;
1139
1140 case VisibilityUnobscured:
1141 form->visibility = GDK_VISIBILITY_UNOBSCURED;
1142 break;
1143 }
1144
1145 return GDK_FILTER_REMOVE;
1146 }
1147 return GDK_FILTER_CONTINUE;
1148}
Bram Moolenaar98921892016-02-23 17:14:37 +01001149#endif /* !GTK_CHECK_VERSION(3,0,0) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001150
Bram Moolenaar98921892016-02-23 17:14:37 +01001151#if !GTK_CHECK_VERSION(3,16,0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001152 static void
1153gtk_form_set_static_gravity(GdkWindow *window, gboolean use_static)
1154{
Bram Moolenaar5e69de42009-09-11 14:17:54 +00001155 /* We don't check if static gravity is actually supported, because it
1156 * results in an annoying assertion error message. */
1157 gdk_window_set_static_gravities(window, use_static);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001158}
Bram Moolenaar98921892016-02-23 17:14:37 +01001159#endif /* !GTK_CHECK_VERSION(3,16,0) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001160
1161 void
1162gtk_form_move_resize(GtkForm *form, GtkWidget *widget,
1163 gint x, gint y, gint w, gint h)
1164{
Bram Moolenaar98921892016-02-23 17:14:37 +01001165#if GTK_CHECK_VERSION(3,0,0)
1166 gtk_widget_set_size_request(widget, w, h);
1167#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001168 widget->requisition.width = w;
1169 widget->requisition.height = h;
Bram Moolenaar98921892016-02-23 17:14:37 +01001170#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001171
1172 gtk_form_move(form, widget, x, y);
1173}
1174
1175 static void
1176gtk_form_send_configure(GtkForm *form)
1177{
1178 GtkWidget *widget;
1179 GdkEventConfigure event;
1180
1181 widget = GTK_WIDGET(form);
1182
1183 event.type = GDK_CONFIGURE;
Bram Moolenaar98921892016-02-23 17:14:37 +01001184#if GTK_CHECK_VERSION(3,0,0)
1185 event.window = gtk_widget_get_window(widget);
1186 {
1187 GtkAllocation allocation;
1188
1189 gtk_widget_get_allocation(widget, &allocation);
1190 event.x = allocation.x;
1191 event.y = allocation.y;
1192 event.width = allocation.width;
1193 event.height = allocation.height;
1194 }
1195#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001196 event.window = widget->window;
1197 event.x = widget->allocation.x;
1198 event.y = widget->allocation.y;
1199 event.width = widget->allocation.width;
1200 event.height = widget->allocation.height;
Bram Moolenaar98921892016-02-23 17:14:37 +01001201#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001202
Bram Moolenaar071d4272004-06-13 20:20:40 +00001203 gtk_main_do_event((GdkEvent*)&event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001204}
1205
Bram Moolenaar071d4272004-06-13 20:20:40 +00001206 static void
Bram Moolenaarb85cb212009-05-17 14:24:23 +00001207gtk_form_child_map(GtkWidget *widget UNUSED, gpointer user_data)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001208{
1209 GtkFormChild *child;
1210
1211 child = (GtkFormChild *)user_data;
1212
1213 child->mapped = TRUE;
1214 gdk_window_show(child->window);
1215}
1216
Bram Moolenaar071d4272004-06-13 20:20:40 +00001217 static void
Bram Moolenaarb85cb212009-05-17 14:24:23 +00001218gtk_form_child_unmap(GtkWidget *widget UNUSED, gpointer user_data)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001219{
1220 GtkFormChild *child;
1221
1222 child = (GtkFormChild *)user_data;
1223
1224 child->mapped = FALSE;
1225 gdk_window_hide(child->window);
1226}