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