]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/win_gtk.c
Fix compilo under MINGW32
[wxWidgets.git] / src / gtk / win_gtk.c
CommitLineData
c67daf87 1/* ///////////////////////////////////////////////////////////////////////////
0ba6a836 2// Name: src/gtk/win_gtk.c
77ffb593 3// Purpose: Native GTK+ widget for wxWidgets, based on GtkLayout and
ed673c6a
RR
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
77ffb593 9// Licence: wxWidgets licence
c67daf87 10/////////////////////////////////////////////////////////////////////////// */
c801d85f 11
d02af7bb
JJ
12#ifdef VMS
13#define XCheckIfEvent XCHECKIFEVENT
3fa056ab 14#endif
27df579a 15
79918119 16#include "wx/platform.h"
27df579a 17#include "wx/gtk/win_gtk.h"
38c7b3d3 18
c801d85f
KB
19#ifdef __cplusplus
20extern "C" {
21#endif /* __cplusplus */
22
da048e3d 23typedef struct _GtkPizzaAdjData GtkPizzaAdjData;
ed673c6a 24
bf3dab48 25struct _GtkPizzaAdjData
ed673c6a
RR
26{
27 gint dx;
28 gint dy;
29};
30
b6fa52db
RR
31static void gtk_pizza_class_init (GtkPizzaClass *klass);
32static void gtk_pizza_init (GtkPizza *pizza);
ed673c6a 33
b6fa52db
RR
34static void gtk_pizza_realize (GtkWidget *widget);
35static void gtk_pizza_unrealize (GtkWidget *widget);
ed673c6a 36
b6fa52db 37static void gtk_pizza_map (GtkWidget *widget);
ed673c6a 38
da048e3d 39static void gtk_pizza_size_request (GtkWidget *widget,
bf3dab48 40 GtkRequisition *requisition);
da048e3d 41static void gtk_pizza_size_allocate (GtkWidget *widget,
bf3dab48 42 GtkAllocation *allocation);
da048e3d 43static gint gtk_pizza_expose (GtkWidget *widget,
bf3dab48 44 GdkEventExpose *event);
22aff579
VS
45static void gtk_pizza_style_set (GtkWidget *widget,
46 GtkStyle *previous_style);
da048e3d 47static void gtk_pizza_add (GtkContainer *container,
bf3dab48 48 GtkWidget *widget);
da048e3d 49static void gtk_pizza_remove (GtkContainer *container,
bf3dab48 50 GtkWidget *widget);
b6fa52db
RR
51static void gtk_pizza_forall (GtkContainer *container,
52 gboolean include_internals,
53 GtkCallback callback,
54 gpointer callback_data);
17a1ebd1 55
67d78217
RR
56static void gtk_pizza_allocate_child (GtkPizza *pizza,
57 GtkPizzaChild *child);
3fc6e5fa
RR
58static void gtk_pizza_adjust_allocations_recurse (GtkWidget *widget,
59 gpointer cb_data);
ed673c6a 60
da048e3d 61static GtkType gtk_pizza_child_type (GtkContainer *container);
c801d85f 62
b6fa52db 63static void gtk_pizza_scroll_set_adjustments (GtkPizza *pizza,
bf3dab48
VZ
64 GtkAdjustment *hadj,
65 GtkAdjustment *vadj);
c801d85f 66
c764029c 67static GtkWidgetClass* pizza_parent_class;
034be888 68
e1ff9329 69GtkType
da048e3d 70gtk_pizza_get_type ()
c801d85f 71{
e1ff9329 72 static GtkType pizza_type = 0;
c801d85f 73
da048e3d 74 if (!pizza_type)
c801d85f 75 {
67d78217
RR
76 static const GTypeInfo pizza_info =
77 {
78 sizeof (GtkPizzaClass),
79 NULL, /* base_init */
80 NULL, /* base_finalize */
81 (GClassInitFunc) gtk_pizza_class_init,
82 NULL, /* class_finalize */
83 NULL, /* class_data */
84 sizeof (GtkPizza),
85 16, /* n_preallocs */
86 (GInstanceInitFunc) gtk_pizza_init,
87 };
17a1ebd1 88 pizza_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkPizza", &pizza_info, (GTypeFlags)0);
c801d85f 89 }
bf3dab48 90
da048e3d 91 return pizza_type;
c801d85f
KB
92}
93
02a525b3
VZ
94/* Marshaller needed for set_scroll_adjustments signal,
95 generated with GLib-2.4.6 glib-genmarshal */
143318dd
RR
96#define g_marshal_value_peek_object(v) g_value_get_object (v)
97static void
98g_cclosure_user_marshal_VOID__OBJECT_OBJECT (GClosure *closure,
99 GValue *return_value,
100 guint n_param_values,
101 const GValue *param_values,
102 gpointer invocation_hint,
103 gpointer marshal_data)
104{
105 typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT) (gpointer data1,
106 gpointer arg_1,
107 gpointer arg_2,
108 gpointer data2);
109 register GMarshalFunc_VOID__OBJECT_OBJECT callback;
110 register GCClosure *cc = (GCClosure*) closure;
111 register gpointer data1, data2;
112
113 g_return_if_fail (n_param_values == 3);
114
115 if (G_CCLOSURE_SWAP_DATA (closure))
116 {
117 data1 = closure->data;
118 data2 = g_value_peek_pointer (param_values + 0);
119 }
120 else
121 {
122 data1 = g_value_peek_pointer (param_values + 0);
123 data2 = closure->data;
124 }
125 callback = (GMarshalFunc_VOID__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback);
126
127 callback (data1,
128 g_marshal_value_peek_object (param_values + 1),
129 g_marshal_value_peek_object (param_values + 2),
130 data2);
131}
143318dd 132
c801d85f 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;
67d78217 143 pizza_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;
da048e3d 150 widget_class->expose_event = gtk_pizza_expose;
22aff579 151 widget_class->style_set = gtk_pizza_style_set;
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 =
143318dd
RR
162 g_signal_new(
163 "set_scroll_adjustments",
164 G_TYPE_FROM_CLASS(object_class),
165 G_SIGNAL_RUN_LAST,
166 G_STRUCT_OFFSET(GtkPizzaClass, set_scroll_adjustments),
167 NULL,
168 NULL,
169 g_cclosure_user_marshal_VOID__OBJECT_OBJECT,
170 G_TYPE_NONE,
171 2,
172 GTK_TYPE_ADJUSTMENT,
173 GTK_TYPE_ADJUSTMENT);
38c7b3d3
RR
174}
175
38c7b3d3 176static GtkType
da048e3d 177gtk_pizza_child_type (GtkContainer *container)
38c7b3d3 178{
053f9cc1 179 return GTK_TYPE_WIDGET;
c801d85f
KB
180}
181
182static void
da048e3d 183gtk_pizza_init (GtkPizza *pizza)
c801d85f 184{
da048e3d 185 GTK_WIDGET_UNSET_FLAGS (pizza, GTK_NO_WINDOW);
bf3dab48 186
da048e3d 187 pizza->shadow_type = GTK_MYSHADOW_NONE;
034be888 188
da048e3d 189 pizza->children = NULL;
bf3dab48 190
da048e3d 191 pizza->bin_window = NULL;
3dd9b88a 192
a31bb944
RR
193 pizza->m_xoffset = 0;
194 pizza->m_yoffset = 0;
69597639
RR
195
196 pizza->m_width = -1;
c801d85f
KB
197}
198
199GtkWidget*
da048e3d 200gtk_pizza_new ()
c801d85f 201{
da048e3d 202 GtkPizza *pizza;
c801d85f 203
efc8ab7c 204 pizza = g_object_new (gtk_pizza_get_type (), NULL);
bf3dab48 205
da048e3d 206 return GTK_WIDGET (pizza);
c801d85f
KB
207}
208
a31bb944
RR
209gint gtk_pizza_get_xoffset (GtkPizza *pizza)
210{
211 g_return_val_if_fail ( (pizza != NULL), -1 );
212 g_return_val_if_fail ( (GTK_IS_PIZZA (pizza)), -1 );
213
214 return pizza->m_xoffset;
215}
216
217gint gtk_pizza_get_yoffset (GtkPizza *pizza)
218{
219 g_return_val_if_fail ( (pizza != NULL), -1 );
220 g_return_val_if_fail ( (GTK_IS_PIZZA (pizza)), -1 );
221
222 return pizza->m_yoffset;
223}
224
225void gtk_pizza_set_xoffset (GtkPizza *pizza, gint xoffset)
226{
227 g_return_if_fail (pizza != NULL);
228 g_return_if_fail (GTK_IS_PIZZA (pizza));
229
230 pizza->m_xoffset = xoffset;
231 // do something
232}
233
234void gtk_pizza_set_yoffset (GtkPizza *pizza, gint yoffset)
235{
236 g_return_if_fail (pizza != NULL);
237 g_return_if_fail (GTK_IS_PIZZA (pizza));
238
239 pizza->m_xoffset = yoffset;
240 // do something
241}
242
428f4657
RR
243gint gtk_pizza_get_rtl_offset (GtkPizza *pizza)
244{
245 gint width;
246
247 g_return_val_if_fail ( (pizza != NULL), 0 );
248 g_return_val_if_fail ( (GTK_IS_PIZZA (pizza)), 0 );
249
250 if (!pizza->bin_window) return 0;
251
252 gdk_window_get_geometry( pizza->bin_window, NULL, NULL, &width, NULL, NULL );
253
254 return width;
255}
256
257
bf3dab48 258static void
da048e3d 259gtk_pizza_scroll_set_adjustments (GtkPizza *pizza,
bf3dab48
VZ
260 GtkAdjustment *hadj,
261 GtkAdjustment *vadj)
034be888 262{
ed673c6a 263 /* We handle scrolling in the wxScrolledWindow, not here. */
034be888
RR
264}
265
bf3dab48 266void
b6fa52db 267gtk_pizza_set_shadow_type (GtkPizza *pizza,
0e09f76e 268 GtkMyShadowType type)
034be888 269{
da048e3d
RR
270 g_return_if_fail (pizza != NULL);
271 g_return_if_fail (GTK_IS_PIZZA (pizza));
034be888 272
efc8ab7c 273 if (pizza->shadow_type != type)
034be888 274 {
da048e3d 275 pizza->shadow_type = type;
034be888 276
da048e3d 277 if (GTK_WIDGET_VISIBLE (pizza))
bf3dab48
VZ
278 {
279 gtk_widget_size_allocate (GTK_WIDGET (pizza), &(GTK_WIDGET (pizza)->allocation));
280 gtk_widget_queue_draw (GTK_WIDGET (pizza));
281 }
034be888
RR
282 }
283}
034be888 284
c801d85f 285void
b6fa52db
RR
286gtk_pizza_put (GtkPizza *pizza,
287 GtkWidget *widget,
288 gint x,
289 gint y,
290 gint width,
291 gint height)
c801d85f 292{
da048e3d 293 GtkPizzaChild *child_info;
053f9cc1 294
da048e3d
RR
295 g_return_if_fail (pizza != NULL);
296 g_return_if_fail (GTK_IS_PIZZA (pizza));
053f9cc1
RR
297 g_return_if_fail (widget != NULL);
298
69597639
RR
299 if (gtk_widget_get_direction( GTK_WIDGET(pizza) ) == GTK_TEXT_DIR_RTL)
300 {
301 // reverse horizontal placement
302 x = pizza->m_width - x - width;
303 }
304
da048e3d 305 child_info = g_new (GtkPizzaChild, 1);
bf3dab48 306
053f9cc1
RR
307 child_info->widget = widget;
308 child_info->x = x;
309 child_info->y = y;
310 child_info->width = width;
311 child_info->height = height;
bf3dab48 312
69597639
RR
313 if (GTK_IS_PIZZA(widget))
314 GTK_PIZZA(widget)->m_width = width;
315
bf3dab48 316 pizza->children = g_list_append (pizza->children, child_info);
ed673c6a 317
da048e3d
RR
318 if (GTK_WIDGET_REALIZED (pizza))
319 gtk_widget_set_parent_window (widget, pizza->bin_window);
bf3dab48 320
2b5f62a0
VZ
321 gtk_widget_set_parent (widget, GTK_WIDGET (pizza));
322
370dc79c 323 gtk_widget_set_size_request (widget, width, height);
c801d85f
KB
324}
325
fdd3ed7a 326void
b6fa52db
RR
327gtk_pizza_set_size (GtkPizza *pizza,
328 GtkWidget *widget,
329 gint x,
330 gint y,
331 gint width,
332 gint height)
fdd3ed7a 333{
da048e3d 334 GtkPizzaChild *child;
053f9cc1 335 GList *children;
fdd3ed7a 336
da048e3d
RR
337 g_return_if_fail (pizza != NULL);
338 g_return_if_fail (GTK_IS_PIZZA (pizza));
053f9cc1 339 g_return_if_fail (widget != NULL);
fdd3ed7a 340
aaf53059 341#ifndef WX_WARN_ILLEGAL_SETSIZE
6b71411a 342 /* this really shouldn't happen -- but it does, a lot, right now and we
aaf53059
MR
343 can't pass negative values to gtk_widget_set_size_request() without getting
344 a warning printed out, so filter them out here */
6b71411a
VZ
345 if ( width < 0 )
346 width = 0;
347 if ( height < 0 )
348 height = 0;
aaf53059 349#endif
6b71411a 350
da048e3d 351 children = pizza->children;
053f9cc1 352 while (children)
c801d85f 353 {
053f9cc1
RR
354 child = children->data;
355 children = children->next;
c801d85f 356
053f9cc1 357 if (child->widget == widget)
c801d85f 358 {
69597639
RR
359 gint new_x = x;
360 if (gtk_widget_get_direction( GTK_WIDGET(pizza) ) == GTK_TEXT_DIR_RTL)
361 {
362 // reverse horizontal placement
363 new_x = pizza->m_width - new_x - width;
364 }
365
366 if ((child->x == new_x) &&
bf3dab48
VZ
367 (child->y == y) &&
368 (child->width == width) &&
369 (child->height == height)) return;
370
69597639 371 child->x = new_x;
053f9cc1
RR
372 child->y = y;
373 child->width = width;
374 child->height = height;
69597639
RR
375
376 if (GTK_IS_PIZZA(widget))
377 GTK_PIZZA(widget)->m_width = width;
bf3dab48 378
370dc79c 379 gtk_widget_set_size_request (widget, width, height);
bf3dab48 380
6d693bb4 381 return;
c801d85f
KB
382 }
383 }
384}
385
386static void
da048e3d 387gtk_pizza_map (GtkWidget *widget)
c801d85f 388{
da048e3d
RR
389 GtkPizza *pizza;
390 GtkPizzaChild *child;
053f9cc1 391 GList *children;
c801d85f 392
053f9cc1 393 g_return_if_fail (widget != NULL);
da048e3d 394 g_return_if_fail (GTK_IS_PIZZA (widget));
c801d85f 395
053f9cc1 396 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
da048e3d 397 pizza = GTK_PIZZA (widget);
c801d85f 398
da048e3d 399 children = pizza->children;
053f9cc1 400 while (children)
c801d85f 401 {
053f9cc1
RR
402 child = children->data;
403 children = children->next;
c801d85f 404
bf3dab48 405 if ( GTK_WIDGET_VISIBLE (child->widget) &&
efc8ab7c 406 !GTK_WIDGET_MAPPED (child->widget) )
bf3dab48
VZ
407 {
408 gtk_widget_map (child->widget);
409 }
c801d85f 410 }
bf3dab48 411
053f9cc1 412 gdk_window_show (widget->window);
da048e3d 413 gdk_window_show (pizza->bin_window);
c801d85f
KB
414}
415
c801d85f 416static void
da048e3d 417gtk_pizza_realize (GtkWidget *widget)
c801d85f 418{
da048e3d 419 GtkPizza *pizza;
053f9cc1
RR
420 GdkWindowAttr attributes;
421 gint attributes_mask;
da048e3d 422 GtkPizzaChild *child;
ed673c6a 423 GList *children;
c801d85f 424
053f9cc1 425 g_return_if_fail (widget != NULL);
da048e3d 426 g_return_if_fail (GTK_IS_PIZZA (widget));
c801d85f 427
da048e3d 428 pizza = GTK_PIZZA (widget);
053f9cc1 429 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
c801d85f 430
053f9cc1 431 attributes.window_type = GDK_WINDOW_CHILD;
bf3dab48 432
053f9cc1
RR
433 attributes.x = widget->allocation.x;
434 attributes.y = widget->allocation.y;
435 attributes.width = widget->allocation.width;
436 attributes.height = widget->allocation.height;
437
1e6feb95 438#ifndef __WXUNIVERSAL__
da048e3d 439 if (pizza->shadow_type == GTK_MYSHADOW_NONE)
053f9cc1 440 {
5e014a0c 441 /* no border, no changes to sizes */
1e6feb95
VZ
442 }
443 else if (pizza->shadow_type == GTK_MYSHADOW_THIN)
5e014a0c
RR
444 {
445 /* GTK_MYSHADOW_THIN == wxSIMPLE_BORDER */
446 attributes.x += 1;
447 attributes.y += 1;
448 attributes.width -= 2;
449 attributes.height -= 2;
1e6feb95
VZ
450 }
451 else
5e014a0c
RR
452 {
453 /* GTK_MYSHADOW_IN == wxSUNKEN_BORDER */
454 /* GTK_MYSHADOW_OUT == wxRAISED_BORDER */
053f9cc1
RR
455 attributes.x += 2;
456 attributes.y += 2;
457 attributes.width -= 4;
458 attributes.height -= 4;
459 }
1e6feb95 460#endif /* __WXUNIVERSAL__ */
bf3dab48 461
ed673c6a 462 /* minimal size */
053f9cc1
RR
463 if (attributes.width < 2) attributes.width = 2;
464 if (attributes.height < 2) attributes.height = 2;
bf3dab48 465
053f9cc1
RR
466 attributes.wclass = GDK_INPUT_OUTPUT;
467 attributes.visual = gtk_widget_get_visual (widget);
468 attributes.colormap = gtk_widget_get_colormap (widget);
3dd9b88a 469 attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
ed673c6a 470 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
bf3dab48 471
c916e13b 472 widget->window = gdk_window_new(gtk_widget_get_parent_window (widget),
bf3dab48 473 &attributes, attributes_mask);
ed673c6a
RR
474 gdk_window_set_user_data (widget->window, widget);
475
476 attributes.x = 0;
477 attributes.y = 0;
bf3dab48 478
053f9cc1 479 attributes.event_mask = gtk_widget_get_events (widget);
3dd9b88a 480 attributes.event_mask |= GDK_EXPOSURE_MASK |
67d78217 481 GDK_SCROLL_MASK |
3dd9b88a
VZ
482 GDK_POINTER_MOTION_MASK |
483 GDK_POINTER_MOTION_HINT_MASK |
484 GDK_BUTTON_MOTION_MASK |
485 GDK_BUTTON1_MOTION_MASK |
486 GDK_BUTTON2_MOTION_MASK |
487 GDK_BUTTON3_MOTION_MASK |
488 GDK_BUTTON_PRESS_MASK |
489 GDK_BUTTON_RELEASE_MASK |
490 GDK_KEY_PRESS_MASK |
491 GDK_KEY_RELEASE_MASK |
492 GDK_ENTER_NOTIFY_MASK |
493 GDK_LEAVE_NOTIFY_MASK |
494 GDK_FOCUS_CHANGE_MASK;
053f9cc1 495
c916e13b 496 pizza->bin_window = gdk_window_new(widget->window,
bf3dab48 497 &attributes, attributes_mask);
da048e3d 498 gdk_window_set_user_data (pizza->bin_window, widget);
bf3dab48 499
053f9cc1
RR
500 widget->style = gtk_style_attach (widget->style, widget->window);
501 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
b6fa52db 502 gtk_style_set_background (widget->style, pizza->bin_window, GTK_STATE_NORMAL );
17a1ebd1 503
33611ebb
RR
504/*
505 gdk_window_set_back_pixmap( widget->window, NULL, FALSE );
506 gdk_window_set_back_pixmap( pizza->bin_window, NULL, FALSE );
507*/
bf3dab48 508
ed673c6a 509 /* cannot be done before realisation */
da048e3d 510 children = pizza->children;
ed673c6a
RR
511 while (children)
512 {
513 child = children->data;
514 children = children->next;
515
da048e3d 516 gtk_widget_set_parent_window (child->widget, pizza->bin_window);
ed673c6a
RR
517 }
518}
519
bf3dab48 520static void
da048e3d 521gtk_pizza_unrealize (GtkWidget *widget)
ed673c6a 522{
d5ab387d 523 GtkPizza *pizza;
ed673c6a 524
d5ab387d
RR
525 g_return_if_fail (widget != NULL);
526 g_return_if_fail (GTK_IS_PIZZA (widget));
ed673c6a 527
d5ab387d 528 pizza = GTK_PIZZA (widget);
ed673c6a 529
d5ab387d
RR
530 gdk_window_set_user_data (pizza->bin_window, NULL);
531 gdk_window_destroy (pizza->bin_window);
532 pizza->bin_window = NULL;
ed673c6a 533
c764029c
PC
534 if (pizza_parent_class->unrealize)
535 pizza_parent_class->unrealize(widget);
c801d85f
KB
536}
537
538static void
da048e3d 539gtk_pizza_size_request (GtkWidget *widget,
b6fa52db 540 GtkRequisition *requisition)
c801d85f 541{
da048e3d
RR
542 GtkPizza *pizza;
543 GtkPizzaChild *child;
053f9cc1
RR
544 GList *children;
545 GtkRequisition child_requisition;
bf3dab48 546
053f9cc1 547 g_return_if_fail (widget != NULL);
da048e3d 548 g_return_if_fail (GTK_IS_PIZZA (widget));
053f9cc1 549 g_return_if_fail (requisition != NULL);
c801d85f 550
da048e3d 551 pizza = GTK_PIZZA (widget);
bf3dab48 552
da048e3d 553 children = pizza->children;
053f9cc1 554 while (children)
c801d85f 555 {
053f9cc1
RR
556 child = children->data;
557 children = children->next;
c801d85f 558
053f9cc1 559 if (GTK_WIDGET_VISIBLE (child->widget))
bf3dab48 560 {
053f9cc1 561 gtk_widget_size_request (child->widget, &child_requisition);
bf3dab48 562 }
c801d85f 563 }
bf3dab48 564
053f9cc1
RR
565 /* request very little, I'm not sure if requesting nothing
566 will always have positive effects on stability... */
567 requisition->width = 2;
568 requisition->height = 2;
c801d85f
KB
569}
570
571static void
da048e3d 572gtk_pizza_size_allocate (GtkWidget *widget,
b6fa52db 573 GtkAllocation *allocation)
c801d85f 574{
da048e3d 575 GtkPizza *pizza;
053f9cc1 576 gint border;
ed673c6a 577 gint x,y,w,h;
da048e3d 578 GtkPizzaChild *child;
ed673c6a 579 GList *children;
c801d85f 580
053f9cc1 581 g_return_if_fail (widget != NULL);
da048e3d 582 g_return_if_fail (GTK_IS_PIZZA(widget));
053f9cc1 583 g_return_if_fail (allocation != NULL);
c801d85f 584
da048e3d 585 pizza = GTK_PIZZA (widget);
bf3dab48 586
227e5e99 587 widget->allocation = *allocation;
bf3dab48 588
da048e3d 589 if (pizza->shadow_type == GTK_MYSHADOW_NONE)
053f9cc1 590 border = 0;
5e014a0c 591 else
da048e3d 592 if (pizza->shadow_type == GTK_MYSHADOW_THIN)
5e014a0c 593 border = 1;
053f9cc1
RR
594 else
595 border = 2;
bf3dab48 596
ed673c6a
RR
597 x = allocation->x + border;
598 y = allocation->y + border;
599 w = allocation->width - border*2;
600 h = allocation->height - border*2;
69346023
PC
601 if (w < 0)
602 w = 0;
603 if (h < 0)
604 h = 0;
034be888 605
053f9cc1
RR
606 if (GTK_WIDGET_REALIZED (widget))
607 {
ed673c6a 608 gdk_window_move_resize( widget->window, x, y, w, h );
da048e3d 609 gdk_window_move_resize( pizza->bin_window, 0, 0, w, h );
053f9cc1 610 }
bf3dab48 611
da048e3d 612 children = pizza->children;
6d693bb4
RR
613 while (children)
614 {
615 child = children->data;
616 children = children->next;
bf3dab48 617
da048e3d 618 gtk_pizza_allocate_child (pizza, child);
6d693bb4 619 }
c801d85f
KB
620}
621
c801d85f 622static gint
da048e3d 623gtk_pizza_expose (GtkWidget *widget,
b6fa52db 624 GdkEventExpose *event)
c801d85f 625{
b420fb6a 626 GtkPizza *pizza;
b420fb6a
RR
627
628 g_return_val_if_fail (widget != NULL, FALSE);
629 g_return_val_if_fail (GTK_IS_PIZZA (widget), FALSE);
630 g_return_val_if_fail (event != NULL, FALSE);
631
c764029c 632 pizza = (GtkPizza*)widget;
b420fb6a 633
67d78217
RR
634 if (event->window != pizza->bin_window)
635 return FALSE;
4e5a4c69 636
c764029c 637 pizza_parent_class->expose_event(widget, event);
17a1ebd1 638
67d78217 639 return FALSE;
c801d85f
KB
640}
641
22aff579
VS
642static void
643gtk_pizza_style_set(GtkWidget *widget, GtkStyle *previous_style)
644{
645 if (GTK_WIDGET_REALIZED(widget))
646 {
647 gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL);
648 gtk_style_set_background(widget->style, GTK_PIZZA(widget)->bin_window, GTK_STATE_NORMAL );
649 }
650
c764029c 651 pizza_parent_class->style_set(widget, previous_style);
22aff579
VS
652}
653
c801d85f 654static void
da048e3d 655gtk_pizza_add (GtkContainer *container,
bf3dab48 656 GtkWidget *widget)
c801d85f 657{
ed673c6a 658 g_return_if_fail (container != NULL);
da048e3d 659 g_return_if_fail (GTK_IS_PIZZA (container));
ed673c6a 660 g_return_if_fail (widget != NULL);
c801d85f 661
da048e3d 662 gtk_pizza_put (GTK_PIZZA (container), widget, 0, 0, 20, 20 );
c801d85f
KB
663}
664
665static void
da048e3d 666gtk_pizza_remove (GtkContainer *container,
b6fa52db 667 GtkWidget *widget)
c801d85f 668{
da048e3d
RR
669 GtkPizza *pizza;
670 GtkPizzaChild *child;
ed673c6a 671 GList *children;
c801d85f 672
ed673c6a 673 g_return_if_fail (container != NULL);
da048e3d 674 g_return_if_fail (GTK_IS_PIZZA (container));
ed673c6a 675 g_return_if_fail (widget != NULL);
c801d85f 676
da048e3d 677 pizza = GTK_PIZZA (container);
c801d85f 678
da048e3d 679 children = pizza->children;
ed673c6a 680 while (children)
c801d85f 681 {
ed673c6a 682 child = children->data;
c801d85f 683
ed673c6a 684 if (child->widget == widget)
bf3dab48
VZ
685 {
686 gtk_widget_unparent (widget);
c801d85f 687
ed673c6a
RR
688 /* security checks */
689 g_return_if_fail (GTK_IS_WIDGET (widget));
bf3dab48
VZ
690
691 pizza->children = g_list_remove_link (pizza->children, children);
692 g_list_free (children);
693 g_free (child);
c801d85f 694
ed673c6a 695 /* security checks */
bf3dab48
VZ
696 g_return_if_fail (GTK_IS_WIDGET (widget));
697
bf3dab48
VZ
698 break;
699 }
c801d85f 700
ed673c6a 701 children = children->next;
c801d85f
KB
702 }
703}
704
705static void
da048e3d 706gtk_pizza_forall (GtkContainer *container,
b6fa52db
RR
707 gboolean include_internals,
708 GtkCallback callback,
709 gpointer callback_data)
c801d85f 710{
da048e3d
RR
711 GtkPizza *pizza;
712 GtkPizzaChild *child;
6d693bb4 713 GList *children;
c801d85f 714
6d693bb4 715 g_return_if_fail (container != NULL);
da048e3d 716 g_return_if_fail (GTK_IS_PIZZA (container));
90350682 717 g_return_if_fail (callback != (GtkCallback)NULL);
c801d85f 718
da048e3d 719 pizza = GTK_PIZZA (container);
c801d85f 720
da048e3d 721 children = pizza->children;
6d693bb4 722 while (children)
c801d85f 723 {
6d693bb4
RR
724 child = children->data;
725 children = children->next;
c801d85f 726
6d693bb4 727 (* callback) (child->widget, callback_data);
c801d85f
KB
728 }
729}
730
67d78217
RR
731static void
732gtk_pizza_allocate_child (GtkPizza *pizza,
733 GtkPizzaChild *child)
734{
735 GtkAllocation allocation;
736 GtkRequisition requisition;
c801d85f 737
a31bb944
RR
738 allocation.x = child->x - pizza->m_xoffset;
739 allocation.y = child->y - pizza->m_yoffset;
67d78217
RR
740 gtk_widget_get_child_requisition (child->widget, &requisition);
741 allocation.width = requisition.width;
742 allocation.height = requisition.height;
743
744 gtk_widget_size_allocate (child->widget, &allocation);
745}
ed673c6a 746
ed673c6a 747static void
da048e3d 748gtk_pizza_adjust_allocations_recurse (GtkWidget *widget,
bf3dab48 749 gpointer cb_data)
ed673c6a 750{
da048e3d 751 GtkPizzaAdjData *data = cb_data;
ed673c6a 752
6d693bb4
RR
753 widget->allocation.x += data->dx;
754 widget->allocation.y += data->dy;
ed673c6a 755
6d693bb4
RR
756 if (GTK_WIDGET_NO_WINDOW (widget) && GTK_IS_CONTAINER (widget))
757 {
bf3dab48
VZ
758 gtk_container_forall (GTK_CONTAINER (widget),
759 gtk_pizza_adjust_allocations_recurse,
760 cb_data);
6d693bb4 761 }
ed673c6a
RR
762}
763
764static void
da048e3d 765gtk_pizza_adjust_allocations (GtkPizza *pizza,
bf3dab48
VZ
766 gint dx,
767 gint dy)
ed673c6a 768{
0e09f76e
RR
769 GList *tmp_list;
770 GtkPizzaAdjData data;
ed673c6a 771
0e09f76e
RR
772 data.dx = dx;
773 data.dy = dy;
ed673c6a 774
0e09f76e
RR
775 tmp_list = pizza->children;
776 while (tmp_list)
ed673c6a 777 {
0e09f76e
RR
778 GtkPizzaChild *child = tmp_list->data;
779 tmp_list = tmp_list->next;
bf3dab48 780
0e09f76e
RR
781 child->widget->allocation.x += dx;
782 child->widget->allocation.y += dy;
ed673c6a 783
0e09f76e
RR
784 if (GTK_WIDGET_NO_WINDOW (child->widget) &&
785 GTK_IS_CONTAINER (child->widget))
786 {
787 gtk_container_forall (GTK_CONTAINER (child->widget),
788 gtk_pizza_adjust_allocations_recurse,
789 &data);
790 }
ed673c6a
RR
791 }
792}
bf3dab48 793
ed673c6a 794void
da048e3d 795gtk_pizza_scroll (GtkPizza *pizza, gint dx, gint dy)
ed673c6a 796{
a31bb944
RR
797 pizza->m_xoffset += dx;
798 pizza->m_yoffset += dy;
3fc6e5fa
RR
799
800 gtk_pizza_adjust_allocations (pizza, -dx, -dy);
801
802 if (pizza->bin_window)
803 gdk_window_scroll( pizza->bin_window, -dx, -dy );
ed673c6a
RR
804}
805
c801d85f
KB
806#ifdef __cplusplus
807}
808#endif /* __cplusplus */