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