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