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