]> Pileus Git - ~andy/gtk/blob - gtk/gtkviewport.c
Patch from Matthias Clasen to remove remove all instances of
[~andy/gtk] / gtk / gtkviewport.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "gtksignal.h"
28 #include "gtkviewport.h"
29 #include "gtkintl.h"
30
31 enum {
32   PROP_0,
33   PROP_HADJUSTMENT,
34   PROP_VADJUSTMENT,
35   PROP_SHADOW_TYPE
36 };
37
38
39 static void gtk_viewport_class_init               (GtkViewportClass *klass);
40 static void gtk_viewport_init                     (GtkViewport      *viewport);
41 static void gtk_viewport_destroy                  (GtkObject        *object);
42 static void gtk_viewport_set_property             (GObject         *object,
43                                                    guint            prop_id,
44                                                    const GValue    *value,
45                                                    GParamSpec      *pspec);
46 static void gtk_viewport_get_property             (GObject         *object,
47                                                    guint            prop_id,
48                                                    GValue          *value,
49                                                    GParamSpec      *pspec);
50 static void gtk_viewport_set_scroll_adjustments   (GtkViewport      *viewport,
51                                                    GtkAdjustment    *hadjustment,
52                                                    GtkAdjustment    *vadjustment);
53 static void gtk_viewport_map                      (GtkWidget        *widget);
54 static void gtk_viewport_unmap                    (GtkWidget        *widget);
55 static void gtk_viewport_realize                  (GtkWidget        *widget);
56 static void gtk_viewport_unrealize                (GtkWidget        *widget);
57 static void gtk_viewport_paint                    (GtkWidget        *widget,
58                                                    GdkRectangle     *area);
59 static gint gtk_viewport_expose                   (GtkWidget        *widget,
60                                                    GdkEventExpose   *event);
61 static void gtk_viewport_add                      (GtkContainer     *container,
62                                                    GtkWidget        *widget);
63 static void gtk_viewport_size_request             (GtkWidget        *widget,
64                                                    GtkRequisition   *requisition);
65 static void gtk_viewport_size_allocate            (GtkWidget        *widget,
66                                                    GtkAllocation    *allocation);
67 static void gtk_viewport_adjustment_changed       (GtkAdjustment    *adjustment,
68                                                    gpointer          data);
69 static void gtk_viewport_adjustment_value_changed (GtkAdjustment    *adjustment,
70                                                    gpointer          data);
71 static void gtk_viewport_style_set                (GtkWidget *widget,
72                                                    GtkStyle  *previous_style);
73
74 static GtkBinClass *parent_class;
75
76 GtkType
77 gtk_viewport_get_type (void)
78 {
79   static GtkType viewport_type = 0;
80
81   if (!viewport_type)
82     {
83       static const GtkTypeInfo viewport_info =
84       {
85         "GtkViewport",
86         sizeof (GtkViewport),
87         sizeof (GtkViewportClass),
88         (GtkClassInitFunc) gtk_viewport_class_init,
89         (GtkObjectInitFunc) gtk_viewport_init,
90         /* reserved_1 */ NULL,
91         /* reserved_2 */ NULL,
92         (GtkClassInitFunc) NULL,
93       };
94
95       viewport_type = gtk_type_unique (GTK_TYPE_BIN, &viewport_info);
96     }
97
98   return viewport_type;
99 }
100
101 static void
102 gtk_viewport_class_init (GtkViewportClass *class)
103 {
104   GtkObjectClass *object_class;
105   GObjectClass   *gobject_class;
106   GtkWidgetClass *widget_class;
107   GtkContainerClass *container_class;
108
109   object_class = (GtkObjectClass*) class;
110   gobject_class = G_OBJECT_CLASS (class);
111   widget_class = (GtkWidgetClass*) class;
112   container_class = (GtkContainerClass*) class;
113   parent_class = (GtkBinClass*) gtk_type_class (GTK_TYPE_BIN);
114
115   gobject_class->set_property = gtk_viewport_set_property;
116   gobject_class->get_property = gtk_viewport_get_property;
117   object_class->destroy = gtk_viewport_destroy;
118   
119   widget_class->map = gtk_viewport_map;
120   widget_class->unmap = gtk_viewport_unmap;
121   widget_class->realize = gtk_viewport_realize;
122   widget_class->unrealize = gtk_viewport_unrealize;
123   widget_class->expose_event = gtk_viewport_expose;
124   widget_class->size_request = gtk_viewport_size_request;
125   widget_class->size_allocate = gtk_viewport_size_allocate;
126   widget_class->style_set = gtk_viewport_style_set;
127   
128   container_class->add = gtk_viewport_add;
129
130   class->set_scroll_adjustments = gtk_viewport_set_scroll_adjustments;
131
132   g_object_class_install_property (gobject_class,
133                                    PROP_HADJUSTMENT,
134                                    g_param_spec_object ("hadjustment",
135                                                         _("Horizontal adjustment"),
136                                                         _("The GtkAdjustment that determines the values of the horizontal position for this viewport."),
137                                                         GTK_TYPE_ADJUSTMENT,
138                                                         G_PARAM_READWRITE));
139
140   g_object_class_install_property (gobject_class,
141                                    PROP_VADJUSTMENT,
142                                    g_param_spec_object ("vadjustment",
143                                                         _("Vertical adjustment"),
144                                                         _("The GtkAdjustment that determines the values of the vertical position for this viewport."),
145                                                         GTK_TYPE_ADJUSTMENT,
146                                                         G_PARAM_READWRITE));
147
148   g_object_class_install_property (gobject_class,
149                                    PROP_SHADOW_TYPE,
150                                    g_param_spec_enum ("shadow_type",
151                                                       _("Shadow type"),
152                                                       _("Determines how the shadowed box around the viewport is drawn."),
153                                                       GTK_TYPE_SHADOW_TYPE,
154                                                       GTK_SHADOW_IN,
155                                                       G_PARAM_READWRITE));
156
157   widget_class->set_scroll_adjustments_signal =
158     gtk_signal_new ("set_scroll_adjustments",
159                     GTK_RUN_LAST,
160                     GTK_CLASS_TYPE (object_class),
161                     GTK_SIGNAL_OFFSET (GtkViewportClass, set_scroll_adjustments),
162                     gtk_marshal_VOID__OBJECT_OBJECT,
163                     GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
164 }
165
166 static void
167 gtk_viewport_set_property (GObject         *object,
168                            guint            prop_id,
169                            const GValue    *value,
170                            GParamSpec      *pspec)
171 {
172   GtkViewport *viewport;
173
174   viewport = GTK_VIEWPORT (object);
175
176   switch (prop_id)
177     {
178     case PROP_HADJUSTMENT:
179       gtk_viewport_set_hadjustment (viewport, g_value_get_object (value));
180       break;
181     case PROP_VADJUSTMENT:
182       gtk_viewport_set_vadjustment (viewport, g_value_get_object (value));
183       break;
184     case PROP_SHADOW_TYPE:
185       gtk_viewport_set_shadow_type (viewport, g_value_get_enum (value));
186       break;
187     default:
188       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
189       break;
190     }
191 }
192
193 static void
194 gtk_viewport_get_property (GObject         *object,
195                            guint            prop_id,
196                            GValue          *value,
197                            GParamSpec      *pspec)
198 {
199   GtkViewport *viewport;
200
201   viewport = GTK_VIEWPORT (object);
202
203   switch (prop_id)
204     {
205     case PROP_HADJUSTMENT:
206       g_value_set_object (value, G_OBJECT (viewport->hadjustment));
207       break;
208     case PROP_VADJUSTMENT:
209       g_value_set_object (value, G_OBJECT (viewport->vadjustment));
210       break;
211     case PROP_SHADOW_TYPE:
212       g_value_set_enum (value, viewport->shadow_type);
213       break;
214     default:
215       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
216       break;
217     }
218 }
219
220 static void
221 gtk_viewport_init (GtkViewport *viewport)
222 {
223   GTK_WIDGET_UNSET_FLAGS (viewport, GTK_NO_WINDOW);
224
225   gtk_container_set_resize_mode (GTK_CONTAINER (viewport), GTK_RESIZE_QUEUE);
226   
227   viewport->shadow_type = GTK_SHADOW_IN;
228   viewport->view_window = NULL;
229   viewport->bin_window = NULL;
230   viewport->hadjustment = NULL;
231   viewport->vadjustment = NULL;
232 }
233
234 GtkWidget*
235 gtk_viewport_new (GtkAdjustment *hadjustment,
236                   GtkAdjustment *vadjustment)
237 {
238   GtkWidget *viewport;
239
240   viewport = gtk_widget_new (GTK_TYPE_VIEWPORT,
241                              "hadjustment", hadjustment,
242                              "vadjustment", vadjustment,
243                              NULL);
244
245   return viewport;
246 }
247
248 static void
249 gtk_viewport_destroy (GtkObject *object)
250 {
251   GtkViewport *viewport = GTK_VIEWPORT (object);
252
253   if (viewport->hadjustment)
254     {
255       gtk_signal_disconnect_by_data (GTK_OBJECT (viewport->hadjustment), viewport);
256       gtk_object_unref (GTK_OBJECT (viewport->hadjustment));
257       viewport->hadjustment = NULL;
258     }
259   if (viewport->vadjustment)
260     {
261       gtk_signal_disconnect_by_data (GTK_OBJECT (viewport->vadjustment), viewport);
262       gtk_object_unref (GTK_OBJECT (viewport->vadjustment));
263       viewport->vadjustment = NULL;
264     }
265
266   GTK_OBJECT_CLASS (parent_class)->destroy (object);
267 }
268
269 GtkAdjustment*
270 gtk_viewport_get_hadjustment (GtkViewport *viewport)
271 {
272   g_return_val_if_fail (GTK_IS_VIEWPORT (viewport), NULL);
273
274   if (!viewport->hadjustment)
275     gtk_viewport_set_hadjustment (viewport, NULL);
276
277   return viewport->hadjustment;
278 }
279
280 GtkAdjustment*
281 gtk_viewport_get_vadjustment (GtkViewport *viewport)
282 {
283   g_return_val_if_fail (GTK_IS_VIEWPORT (viewport), NULL);
284
285   if (!viewport->vadjustment)
286     gtk_viewport_set_vadjustment (viewport, NULL);
287
288   return viewport->vadjustment;
289 }
290
291 void
292 gtk_viewport_set_hadjustment (GtkViewport   *viewport,
293                               GtkAdjustment *adjustment)
294 {
295   g_return_if_fail (GTK_IS_VIEWPORT (viewport));
296   if (adjustment)
297     g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
298
299   if (viewport->hadjustment && viewport->hadjustment != adjustment)
300     {
301       gtk_signal_disconnect_by_data (GTK_OBJECT (viewport->hadjustment), viewport);
302       gtk_object_unref (GTK_OBJECT (viewport->hadjustment));
303       viewport->hadjustment = NULL;
304     }
305
306   if (!adjustment)
307     adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0,
308                                                      0.0, 0.0, 0.0));
309
310   if (viewport->hadjustment != adjustment)
311     {
312       viewport->hadjustment = adjustment;
313       gtk_object_ref (GTK_OBJECT (viewport->hadjustment));
314       gtk_object_sink (GTK_OBJECT (viewport->hadjustment));
315       
316       gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
317                           (GtkSignalFunc) gtk_viewport_adjustment_changed,
318                           (gpointer) viewport);
319       gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
320                           (GtkSignalFunc) gtk_viewport_adjustment_value_changed,
321                           (gpointer) viewport);
322
323       gtk_viewport_adjustment_changed (adjustment, viewport);
324     }
325
326   g_object_notify (G_OBJECT (viewport), "hadjustment");
327 }
328
329 void
330 gtk_viewport_set_vadjustment (GtkViewport   *viewport,
331                               GtkAdjustment *adjustment)
332 {
333   g_return_if_fail (GTK_IS_VIEWPORT (viewport));
334   if (adjustment)
335     g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
336
337   if (viewport->vadjustment && viewport->vadjustment != adjustment)
338     {
339       gtk_signal_disconnect_by_data (GTK_OBJECT (viewport->vadjustment), viewport);
340       gtk_object_unref (GTK_OBJECT (viewport->vadjustment));
341       viewport->vadjustment = NULL;
342     }
343
344   if (!adjustment)
345     adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0,
346                                                      0.0, 0.0, 0.0));
347
348   if (viewport->vadjustment != adjustment)
349     {
350       viewport->vadjustment = adjustment;
351       gtk_object_ref (GTK_OBJECT (viewport->vadjustment));
352       gtk_object_sink (GTK_OBJECT (viewport->vadjustment));
353       
354       gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
355                           (GtkSignalFunc) gtk_viewport_adjustment_changed,
356                           (gpointer) viewport);
357       gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
358                           (GtkSignalFunc) gtk_viewport_adjustment_value_changed,
359                           (gpointer) viewport);
360
361       gtk_viewport_adjustment_changed (adjustment, viewport);
362     }
363
364   g_object_notify (G_OBJECT (viewport), "vadjustment");
365 }
366
367 static void
368 gtk_viewport_set_scroll_adjustments (GtkViewport      *viewport,
369                                      GtkAdjustment    *hadjustment,
370                                      GtkAdjustment    *vadjustment)
371 {
372   if (viewport->hadjustment != hadjustment)
373     gtk_viewport_set_hadjustment (viewport, hadjustment);
374   if (viewport->vadjustment != vadjustment)
375     gtk_viewport_set_vadjustment (viewport, vadjustment);
376 }
377
378 void
379 gtk_viewport_set_shadow_type (GtkViewport   *viewport,
380                               GtkShadowType  type)
381 {
382   g_return_if_fail (GTK_IS_VIEWPORT (viewport));
383
384   if ((GtkShadowType) viewport->shadow_type != type)
385     {
386       viewport->shadow_type = type;
387
388       if (GTK_WIDGET_VISIBLE (viewport))
389         {
390           gtk_widget_size_allocate (GTK_WIDGET (viewport), &(GTK_WIDGET (viewport)->allocation));
391           gtk_widget_queue_draw (GTK_WIDGET (viewport));
392         }
393     }
394
395   g_object_notify (G_OBJECT (viewport), "shadow_type");
396 }
397
398 /**
399  * gtk_viewport_get_shadow_type:
400  * @viewport: a #GtkViewport
401  *
402  * Gets the shadow type of the #GtkViewport. See
403  * gtk_viewport_set_shadow_type().
404  
405  * Return value: the shadow type 
406  **/
407 GtkShadowType
408 gtk_viewport_get_shadow_type (GtkViewport *viewport)
409 {
410   g_return_val_if_fail (GTK_IS_VIEWPORT (viewport), GTK_SHADOW_NONE);
411
412   return viewport->shadow_type;
413 }
414
415 static void
416 gtk_viewport_map (GtkWidget *widget)
417 {
418   GtkBin *bin;
419
420   g_return_if_fail (GTK_IS_VIEWPORT (widget));
421
422   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
423   bin = GTK_BIN (widget);
424
425   if (bin->child &&
426       GTK_WIDGET_VISIBLE (bin->child) &&
427       !GTK_WIDGET_MAPPED (bin->child))
428     gtk_widget_map (bin->child);
429
430   gdk_window_show (widget->window);
431 }
432
433 static void
434 gtk_viewport_unmap (GtkWidget *widget)
435 {
436   g_return_if_fail (GTK_IS_VIEWPORT (widget));
437
438   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
439   
440   gdk_window_hide (widget->window);
441 }
442
443 static void
444 gtk_viewport_realize (GtkWidget *widget)
445 {
446   GtkBin *bin;
447   GtkViewport *viewport;
448   GdkWindowAttr attributes;
449   gint attributes_mask;
450   gint event_mask;
451   gint border_width;
452
453   g_return_if_fail (GTK_IS_VIEWPORT (widget));
454
455   border_width = GTK_CONTAINER (widget)->border_width;
456
457   bin = GTK_BIN (widget);
458   viewport = GTK_VIEWPORT (widget);
459   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
460
461   attributes.x = widget->allocation.x + border_width;
462   attributes.y = widget->allocation.y + border_width;
463   attributes.width = widget->allocation.width - border_width * 2;
464   attributes.height = widget->allocation.height - border_width * 2;
465   attributes.window_type = GDK_WINDOW_CHILD;
466   attributes.wclass = GDK_INPUT_OUTPUT;
467   attributes.visual = gtk_widget_get_visual (widget);
468   attributes.colormap = gtk_widget_get_colormap (widget);
469
470   event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
471   /* We select on button_press_mask so that button 4-5 scrolls are trapped.
472    */
473   attributes.event_mask = event_mask | GDK_BUTTON_PRESS_MASK;
474
475   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
476
477   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
478                                    &attributes, attributes_mask);
479   gdk_window_set_user_data (widget->window, viewport);
480
481   if (viewport->shadow_type != GTK_SHADOW_NONE)
482     {
483       attributes.x = widget->style->xthickness;
484       attributes.y = widget->style->ythickness;
485     }
486   else
487     {
488       attributes.x = 0;
489       attributes.y = 0;
490     }
491
492   attributes.width = MAX (1, (gint)widget->allocation.width - attributes.x * 2 - border_width * 2);
493   attributes.height = MAX (1, (gint)widget->allocation.height - attributes.y * 2 - border_width * 2);
494   attributes.event_mask = 0;
495
496   viewport->view_window = gdk_window_new (widget->window, &attributes, attributes_mask);
497   gdk_window_set_user_data (viewport->view_window, viewport);
498
499   attributes.x = 0;
500   attributes.y = 0;
501
502   if (bin->child)
503     {
504       attributes.width = viewport->hadjustment->upper;
505       attributes.height = viewport->vadjustment->upper;
506     }
507   
508   attributes.event_mask = event_mask;
509
510   viewport->bin_window = gdk_window_new (viewport->view_window, &attributes, attributes_mask);
511   gdk_window_set_user_data (viewport->bin_window, viewport);
512
513   if (bin->child)
514     gtk_widget_set_parent_window (bin->child, viewport->bin_window);
515
516   widget->style = gtk_style_attach (widget->style, widget->window);
517   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
518   gtk_style_set_background (widget->style, viewport->bin_window, GTK_STATE_NORMAL);
519
520    gtk_paint_flat_box(widget->style, viewport->bin_window, GTK_STATE_NORMAL,
521                       GTK_SHADOW_NONE,
522                       NULL, widget, "viewportbin",
523                       0, 0, -1, -1);
524    
525   gdk_window_show (viewport->bin_window);
526   gdk_window_show (viewport->view_window);
527 }
528
529 static void
530 gtk_viewport_unrealize (GtkWidget *widget)
531 {
532   GtkViewport *viewport;
533
534   g_return_if_fail (GTK_IS_VIEWPORT (widget));
535
536   viewport = GTK_VIEWPORT (widget);
537
538   gdk_window_set_user_data (viewport->view_window, NULL);
539   gdk_window_destroy (viewport->view_window);
540   viewport->view_window = NULL;
541
542   gdk_window_set_user_data (viewport->bin_window, NULL);
543   gdk_window_destroy (viewport->bin_window);
544   viewport->bin_window = NULL;
545
546   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
547     (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
548 }
549
550 static void
551 gtk_viewport_paint (GtkWidget    *widget,
552                     GdkRectangle *area)
553 {
554   GtkViewport *viewport;
555
556   g_return_if_fail (GTK_IS_VIEWPORT (widget));
557   g_return_if_fail (area != NULL);
558
559   if (GTK_WIDGET_DRAWABLE (widget))
560     {
561       viewport = GTK_VIEWPORT (widget);
562
563       gtk_draw_shadow (widget->style, widget->window,
564                        GTK_STATE_NORMAL, viewport->shadow_type,
565                        0, 0, -1, -1);
566     }
567 }
568
569 static gint
570 gtk_viewport_expose (GtkWidget      *widget,
571                      GdkEventExpose *event)
572 {
573   GtkViewport *viewport;
574   GtkBin *bin;
575   GdkEventExpose child_event;
576
577   g_return_val_if_fail (GTK_IS_VIEWPORT (widget), FALSE);
578   g_return_val_if_fail (event != NULL, FALSE);
579
580   if (GTK_WIDGET_DRAWABLE (widget))
581     {
582       viewport = GTK_VIEWPORT (widget);
583       bin = GTK_BIN (widget);
584
585       if (event->window == widget->window)
586         gtk_viewport_paint (widget, &event->area);
587       else if (event->window == viewport->bin_window)
588         {
589           child_event = *event;
590
591           gtk_paint_flat_box(widget->style, viewport->bin_window, 
592                              GTK_STATE_NORMAL, GTK_SHADOW_NONE,
593                              &event->area, widget, "viewportbin",
594                              0, 0, -1, -1);
595           
596           (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
597         }
598         
599
600     }
601
602   return FALSE;
603 }
604
605 static void
606 gtk_viewport_add (GtkContainer *container,
607                   GtkWidget    *child)
608 {
609   GtkBin *bin;
610
611   g_return_if_fail (GTK_IS_VIEWPORT (container));
612   g_return_if_fail (child != NULL);
613
614   bin = GTK_BIN (container);
615   g_return_if_fail (bin->child == NULL);
616
617   gtk_widget_set_parent_window (child, GTK_VIEWPORT (bin)->bin_window);
618
619   GTK_CONTAINER_CLASS (parent_class)->add (container, child);
620 }
621
622 static void
623 gtk_viewport_size_request (GtkWidget      *widget,
624                            GtkRequisition *requisition)
625 {
626   GtkViewport *viewport;
627   GtkBin *bin;
628   GtkRequisition child_requisition;
629
630   g_return_if_fail (GTK_IS_VIEWPORT (widget));
631   g_return_if_fail (requisition != NULL);
632
633   viewport = GTK_VIEWPORT (widget);
634   bin = GTK_BIN (widget);
635
636   requisition->width = (GTK_CONTAINER (widget)->border_width +
637                         GTK_WIDGET (widget)->style->xthickness) * 2 + 5;
638
639   requisition->height = (GTK_CONTAINER (widget)->border_width * 2 +
640                          GTK_WIDGET (widget)->style->ythickness) * 2 + 5;
641
642   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
643     {
644       gtk_widget_size_request (bin->child, &child_requisition);
645       requisition->width += child_requisition.width;
646       requisition->height += child_requisition.height;
647     }
648 }
649
650 static void
651 gtk_viewport_size_allocate (GtkWidget     *widget,
652                             GtkAllocation *allocation)
653 {
654   GtkViewport *viewport;
655   GtkBin *bin;
656   GtkAllocation child_allocation;
657   gint hval, vval;
658   gint border_width;
659
660   g_return_if_fail (GTK_IS_VIEWPORT (widget));
661   g_return_if_fail (allocation != NULL);
662
663   widget->allocation = *allocation;
664   viewport = GTK_VIEWPORT (widget);
665   bin = GTK_BIN (widget);
666
667   /* demand creation */
668   if (!viewport->hadjustment)
669     gtk_viewport_set_hadjustment (viewport, NULL);
670   if (!viewport->vadjustment)
671     gtk_viewport_set_hadjustment (viewport, NULL);
672
673   border_width = GTK_CONTAINER (widget)->border_width;
674
675   child_allocation.x = 0;
676   child_allocation.y = 0;
677
678   if (viewport->shadow_type != GTK_SHADOW_NONE)
679     {
680       child_allocation.x = GTK_WIDGET (viewport)->style->xthickness;
681       child_allocation.y = GTK_WIDGET (viewport)->style->ythickness;
682     }
683
684   child_allocation.width = MAX (1, allocation->width - child_allocation.x * 2 - border_width * 2);
685   child_allocation.height = MAX (1, allocation->height - child_allocation.y * 2 - border_width * 2);
686
687   if (GTK_WIDGET_REALIZED (widget))
688     {
689       gdk_window_move_resize (widget->window,
690                               allocation->x + border_width,
691                               allocation->y + border_width,
692                               allocation->width - border_width * 2,
693                               allocation->height - border_width * 2);
694
695       gdk_window_move_resize (viewport->view_window,
696                               child_allocation.x,
697                               child_allocation.y,
698                               child_allocation.width,
699                               child_allocation.height);
700     }
701
702   viewport->hadjustment->page_size = child_allocation.width;
703   viewport->hadjustment->page_increment = viewport->hadjustment->page_size / 2;
704   viewport->hadjustment->step_increment = 10;
705
706   viewport->vadjustment->page_size = child_allocation.height;
707   viewport->vadjustment->page_increment = viewport->vadjustment->page_size / 2;
708   viewport->vadjustment->step_increment = 10;
709
710   hval = viewport->hadjustment->value;
711   vval = viewport->vadjustment->value;
712
713   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
714     {
715       GtkRequisition child_requisition;
716       gtk_widget_get_child_requisition (bin->child, &child_requisition);
717       
718       viewport->hadjustment->lower = 0;
719       viewport->hadjustment->upper = MAX (child_requisition.width,
720                                           child_allocation.width);
721
722       hval = CLAMP (hval, 0,
723                     viewport->hadjustment->upper -
724                     viewport->hadjustment->page_size);
725
726       viewport->vadjustment->lower = 0;
727       viewport->vadjustment->upper = MAX (child_requisition.height,
728                                           child_allocation.height);
729
730       vval = CLAMP (vval, 0,
731                     viewport->vadjustment->upper -
732                     viewport->vadjustment->page_size);
733     }
734
735   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
736     {
737       child_allocation.x = 0;
738       child_allocation.y = 0;
739
740       child_allocation.width = viewport->hadjustment->upper;
741       child_allocation.height = viewport->vadjustment->upper;
742
743       if (GTK_WIDGET_REALIZED (widget))
744         gdk_window_resize (viewport->bin_window,
745                            child_allocation.width,
746                            child_allocation.height);
747
748       child_allocation.x = 0;
749       child_allocation.y = 0;
750       gtk_widget_size_allocate (bin->child, &child_allocation);
751     }
752
753   gtk_signal_emit_by_name (GTK_OBJECT (viewport->hadjustment), "changed");
754   gtk_signal_emit_by_name (GTK_OBJECT (viewport->vadjustment), "changed");
755   if (viewport->hadjustment->value != hval)
756     {
757       viewport->hadjustment->value = hval;
758       gtk_signal_emit_by_name (GTK_OBJECT (viewport->hadjustment), "value_changed");
759     }
760   if (viewport->vadjustment->value != vval)
761     {
762       viewport->vadjustment->value = vval;
763       gtk_signal_emit_by_name (GTK_OBJECT (viewport->vadjustment), "value_changed");
764     }
765 }
766
767 static void
768 gtk_viewport_adjustment_changed (GtkAdjustment *adjustment,
769                                  gpointer       data)
770 {
771   GtkViewport *viewport;
772
773   g_return_if_fail (adjustment != NULL);
774   g_return_if_fail (GTK_IS_VIEWPORT (data));
775
776   viewport = GTK_VIEWPORT (data);
777 }
778
779 static void
780 gtk_viewport_adjustment_value_changed (GtkAdjustment *adjustment,
781                                        gpointer       data)
782 {
783   GtkViewport *viewport;
784   GtkBin *bin;
785   GtkAllocation child_allocation;
786
787   g_return_if_fail (adjustment != NULL);
788   g_return_if_fail (GTK_IS_VIEWPORT (data));
789
790   viewport = GTK_VIEWPORT (data);
791   bin = GTK_BIN (data);
792
793   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
794     {
795       child_allocation.x = 0;
796       child_allocation.y = 0;
797
798       if (viewport->hadjustment->lower != (viewport->hadjustment->upper -
799                                            viewport->hadjustment->page_size))
800         child_allocation.x =  viewport->hadjustment->lower - viewport->hadjustment->value;
801
802       if (viewport->vadjustment->lower != (viewport->vadjustment->upper -
803                                            viewport->vadjustment->page_size))
804         child_allocation.y = viewport->vadjustment->lower - viewport->vadjustment->value;
805
806       if (GTK_WIDGET_REALIZED (viewport))
807         {
808           gdk_window_move (viewport->bin_window,
809                            child_allocation.x,
810                            child_allocation.y);
811       
812           gdk_window_process_updates (viewport->bin_window, TRUE);
813         }
814     }
815 }
816
817 static void
818 gtk_viewport_style_set (GtkWidget *widget,
819                         GtkStyle  *previous_style)
820 {
821    GtkViewport *viewport;
822    
823    if (GTK_WIDGET_REALIZED (widget) &&
824        !GTK_WIDGET_NO_WINDOW (widget))
825      {
826         viewport = GTK_VIEWPORT (widget);
827         
828         gtk_style_set_background (widget->style, viewport->bin_window, GTK_STATE_NORMAL);
829         gtk_style_set_background (widget->style, widget->window, widget->state);
830      }
831 }