]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/win_gtk.c
Fix scrolling bug where client size was reported wrong
[wxWidgets.git] / src / gtk / win_gtk.c
1 /* ///////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/win_gtk.c
3 // Purpose: Native GTK+ widget for wxWidgets, based on GtkLayout and
4 // GtkFixed. It makes use of the gravity window property and
5 // therefore does not work with GTK 1.0.
6 // Author: Robert Roebling
7 // Id: $Id$
8 // Copyright: (c) 1998 Robert Roebling
9 // Licence: wxWidgets licence
10 /////////////////////////////////////////////////////////////////////////// */
11
12 #ifdef VMS
13 #define XCheckIfEvent XCHECKIFEVENT
14 #endif
15
16 #include "wx/platform.h"
17 #include "wx/gtk/win_gtk.h"
18
19 #ifdef __cplusplus
20 extern "C" {
21 #endif /* __cplusplus */
22
23 typedef struct _GtkPizzaAdjData GtkPizzaAdjData;
24
25 struct _GtkPizzaAdjData
26 {
27 gint dx;
28 gint dy;
29 };
30
31 static void gtk_pizza_class_init (GtkPizzaClass *klass);
32 static void gtk_pizza_init (GtkPizza *pizza);
33
34 static void gtk_pizza_realize (GtkWidget *widget);
35 static void gtk_pizza_unrealize (GtkWidget *widget);
36
37 static void gtk_pizza_map (GtkWidget *widget);
38
39 static void gtk_pizza_size_request (GtkWidget *widget,
40 GtkRequisition *requisition);
41 static void gtk_pizza_size_allocate (GtkWidget *widget,
42 GtkAllocation *allocation);
43 static gint gtk_pizza_expose (GtkWidget *widget,
44 GdkEventExpose *event);
45 static void gtk_pizza_style_set (GtkWidget *widget,
46 GtkStyle *previous_style);
47 static void gtk_pizza_add (GtkContainer *container,
48 GtkWidget *widget);
49 static void gtk_pizza_remove (GtkContainer *container,
50 GtkWidget *widget);
51 static void gtk_pizza_forall (GtkContainer *container,
52 gboolean include_internals,
53 GtkCallback callback,
54 gpointer callback_data);
55
56 static void gtk_pizza_allocate_child (GtkPizza *pizza,
57 GtkPizzaChild *child);
58 static void gtk_pizza_adjust_allocations_recurse (GtkWidget *widget,
59 gpointer cb_data);
60
61 static GtkType gtk_pizza_child_type (GtkContainer *container);
62
63 static void gtk_pizza_scroll_set_adjustments (GtkPizza *pizza,
64 GtkAdjustment *hadj,
65 GtkAdjustment *vadj);
66
67 static GtkWidgetClass* pizza_parent_class;
68
69 GtkType
70 gtk_pizza_get_type ()
71 {
72 static GtkType pizza_type = 0;
73
74 if (!pizza_type)
75 {
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 };
88 pizza_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkPizza", &pizza_info, (GTypeFlags)0);
89 }
90
91 return pizza_type;
92 }
93
94 /* Marshaller needed for set_scroll_adjustments signal,
95 generated with GLib-2.4.6 glib-genmarshal */
96 #define g_marshal_value_peek_object(v) g_value_get_object (v)
97 static void
98 g_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 }
132
133 static void
134 gtk_pizza_class_init (GtkPizzaClass *klass)
135 {
136 GtkObjectClass *object_class;
137 GtkWidgetClass *widget_class;
138 GtkContainerClass *container_class;
139
140 object_class = (GtkObjectClass*) klass;
141 widget_class = (GtkWidgetClass*) klass;
142 container_class = (GtkContainerClass*) klass;
143 pizza_parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
144
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->expose_event = gtk_pizza_expose;
151 widget_class->style_set = gtk_pizza_style_set;
152
153 container_class->add = gtk_pizza_add;
154 container_class->remove = gtk_pizza_remove;
155 container_class->forall = gtk_pizza_forall;
156
157 container_class->child_type = gtk_pizza_child_type;
158
159 klass->set_scroll_adjustments = gtk_pizza_scroll_set_adjustments;
160
161 widget_class->set_scroll_adjustments_signal =
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);
174 }
175
176 static GtkType
177 gtk_pizza_child_type (GtkContainer *container)
178 {
179 return GTK_TYPE_WIDGET;
180 }
181
182 static void
183 gtk_pizza_init (GtkPizza *pizza)
184 {
185 GTK_WIDGET_UNSET_FLAGS (pizza, GTK_NO_WINDOW);
186
187 pizza->shadow_type = GTK_MYSHADOW_NONE;
188
189 pizza->children = NULL;
190
191 pizza->bin_window = NULL;
192
193 pizza->m_xoffset = 0;
194 pizza->m_yoffset = 0;
195
196 pizza->m_width = -1;
197 }
198
199 GtkWidget*
200 gtk_pizza_new ()
201 {
202 GtkPizza *pizza;
203
204 pizza = g_object_new (gtk_pizza_get_type (), NULL);
205
206 return GTK_WIDGET (pizza);
207 }
208
209 gint 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
217 gint 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
225 void 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
234 void 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
243 gint 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
258 static void
259 gtk_pizza_scroll_set_adjustments (GtkPizza *pizza,
260 GtkAdjustment *hadj,
261 GtkAdjustment *vadj)
262 {
263 /* We handle scrolling in the wxScrolledWindow, not here. */
264 }
265
266 void
267 gtk_pizza_set_shadow_type (GtkPizza *pizza,
268 GtkMyShadowType type)
269 {
270 g_return_if_fail (pizza != NULL);
271 g_return_if_fail (GTK_IS_PIZZA (pizza));
272
273 if (pizza->shadow_type != type)
274 {
275 pizza->shadow_type = type;
276
277 if (GTK_WIDGET_VISIBLE (pizza))
278 {
279 gtk_widget_size_allocate (GTK_WIDGET (pizza), &(GTK_WIDGET (pizza)->allocation));
280 gtk_widget_queue_draw (GTK_WIDGET (pizza));
281 }
282 }
283 }
284
285 void
286 gtk_pizza_put (GtkPizza *pizza,
287 GtkWidget *widget,
288 gint x,
289 gint y,
290 gint width,
291 gint height)
292 {
293 GtkPizzaChild *child_info;
294
295 g_return_if_fail (pizza != NULL);
296 g_return_if_fail (GTK_IS_PIZZA (pizza));
297 g_return_if_fail (widget != NULL);
298
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
305 child_info = g_new (GtkPizzaChild, 1);
306
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;
312
313 if (GTK_IS_PIZZA(widget))
314 GTK_PIZZA(widget)->m_width = width;
315
316 pizza->children = g_list_append (pizza->children, child_info);
317
318 if (GTK_WIDGET_REALIZED (pizza))
319 gtk_widget_set_parent_window (widget, pizza->bin_window);
320
321 gtk_widget_set_parent (widget, GTK_WIDGET (pizza));
322
323 gtk_widget_set_size_request (widget, width, height);
324 }
325
326 void
327 gtk_pizza_set_size (GtkPizza *pizza,
328 GtkWidget *widget,
329 gint x,
330 gint y,
331 gint width,
332 gint height)
333 {
334 GtkPizzaChild *child;
335 GList *children;
336
337 g_return_if_fail (pizza != NULL);
338 g_return_if_fail (GTK_IS_PIZZA (pizza));
339 g_return_if_fail (widget != NULL);
340
341 #ifndef WX_WARN_ILLEGAL_SETSIZE
342 /* this really shouldn't happen -- but it does, a lot, right now and we
343 can't pass negative values to gtk_widget_set_size_request() without getting
344 a warning printed out, so filter them out here */
345 if ( width < 0 )
346 width = 0;
347 if ( height < 0 )
348 height = 0;
349 #endif
350
351 children = pizza->children;
352 while (children)
353 {
354 child = children->data;
355 children = children->next;
356
357 if (child->widget == widget)
358 {
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) &&
367 (child->y == y) &&
368 (child->width == width) &&
369 (child->height == height)) return;
370
371 child->x = new_x;
372 child->y = y;
373 child->width = width;
374 child->height = height;
375
376 if (GTK_IS_PIZZA(widget))
377 GTK_PIZZA(widget)->m_width = width;
378
379 gtk_widget_set_size_request (widget, width, height);
380
381 return;
382 }
383 }
384 }
385
386 static void
387 gtk_pizza_map (GtkWidget *widget)
388 {
389 GtkPizza *pizza;
390 GtkPizzaChild *child;
391 GList *children;
392
393 g_return_if_fail (widget != NULL);
394 g_return_if_fail (GTK_IS_PIZZA (widget));
395
396 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
397 pizza = GTK_PIZZA (widget);
398
399 children = pizza->children;
400 while (children)
401 {
402 child = children->data;
403 children = children->next;
404
405 if ( GTK_WIDGET_VISIBLE (child->widget) &&
406 !GTK_WIDGET_MAPPED (child->widget) )
407 {
408 gtk_widget_map (child->widget);
409 }
410 }
411
412 gdk_window_show (widget->window);
413 gdk_window_show (pizza->bin_window);
414 }
415
416 static void
417 gtk_pizza_realize (GtkWidget *widget)
418 {
419 GtkPizza *pizza;
420 GdkWindowAttr attributes;
421 gint attributes_mask;
422 GtkPizzaChild *child;
423 GList *children;
424
425 g_return_if_fail (widget != NULL);
426 g_return_if_fail (GTK_IS_PIZZA (widget));
427
428 pizza = GTK_PIZZA (widget);
429 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
430
431 attributes.window_type = GDK_WINDOW_CHILD;
432
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
438 #ifndef __WXUNIVERSAL__
439 if (pizza->shadow_type == GTK_MYSHADOW_NONE)
440 {
441 /* no border, no changes to sizes */
442 }
443 else if (pizza->shadow_type == GTK_MYSHADOW_THIN)
444 {
445 /* GTK_MYSHADOW_THIN == wxSIMPLE_BORDER */
446 attributes.x += 1;
447 attributes.y += 1;
448 attributes.width -= 2;
449 attributes.height -= 2;
450 }
451 else
452 {
453 /* GTK_MYSHADOW_IN == wxSUNKEN_BORDER */
454 /* GTK_MYSHADOW_OUT == wxRAISED_BORDER */
455 attributes.x += 2;
456 attributes.y += 2;
457 attributes.width -= 4;
458 attributes.height -= 4;
459 }
460 #endif /* __WXUNIVERSAL__ */
461
462 /* minimal size */
463 if (attributes.width < 2) attributes.width = 2;
464 if (attributes.height < 2) attributes.height = 2;
465
466 attributes.wclass = GDK_INPUT_OUTPUT;
467 attributes.visual = gtk_widget_get_visual (widget);
468 attributes.colormap = gtk_widget_get_colormap (widget);
469 attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
470 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
471
472 widget->window = gdk_window_new(gtk_widget_get_parent_window (widget),
473 &attributes, attributes_mask);
474 gdk_window_set_user_data (widget->window, widget);
475
476 attributes.x = 0;
477 attributes.y = 0;
478
479 attributes.event_mask = gtk_widget_get_events (widget);
480 attributes.event_mask |= GDK_EXPOSURE_MASK |
481 GDK_SCROLL_MASK |
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;
495
496 pizza->bin_window = gdk_window_new(widget->window,
497 &attributes, attributes_mask);
498 gdk_window_set_user_data (pizza->bin_window, widget);
499
500 widget->style = gtk_style_attach (widget->style, widget->window);
501 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
502 gtk_style_set_background (widget->style, pizza->bin_window, GTK_STATE_NORMAL );
503
504 /*
505 gdk_window_set_back_pixmap( widget->window, NULL, FALSE );
506 gdk_window_set_back_pixmap( pizza->bin_window, NULL, FALSE );
507 */
508
509 /* cannot be done before realisation */
510 children = pizza->children;
511 while (children)
512 {
513 child = children->data;
514 children = children->next;
515
516 gtk_widget_set_parent_window (child->widget, pizza->bin_window);
517 }
518 }
519
520 static void
521 gtk_pizza_unrealize (GtkWidget *widget)
522 {
523 GtkPizza *pizza;
524
525 g_return_if_fail (widget != NULL);
526 g_return_if_fail (GTK_IS_PIZZA (widget));
527
528 pizza = GTK_PIZZA (widget);
529
530 gdk_window_set_user_data (pizza->bin_window, NULL);
531 gdk_window_destroy (pizza->bin_window);
532 pizza->bin_window = NULL;
533
534 if (pizza_parent_class->unrealize)
535 pizza_parent_class->unrealize(widget);
536 }
537
538 static void
539 gtk_pizza_size_request (GtkWidget *widget,
540 GtkRequisition *requisition)
541 {
542 GtkPizza *pizza;
543 GtkPizzaChild *child;
544 GList *children;
545 GtkRequisition child_requisition;
546
547 g_return_if_fail (widget != NULL);
548 g_return_if_fail (GTK_IS_PIZZA (widget));
549 g_return_if_fail (requisition != NULL);
550
551 pizza = GTK_PIZZA (widget);
552
553 children = pizza->children;
554 while (children)
555 {
556 child = children->data;
557 children = children->next;
558
559 if (GTK_WIDGET_VISIBLE (child->widget))
560 {
561 gtk_widget_size_request (child->widget, &child_requisition);
562 }
563 }
564
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;
569 }
570
571 static void
572 gtk_pizza_size_allocate (GtkWidget *widget,
573 GtkAllocation *allocation)
574 {
575 GtkPizza *pizza;
576 gint border;
577 gint x,y,w,h;
578 GtkPizzaChild *child;
579 GList *children;
580
581 g_return_if_fail (widget != NULL);
582 g_return_if_fail (GTK_IS_PIZZA(widget));
583 g_return_if_fail (allocation != NULL);
584
585 pizza = GTK_PIZZA (widget);
586
587 widget->allocation = *allocation;
588
589 if (pizza->shadow_type == GTK_MYSHADOW_NONE)
590 border = 0;
591 else
592 if (pizza->shadow_type == GTK_MYSHADOW_THIN)
593 border = 1;
594 else
595 border = 2;
596
597 x = allocation->x + border;
598 y = allocation->y + border;
599 w = allocation->width - border*2;
600 h = allocation->height - border*2;
601 if (w < 0)
602 w = 0;
603 if (h < 0)
604 h = 0;
605
606 if (GTK_WIDGET_REALIZED (widget))
607 {
608 gdk_window_move_resize( widget->window, x, y, w, h );
609 gdk_window_move_resize( pizza->bin_window, 0, 0, w, h );
610 }
611
612 children = pizza->children;
613 while (children)
614 {
615 child = children->data;
616 children = children->next;
617
618 gtk_pizza_allocate_child (pizza, child);
619 }
620 }
621
622 static gint
623 gtk_pizza_expose (GtkWidget *widget,
624 GdkEventExpose *event)
625 {
626 GtkPizza *pizza;
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
632 pizza = (GtkPizza*)widget;
633
634 if (event->window != pizza->bin_window)
635 return FALSE;
636
637 pizza_parent_class->expose_event(widget, event);
638
639 return FALSE;
640 }
641
642 static void
643 gtk_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
651 pizza_parent_class->style_set(widget, previous_style);
652 }
653
654 static void
655 gtk_pizza_add (GtkContainer *container,
656 GtkWidget *widget)
657 {
658 g_return_if_fail (container != NULL);
659 g_return_if_fail (GTK_IS_PIZZA (container));
660 g_return_if_fail (widget != NULL);
661
662 gtk_pizza_put (GTK_PIZZA (container), widget, 0, 0, 20, 20 );
663 }
664
665 static void
666 gtk_pizza_remove (GtkContainer *container,
667 GtkWidget *widget)
668 {
669 GtkPizza *pizza;
670 GtkPizzaChild *child;
671 GList *children;
672
673 g_return_if_fail (container != NULL);
674 g_return_if_fail (GTK_IS_PIZZA (container));
675 g_return_if_fail (widget != NULL);
676
677 pizza = GTK_PIZZA (container);
678
679 children = pizza->children;
680 while (children)
681 {
682 child = children->data;
683
684 if (child->widget == widget)
685 {
686 gtk_widget_unparent (widget);
687
688 /* security checks */
689 g_return_if_fail (GTK_IS_WIDGET (widget));
690
691 pizza->children = g_list_remove_link (pizza->children, children);
692 g_list_free (children);
693 g_free (child);
694
695 /* security checks */
696 g_return_if_fail (GTK_IS_WIDGET (widget));
697
698 break;
699 }
700
701 children = children->next;
702 }
703 }
704
705 static void
706 gtk_pizza_forall (GtkContainer *container,
707 gboolean include_internals,
708 GtkCallback callback,
709 gpointer callback_data)
710 {
711 GtkPizza *pizza;
712 GtkPizzaChild *child;
713 GList *children;
714
715 g_return_if_fail (container != NULL);
716 g_return_if_fail (GTK_IS_PIZZA (container));
717 g_return_if_fail (callback != (GtkCallback)NULL);
718
719 pizza = GTK_PIZZA (container);
720
721 children = pizza->children;
722 while (children)
723 {
724 child = children->data;
725 children = children->next;
726
727 (* callback) (child->widget, callback_data);
728 }
729 }
730
731 static void
732 gtk_pizza_allocate_child (GtkPizza *pizza,
733 GtkPizzaChild *child)
734 {
735 GtkAllocation allocation;
736 GtkRequisition requisition;
737
738 allocation.x = child->x - pizza->m_xoffset;
739 allocation.y = child->y - pizza->m_yoffset;
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 }
746
747 static void
748 gtk_pizza_adjust_allocations_recurse (GtkWidget *widget,
749 gpointer cb_data)
750 {
751 GtkPizzaAdjData *data = cb_data;
752
753 widget->allocation.x += data->dx;
754 widget->allocation.y += data->dy;
755
756 if (GTK_WIDGET_NO_WINDOW (widget) && GTK_IS_CONTAINER (widget))
757 {
758 gtk_container_forall (GTK_CONTAINER (widget),
759 gtk_pizza_adjust_allocations_recurse,
760 cb_data);
761 }
762 }
763
764 static void
765 gtk_pizza_adjust_allocations (GtkPizza *pizza,
766 gint dx,
767 gint dy)
768 {
769 GList *tmp_list;
770 GtkPizzaAdjData data;
771
772 data.dx = dx;
773 data.dy = dy;
774
775 tmp_list = pizza->children;
776 while (tmp_list)
777 {
778 GtkPizzaChild *child = tmp_list->data;
779 tmp_list = tmp_list->next;
780
781 child->widget->allocation.x += dx;
782 child->widget->allocation.y += dy;
783
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 }
791 }
792 }
793
794 void
795 gtk_pizza_scroll (GtkPizza *pizza, gint dx, gint dy)
796 {
797 pizza->m_xoffset += dx;
798 pizza->m_yoffset += dy;
799
800 gtk_pizza_adjust_allocations (pizza, -dx, -dy);
801
802 if (pizza->bin_window)
803 gdk_window_scroll( pizza->bin_window, -dx, -dy );
804 }
805
806 #ifdef __cplusplus
807 }
808 #endif /* __cplusplus */