]> Pileus Git - ~andy/gtk/blob - gtk/gtkviewport.c
Use the correct screen for getting the height. (Fix from Stephen Browne,
[~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 "gtkviewport.h"
28 #include "gtkintl.h"
29 #include "gtkmarshalers.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_realize                  (GtkWidget        *widget);
54 static void gtk_viewport_unrealize                (GtkWidget        *widget);
55 static void gtk_viewport_paint                    (GtkWidget        *widget,
56                                                    GdkRectangle     *area);
57 static gint gtk_viewport_expose                   (GtkWidget        *widget,
58                                                    GdkEventExpose   *event);
59 static void gtk_viewport_add                      (GtkContainer     *container,
60                                                    GtkWidget        *widget);
61 static void gtk_viewport_size_request             (GtkWidget        *widget,
62                                                    GtkRequisition   *requisition);
63 static void gtk_viewport_size_allocate            (GtkWidget        *widget,
64                                                    GtkAllocation    *allocation);
65 static void gtk_viewport_adjustment_changed       (GtkAdjustment    *adjustment,
66                                                    gpointer          data);
67 static void gtk_viewport_adjustment_value_changed (GtkAdjustment    *adjustment,
68                                                    gpointer          data);
69 static void gtk_viewport_style_set                (GtkWidget *widget,
70                                                    GtkStyle  *previous_style);
71
72 static GtkBinClass *parent_class;
73
74 GType
75 gtk_viewport_get_type (void)
76 {
77   static GType viewport_type = 0;
78
79   if (!viewport_type)
80     {
81       static const GTypeInfo viewport_info =
82       {
83         sizeof (GtkViewportClass),
84         NULL,           /* base_init */
85         NULL,           /* base_finalize */
86         (GClassInitFunc) gtk_viewport_class_init,
87         NULL,           /* class_finalize */
88         NULL,           /* class_data */
89         sizeof (GtkViewport),
90         0,              /* n_preallocs */
91         (GInstanceInitFunc) gtk_viewport_init,
92       };
93
94       viewport_type = g_type_register_static (GTK_TYPE_BIN, "GtkViewport",
95                                               &viewport_info, 0);
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
114   parent_class = g_type_class_peek_parent (class);
115
116   gobject_class->set_property = gtk_viewport_set_property;
117   gobject_class->get_property = gtk_viewport_get_property;
118   object_class->destroy = gtk_viewport_destroy;
119   
120   widget_class->realize = gtk_viewport_realize;
121   widget_class->unrealize = gtk_viewport_unrealize;
122   widget_class->expose_event = gtk_viewport_expose;
123   widget_class->size_request = gtk_viewport_size_request;
124   widget_class->size_allocate = gtk_viewport_size_allocate;
125   widget_class->style_set = gtk_viewport_style_set;
126   
127   container_class->add = gtk_viewport_add;
128
129   class->set_scroll_adjustments = gtk_viewport_set_scroll_adjustments;
130
131   g_object_class_install_property (gobject_class,
132                                    PROP_HADJUSTMENT,
133                                    g_param_spec_object ("hadjustment",
134                                                         _("Horizontal adjustment"),
135                                                         _("The GtkAdjustment that determines the values of the horizontal position for this viewport"),
136                                                         GTK_TYPE_ADJUSTMENT,
137                                                         G_PARAM_READWRITE));
138
139   g_object_class_install_property (gobject_class,
140                                    PROP_VADJUSTMENT,
141                                    g_param_spec_object ("vadjustment",
142                                                         _("Vertical adjustment"),
143                                                         _("The GtkAdjustment that determines the values of the vertical position for this viewport"),
144                                                         GTK_TYPE_ADJUSTMENT,
145                                                         G_PARAM_READWRITE));
146
147   g_object_class_install_property (gobject_class,
148                                    PROP_SHADOW_TYPE,
149                                    g_param_spec_enum ("shadow_type",
150                                                       _("Shadow type"),
151                                                       _("Determines how the shadowed box around the viewport is drawn"),
152                                                       GTK_TYPE_SHADOW_TYPE,
153                                                       GTK_SHADOW_IN,
154                                                       G_PARAM_READWRITE));
155
156   widget_class->set_scroll_adjustments_signal =
157     g_signal_new ("set_scroll_adjustments",
158                   G_OBJECT_CLASS_TYPE (gobject_class),
159                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
160                   G_STRUCT_OFFSET (GtkViewportClass, set_scroll_adjustments),
161                   NULL, NULL,
162                   _gtk_marshal_VOID__OBJECT_OBJECT,
163                   G_TYPE_NONE, 2,
164                   GTK_TYPE_ADJUSTMENT,
165                   GTK_TYPE_ADJUSTMENT);
166 }
167
168 static void
169 gtk_viewport_set_property (GObject         *object,
170                            guint            prop_id,
171                            const GValue    *value,
172                            GParamSpec      *pspec)
173 {
174   GtkViewport *viewport;
175
176   viewport = GTK_VIEWPORT (object);
177
178   switch (prop_id)
179     {
180     case PROP_HADJUSTMENT:
181       gtk_viewport_set_hadjustment (viewport, g_value_get_object (value));
182       break;
183     case PROP_VADJUSTMENT:
184       gtk_viewport_set_vadjustment (viewport, g_value_get_object (value));
185       break;
186     case PROP_SHADOW_TYPE:
187       gtk_viewport_set_shadow_type (viewport, g_value_get_enum (value));
188       break;
189     default:
190       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
191       break;
192     }
193 }
194
195 static void
196 gtk_viewport_get_property (GObject         *object,
197                            guint            prop_id,
198                            GValue          *value,
199                            GParamSpec      *pspec)
200 {
201   GtkViewport *viewport;
202
203   viewport = GTK_VIEWPORT (object);
204
205   switch (prop_id)
206     {
207     case PROP_HADJUSTMENT:
208       g_value_set_object (value, viewport->hadjustment);
209       break;
210     case PROP_VADJUSTMENT:
211       g_value_set_object (value, viewport->vadjustment);
212       break;
213     case PROP_SHADOW_TYPE:
214       g_value_set_enum (value, viewport->shadow_type);
215       break;
216     default:
217       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
218       break;
219     }
220 }
221
222 static void
223 gtk_viewport_init (GtkViewport *viewport)
224 {
225   GTK_WIDGET_UNSET_FLAGS (viewport, GTK_NO_WINDOW);
226
227   gtk_widget_set_redraw_on_allocate (GTK_WIDGET (viewport), FALSE);
228   gtk_container_set_resize_mode (GTK_CONTAINER (viewport), GTK_RESIZE_QUEUE);
229   
230   viewport->shadow_type = GTK_SHADOW_IN;
231   viewport->view_window = NULL;
232   viewport->bin_window = NULL;
233   viewport->hadjustment = NULL;
234   viewport->vadjustment = NULL;
235 }
236
237 /**
238  * gtk_viewport_new:
239  * @hadjustment: horizontal adjustment.
240  * @vadjustment: vertical adjustment.
241  * @returns: a new #GtkViewport.
242  *
243  * Creates a new #GtkViewport with the given adjustments.
244  *
245  **/
246 GtkWidget*
247 gtk_viewport_new (GtkAdjustment *hadjustment,
248                   GtkAdjustment *vadjustment)
249 {
250   GtkWidget *viewport;
251
252   viewport = gtk_widget_new (GTK_TYPE_VIEWPORT,
253                              "hadjustment", hadjustment,
254                              "vadjustment", vadjustment,
255                              NULL);
256
257   return viewport;
258 }
259
260 static void
261 gtk_viewport_destroy (GtkObject *object)
262 {
263   GtkViewport *viewport = GTK_VIEWPORT (object);
264
265   if (viewport->hadjustment)
266     {
267       g_signal_handlers_disconnect_by_func (viewport->hadjustment,
268                                             gtk_viewport_adjustment_changed,
269                                             viewport);
270       g_signal_handlers_disconnect_by_func (viewport->hadjustment,
271                                             gtk_viewport_adjustment_value_changed,
272                                             viewport);
273       g_object_unref (viewport->hadjustment);
274       viewport->hadjustment = NULL;
275     }
276   if (viewport->vadjustment)
277     {
278       g_signal_handlers_disconnect_by_func (viewport->vadjustment,
279                                             gtk_viewport_adjustment_changed,
280                                             viewport);
281       g_signal_handlers_disconnect_by_func (viewport->vadjustment,
282                                             gtk_viewport_adjustment_value_changed,
283                                             viewport);
284       g_object_unref (viewport->vadjustment);
285       viewport->vadjustment = NULL;
286     }
287
288   GTK_OBJECT_CLASS (parent_class)->destroy (object);
289 }
290
291 /**
292  * gtk_viewport_get_hadjustment:
293  * @viewport: a #GtkViewport.
294  * 
295  * Returns the horizontal adjustment of the viewport.
296  *
297  * Return value: the horizontal adjustment of @viewport.
298  **/
299 GtkAdjustment*
300 gtk_viewport_get_hadjustment (GtkViewport *viewport)
301 {
302   g_return_val_if_fail (GTK_IS_VIEWPORT (viewport), NULL);
303
304   if (!viewport->hadjustment)
305     gtk_viewport_set_hadjustment (viewport, NULL);
306
307   return viewport->hadjustment;
308 }
309
310 /**
311  * gtk_viewport_get_vadjustment:
312  * @viewport: a #GtkViewport.
313  * 
314  * Returns the vertical adjustment of the viewport.
315  *
316  * Return value: the vertical adjustment of @viewport.
317  **/
318 GtkAdjustment*
319 gtk_viewport_get_vadjustment (GtkViewport *viewport)
320 {
321   g_return_val_if_fail (GTK_IS_VIEWPORT (viewport), NULL);
322
323   if (!viewport->vadjustment)
324     gtk_viewport_set_vadjustment (viewport, NULL);
325
326   return viewport->vadjustment;
327 }
328
329 /**
330  * gtk_viewport_set_hadjustment:
331  * @viewport: a #GtkViewport.
332  * @adjustment: a #GtkAdjustment.
333  * 
334  * Sets the horizontal adjustment of the viewport.
335  **/
336 void
337 gtk_viewport_set_hadjustment (GtkViewport   *viewport,
338                               GtkAdjustment *adjustment)
339 {
340   g_return_if_fail (GTK_IS_VIEWPORT (viewport));
341   if (adjustment)
342     g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
343
344   if (viewport->hadjustment && viewport->hadjustment != adjustment)
345     {
346       g_signal_handlers_disconnect_by_func (viewport->hadjustment,
347                                             gtk_viewport_adjustment_changed,
348                                             viewport);
349       g_signal_handlers_disconnect_by_func (viewport->hadjustment,
350                                             gtk_viewport_adjustment_value_changed,
351                                             viewport);
352       g_object_unref (viewport->hadjustment);
353       viewport->hadjustment = NULL;
354     }
355
356   if (!adjustment)
357     adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0,
358                                                      0.0, 0.0, 0.0));
359
360   if (viewport->hadjustment != adjustment)
361     {
362       viewport->hadjustment = adjustment;
363       g_object_ref (viewport->hadjustment);
364       gtk_object_sink (GTK_OBJECT (viewport->hadjustment));
365       
366       g_signal_connect (adjustment, "changed",
367                         G_CALLBACK (gtk_viewport_adjustment_changed),
368                         viewport);
369       g_signal_connect (adjustment, "value_changed",
370                         G_CALLBACK (gtk_viewport_adjustment_value_changed),
371                         viewport);
372
373       gtk_viewport_adjustment_changed (adjustment, viewport);
374     }
375
376   g_object_notify (G_OBJECT (viewport), "hadjustment");
377 }
378
379 /**
380  * gtk_viewport_set_vadjustment:
381  * @viewport: a #GtkViewport.
382  * @adjustment: a #GtkAdjustment.
383  * 
384  * Sets the vertical adjustment of the viewport.
385  **/
386 void
387 gtk_viewport_set_vadjustment (GtkViewport   *viewport,
388                               GtkAdjustment *adjustment)
389 {
390   g_return_if_fail (GTK_IS_VIEWPORT (viewport));
391   if (adjustment)
392     g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
393
394   if (viewport->vadjustment && viewport->vadjustment != adjustment)
395     {
396       g_signal_handlers_disconnect_by_func (viewport->vadjustment,
397                                             gtk_viewport_adjustment_changed,
398                                             viewport);
399       g_signal_handlers_disconnect_by_func (viewport->vadjustment,
400                                             gtk_viewport_adjustment_value_changed,
401                                             viewport);
402       g_object_unref (viewport->vadjustment);
403       viewport->vadjustment = NULL;
404     }
405
406   if (!adjustment)
407     adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0,
408                                                      0.0, 0.0, 0.0));
409
410   if (viewport->vadjustment != adjustment)
411     {
412       viewport->vadjustment = adjustment;
413       g_object_ref (viewport->vadjustment);
414       gtk_object_sink (GTK_OBJECT (viewport->vadjustment));
415       
416       g_signal_connect (adjustment, "changed",
417                         G_CALLBACK (gtk_viewport_adjustment_changed),
418                         viewport);
419       g_signal_connect (adjustment, "value_changed",
420                         G_CALLBACK (gtk_viewport_adjustment_value_changed),
421                         viewport);
422
423       gtk_viewport_adjustment_changed (adjustment, viewport);
424     }
425
426     g_object_notify (G_OBJECT (viewport), "vadjustment");
427 }
428
429 static void
430 gtk_viewport_set_scroll_adjustments (GtkViewport      *viewport,
431                                      GtkAdjustment    *hadjustment,
432                                      GtkAdjustment    *vadjustment)
433 {
434   if (viewport->hadjustment != hadjustment)
435     gtk_viewport_set_hadjustment (viewport, hadjustment);
436   if (viewport->vadjustment != vadjustment)
437     gtk_viewport_set_vadjustment (viewport, vadjustment);
438 }
439
440 /** 
441  * gtk_viewport_set_shadow_type:
442  * @viewport: a #GtkViewport.
443  * @type: the new shadow type.
444  *
445  * Sets the shadow type of the viewport.
446  **/ 
447 void
448 gtk_viewport_set_shadow_type (GtkViewport   *viewport,
449                               GtkShadowType  type)
450 {
451   g_return_if_fail (GTK_IS_VIEWPORT (viewport));
452
453   if ((GtkShadowType) viewport->shadow_type != type)
454     {
455       viewport->shadow_type = type;
456
457       if (GTK_WIDGET_VISIBLE (viewport))
458         {
459           gtk_widget_size_allocate (GTK_WIDGET (viewport), &(GTK_WIDGET (viewport)->allocation));
460           gtk_widget_queue_draw (GTK_WIDGET (viewport));
461         }
462
463       g_object_notify (G_OBJECT (viewport), "shadow_type");
464     }
465 }
466
467 /**
468  * gtk_viewport_get_shadow_type:
469  * @viewport: a #GtkViewport
470  *
471  * Gets the shadow type of the #GtkViewport. See
472  * gtk_viewport_set_shadow_type().
473  
474  * Return value: the shadow type 
475  **/
476 GtkShadowType
477 gtk_viewport_get_shadow_type (GtkViewport *viewport)
478 {
479   g_return_val_if_fail (GTK_IS_VIEWPORT (viewport), GTK_SHADOW_NONE);
480
481   return viewport->shadow_type;
482 }
483
484 static void
485 gtk_viewport_realize (GtkWidget *widget)
486 {
487   GtkBin *bin;
488   GtkViewport *viewport;
489   GdkWindowAttr attributes;
490   gint attributes_mask;
491   gint event_mask;
492   gint border_width;
493
494   border_width = GTK_CONTAINER (widget)->border_width;
495
496   bin = GTK_BIN (widget);
497   viewport = GTK_VIEWPORT (widget);
498   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
499
500   attributes.x = widget->allocation.x + border_width;
501   attributes.y = widget->allocation.y + border_width;
502   attributes.width = widget->allocation.width - border_width * 2;
503   attributes.height = widget->allocation.height - border_width * 2;
504   attributes.window_type = GDK_WINDOW_CHILD;
505   attributes.wclass = GDK_INPUT_OUTPUT;
506   attributes.visual = gtk_widget_get_visual (widget);
507   attributes.colormap = gtk_widget_get_colormap (widget);
508
509   event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
510   /* We select on button_press_mask so that button 4-5 scrolls are trapped.
511    */
512   attributes.event_mask = event_mask | GDK_BUTTON_PRESS_MASK;
513
514   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
515
516   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
517                                    &attributes, attributes_mask);
518   gdk_window_set_user_data (widget->window, viewport);
519
520   if (viewport->shadow_type != GTK_SHADOW_NONE)
521     {
522       attributes.x = widget->style->xthickness;
523       attributes.y = widget->style->ythickness;
524     }
525   else
526     {
527       attributes.x = 0;
528       attributes.y = 0;
529     }
530
531   attributes.width = MAX (1, (gint)widget->allocation.width - attributes.x * 2 - border_width * 2);
532   attributes.height = MAX (1, (gint)widget->allocation.height - attributes.y * 2 - border_width * 2);
533   attributes.event_mask = 0;
534
535   viewport->view_window = gdk_window_new (widget->window, &attributes, attributes_mask);
536   gdk_window_set_user_data (viewport->view_window, viewport);
537
538   attributes.x = 0;
539   attributes.y = 0;
540
541   if (bin->child)
542     {
543       attributes.width = viewport->hadjustment->upper;
544       attributes.height = viewport->vadjustment->upper;
545     }
546   
547   attributes.event_mask = event_mask;
548
549   viewport->bin_window = gdk_window_new (viewport->view_window, &attributes, attributes_mask);
550   gdk_window_set_user_data (viewport->bin_window, viewport);
551
552   if (bin->child)
553     gtk_widget_set_parent_window (bin->child, viewport->bin_window);
554
555   widget->style = gtk_style_attach (widget->style, widget->window);
556   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
557   gtk_style_set_background (widget->style, viewport->bin_window, GTK_STATE_NORMAL);
558
559    gtk_paint_flat_box(widget->style, viewport->bin_window, GTK_STATE_NORMAL,
560                       GTK_SHADOW_NONE,
561                       NULL, widget, "viewportbin",
562                       0, 0, -1, -1);
563    
564   gdk_window_show (viewport->bin_window);
565   gdk_window_show (viewport->view_window);
566 }
567
568 static void
569 gtk_viewport_unrealize (GtkWidget *widget)
570 {
571   GtkViewport *viewport = GTK_VIEWPORT (widget);
572
573   gdk_window_set_user_data (viewport->view_window, NULL);
574   gdk_window_destroy (viewport->view_window);
575   viewport->view_window = NULL;
576
577   gdk_window_set_user_data (viewport->bin_window, NULL);
578   gdk_window_destroy (viewport->bin_window);
579   viewport->bin_window = NULL;
580
581   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
582     (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
583 }
584
585 static void
586 gtk_viewport_paint (GtkWidget    *widget,
587                     GdkRectangle *area)
588 {
589   GtkViewport *viewport;
590
591   g_return_if_fail (GTK_IS_VIEWPORT (widget));
592   g_return_if_fail (area != NULL);
593
594   if (GTK_WIDGET_DRAWABLE (widget))
595     {
596       viewport = GTK_VIEWPORT (widget);
597
598       gtk_paint_shadow (widget->style, widget->window,
599                         GTK_STATE_NORMAL, viewport->shadow_type,
600                         NULL, widget, "viewport",
601                         0, 0, -1, -1);
602     }
603 }
604
605 static gint
606 gtk_viewport_expose (GtkWidget      *widget,
607                      GdkEventExpose *event)
608 {
609   GtkViewport *viewport;
610   GtkBin *bin;
611
612   if (GTK_WIDGET_DRAWABLE (widget))
613     {
614       viewport = GTK_VIEWPORT (widget);
615       bin = GTK_BIN (widget);
616
617       if (event->window == widget->window)
618         gtk_viewport_paint (widget, &event->area);
619       else if (event->window == viewport->bin_window)
620         {
621           gtk_paint_flat_box(widget->style, viewport->bin_window, 
622                              GTK_STATE_NORMAL, GTK_SHADOW_NONE,
623                              &event->area, widget, "viewportbin",
624                              0, 0, -1, -1);
625           
626           (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
627         }
628         
629
630     }
631
632   return FALSE;
633 }
634
635 static void
636 gtk_viewport_add (GtkContainer *container,
637                   GtkWidget    *child)
638 {
639   GtkBin *bin;
640
641   g_return_if_fail (GTK_IS_WIDGET (child));
642
643   bin = GTK_BIN (container);
644   g_return_if_fail (bin->child == NULL);
645
646   gtk_widget_set_parent_window (child, GTK_VIEWPORT (bin)->bin_window);
647
648   GTK_CONTAINER_CLASS (parent_class)->add (container, child);
649 }
650
651 static void
652 gtk_viewport_size_request (GtkWidget      *widget,
653                            GtkRequisition *requisition)
654 {
655   GtkViewport *viewport;
656   GtkBin *bin;
657   GtkRequisition child_requisition;
658
659   viewport = GTK_VIEWPORT (widget);
660   bin = GTK_BIN (widget);
661
662   requisition->width = (GTK_CONTAINER (widget)->border_width +
663                         GTK_WIDGET (widget)->style->xthickness) * 2;
664
665   requisition->height = (GTK_CONTAINER (widget)->border_width * 2 +
666                          GTK_WIDGET (widget)->style->ythickness) * 2;
667
668   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
669     {
670       gtk_widget_size_request (bin->child, &child_requisition);
671       requisition->width += child_requisition.width;
672       requisition->height += child_requisition.height;
673     }
674 }
675
676 static void
677 gtk_viewport_size_allocate (GtkWidget     *widget,
678                             GtkAllocation *allocation)
679 {
680   GtkViewport *viewport = GTK_VIEWPORT (widget);
681   GtkBin *bin = GTK_BIN (widget);
682   GtkAllocation child_allocation;
683   gint hval, vval;
684   gint border_width = GTK_CONTAINER (widget)->border_width;
685
686   /* demand creation */
687   if (!viewport->hadjustment)
688     gtk_viewport_set_hadjustment (viewport, NULL);
689   if (!viewport->vadjustment)
690     gtk_viewport_set_vadjustment (viewport, NULL);
691
692   /* If our size changed, and we have a shadow, queue a redraw on widget->window to
693    * redraw the shadow correctly.
694    */
695   if (GTK_WIDGET_MAPPED (widget) &&
696       viewport->shadow_type != GTK_SHADOW_NONE &&
697       (widget->allocation.width != allocation->width ||
698        widget->allocation.height != allocation->height))
699     gdk_window_invalidate_rect (widget->window, NULL, FALSE);
700   
701   widget->allocation = *allocation;
702
703   child_allocation.x = 0;
704   child_allocation.y = 0;
705
706   if (viewport->shadow_type != GTK_SHADOW_NONE)
707     {
708       child_allocation.x = widget->style->xthickness;
709       child_allocation.y = widget->style->ythickness;
710     }
711
712   child_allocation.width = MAX (1, allocation->width - child_allocation.x * 2 - border_width * 2);
713   child_allocation.height = MAX (1, allocation->height - child_allocation.y * 2 - border_width * 2);
714
715   if (GTK_WIDGET_REALIZED (widget))
716     {
717       gdk_window_move_resize (widget->window,
718                               allocation->x + border_width,
719                               allocation->y + border_width,
720                               allocation->width - border_width * 2,
721                               allocation->height - border_width * 2);
722
723       gdk_window_move_resize (viewport->view_window,
724                               child_allocation.x,
725                               child_allocation.y,
726                               child_allocation.width,
727                               child_allocation.height);
728     }
729
730   viewport->hadjustment->page_size = child_allocation.width;
731   viewport->hadjustment->step_increment = child_allocation.width * 0.1;
732   viewport->hadjustment->page_increment = child_allocation.width * 0.9;
733
734   viewport->vadjustment->page_size = child_allocation.height;
735   viewport->vadjustment->step_increment = child_allocation.height * 0.1;
736   viewport->vadjustment->page_increment = child_allocation.height * 0.9;
737
738   hval = viewport->hadjustment->value;
739   vval = viewport->vadjustment->value;
740
741   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
742     {
743       GtkRequisition child_requisition;
744       gtk_widget_get_child_requisition (bin->child, &child_requisition);
745       
746       viewport->hadjustment->lower = 0;
747       viewport->hadjustment->upper = MAX (child_requisition.width,
748                                           child_allocation.width);
749
750       hval = CLAMP (hval, 0,
751                     viewport->hadjustment->upper -
752                     viewport->hadjustment->page_size);
753
754       viewport->vadjustment->lower = 0;
755       viewport->vadjustment->upper = MAX (child_requisition.height,
756                                           child_allocation.height);
757
758       vval = CLAMP (vval, 0,
759                     viewport->vadjustment->upper -
760                     viewport->vadjustment->page_size);
761     }
762
763   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
764     {
765       child_allocation.x = 0;
766       child_allocation.y = 0;
767
768       child_allocation.width = viewport->hadjustment->upper;
769       child_allocation.height = viewport->vadjustment->upper;
770
771       if (GTK_WIDGET_REALIZED (widget))
772         gdk_window_resize (viewport->bin_window,
773                            child_allocation.width,
774                            child_allocation.height);
775
776       child_allocation.x = 0;
777       child_allocation.y = 0;
778       gtk_widget_size_allocate (bin->child, &child_allocation);
779     }
780
781   gtk_adjustment_changed (viewport->hadjustment);
782   gtk_adjustment_changed (viewport->vadjustment);
783   if (viewport->hadjustment->value != hval)
784     {
785       viewport->hadjustment->value = hval;
786       gtk_adjustment_value_changed (viewport->hadjustment);
787     }
788   if (viewport->vadjustment->value != vval)
789     {
790       viewport->vadjustment->value = vval;
791       gtk_adjustment_value_changed (viewport->vadjustment);
792     }
793 }
794
795 static void
796 gtk_viewport_adjustment_changed (GtkAdjustment *adjustment,
797                                  gpointer       data)
798 {
799   GtkViewport *viewport;
800
801   g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
802   g_return_if_fail (GTK_IS_VIEWPORT (data));
803
804   viewport = GTK_VIEWPORT (data);
805 }
806
807 static void
808 gtk_viewport_adjustment_value_changed (GtkAdjustment *adjustment,
809                                        gpointer       data)
810 {
811   GtkViewport *viewport;
812   GtkBin *bin;
813   GtkAllocation child_allocation;
814
815   g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
816   g_return_if_fail (GTK_IS_VIEWPORT (data));
817
818   viewport = GTK_VIEWPORT (data);
819   bin = GTK_BIN (data);
820
821   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
822     {
823       child_allocation.x = 0;
824       child_allocation.y = 0;
825
826       if (viewport->hadjustment->lower != (viewport->hadjustment->upper -
827                                            viewport->hadjustment->page_size))
828         child_allocation.x =  viewport->hadjustment->lower - viewport->hadjustment->value;
829
830       if (viewport->vadjustment->lower != (viewport->vadjustment->upper -
831                                            viewport->vadjustment->page_size))
832         child_allocation.y = viewport->vadjustment->lower - viewport->vadjustment->value;
833
834       if (GTK_WIDGET_REALIZED (viewport))
835         {
836           gdk_window_move (viewport->bin_window,
837                            child_allocation.x,
838                            child_allocation.y);
839       
840           gdk_window_process_updates (viewport->bin_window, TRUE);
841         }
842     }
843 }
844
845 static void
846 gtk_viewport_style_set (GtkWidget *widget,
847                         GtkStyle  *previous_style)
848 {
849    GtkViewport *viewport;
850    
851    if (GTK_WIDGET_REALIZED (widget) &&
852        !GTK_WIDGET_NO_WINDOW (widget))
853      {
854         viewport = GTK_VIEWPORT (widget);
855         
856         gtk_style_set_background (widget->style, viewport->bin_window, GTK_STATE_NORMAL);
857         gtk_style_set_background (widget->style, widget->window, widget->state);
858      }
859 }