]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/win_gtk.c
no more _ftime instead of ftime
[wxWidgets.git] / src / gtk1 / win_gtk.c
CommitLineData
c67daf87 1/* ///////////////////////////////////////////////////////////////////////////
c67d8618 2// Name: win_gtk.c
ed673c6a
RR
3// Purpose: Native GTK+ widget for wxWindows, based on GtkLayout and
4// GtkFixed. It makes use of the gravity window property and
5// therefore does not work with GTK 1.0.
c801d85f 6// Author: Robert Roebling
c67d8618 7// Id: $Id$
01111366 8// Copyright: (c) 1998 Robert Roebling
bf3dab48 9// Licence: wxWindows licence
c67daf87 10/////////////////////////////////////////////////////////////////////////// */
c801d85f
KB
11
12#include "wx/gtk/win_gtk.h"
034be888 13#include "gtk/gtksignal.h"
ed673c6a
RR
14#include "gtk/gtkprivate.h"
15#include "gdk/gdkx.h"
38c7b3d3 16
c801d85f
KB
17#ifdef __cplusplus
18extern "C" {
19#endif /* __cplusplus */
20
c916e13b
RR
21#include <X11/Xlib.h>
22#include <X11/Xutil.h>
23#include <X11/Xatom.h>
24
ed673c6a
RR
25#define IS_ONSCREEN(x,y) ((x >= G_MINSHORT) && (x <= G_MAXSHORT) && \
26 (y >= G_MINSHORT) && (y <= G_MAXSHORT))
27
da048e3d
RR
28typedef struct _GtkPizzaAdjData GtkPizzaAdjData;
29typedef struct _GtkPizzaChild GtkPizzaChild;
ed673c6a 30
bf3dab48 31struct _GtkPizzaAdjData
ed673c6a
RR
32{
33 gint dx;
34 gint dy;
35};
36
da048e3d 37struct _GtkPizzaChild
ed673c6a
RR
38{
39 GtkWidget *widget;
40 gint x;
41 gint y;
42 gint width;
43 gint height;
44};
45
da048e3d
RR
46static void gtk_pizza_class_init (GtkPizzaClass *klass);
47static void gtk_pizza_init (GtkPizza *pizza);
ed673c6a 48
da048e3d
RR
49static void gtk_pizza_realize (GtkWidget *widget);
50static void gtk_pizza_unrealize (GtkWidget *widget);
ed673c6a 51
da048e3d 52static void gtk_pizza_map (GtkWidget *widget);
ed673c6a 53
da048e3d 54static void gtk_pizza_size_request (GtkWidget *widget,
bf3dab48 55 GtkRequisition *requisition);
da048e3d 56static void gtk_pizza_size_allocate (GtkWidget *widget,
bf3dab48 57 GtkAllocation *allocation);
da048e3d 58static void gtk_pizza_draw (GtkWidget *widget,
bf3dab48 59 GdkRectangle *area);
da048e3d 60static gint gtk_pizza_expose (GtkWidget *widget,
bf3dab48 61 GdkEventExpose *event);
da048e3d 62static void gtk_pizza_add (GtkContainer *container,
bf3dab48 63 GtkWidget *widget);
da048e3d 64static void gtk_pizza_remove (GtkContainer *container,
bf3dab48 65 GtkWidget *widget);
da048e3d 66static void gtk_pizza_forall (GtkContainer *container,
bf3dab48
VZ
67 gboolean include_internals,
68 GtkCallback callback,
69 gpointer callback_data);
ed673c6a 70
da048e3d 71static void gtk_pizza_position_child (GtkPizza *pizza,
bf3dab48 72 GtkPizzaChild *child);
da048e3d 73static void gtk_pizza_allocate_child (GtkPizza *pizza,
bf3dab48 74 GtkPizzaChild *child);
da048e3d 75static void gtk_pizza_position_children (GtkPizza *pizza);
ed673c6a 76
da048e3d 77static void gtk_pizza_adjust_allocations_recurse (GtkWidget *widget,
bf3dab48 78 gpointer cb_data);
da048e3d 79static void gtk_pizza_adjust_allocations (GtkPizza *pizza,
bf3dab48
VZ
80 gint dx,
81 gint dy);
ed673c6a
RR
82
83
da048e3d 84static void gtk_pizza_expose_area (GtkPizza *pizza,
bf3dab48
VZ
85 gint x,
86 gint y,
87 gint width,
88 gint height);
da048e3d 89static void gtk_pizza_adjustment_changed (GtkAdjustment *adjustment,
bf3dab48 90 GtkPizza *pizza);
da048e3d 91static GdkFilterReturn gtk_pizza_filter (GdkXEvent *gdk_xevent,
bf3dab48
VZ
92 GdkEvent *event,
93 gpointer data);
da048e3d 94static GdkFilterReturn gtk_pizza_main_filter (GdkXEvent *gdk_xevent,
bf3dab48
VZ
95 GdkEvent *event,
96 gpointer data);
ed673c6a
RR
97
98
da048e3d 99static GtkType gtk_pizza_child_type (GtkContainer *container);
c801d85f 100
da048e3d 101static void gtk_pizza_scroll_set_adjustments (GtkPizza *pizza,
bf3dab48
VZ
102 GtkAdjustment *hadj,
103 GtkAdjustment *vadj);
c801d85f
KB
104
105
034be888 106static GtkContainerClass *parent_class = NULL;
ed673c6a 107static gboolean gravity_works;
034be888 108
c801d85f 109guint
da048e3d 110gtk_pizza_get_type ()
c801d85f 111{
da048e3d 112 static guint pizza_type = 0;
c801d85f 113
da048e3d 114 if (!pizza_type)
c801d85f 115 {
da048e3d 116 GtkTypeInfo pizza_info =
053f9cc1 117 {
bf3dab48
VZ
118 "GtkPizza",
119 sizeof (GtkPizza),
120 sizeof (GtkPizzaClass),
121 (GtkClassInitFunc) gtk_pizza_class_init,
122 (GtkObjectInitFunc) gtk_pizza_init,
123 /* reserved_1 */ NULL,
053f9cc1
RR
124 /* reserved_2 */ NULL,
125 (GtkClassInitFunc) NULL,
053f9cc1 126 };
da048e3d 127 pizza_type = gtk_type_unique (gtk_container_get_type (), &pizza_info);
c801d85f 128 }
bf3dab48 129
da048e3d 130 return pizza_type;
c801d85f
KB
131}
132
133static void
da048e3d 134gtk_pizza_class_init (GtkPizzaClass *klass)
c801d85f 135{
053f9cc1
RR
136 GtkObjectClass *object_class;
137 GtkWidgetClass *widget_class;
138 GtkContainerClass *container_class;
c801d85f 139
053f9cc1
RR
140 object_class = (GtkObjectClass*) klass;
141 widget_class = (GtkWidgetClass*) klass;
142 container_class = (GtkContainerClass*) klass;
053f9cc1 143 parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
c801d85f 144
da048e3d
RR
145 widget_class->map = gtk_pizza_map;
146 widget_class->realize = gtk_pizza_realize;
147 widget_class->unrealize = gtk_pizza_unrealize;
148 widget_class->size_request = gtk_pizza_size_request;
149 widget_class->size_allocate = gtk_pizza_size_allocate;
150 widget_class->draw = gtk_pizza_draw;
151 widget_class->expose_event = gtk_pizza_expose;
053f9cc1 152
da048e3d
RR
153 container_class->add = gtk_pizza_add;
154 container_class->remove = gtk_pizza_remove;
155 container_class->forall = gtk_pizza_forall;
38c7b3d3 156
da048e3d 157 container_class->child_type = gtk_pizza_child_type;
034be888 158
da048e3d 159 klass->set_scroll_adjustments = gtk_pizza_scroll_set_adjustments;
034be888 160
053f9cc1 161 widget_class->set_scroll_adjustments_signal =
034be888 162 gtk_signal_new ("set_scroll_adjustments",
bf3dab48
VZ
163 GTK_RUN_LAST,
164 object_class->type,
165 GTK_SIGNAL_OFFSET (GtkPizzaClass, set_scroll_adjustments),
166 gtk_marshal_NONE__POINTER_POINTER,
167 GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
38c7b3d3
RR
168}
169
38c7b3d3 170static GtkType
da048e3d 171gtk_pizza_child_type (GtkContainer *container)
38c7b3d3 172{
053f9cc1 173 return GTK_TYPE_WIDGET;
c801d85f
KB
174}
175
176static void
da048e3d 177gtk_pizza_init (GtkPizza *pizza)
c801d85f 178{
da048e3d 179 GTK_WIDGET_UNSET_FLAGS (pizza, GTK_NO_WINDOW);
bf3dab48 180
da048e3d 181 pizza->shadow_type = GTK_MYSHADOW_NONE;
034be888 182
da048e3d 183 pizza->children = NULL;
bf3dab48 184
da048e3d
RR
185 pizza->width = 20;
186 pizza->height = 20;
ed673c6a 187
da048e3d 188 pizza->bin_window = NULL;
8e217128
RR
189
190 pizza->xoffset = 0;
191 pizza->yoffset = 0;
ed673c6a 192
da048e3d
RR
193 pizza->configure_serial = 0;
194 pizza->scroll_x = 0;
195 pizza->scroll_y = 0;
196 pizza->visibility = GDK_VISIBILITY_PARTIAL;
bf3dab48 197
da048e3d 198 pizza->clear_on_draw = TRUE;
0e09f76e 199 pizza->use_filter = FALSE;
c801d85f
KB
200}
201
202GtkWidget*
da048e3d 203gtk_pizza_new ()
c801d85f 204{
da048e3d 205 GtkPizza *pizza;
c801d85f 206
da048e3d 207 pizza = gtk_type_new (gtk_pizza_get_type ());
bf3dab48 208
da048e3d 209 return GTK_WIDGET (pizza);
c801d85f
KB
210}
211
bf3dab48 212static void
da048e3d 213gtk_pizza_scroll_set_adjustments (GtkPizza *pizza,
bf3dab48
VZ
214 GtkAdjustment *hadj,
215 GtkAdjustment *vadj)
034be888 216{
ed673c6a 217 /* We handle scrolling in the wxScrolledWindow, not here. */
034be888
RR
218}
219
bf3dab48 220void
da048e3d 221gtk_pizza_set_shadow_type (GtkPizza *pizza,
0e09f76e 222 GtkMyShadowType type)
034be888 223{
da048e3d
RR
224 g_return_if_fail (pizza != NULL);
225 g_return_if_fail (GTK_IS_PIZZA (pizza));
034be888 226
da048e3d 227 if ((GtkMyShadowType) pizza->shadow_type != type)
034be888 228 {
da048e3d 229 pizza->shadow_type = type;
034be888 230
da048e3d 231 if (GTK_WIDGET_VISIBLE (pizza))
bf3dab48
VZ
232 {
233 gtk_widget_size_allocate (GTK_WIDGET (pizza), &(GTK_WIDGET (pizza)->allocation));
234 gtk_widget_queue_draw (GTK_WIDGET (pizza));
235 }
034be888
RR
236 }
237}
034be888 238
bf3dab48 239void
da048e3d 240gtk_pizza_set_clear (GtkPizza *pizza,
0e09f76e 241 gboolean clear)
147bc491 242{
da048e3d
RR
243 g_return_if_fail (pizza != NULL);
244 g_return_if_fail (GTK_IS_PIZZA (pizza));
bf3dab48 245
da048e3d 246 pizza->clear_on_draw = clear;
bf3dab48
VZ
247}
248
0e09f76e
RR
249void
250gtk_pizza_set_filter (GtkPizza *pizza,
251 gboolean use)
252{
253 g_return_if_fail (pizza != NULL);
254 g_return_if_fail (GTK_IS_PIZZA (pizza));
255
256 pizza->use_filter = use;
257}
258
c801d85f 259void
da048e3d 260gtk_pizza_put (GtkPizza *pizza,
053f9cc1 261 GtkWidget *widget,
ed673c6a
RR
262 gint x,
263 gint y,
bf3dab48
VZ
264 gint width,
265 gint height)
c801d85f 266{
da048e3d 267 GtkPizzaChild *child_info;
053f9cc1 268
da048e3d
RR
269 g_return_if_fail (pizza != NULL);
270 g_return_if_fail (GTK_IS_PIZZA (pizza));
053f9cc1
RR
271 g_return_if_fail (widget != NULL);
272
da048e3d 273 child_info = g_new (GtkPizzaChild, 1);
bf3dab48 274
053f9cc1
RR
275 child_info->widget = widget;
276 child_info->x = x;
277 child_info->y = y;
278 child_info->width = width;
279 child_info->height = height;
bf3dab48
VZ
280
281 pizza->children = g_list_append (pizza->children, child_info);
ed673c6a 282
da048e3d 283 gtk_widget_set_parent (widget, GTK_WIDGET (pizza));
c801d85f 284
da048e3d
RR
285 if (GTK_WIDGET_REALIZED (pizza))
286 gtk_widget_set_parent_window (widget, pizza->bin_window);
bf3dab48 287
ed673c6a
RR
288 if (!IS_ONSCREEN (x, y))
289 GTK_PRIVATE_SET_FLAG (widget, GTK_IS_OFFSCREEN);
c801d85f 290
0e09f76e 291/*
da048e3d 292 if (GTK_WIDGET_REALIZED (pizza))
053f9cc1 293 gtk_widget_realize (widget);
0e09f76e 294*/
c801d85f 295
ed673c6a 296 gtk_widget_set_usize (widget, width, height);
bf3dab48 297
0e09f76e 298/*
da048e3d 299 if (GTK_WIDGET_VISIBLE (pizza) && GTK_WIDGET_VISIBLE (widget))
326f9654 300 {
da048e3d 301 if (GTK_WIDGET_MAPPED (pizza))
bf3dab48
VZ
302 gtk_widget_map (widget);
303
ed673c6a 304 gtk_widget_queue_resize (widget);
326f9654 305 }
0e09f76e 306*/
c801d85f
KB
307}
308
309void
da048e3d 310gtk_pizza_move (GtkPizza *pizza,
053f9cc1 311 GtkWidget *widget,
ed673c6a
RR
312 gint x,
313 gint y)
c801d85f 314{
da048e3d 315 GtkPizzaChild *child;
053f9cc1 316 GList *children;
c801d85f 317
da048e3d
RR
318 g_return_if_fail (pizza != NULL);
319 g_return_if_fail (GTK_IS_PIZZA (pizza));
053f9cc1 320 g_return_if_fail (widget != NULL);
c801d85f 321
da048e3d 322 children = pizza->children;
053f9cc1 323 while (children)
fdd3ed7a 324 {
053f9cc1
RR
325 child = children->data;
326 children = children->next;
bf3dab48 327
053f9cc1 328 if (child->widget == widget)
fdd3ed7a 329 {
bf3dab48
VZ
330 if ((child->x == x) && (child->y == y))
331 break;
332
ed673c6a
RR
333 child->x = x;
334 child->y = y;
bf3dab48
VZ
335
336 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (pizza))
337 gtk_widget_queue_resize (widget);
338 break;
339 }
fdd3ed7a
RR
340 }
341}
342
343void
da048e3d 344gtk_pizza_resize (GtkPizza *pizza,
fdd3ed7a 345 GtkWidget *widget,
bf3dab48
VZ
346 gint width,
347 gint height)
fdd3ed7a 348{
da048e3d 349 GtkPizzaChild *child;
053f9cc1 350 GList *children;
fdd3ed7a 351
da048e3d
RR
352 g_return_if_fail (pizza != NULL);
353 g_return_if_fail (GTK_IS_PIZZA (pizza));
053f9cc1 354 g_return_if_fail (widget != NULL);
fdd3ed7a 355
da048e3d 356 children = pizza->children;
053f9cc1 357 while (children)
fdd3ed7a 358 {
053f9cc1
RR
359 child = children->data;
360 children = children->next;
bf3dab48 361
053f9cc1 362 if (child->widget == widget)
fdd3ed7a 363 {
bf3dab48
VZ
364 if ((child->width == width) && (child->height == height))
365 break;
366
ed673c6a
RR
367 child->width = width;
368 child->height = height;
bf3dab48
VZ
369
370 gtk_widget_set_usize (widget, width, height);
371
da048e3d 372 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (pizza))
bf3dab48
VZ
373 gtk_widget_queue_resize (widget);
374 break;
375 }
fdd3ed7a
RR
376 }
377}
378
379void
da048e3d 380gtk_pizza_set_size (GtkPizza *pizza,
053f9cc1 381 GtkWidget *widget,
ed673c6a
RR
382 gint x,
383 gint y,
bf3dab48
VZ
384 gint width,
385 gint height)
fdd3ed7a 386{
da048e3d 387 GtkPizzaChild *child;
053f9cc1 388 GList *children;
fdd3ed7a 389
da048e3d
RR
390 g_return_if_fail (pizza != NULL);
391 g_return_if_fail (GTK_IS_PIZZA (pizza));
053f9cc1 392 g_return_if_fail (widget != NULL);
fdd3ed7a 393
da048e3d 394 children = pizza->children;
053f9cc1 395 while (children)
c801d85f 396 {
053f9cc1
RR
397 child = children->data;
398 children = children->next;
c801d85f 399
053f9cc1 400 if (child->widget == widget)
c801d85f 401 {
bf3dab48
VZ
402 if ((child->x == x) &&
403 (child->y == y) &&
404 (child->width == width) &&
405 (child->height == height)) return;
406
053f9cc1
RR
407 child->x = x;
408 child->y = y;
409 child->width = width;
410 child->height = height;
bf3dab48
VZ
411
412 gtk_widget_set_usize (widget, width, height);
413
da048e3d 414 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (pizza))
bf3dab48
VZ
415 gtk_widget_queue_resize (widget);
416
6d693bb4 417 return;
c801d85f
KB
418 }
419 }
420}
421
422static void
da048e3d 423gtk_pizza_map (GtkWidget *widget)
c801d85f 424{
da048e3d
RR
425 GtkPizza *pizza;
426 GtkPizzaChild *child;
053f9cc1 427 GList *children;
c801d85f 428
053f9cc1 429 g_return_if_fail (widget != NULL);
da048e3d 430 g_return_if_fail (GTK_IS_PIZZA (widget));
c801d85f 431
053f9cc1 432 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
da048e3d 433 pizza = GTK_PIZZA (widget);
c801d85f 434
da048e3d 435 children = pizza->children;
053f9cc1 436 while (children)
c801d85f 437 {
053f9cc1
RR
438 child = children->data;
439 children = children->next;
c801d85f 440
bf3dab48
VZ
441 if ( GTK_WIDGET_VISIBLE (child->widget) &&
442 !GTK_WIDGET_MAPPED (child->widget) &&
443 !GTK_WIDGET_IS_OFFSCREEN (child->widget))
444 {
445 gtk_widget_map (child->widget);
446 }
c801d85f 447 }
bf3dab48 448
053f9cc1 449 gdk_window_show (widget->window);
da048e3d 450 gdk_window_show (pizza->bin_window);
c801d85f
KB
451}
452
c801d85f 453static void
da048e3d 454gtk_pizza_realize (GtkWidget *widget)
c801d85f 455{
da048e3d 456 GtkPizza *pizza;
053f9cc1
RR
457 GdkWindowAttr attributes;
458 gint attributes_mask;
da048e3d 459 GtkPizzaChild *child;
ed673c6a 460 GList *children;
c801d85f 461
053f9cc1 462 g_return_if_fail (widget != NULL);
da048e3d 463 g_return_if_fail (GTK_IS_PIZZA (widget));
c801d85f 464
da048e3d 465 pizza = GTK_PIZZA (widget);
bf3dab48 466
053f9cc1 467 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
c801d85f 468
053f9cc1 469 attributes.window_type = GDK_WINDOW_CHILD;
bf3dab48 470
053f9cc1
RR
471 attributes.x = widget->allocation.x;
472 attributes.y = widget->allocation.y;
473 attributes.width = widget->allocation.width;
474 attributes.height = widget->allocation.height;
475
da048e3d 476 if (pizza->shadow_type == GTK_MYSHADOW_NONE)
053f9cc1 477 {
5e014a0c
RR
478 /* no border, no changes to sizes */
479 } else
da048e3d 480 if (pizza->shadow_type == GTK_MYSHADOW_THIN)
5e014a0c
RR
481 {
482 /* GTK_MYSHADOW_THIN == wxSIMPLE_BORDER */
483 attributes.x += 1;
484 attributes.y += 1;
485 attributes.width -= 2;
486 attributes.height -= 2;
487 } else
488 {
489 /* GTK_MYSHADOW_IN == wxSUNKEN_BORDER */
490 /* GTK_MYSHADOW_OUT == wxRAISED_BORDER */
053f9cc1
RR
491 attributes.x += 2;
492 attributes.y += 2;
493 attributes.width -= 4;
494 attributes.height -= 4;
495 }
bf3dab48 496
ed673c6a 497 /* minimal size */
053f9cc1
RR
498 if (attributes.width < 2) attributes.width = 2;
499 if (attributes.height < 2) attributes.height = 2;
bf3dab48 500
053f9cc1
RR
501 attributes.wclass = GDK_INPUT_OUTPUT;
502 attributes.visual = gtk_widget_get_visual (widget);
503 attributes.colormap = gtk_widget_get_colormap (widget);
bf3dab48 504 attributes.event_mask =
ed673c6a
RR
505 GDK_VISIBILITY_NOTIFY_MASK;
506 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
bf3dab48 507
c916e13b 508 widget->window = gdk_window_new(gtk_widget_get_parent_window (widget),
bf3dab48 509 &attributes, attributes_mask);
ed673c6a
RR
510 gdk_window_set_user_data (widget->window, widget);
511
512 attributes.x = 0;
513 attributes.y = 0;
bf3dab48 514
053f9cc1 515 attributes.event_mask = gtk_widget_get_events (widget);
bf3dab48
VZ
516 attributes.event_mask |=
517 GDK_EXPOSURE_MASK |
518 GDK_POINTER_MOTION_MASK |
053f9cc1 519 GDK_POINTER_MOTION_HINT_MASK |
bf3dab48
VZ
520 GDK_BUTTON_MOTION_MASK |
521 GDK_BUTTON1_MOTION_MASK |
522 GDK_BUTTON2_MOTION_MASK |
523 GDK_BUTTON3_MOTION_MASK |
524 GDK_BUTTON_PRESS_MASK |
525 GDK_BUTTON_RELEASE_MASK |
526 GDK_KEY_PRESS_MASK |
527 GDK_KEY_RELEASE_MASK |
528 GDK_ENTER_NOTIFY_MASK |
529 GDK_LEAVE_NOTIFY_MASK |
053f9cc1 530 GDK_FOCUS_CHANGE_MASK;
053f9cc1 531
c916e13b 532 pizza->bin_window = gdk_window_new(widget->window,
bf3dab48 533 &attributes, attributes_mask);
da048e3d 534 gdk_window_set_user_data (pizza->bin_window, widget);
bf3dab48 535
053f9cc1
RR
536 widget->style = gtk_style_attach (widget->style, widget->window);
537 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
da048e3d 538 gtk_style_set_background (widget->style, pizza->bin_window, GTK_STATE_NORMAL);
bf3dab48 539
ed673c6a 540 /* add filters for intercepting visibility and expose events */
da048e3d
RR
541 gdk_window_add_filter (widget->window, gtk_pizza_main_filter, pizza);
542 gdk_window_add_filter (pizza->bin_window, gtk_pizza_filter, pizza);
ed673c6a
RR
543
544 /* we NEED gravity or we'll give up */
da048e3d 545 gravity_works = gdk_window_set_static_gravities (pizza->bin_window, TRUE);
ed673c6a
RR
546
547 /* cannot be done before realisation */
da048e3d 548 children = pizza->children;
ed673c6a
RR
549 while (children)
550 {
551 child = children->data;
552 children = children->next;
553
da048e3d 554 gtk_widget_set_parent_window (child->widget, pizza->bin_window);
ed673c6a
RR
555 }
556}
557
bf3dab48 558static void
da048e3d 559gtk_pizza_unrealize (GtkWidget *widget)
ed673c6a 560{
da048e3d 561 GtkPizza *pizza;
ed673c6a
RR
562
563 g_return_if_fail (widget != NULL);
da048e3d 564 g_return_if_fail (GTK_IS_PIZZA (widget));
ed673c6a 565
da048e3d 566 pizza = GTK_PIZZA (widget);
ed673c6a 567
da048e3d
RR
568 gdk_window_set_user_data (pizza->bin_window, NULL);
569 gdk_window_destroy (pizza->bin_window);
570 pizza->bin_window = NULL;
ed673c6a
RR
571
572 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
573 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
c801d85f
KB
574}
575
576static void
da048e3d 577gtk_pizza_size_request (GtkWidget *widget,
bf3dab48 578 GtkRequisition *requisition)
c801d85f 579{
da048e3d
RR
580 GtkPizza *pizza;
581 GtkPizzaChild *child;
053f9cc1
RR
582 GList *children;
583 GtkRequisition child_requisition;
bf3dab48 584
053f9cc1 585 g_return_if_fail (widget != NULL);
da048e3d 586 g_return_if_fail (GTK_IS_PIZZA (widget));
053f9cc1 587 g_return_if_fail (requisition != NULL);
c801d85f 588
da048e3d 589 pizza = GTK_PIZZA (widget);
bf3dab48 590
da048e3d 591 children = pizza->children;
053f9cc1 592 while (children)
c801d85f 593 {
053f9cc1
RR
594 child = children->data;
595 children = children->next;
c801d85f 596
053f9cc1 597 if (GTK_WIDGET_VISIBLE (child->widget))
bf3dab48 598 {
053f9cc1 599 gtk_widget_size_request (child->widget, &child_requisition);
bf3dab48 600 }
c801d85f 601 }
bf3dab48 602
053f9cc1
RR
603 /* request very little, I'm not sure if requesting nothing
604 will always have positive effects on stability... */
605 requisition->width = 2;
606 requisition->height = 2;
c801d85f
KB
607}
608
609static void
da048e3d 610gtk_pizza_size_allocate (GtkWidget *widget,
bf3dab48 611 GtkAllocation *allocation)
c801d85f 612{
da048e3d 613 GtkPizza *pizza;
053f9cc1 614 gint border;
ed673c6a 615 gint x,y,w,h;
da048e3d 616 GtkPizzaChild *child;
ed673c6a 617 GList *children;
c801d85f 618
053f9cc1 619 g_return_if_fail (widget != NULL);
da048e3d 620 g_return_if_fail (GTK_IS_PIZZA(widget));
053f9cc1 621 g_return_if_fail (allocation != NULL);
c801d85f 622
da048e3d 623 pizza = GTK_PIZZA (widget);
bf3dab48 624
227e5e99 625 widget->allocation = *allocation;
bf3dab48 626
da048e3d 627 if (pizza->shadow_type == GTK_MYSHADOW_NONE)
053f9cc1 628 border = 0;
5e014a0c 629 else
da048e3d 630 if (pizza->shadow_type == GTK_MYSHADOW_THIN)
5e014a0c 631 border = 1;
053f9cc1
RR
632 else
633 border = 2;
bf3dab48 634
ed673c6a
RR
635 x = allocation->x + border;
636 y = allocation->y + border;
637 w = allocation->width - border*2;
638 h = allocation->height - border*2;
034be888 639
053f9cc1
RR
640 if (GTK_WIDGET_REALIZED (widget))
641 {
ed673c6a 642 gdk_window_move_resize( widget->window, x, y, w, h );
da048e3d 643 gdk_window_move_resize( pizza->bin_window, 0, 0, w, h );
053f9cc1 644 }
bf3dab48 645
da048e3d 646 children = pizza->children;
6d693bb4
RR
647 while (children)
648 {
649 child = children->data;
650 children = children->next;
bf3dab48 651
da048e3d
RR
652 gtk_pizza_position_child (pizza, child);
653 gtk_pizza_allocate_child (pizza, child);
6d693bb4 654 }
c801d85f
KB
655}
656
657static void
da048e3d 658gtk_pizza_draw (GtkWidget *widget,
bf3dab48 659 GdkRectangle *area)
c801d85f 660{
da048e3d
RR
661 GtkPizza *pizza;
662 GtkPizzaChild *child;
ed673c6a
RR
663 GdkRectangle child_area;
664 GList *children;
665
053f9cc1 666 g_return_if_fail (widget != NULL);
da048e3d 667 g_return_if_fail (GTK_IS_PIZZA (widget));
053f9cc1 668
da048e3d 669 pizza = GTK_PIZZA (widget);
bf3dab48 670
da048e3d 671 children = pizza->children;
147bc491 672 if ( !(GTK_WIDGET_APP_PAINTABLE (widget)) &&
da048e3d 673 (pizza->clear_on_draw))
ed673c6a 674 {
da048e3d 675 gdk_window_clear_area( pizza->bin_window,
bf3dab48 676 area->x, area->y, area->width, area->height);
ed673c6a
RR
677 }
678
679 while (children)
680 {
bf3dab48
VZ
681 child = children->data;
682 children = children->next;
ed673c6a 683
bf3dab48
VZ
684 if (gtk_widget_intersect (child->widget, area, &child_area))
685 gtk_widget_draw (child->widget, &child_area);
ed673c6a 686 }
c801d85f
KB
687}
688
c801d85f 689static gint
da048e3d 690gtk_pizza_expose (GtkWidget *widget,
bf3dab48 691 GdkEventExpose *event)
c801d85f 692{
da048e3d
RR
693 GtkPizza *pizza;
694 GtkPizzaChild *child;
ed673c6a
RR
695 GdkEventExpose child_event;
696 GList *children;
c801d85f 697
ed673c6a 698 g_return_val_if_fail (widget != NULL, FALSE);
da048e3d 699 g_return_val_if_fail (GTK_IS_PIZZA (widget), FALSE);
ed673c6a
RR
700 g_return_val_if_fail (event != NULL, FALSE);
701
da048e3d 702 pizza = GTK_PIZZA (widget);
c801d85f 703
da048e3d 704 if (event->window != pizza->bin_window)
ed673c6a 705 return FALSE;
c801d85f 706
da048e3d 707 children = pizza->children;
ed673c6a
RR
708 while (children)
709 {
bf3dab48
VZ
710 child = children->data;
711 children = children->next;
c801d85f 712
ed673c6a
RR
713 child_event = *event;
714
bf3dab48
VZ
715 if (GTK_WIDGET_NO_WINDOW (child->widget) &&
716 GTK_WIDGET_DRAWABLE (child->widget) &&
717 gtk_widget_intersect (child->widget, &event->area, &child_event.area))
718 {
719 gtk_widget_event (child->widget, (GdkEvent*) &child_event);
720 }
c801d85f
KB
721 }
722
ed673c6a 723 return FALSE;
c801d85f
KB
724}
725
726static void
da048e3d 727gtk_pizza_add (GtkContainer *container,
bf3dab48 728 GtkWidget *widget)
c801d85f 729{
ed673c6a 730 g_return_if_fail (container != NULL);
da048e3d 731 g_return_if_fail (GTK_IS_PIZZA (container));
ed673c6a 732 g_return_if_fail (widget != NULL);
c801d85f 733
da048e3d 734 gtk_pizza_put (GTK_PIZZA (container), widget, 0, 0, 20, 20 );
c801d85f
KB
735}
736
737static void
da048e3d 738gtk_pizza_remove (GtkContainer *container,
bf3dab48 739 GtkWidget *widget)
c801d85f 740{
da048e3d
RR
741 GtkPizza *pizza;
742 GtkPizzaChild *child;
ed673c6a 743 GList *children;
c801d85f 744
ed673c6a 745 g_return_if_fail (container != NULL);
da048e3d 746 g_return_if_fail (GTK_IS_PIZZA (container));
ed673c6a 747 g_return_if_fail (widget != NULL);
c801d85f 748
da048e3d 749 pizza = GTK_PIZZA (container);
c801d85f 750
da048e3d 751 children = pizza->children;
ed673c6a 752 while (children)
c801d85f 753 {
ed673c6a 754 child = children->data;
c801d85f 755
ed673c6a 756 if (child->widget == widget)
bf3dab48
VZ
757 {
758 gtk_widget_unparent (widget);
c801d85f 759
ed673c6a
RR
760 /* security checks */
761 g_return_if_fail (GTK_IS_WIDGET (widget));
bf3dab48
VZ
762
763 pizza->children = g_list_remove_link (pizza->children, children);
764 g_list_free (children);
765 g_free (child);
c801d85f 766
ed673c6a 767 /* security checks */
bf3dab48
VZ
768 g_return_if_fail (GTK_IS_WIDGET (widget));
769
ed673c6a 770 GTK_PRIVATE_UNSET_FLAG (widget, GTK_IS_OFFSCREEN);
bf3dab48
VZ
771
772 break;
773 }
c801d85f 774
ed673c6a 775 children = children->next;
c801d85f
KB
776 }
777}
778
779static void
da048e3d 780gtk_pizza_forall (GtkContainer *container,
bf3dab48
VZ
781 gboolean include_internals,
782 GtkCallback callback,
783 gpointer callback_data)
c801d85f 784{
da048e3d
RR
785 GtkPizza *pizza;
786 GtkPizzaChild *child;
6d693bb4 787 GList *children;
c801d85f 788
6d693bb4 789 g_return_if_fail (container != NULL);
da048e3d 790 g_return_if_fail (GTK_IS_PIZZA (container));
6d693bb4 791 g_return_if_fail (callback != NULL);
c801d85f 792
da048e3d 793 pizza = GTK_PIZZA (container);
c801d85f 794
da048e3d 795 children = pizza->children;
6d693bb4 796 while (children)
c801d85f 797 {
6d693bb4
RR
798 child = children->data;
799 children = children->next;
c801d85f 800
6d693bb4 801 (* callback) (child->widget, callback_data);
c801d85f
KB
802 }
803}
804
805
ed673c6a
RR
806/* Operations on children
807 */
808
809static void
da048e3d 810gtk_pizza_position_child (GtkPizza *pizza,
bf3dab48 811 GtkPizzaChild *child)
ed673c6a 812{
6d693bb4
RR
813 gint x;
814 gint y;
ed673c6a 815
da048e3d
RR
816 x = child->x - pizza->xoffset;
817 y = child->y - pizza->yoffset;
ed673c6a 818
6d693bb4 819 if (IS_ONSCREEN (x,y))
ed673c6a 820 {
da048e3d 821 if (GTK_WIDGET_MAPPED (pizza) &&
bf3dab48
VZ
822 GTK_WIDGET_VISIBLE (child->widget))
823 {
824 if (!GTK_WIDGET_MAPPED (child->widget))
825 gtk_widget_map (child->widget);
826 }
ed673c6a 827
6d693bb4 828 if (GTK_WIDGET_IS_OFFSCREEN (child->widget))
bf3dab48 829 GTK_PRIVATE_UNSET_FLAG (child->widget, GTK_IS_OFFSCREEN);
ed673c6a 830 }
6d693bb4 831 else
ed673c6a 832 {
6d693bb4 833 if (!GTK_WIDGET_IS_OFFSCREEN (child->widget))
bf3dab48 834 GTK_PRIVATE_SET_FLAG (child->widget, GTK_IS_OFFSCREEN);
ed673c6a 835
6d693bb4 836 if (GTK_WIDGET_MAPPED (child->widget))
bf3dab48 837 gtk_widget_unmap (child->widget);
ed673c6a
RR
838 }
839}
840
841static void
da048e3d 842gtk_pizza_allocate_child (GtkPizza *pizza,
bf3dab48 843 GtkPizzaChild *child)
ed673c6a 844{
6d693bb4
RR
845 GtkAllocation allocation;
846 GtkRequisition requisition;
847
da048e3d
RR
848 allocation.x = child->x - pizza->xoffset;
849 allocation.y = child->y - pizza->yoffset;
6d693bb4
RR
850 gtk_widget_get_child_requisition (child->widget, &requisition);
851 allocation.width = requisition.width;
852 allocation.height = requisition.height;
bf3dab48 853
6d693bb4 854 gtk_widget_size_allocate (child->widget, &allocation);
ed673c6a
RR
855}
856
857static void
da048e3d 858gtk_pizza_position_children (GtkPizza *pizza)
ed673c6a 859{
6d693bb4 860 GList *tmp_list;
ed673c6a 861
da048e3d 862 tmp_list = pizza->children;
6d693bb4 863 while (tmp_list)
ed673c6a 864 {
da048e3d 865 GtkPizzaChild *child = tmp_list->data;
6d693bb4 866 tmp_list = tmp_list->next;
bf3dab48 867
da048e3d 868 gtk_pizza_position_child (pizza, child);
ed673c6a
RR
869 }
870}
871
872static void
da048e3d 873gtk_pizza_adjust_allocations_recurse (GtkWidget *widget,
bf3dab48 874 gpointer cb_data)
ed673c6a 875{
da048e3d 876 GtkPizzaAdjData *data = cb_data;
ed673c6a 877
6d693bb4
RR
878 widget->allocation.x += data->dx;
879 widget->allocation.y += data->dy;
ed673c6a 880
6d693bb4
RR
881 if (GTK_WIDGET_NO_WINDOW (widget) && GTK_IS_CONTAINER (widget))
882 {
bf3dab48
VZ
883 gtk_container_forall (GTK_CONTAINER (widget),
884 gtk_pizza_adjust_allocations_recurse,
885 cb_data);
6d693bb4 886 }
ed673c6a
RR
887}
888
889static void
da048e3d 890gtk_pizza_adjust_allocations (GtkPizza *pizza,
bf3dab48
VZ
891 gint dx,
892 gint dy)
ed673c6a 893{
0e09f76e
RR
894 GList *tmp_list;
895 GtkPizzaAdjData data;
ed673c6a 896
0e09f76e
RR
897 data.dx = dx;
898 data.dy = dy;
ed673c6a 899
0e09f76e
RR
900 tmp_list = pizza->children;
901 while (tmp_list)
ed673c6a 902 {
0e09f76e
RR
903 GtkPizzaChild *child = tmp_list->data;
904 tmp_list = tmp_list->next;
bf3dab48 905
0e09f76e
RR
906 child->widget->allocation.x += dx;
907 child->widget->allocation.y += dy;
ed673c6a 908
0e09f76e
RR
909 if (GTK_WIDGET_NO_WINDOW (child->widget) &&
910 GTK_IS_CONTAINER (child->widget))
911 {
912 gtk_container_forall (GTK_CONTAINER (child->widget),
913 gtk_pizza_adjust_allocations_recurse,
914 &data);
915 }
ed673c6a
RR
916 }
917}
bf3dab48 918
ed673c6a
RR
919/* Callbacks */
920
921/* Send a synthetic expose event to the widget
922 */
923static void
da048e3d 924gtk_pizza_expose_area (GtkPizza *pizza,
bf3dab48 925 gint x, gint y, gint width, gint height)
ed673c6a 926{
0e09f76e 927 if (pizza->visibility == GDK_VISIBILITY_UNOBSCURED)
ed673c6a 928 {
0e09f76e 929 GdkEventExpose event;
bf3dab48 930
0e09f76e
RR
931 event.type = GDK_EXPOSE;
932 event.send_event = TRUE;
933 event.window = pizza->bin_window;
934 event.count = 0;
bf3dab48 935
0e09f76e
RR
936 event.area.x = x;
937 event.area.y = y;
938 event.area.width = width;
939 event.area.height = height;
bf3dab48 940
0e09f76e
RR
941 gdk_window_ref (event.window);
942 gtk_widget_event (GTK_WIDGET (pizza), (GdkEvent *)&event);
943 gdk_window_unref (event.window);
ed673c6a
RR
944 }
945}
946
947/* This function is used to find events to process while scrolling
948 */
949
bf3dab48
VZ
950static Bool
951gtk_pizza_expose_predicate (Display *display,
952 XEvent *xevent,
953 XPointer arg)
ed673c6a 954{
bf3dab48 955 if ((xevent->type == Expose) ||
ed673c6a
RR
956 ((xevent->xany.window == *(Window *)arg) &&
957 (xevent->type == ConfigureNotify)))
958 return True;
959 else
960 return False;
961}
962
963/* This is the main routine to do the scrolling. Scrolling is
964 * done by "Guffaw" scrolling, as in the Mozilla XFE, with
965 * a few modifications.
bf3dab48 966 *
ed673c6a
RR
967 * The main improvement is that we keep track of whether we
968 * are obscured or not. If not, we ignore the generated expose
969 * events and instead do the exposes ourself, without having
970 * to wait for a roundtrip to the server. This also provides
971 * a limited form of expose-event compression, since we do
972 * the affected area as one big chunk.
973 */
974
975void
da048e3d 976gtk_pizza_scroll (GtkPizza *pizza, gint dx, gint dy)
ed673c6a
RR
977{
978 GtkWidget *widget;
979 XEvent xevent;
980
981 gint x,y,w,h,border;
bf3dab48 982
da048e3d 983 widget = GTK_WIDGET (pizza);
ed673c6a 984
da048e3d
RR
985 pizza->xoffset += dx;
986 pizza->yoffset += dy;
ed673c6a 987
da048e3d 988 if (!GTK_WIDGET_MAPPED (pizza))
ed673c6a 989 {
da048e3d 990 gtk_pizza_position_children (pizza);
ed673c6a
RR
991 return;
992 }
993
da048e3d 994 gtk_pizza_adjust_allocations (pizza, -dx, -dy);
ed673c6a 995
da048e3d 996 if (pizza->shadow_type == GTK_MYSHADOW_NONE)
ed673c6a
RR
997 border = 0;
998 else
da048e3d 999 if (pizza->shadow_type == GTK_MYSHADOW_THIN)
ed673c6a
RR
1000 border = 1;
1001 else
1002 border = 2;
bf3dab48 1003
ed673c6a
RR
1004 x = 0;
1005 y = 0;
1006 w = widget->allocation.width - 2*border;
1007 h = widget->allocation.height - 2*border;
bf3dab48 1008
ed673c6a
RR
1009 if (dx > 0)
1010 {
1011 if (gravity_works)
bf3dab48
VZ
1012 {
1013 gdk_window_resize (pizza->bin_window,
1014 w + dx,
1015 h);
1016 gdk_window_move (pizza->bin_window, x-dx, y);
1017 gdk_window_move_resize (pizza->bin_window, x, y, w, h );
1018 }
ed673c6a 1019 else
bf3dab48
VZ
1020 {
1021 /* FIXME */
1022 }
1023
1024 gtk_pizza_expose_area (pizza,
1025 MAX ((gint)w - dx, 0),
1026 0,
1027 MIN (dx, w),
1028 h);
ed673c6a
RR
1029 }
1030 else if (dx < 0)
1031 {
1032 if (gravity_works)
bf3dab48
VZ
1033 {
1034 gdk_window_move_resize (pizza->bin_window,
1035 x + dx,
1036 y,
1037 w - dx,
1038 h);
1039 gdk_window_move (pizza->bin_window, x, y);
1040 gdk_window_resize (pizza->bin_window, w, h );
1041 }
ed673c6a 1042 else
bf3dab48
VZ
1043 {
1044 /* FIXME */
1045 }
ed673c6a 1046
da048e3d 1047 gtk_pizza_expose_area (pizza,
bf3dab48
VZ
1048 0,
1049 0,
1050 MIN (-dx, w),
1051 h);
ed673c6a
RR
1052 }
1053
1054 if (dy > 0)
1055 {
1056 if (gravity_works)
bf3dab48
VZ
1057 {
1058 gdk_window_resize (pizza->bin_window, w, h + dy);
1059 gdk_window_move (pizza->bin_window, x, y-dy);
1060 gdk_window_move_resize (pizza->bin_window,
1061 x, y, w, h );
1062 }
ed673c6a 1063 else
bf3dab48
VZ
1064 {
1065 /* FIXME */
1066 }
1067
1068 gtk_pizza_expose_area (pizza,
1069 0,
1070 MAX ((gint)h - dy, 0),
1071 w,
1072 MIN (dy, h));
ed673c6a
RR
1073 }
1074 else if (dy < 0)
1075 {
1076 if (gravity_works)
bf3dab48
VZ
1077 {
1078 gdk_window_move_resize (pizza->bin_window,
1079 x, y+dy, w, h - dy );
1080 gdk_window_move (pizza->bin_window, x, y);
1081 gdk_window_resize (pizza->bin_window, w, h );
1082 }
ed673c6a 1083 else
bf3dab48
VZ
1084 {
1085 /* FIXME */
1086 }
1087 gtk_pizza_expose_area (pizza,
1088 0,
1089 0,
1090 w,
1091 MIN (-dy, (gint)h));
ed673c6a
RR
1092 }
1093
da048e3d 1094 gtk_pizza_position_children (pizza);
ed673c6a
RR
1095
1096 /* We have to make sure that all exposes from this scroll get
1097 * processed before we scroll again, or the expose events will
1098 * have invalid coordinates.
1099 *
1100 * We also do expose events for other windows, since otherwise
bf3dab48 1101 * their updating will fall behind the scrolling
ed673c6a
RR
1102 *
1103 * This also avoids a problem in pre-1.0 GTK where filters don't
1104 * have access to configure events that were compressed.
1105 */
1106
1107 gdk_flush();
da048e3d 1108 while (XCheckIfEvent(GDK_WINDOW_XDISPLAY (pizza->bin_window),
bf3dab48
VZ
1109 &xevent,
1110 gtk_pizza_expose_predicate,
1111 (XPointer)&GDK_WINDOW_XWINDOW (pizza->bin_window)))
ed673c6a
RR
1112 {
1113 GdkEvent event;
1114 GtkWidget *event_widget;
1115
da048e3d 1116 if ((xevent.xany.window == GDK_WINDOW_XWINDOW (pizza->bin_window)) &&
bf3dab48
VZ
1117 (gtk_pizza_filter (&xevent, &event, pizza) == GDK_FILTER_REMOVE))
1118 continue;
1119
ed673c6a 1120 if (xevent.type == Expose)
bf3dab48
VZ
1121 {
1122 event.expose.window = gdk_window_lookup (xevent.xany.window);
1123 gdk_window_get_user_data (event.expose.window,
1124 (gpointer *)&event_widget);
1125
1126 if (event_widget)
1127 {
1128 event.expose.type = GDK_EXPOSE;
1129 event.expose.area.x = xevent.xexpose.x;
1130 event.expose.area.y = xevent.xexpose.y;
1131 event.expose.area.width = xevent.xexpose.width;
1132 event.expose.area.height = xevent.xexpose.height;
1133 event.expose.count = xevent.xexpose.count;
1134
1135 gdk_window_ref (event.expose.window);
1136 gtk_widget_event (event_widget, &event);
1137 gdk_window_unref (event.expose.window);
1138 }
1139 }
ed673c6a
RR
1140 }
1141}
1142
1143/* The main event filter. Actually, we probably don't really need
1144 * to install this as a filter at all, since we are calling it
1145 * directly above in the expose-handling hack. But in case scrollbars
1146 * are fixed up in some manner...
1147 *
1148 * This routine identifies expose events that are generated when
1149 * we've temporarily moved the bin_window_origin, and translates
1150 * them or discards them, depending on whether we are obscured
1151 * or not.
1152 */
bf3dab48 1153static GdkFilterReturn
da048e3d 1154gtk_pizza_filter (GdkXEvent *gdk_xevent,
bf3dab48
VZ
1155 GdkEvent *event,
1156 gpointer data)
ed673c6a 1157{
0e09f76e
RR
1158 XEvent *xevent;
1159 GtkPizza *pizza;
ed673c6a 1160
0e09f76e
RR
1161 xevent = (XEvent *)gdk_xevent;
1162
1163 pizza = GTK_PIZZA (data);
1164
ed673c6a
RR
1165 switch (xevent->type)
1166 {
1167 case Expose:
da048e3d 1168 if (xevent->xexpose.serial == pizza->configure_serial)
bf3dab48
VZ
1169 {
1170 if (pizza->visibility == GDK_VISIBILITY_UNOBSCURED)
1171 return GDK_FILTER_REMOVE;
1172 else
1173 {
1174 xevent->xexpose.x += pizza->scroll_x;
1175 xevent->xexpose.y += pizza->scroll_y;
1176
1177 break;
1178 }
1179 }
ed673c6a 1180 break;
bf3dab48 1181
ed673c6a
RR
1182 case ConfigureNotify:
1183 if ((xevent->xconfigure.x != 0) || (xevent->xconfigure.y != 0))
bf3dab48
VZ
1184 {
1185 pizza->configure_serial = xevent->xconfigure.serial;
1186 pizza->scroll_x = xevent->xconfigure.x;
1187 pizza->scroll_y = xevent->xconfigure.y;
1188 }
ed673c6a
RR
1189 break;
1190 }
bf3dab48 1191
0e09f76e 1192 return GDK_FILTER_CONTINUE;
ed673c6a
RR
1193}
1194
1195/* Although GDK does have a GDK_VISIBILITY_NOTIFY event,
1196 * there is no corresponding event in GTK, so we have
1197 * to get the events from a filter
1198 */
bf3dab48 1199static GdkFilterReturn
da048e3d 1200gtk_pizza_main_filter (GdkXEvent *gdk_xevent,
bf3dab48
VZ
1201 GdkEvent *event,
1202 gpointer data)
ed673c6a 1203{
0e09f76e
RR
1204 XEvent *xevent;
1205 GtkPizza *pizza;
ed673c6a 1206
0e09f76e
RR
1207 xevent = (XEvent *)gdk_xevent;
1208 pizza = GTK_PIZZA (data);
ed673c6a 1209
0e09f76e 1210 if (xevent->type == VisibilityNotify)
ed673c6a 1211 {
0e09f76e 1212 switch (xevent->xvisibility.state)
bf3dab48 1213 {
0e09f76e
RR
1214 case VisibilityFullyObscured:
1215 pizza->visibility = GDK_VISIBILITY_FULLY_OBSCURED;
1216 break;
ed673c6a 1217
0e09f76e
RR
1218 case VisibilityPartiallyObscured:
1219 pizza->visibility = GDK_VISIBILITY_PARTIAL;
1220 break;
ed673c6a 1221
0e09f76e
RR
1222 case VisibilityUnobscured:
1223 pizza->visibility = GDK_VISIBILITY_UNOBSCURED;
1224 break;
bf3dab48 1225 }
0e09f76e
RR
1226
1227 return GDK_FILTER_REMOVE;
ed673c6a
RR
1228 }
1229
0e09f76e 1230 return GDK_FILTER_CONTINUE;
ed673c6a
RR
1231}
1232
1233
1234
1235
c801d85f
KB
1236#ifdef __cplusplus
1237}
1238#endif /* __cplusplus */
1239