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