]> Pileus Git - ~andy/gtk/blob - gtk/gtkviewport.c
Changed LGPL address for FSF in all .h and .c files
[~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 Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library 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 #include "gtksignal.h"
20 #include "gtkviewport.h"
21
22
23 static void gtk_viewport_class_init               (GtkViewportClass *klass);
24 static void gtk_viewport_init                     (GtkViewport      *viewport);
25 static void gtk_viewport_finalize                 (GtkObject        *object);
26 static void gtk_viewport_map                      (GtkWidget        *widget);
27 static void gtk_viewport_unmap                    (GtkWidget        *widget);
28 static void gtk_viewport_realize                  (GtkWidget        *widget);
29 static void gtk_viewport_unrealize                (GtkWidget        *widget);
30 static void gtk_viewport_paint                    (GtkWidget        *widget,
31                                                    GdkRectangle     *area);
32 static void gtk_viewport_draw                     (GtkWidget        *widget,
33                                                    GdkRectangle     *area);
34 static gint gtk_viewport_expose                   (GtkWidget        *widget,
35                                                    GdkEventExpose   *event);
36 static void gtk_viewport_add                      (GtkContainer     *container,
37                                                    GtkWidget        *widget);
38 static void gtk_viewport_size_request             (GtkWidget        *widget,
39                                                    GtkRequisition   *requisition);
40 static void gtk_viewport_size_allocate            (GtkWidget        *widget,
41                                                    GtkAllocation    *allocation);
42 static gint gtk_viewport_need_resize              (GtkContainer     *container);
43 static void gtk_viewport_adjustment_changed       (GtkAdjustment    *adjustment,
44                                                    gpointer          data);
45 static void gtk_viewport_adjustment_value_changed (GtkAdjustment    *adjustment,
46                                                    gpointer          data);
47
48 static GtkBinClass *parent_class;
49
50 guint
51 gtk_viewport_get_type ()
52 {
53   static guint viewport_type = 0;
54
55   if (!viewport_type)
56     {
57       GtkTypeInfo viewport_info =
58       {
59         "GtkViewport",
60         sizeof (GtkViewport),
61         sizeof (GtkViewportClass),
62         (GtkClassInitFunc) gtk_viewport_class_init,
63         (GtkObjectInitFunc) gtk_viewport_init,
64         (GtkArgSetFunc) NULL,
65         (GtkArgGetFunc) NULL,
66       };
67
68       viewport_type = gtk_type_unique (gtk_bin_get_type (), &viewport_info);
69     }
70
71   return viewport_type;
72 }
73
74 static void
75 gtk_viewport_class_init (GtkViewportClass *class)
76 {
77   GtkObjectClass *object_class;
78   GtkWidgetClass *widget_class;
79   GtkContainerClass *container_class;
80
81   object_class = (GtkObjectClass*) class;
82   widget_class = (GtkWidgetClass*) class;
83   container_class = (GtkContainerClass*) class;
84   parent_class = (GtkBinClass*) gtk_type_class (gtk_bin_get_type ());
85
86   object_class->finalize = gtk_viewport_finalize;
87   
88   widget_class->map = gtk_viewport_map;
89   widget_class->unmap = gtk_viewport_unmap;
90   widget_class->realize = gtk_viewport_realize;
91   widget_class->unrealize = gtk_viewport_unrealize;
92   widget_class->draw = gtk_viewport_draw;
93   widget_class->expose_event = gtk_viewport_expose;
94   widget_class->size_request = gtk_viewport_size_request;
95   widget_class->size_allocate = gtk_viewport_size_allocate;
96
97   container_class->add = gtk_viewport_add;
98   container_class->need_resize = gtk_viewport_need_resize;
99 }
100
101 static void
102 gtk_viewport_init (GtkViewport *viewport)
103 {
104   GTK_WIDGET_UNSET_FLAGS (viewport, GTK_NO_WINDOW);
105   GTK_WIDGET_SET_FLAGS (viewport, GTK_BASIC);
106
107   viewport->shadow_type = GTK_SHADOW_IN;
108   viewport->view_window = NULL;
109   viewport->bin_window = NULL;
110   viewport->hadjustment = NULL;
111   viewport->vadjustment = NULL;
112 }
113
114 GtkWidget*
115 gtk_viewport_new (GtkAdjustment *hadjustment,
116                   GtkAdjustment *vadjustment)
117 {
118   GtkViewport *viewport;
119
120   viewport = gtk_type_new (gtk_viewport_get_type ());
121
122   if (!hadjustment)
123     hadjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
124
125   if (!vadjustment)
126     vadjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
127
128   gtk_viewport_set_hadjustment (viewport, hadjustment);
129   gtk_viewport_set_vadjustment (viewport, vadjustment);
130
131   return GTK_WIDGET (viewport);
132 }
133
134 static void
135 gtk_viewport_finalize (GtkObject *object)
136 {
137   GtkViewport *viewport = GTK_VIEWPORT (object);
138
139   gtk_object_unref (GTK_OBJECT (viewport->hadjustment));
140   gtk_object_unref (GTK_OBJECT (viewport->vadjustment));
141
142   GTK_OBJECT_CLASS(parent_class)->finalize (object);
143 }
144
145 GtkAdjustment*
146 gtk_viewport_get_hadjustment (GtkViewport *viewport)
147 {
148   g_return_val_if_fail (viewport != NULL, NULL);
149   g_return_val_if_fail (GTK_IS_VIEWPORT (viewport), NULL);
150
151   return viewport->hadjustment;
152 }
153
154 GtkAdjustment*
155 gtk_viewport_get_vadjustment (GtkViewport *viewport)
156 {
157   g_return_val_if_fail (viewport != NULL, NULL);
158   g_return_val_if_fail (GTK_IS_VIEWPORT (viewport), NULL);
159
160   return viewport->vadjustment;
161 }
162
163 void
164 gtk_viewport_set_hadjustment (GtkViewport   *viewport,
165                               GtkAdjustment *adjustment)
166 {
167   g_return_if_fail (viewport != NULL);
168   g_return_if_fail (GTK_IS_VIEWPORT (viewport));
169   g_return_if_fail (adjustment != NULL);
170
171   if (viewport->hadjustment != adjustment)
172     {
173       if (viewport->hadjustment)
174         {
175           gtk_signal_disconnect_by_data (GTK_OBJECT (viewport->hadjustment),
176                                          (gpointer) viewport);
177           gtk_object_unref (GTK_OBJECT (viewport->hadjustment));
178         }
179
180       viewport->hadjustment = adjustment;
181       gtk_object_ref (GTK_OBJECT (viewport->hadjustment));
182       gtk_object_sink (GTK_OBJECT (viewport->hadjustment));
183       
184       gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
185                           (GtkSignalFunc) gtk_viewport_adjustment_changed,
186                           (gpointer) viewport);
187       gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
188                           (GtkSignalFunc)gtk_viewport_adjustment_value_changed,
189                           (gpointer) viewport);
190
191       gtk_viewport_adjustment_changed (adjustment, (gpointer) viewport);
192     }
193 }
194
195 void
196 gtk_viewport_set_vadjustment (GtkViewport   *viewport,
197                               GtkAdjustment *adjustment)
198 {
199   g_return_if_fail (viewport != NULL);
200   g_return_if_fail (GTK_IS_VIEWPORT (viewport));
201   g_return_if_fail (adjustment != NULL);
202
203   if (viewport->vadjustment != adjustment)
204     {
205       if (viewport->vadjustment)
206         {
207           gtk_signal_disconnect_by_data (GTK_OBJECT (viewport->vadjustment),
208                                          (gpointer) viewport);
209           gtk_object_unref (GTK_OBJECT (viewport->vadjustment));
210         }
211
212       viewport->vadjustment = adjustment;
213       gtk_object_ref (GTK_OBJECT (viewport->vadjustment));
214       gtk_object_sink (GTK_OBJECT (viewport->vadjustment));
215       
216       gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
217                           (GtkSignalFunc) gtk_viewport_adjustment_changed,
218                           (gpointer) viewport);
219       gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
220                           (GtkSignalFunc)gtk_viewport_adjustment_value_changed,
221                           (gpointer) viewport);
222
223       gtk_viewport_adjustment_changed (adjustment, (gpointer) viewport);
224     }
225 }
226
227 void
228 gtk_viewport_set_shadow_type (GtkViewport   *viewport,
229                               GtkShadowType  type)
230 {
231   g_return_if_fail (viewport != NULL);
232   g_return_if_fail (GTK_IS_VIEWPORT (viewport));
233
234   if ((GtkShadowType) viewport->shadow_type != type)
235     {
236       viewport->shadow_type = type;
237
238       if (GTK_WIDGET_VISIBLE (viewport))
239         {
240           gtk_widget_size_allocate (GTK_WIDGET (viewport), &(GTK_WIDGET (viewport)->allocation));
241           gtk_widget_queue_draw (GTK_WIDGET (viewport));
242         }
243     }
244 }
245
246
247 static void
248 gtk_viewport_map (GtkWidget *widget)
249 {
250   GtkBin *bin;
251
252   g_return_if_fail (widget != NULL);
253   g_return_if_fail (GTK_IS_VIEWPORT (widget));
254
255   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
256   bin = GTK_BIN (widget);
257
258   gdk_window_show (widget->window);
259
260   if (bin->child &&
261       GTK_WIDGET_VISIBLE (bin->child) &&
262       !GTK_WIDGET_MAPPED (bin->child))
263     gtk_widget_map (bin->child);
264 }
265
266 static void
267 gtk_viewport_unmap (GtkWidget *widget)
268 {
269   g_return_if_fail (widget != NULL);
270   g_return_if_fail (GTK_IS_VIEWPORT (widget));
271
272   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
273   
274   gdk_window_hide (widget->window);
275 }
276
277 static void
278 gtk_viewport_realize (GtkWidget *widget)
279 {
280   GtkBin *bin;
281   GtkViewport *viewport;
282   GdkWindowAttr attributes;
283   gint attributes_mask;
284   gint event_mask;
285   gint border_width;
286
287   g_return_if_fail (widget != NULL);
288   g_return_if_fail (GTK_IS_VIEWPORT (widget));
289
290   border_width = GTK_CONTAINER (widget)->border_width;
291
292   bin = GTK_BIN (widget);
293   viewport = GTK_VIEWPORT (widget);
294   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
295
296   attributes.x = widget->allocation.x + border_width;
297   attributes.y = widget->allocation.y + border_width;
298   attributes.width = widget->allocation.width - border_width * 2;
299   attributes.height = widget->allocation.height - border_width * 2;
300   attributes.window_type = GDK_WINDOW_CHILD;
301   attributes.wclass = GDK_INPUT_OUTPUT;
302   attributes.visual = gtk_widget_get_visual (widget);
303   attributes.colormap = gtk_widget_get_colormap (widget);
304
305   event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
306   attributes.event_mask = event_mask;
307
308   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
309
310   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
311                                    &attributes, attributes_mask);
312   gdk_window_set_user_data (widget->window, viewport);
313
314   if (viewport->shadow_type != GTK_SHADOW_NONE)
315     {
316       attributes.x = widget->style->klass->xthickness;
317       attributes.y = widget->style->klass->ythickness;
318     }
319   else
320     {
321       attributes.x = 0;
322       attributes.y = 0;
323     }
324
325   attributes.width = MAX (1, widget->allocation.width - attributes.x * 2 - border_width * 2);
326   attributes.height = MAX (1, widget->allocation.height - attributes.y * 2 - border_width * 2);
327   attributes.event_mask = 0;
328
329   viewport->view_window = gdk_window_new (widget->window, &attributes, attributes_mask);
330   gdk_window_set_user_data (viewport->view_window, viewport);
331
332   attributes.x = 0;
333   attributes.y = 0;
334
335   if (bin->child)
336     {
337       attributes.width = viewport->hadjustment->upper;
338       attributes.height = viewport->vadjustment->upper;
339     }
340   
341   attributes.event_mask = event_mask;
342
343   viewport->bin_window = gdk_window_new (viewport->view_window, &attributes, attributes_mask);
344   gdk_window_set_user_data (viewport->bin_window, viewport);
345
346   if (bin->child)
347     gtk_widget_set_parent_window (bin->child, viewport->bin_window);
348
349   widget->style = gtk_style_attach (widget->style, widget->window);
350   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
351   gtk_style_set_background (widget->style, viewport->bin_window, GTK_STATE_NORMAL);
352   
353   gdk_window_show (viewport->bin_window);
354   gdk_window_show (viewport->view_window);
355 }
356
357 static void
358 gtk_viewport_unrealize (GtkWidget *widget)
359 {
360   GtkViewport *viewport;
361
362   g_return_if_fail (widget != NULL);
363   g_return_if_fail (GTK_IS_VIEWPORT (widget));
364
365   viewport = GTK_VIEWPORT (widget);
366
367   gdk_window_set_user_data (viewport->view_window, NULL);
368   gdk_window_destroy (viewport->view_window);
369   viewport->view_window = NULL;
370
371   gdk_window_set_user_data (viewport->bin_window, NULL);
372   gdk_window_destroy (viewport->bin_window);
373   viewport->bin_window = NULL;
374
375   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
376     (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
377 }
378
379 static void
380 gtk_viewport_paint (GtkWidget    *widget,
381                     GdkRectangle *area)
382 {
383   GtkViewport *viewport;
384
385   g_return_if_fail (widget != NULL);
386   g_return_if_fail (GTK_IS_VIEWPORT (widget));
387   g_return_if_fail (area != NULL);
388
389   if (GTK_WIDGET_DRAWABLE (widget))
390     {
391       viewport = GTK_VIEWPORT (widget);
392
393       gtk_draw_shadow (widget->style, widget->window,
394                        GTK_STATE_NORMAL, viewport->shadow_type,
395                        0, 0, -1, -1);
396     }
397 }
398
399 static void
400 gtk_viewport_draw (GtkWidget    *widget,
401                    GdkRectangle *area)
402 {
403   GtkViewport *viewport;
404   GtkBin *bin;
405   GdkRectangle tmp_area;
406   GdkRectangle child_area;
407   gint border_width;
408
409   g_return_if_fail (widget != NULL);
410   g_return_if_fail (GTK_IS_VIEWPORT (widget));
411   g_return_if_fail (area != NULL);
412
413   if (GTK_WIDGET_DRAWABLE (widget))
414     {
415       viewport = GTK_VIEWPORT (widget);
416       bin = GTK_BIN (widget);
417
418       border_width = GTK_CONTAINER (widget)->border_width;
419       
420       tmp_area = *area;
421       tmp_area.x -= border_width;
422       tmp_area.y -= border_width;
423       
424       gtk_viewport_paint (widget, &tmp_area);
425
426       if (bin->child)
427         {
428           tmp_area.x += viewport->hadjustment->value - widget->style->klass->xthickness;
429           tmp_area.y += viewport->vadjustment->value - widget->style->klass->ythickness;
430
431           if (gtk_widget_intersect (bin->child, &tmp_area, &child_area))
432             gtk_widget_draw (bin->child, &child_area);
433         }
434     }
435 }
436
437 static gint
438 gtk_viewport_expose (GtkWidget      *widget,
439                      GdkEventExpose *event)
440 {
441   GtkViewport *viewport;
442   GtkBin *bin;
443   GdkEventExpose child_event;
444
445   g_return_val_if_fail (widget != NULL, FALSE);
446   g_return_val_if_fail (GTK_IS_VIEWPORT (widget), FALSE);
447   g_return_val_if_fail (event != NULL, FALSE);
448
449   if (GTK_WIDGET_DRAWABLE (widget))
450     {
451       viewport = GTK_VIEWPORT (widget);
452       bin = GTK_BIN (widget);
453
454       if (event->window == widget->window)
455         gtk_viewport_paint (widget, &event->area);
456
457       child_event = *event;
458       if ((event->window == viewport->bin_window) &&
459           (bin->child != NULL) &&
460           GTK_WIDGET_NO_WINDOW (bin->child) &&
461           gtk_widget_intersect (bin->child, &event->area, &child_event.area))
462         gtk_widget_event (bin->child, (GdkEvent*) &child_event);
463     }
464
465   return FALSE;
466 }
467
468 static void
469 gtk_viewport_add (GtkContainer *container,
470                   GtkWidget    *widget)
471 {
472   GtkBin *bin;
473
474   g_return_if_fail (container != NULL);
475   g_return_if_fail (GTK_IS_VIEWPORT (container));
476   g_return_if_fail (widget != NULL);
477
478   bin = GTK_BIN (container);
479
480   if (!bin->child)
481     {
482       gtk_widget_set_parent (widget, GTK_WIDGET (container));
483       gtk_widget_set_parent_window (widget, GTK_VIEWPORT (container)->bin_window);
484       if (GTK_WIDGET_VISIBLE (widget->parent))
485         {
486           if (GTK_WIDGET_MAPPED (widget->parent) &&
487               !GTK_WIDGET_MAPPED (widget))
488             gtk_widget_map (widget);
489         }
490
491       bin->child = widget;
492
493       if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
494         gtk_widget_queue_resize (widget);
495     }
496 }
497
498 static void
499 gtk_viewport_size_request (GtkWidget      *widget,
500                            GtkRequisition *requisition)
501 {
502   GtkViewport *viewport;
503   GtkBin *bin;
504
505   g_return_if_fail (widget != NULL);
506   g_return_if_fail (GTK_IS_VIEWPORT (widget));
507   g_return_if_fail (requisition != NULL);
508
509   viewport = GTK_VIEWPORT (widget);
510   bin = GTK_BIN (widget);
511
512   requisition->width = (GTK_CONTAINER (widget)->border_width +
513                         GTK_WIDGET (widget)->style->klass->xthickness) * 2 + 5;
514
515   requisition->height = (GTK_CONTAINER (widget)->border_width * 2 +
516                          GTK_WIDGET (widget)->style->klass->ythickness) * 2 + 5;
517
518   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
519     gtk_widget_size_request (bin->child, &bin->child->requisition);
520 }
521
522 static void
523 gtk_viewport_size_allocate (GtkWidget     *widget,
524                             GtkAllocation *allocation)
525 {
526   GtkViewport *viewport;
527   GtkBin *bin;
528   GtkAllocation child_allocation;
529   gint hval, vval;
530   gint border_width;
531
532   g_return_if_fail (widget != NULL);
533   g_return_if_fail (GTK_IS_VIEWPORT (widget));
534   g_return_if_fail (allocation != NULL);
535
536   widget->allocation = *allocation;
537   viewport = GTK_VIEWPORT (widget);
538   bin = GTK_BIN (widget);
539
540   border_width = GTK_CONTAINER (widget)->border_width;
541
542   child_allocation.x = 0;
543   child_allocation.y = 0;
544
545   if (viewport->shadow_type != GTK_SHADOW_NONE)
546     {
547       child_allocation.x = GTK_WIDGET (viewport)->style->klass->xthickness;
548       child_allocation.y = GTK_WIDGET (viewport)->style->klass->ythickness;
549     }
550
551   child_allocation.width = MAX (1, allocation->width - child_allocation.x * 2 - border_width * 2);
552   child_allocation.height = MAX (1, allocation->height - child_allocation.y * 2 - border_width * 2);
553
554   if (GTK_WIDGET_REALIZED (widget))
555     {
556       gdk_window_move_resize (widget->window,
557                               allocation->x + border_width,
558                               allocation->y + border_width,
559                               allocation->width - border_width * 2,
560                               allocation->height - border_width * 2);
561
562       gdk_window_move_resize (viewport->view_window,
563                               child_allocation.x,
564                               child_allocation.y,
565                               child_allocation.width,
566                               child_allocation.height);
567     }
568
569   viewport->hadjustment->page_size = child_allocation.width;
570   viewport->hadjustment->page_increment = viewport->hadjustment->page_size / 2;
571   viewport->hadjustment->step_increment = 10;
572
573   viewport->vadjustment->page_size = child_allocation.height;
574   viewport->vadjustment->page_increment = viewport->vadjustment->page_size / 2;
575   viewport->vadjustment->step_increment = 10;
576
577   hval = viewport->hadjustment->value;
578   vval = viewport->vadjustment->value;
579
580   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
581     {
582       viewport->hadjustment->lower = 0;
583       viewport->hadjustment->upper = MAX (bin->child->requisition.width,
584                                           child_allocation.width);
585
586       hval = CLAMP (hval, 0,
587                     viewport->hadjustment->upper -
588                     viewport->hadjustment->page_size);
589
590       viewport->vadjustment->lower = 0;
591       viewport->vadjustment->upper = MAX (bin->child->requisition.height,
592                                           child_allocation.height);
593
594       vval = CLAMP (vval, 0,
595                     viewport->vadjustment->upper -
596                     viewport->vadjustment->page_size);
597     }
598
599   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
600     {
601       child_allocation.x = 0;
602       child_allocation.y = 0;
603
604       child_allocation.width = viewport->hadjustment->upper;
605       child_allocation.height = viewport->vadjustment->upper;
606
607       if (!GTK_WIDGET_REALIZED (widget))
608         gtk_widget_realize (widget);
609
610       gdk_window_resize (viewport->bin_window,
611                          child_allocation.width,
612                          child_allocation.height);
613
614       child_allocation.x = 0;
615       child_allocation.y = 0;
616       gtk_widget_size_allocate (bin->child, &child_allocation);
617     }
618
619   gtk_signal_emit_by_name (GTK_OBJECT (viewport->hadjustment), "changed");
620   gtk_signal_emit_by_name (GTK_OBJECT (viewport->vadjustment), "changed");
621   if (viewport->hadjustment->value != hval)
622     {
623       viewport->hadjustment->value = hval;
624       gtk_signal_emit_by_name (GTK_OBJECT (viewport->hadjustment), "value_changed");
625     }
626   if (viewport->vadjustment->value != vval)
627     {
628       viewport->vadjustment->value = vval;
629       gtk_signal_emit_by_name (GTK_OBJECT (viewport->vadjustment), "value_changed");
630     }
631 }
632
633 static gint
634 gtk_viewport_need_resize (GtkContainer *container)
635 {
636   GtkBin *bin;
637
638   g_return_val_if_fail (container != NULL, FALSE);
639   g_return_val_if_fail (GTK_IS_VIEWPORT (container), FALSE);
640
641   if (GTK_WIDGET_REALIZED (container))
642     {
643       bin = GTK_BIN (container);
644
645       gtk_widget_size_request (bin->child, &bin->child->requisition);
646
647       gtk_widget_size_allocate (GTK_WIDGET (container),
648                                 &(GTK_WIDGET (container)->allocation));
649     }
650
651   return FALSE;
652 }
653
654 static void
655 gtk_viewport_adjustment_changed (GtkAdjustment *adjustment,
656                                  gpointer       data)
657 {
658   GtkViewport *viewport;
659
660   g_return_if_fail (adjustment != NULL);
661   g_return_if_fail (data != NULL);
662   g_return_if_fail (GTK_IS_VIEWPORT (data));
663
664   viewport = GTK_VIEWPORT (data);
665 }
666
667 static void
668 gtk_viewport_adjustment_value_changed (GtkAdjustment *adjustment,
669                                        gpointer       data)
670 {
671   GtkViewport *viewport;
672   GtkBin *bin;
673   GtkAllocation child_allocation;
674   gint width, height;
675
676   g_return_if_fail (adjustment != NULL);
677   g_return_if_fail (data != NULL);
678   g_return_if_fail (GTK_IS_VIEWPORT (data));
679
680   viewport = GTK_VIEWPORT (data);
681   bin = GTK_BIN (data);
682
683   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
684     {
685       gdk_window_get_size (viewport->view_window, &width, &height);
686
687       child_allocation.x = 0;
688       child_allocation.y = 0;
689
690       if (viewport->hadjustment->lower != (viewport->hadjustment->upper -
691                                            viewport->hadjustment->page_size))
692         child_allocation.x =  viewport->hadjustment->lower - viewport->hadjustment->value;
693
694       if (viewport->vadjustment->lower != (viewport->vadjustment->upper -
695                                            viewport->vadjustment->page_size))
696         child_allocation.y = viewport->vadjustment->lower - viewport->vadjustment->value;
697
698       if (GTK_WIDGET_REALIZED (viewport))
699         gdk_window_move (viewport->bin_window,
700                          child_allocation.x,
701                          child_allocation.y);
702     }
703 }