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