]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkviewport.c
Merges from gtk-1-2
[~andy/gtk] / gtk / gtkviewport.c
index dfa00c4b089581d296e7e3ceb483faa599b55148..afffdf01ad5580e4c04824f63c33db81f4f1c2e7 100644 (file)
  * Library General Public License for more details.
  *
  * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
  */
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
 #include "gtksignal.h"
 #include "gtkviewport.h"
 
+enum {
+  ARG_0,
+  ARG_HADJUSTMENT,
+  ARG_VADJUSTMENT,
+  ARG_SHADOW_TYPE
+};
+
 
 static void gtk_viewport_class_init               (GtkViewportClass *klass);
 static void gtk_viewport_init                     (GtkViewport      *viewport);
+static void gtk_viewport_destroy                  (GtkObject        *object);
+static void gtk_viewport_finalize                 (GtkObject        *object);
+static void gtk_viewport_set_arg                 (GtkObject        *object,
+                                                  GtkArg           *arg,
+                                                  guint             arg_id);
+static void gtk_viewport_get_arg                 (GtkObject        *object,
+                                                  GtkArg           *arg,
+                                                  guint             arg_id);
+static void gtk_viewport_set_scroll_adjustments          (GtkViewport      *viewport,
+                                                  GtkAdjustment    *hadjustment,
+                                                  GtkAdjustment    *vadjustment);
 static void gtk_viewport_map                      (GtkWidget        *widget);
 static void gtk_viewport_unmap                    (GtkWidget        *widget);
 static void gtk_viewport_realize                  (GtkWidget        *widget);
@@ -31,35 +58,41 @@ static void gtk_viewport_draw                     (GtkWidget        *widget,
                                                   GdkRectangle     *area);
 static gint gtk_viewport_expose                   (GtkWidget        *widget,
                                                   GdkEventExpose   *event);
+static void gtk_viewport_add                      (GtkContainer     *container,
+                                                  GtkWidget        *widget);
 static void gtk_viewport_size_request             (GtkWidget        *widget,
                                                   GtkRequisition   *requisition);
 static void gtk_viewport_size_allocate            (GtkWidget        *widget,
                                                   GtkAllocation    *allocation);
-static gint gtk_viewport_need_resize              (GtkContainer     *container);
 static void gtk_viewport_adjustment_changed       (GtkAdjustment    *adjustment,
                                                   gpointer          data);
 static void gtk_viewport_adjustment_value_changed (GtkAdjustment    *adjustment,
                                                   gpointer          data);
+static void gtk_viewport_style_set                (GtkWidget *widget,
+                                                  GtkStyle  *previous_style);
 
+static GtkBinClass *parent_class;
 
-guint
-gtk_viewport_get_type ()
+GtkType
+gtk_viewport_get_type (void)
 {
-  static guint viewport_type = 0;
+  static GtkType viewport_type = 0;
 
   if (!viewport_type)
     {
-      GtkTypeInfo viewport_info =
+      static const GtkTypeInfo viewport_info =
       {
        "GtkViewport",
        sizeof (GtkViewport),
        sizeof (GtkViewportClass),
        (GtkClassInitFunc) gtk_viewport_class_init,
        (GtkObjectInitFunc) gtk_viewport_init,
-       (GtkArgFunc) NULL,
+       /* reserved_1 */ NULL,
+        /* reserved_2 */ NULL,
+        (GtkClassInitFunc) NULL,
       };
 
-      viewport_type = gtk_type_unique (gtk_bin_get_type (), &viewport_info);
+      viewport_type = gtk_type_unique (GTK_TYPE_BIN, &viewport_info);
     }
 
   return viewport_type;
@@ -68,12 +101,33 @@ gtk_viewport_get_type ()
 static void
 gtk_viewport_class_init (GtkViewportClass *class)
 {
+  GtkObjectClass *object_class;
   GtkWidgetClass *widget_class;
   GtkContainerClass *container_class;
 
+  object_class = (GtkObjectClass*) class;
   widget_class = (GtkWidgetClass*) class;
   container_class = (GtkContainerClass*) class;
-
+  parent_class = (GtkBinClass*) gtk_type_class (GTK_TYPE_BIN);
+
+  gtk_object_add_arg_type ("GtkViewport::hadjustment",
+                          GTK_TYPE_ADJUSTMENT,
+                          GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
+                          ARG_HADJUSTMENT);
+  gtk_object_add_arg_type ("GtkViewport::vadjustment",
+                          GTK_TYPE_ADJUSTMENT,
+                          GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
+                          ARG_VADJUSTMENT);
+  gtk_object_add_arg_type ("GtkViewport::shadow_type",
+                          GTK_TYPE_SHADOW_TYPE,
+                          GTK_ARG_READWRITE,
+                          ARG_SHADOW_TYPE);
+
+  object_class->set_arg = gtk_viewport_set_arg;
+  object_class->get_arg = gtk_viewport_get_arg;
+  object_class->destroy = gtk_viewport_destroy;
+  object_class->finalize = gtk_viewport_finalize;
+  
   widget_class->map = gtk_viewport_map;
   widget_class->unmap = gtk_viewport_unmap;
   widget_class->realize = gtk_viewport_realize;
@@ -82,19 +136,82 @@ gtk_viewport_class_init (GtkViewportClass *class)
   widget_class->expose_event = gtk_viewport_expose;
   widget_class->size_request = gtk_viewport_size_request;
   widget_class->size_allocate = gtk_viewport_size_allocate;
+  widget_class->style_set = gtk_viewport_style_set;
+
+  widget_class->set_scroll_adjustments_signal =
+    gtk_signal_new ("set_scroll_adjustments",
+                   GTK_RUN_LAST,
+                   object_class->type,
+                   GTK_SIGNAL_OFFSET (GtkViewportClass, set_scroll_adjustments),
+                   gtk_marshal_NONE__POINTER_POINTER,
+                   GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
+  
+  container_class->add = gtk_viewport_add;
 
-  container_class->need_resize = gtk_viewport_need_resize;
+  class->set_scroll_adjustments = gtk_viewport_set_scroll_adjustments;
+}
+
+static void
+gtk_viewport_set_arg (GtkObject        *object,
+                     GtkArg           *arg,
+                     guint             arg_id)
+{
+  GtkViewport *viewport;
+
+  viewport = GTK_VIEWPORT (object);
+
+  switch (arg_id)
+    {
+    case ARG_HADJUSTMENT:
+      gtk_viewport_set_hadjustment (viewport, GTK_VALUE_POINTER (*arg));
+      break;
+    case ARG_VADJUSTMENT:
+      gtk_viewport_set_vadjustment (viewport, GTK_VALUE_POINTER (*arg));
+      break;
+    case ARG_SHADOW_TYPE:
+      gtk_viewport_set_shadow_type (viewport, GTK_VALUE_ENUM (*arg));
+      break;
+    default:
+      break;
+    }
+}
+
+static void
+gtk_viewport_get_arg (GtkObject        *object,
+                     GtkArg           *arg,
+                     guint             arg_id)
+{
+  GtkViewport *viewport;
+
+  viewport = GTK_VIEWPORT (object);
+
+  switch (arg_id)
+    {
+    case ARG_HADJUSTMENT:
+      GTK_VALUE_POINTER (*arg) = viewport->hadjustment;
+      break;
+    case ARG_VADJUSTMENT:
+      GTK_VALUE_POINTER (*arg) = viewport->vadjustment;
+      break;
+    case ARG_SHADOW_TYPE:
+      GTK_VALUE_ENUM (*arg) = viewport->shadow_type;
+      break;
+    default:
+      arg->type = GTK_TYPE_INVALID;
+      break;
+    }
 }
 
 static void
 gtk_viewport_init (GtkViewport *viewport)
 {
   GTK_WIDGET_UNSET_FLAGS (viewport, GTK_NO_WINDOW);
-  GTK_WIDGET_SET_FLAGS (viewport, GTK_BASIC);
 
+  gtk_container_set_resize_mode (GTK_CONTAINER (viewport), GTK_RESIZE_QUEUE);
+  
   viewport->shadow_type = GTK_SHADOW_IN;
-  viewport->main_window = NULL;
   viewport->view_window = NULL;
+  viewport->bin_window = NULL;
   viewport->hadjustment = NULL;
   viewport->vadjustment = NULL;
 }
@@ -103,20 +220,40 @@ GtkWidget*
 gtk_viewport_new (GtkAdjustment *hadjustment,
                  GtkAdjustment *vadjustment)
 {
-  GtkViewport *viewport;
+  GtkWidget *viewport;
+
+  viewport = gtk_widget_new (GTK_TYPE_VIEWPORT,
+                            "hadjustment", hadjustment,
+                            "vadjustment", vadjustment,
+                            NULL);
+
+  return viewport;
+}
 
-  viewport = gtk_type_new (gtk_viewport_get_type ());
+static void
+gtk_viewport_destroy (GtkObject *object)
+{
+  GtkViewport *viewport = GTK_VIEWPORT (object);
 
-  if (!hadjustment)
-    hadjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+  if (viewport->hadjustment)
+    gtk_signal_disconnect_by_data (GTK_OBJECT (viewport->hadjustment),
+                                  viewport);
+  if (viewport->vadjustment)
+    gtk_signal_disconnect_by_data (GTK_OBJECT (viewport->vadjustment),
+                                  viewport);
 
-  if (!vadjustment)
-    vadjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+  GTK_OBJECT_CLASS(parent_class)->destroy (object);
+}
 
-  gtk_viewport_set_hadjustment (viewport, hadjustment);
-  gtk_viewport_set_vadjustment (viewport, vadjustment);
+static void
+gtk_viewport_finalize (GtkObject *object)
+{
+  GtkViewport *viewport = GTK_VIEWPORT (object);
 
-  return GTK_WIDGET (viewport);
+  gtk_object_unref (GTK_OBJECT (viewport->hadjustment));
+  gtk_object_unref (GTK_OBJECT (viewport->vadjustment));
+
+  GTK_OBJECT_CLASS(parent_class)->finalize (object);
 }
 
 GtkAdjustment*
@@ -143,25 +280,35 @@ gtk_viewport_set_hadjustment (GtkViewport   *viewport,
 {
   g_return_if_fail (viewport != NULL);
   g_return_if_fail (GTK_IS_VIEWPORT (viewport));
-  g_return_if_fail (adjustment != NULL);
+  if (adjustment)
+    g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
 
-  if (viewport->hadjustment)
+  if (viewport->hadjustment && viewport->hadjustment != adjustment)
     {
-      gtk_signal_disconnect_by_data (GTK_OBJECT (viewport->hadjustment), (gpointer) viewport);
+      gtk_signal_disconnect_by_data (GTK_OBJECT (viewport->hadjustment),
+                                    (gpointer) viewport);
       gtk_object_unref (GTK_OBJECT (viewport->hadjustment));
     }
 
-  viewport->hadjustment = adjustment;
-  gtk_object_ref (GTK_OBJECT (viewport->hadjustment));
-
-  gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
-                     (GtkSignalFunc) gtk_viewport_adjustment_changed,
-                     (gpointer) viewport);
-  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
-                     (GtkSignalFunc) gtk_viewport_adjustment_value_changed,
-                     (gpointer) viewport);
+  if (!adjustment)
+    adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0,
+                                                    0.0, 0.0, 0.0));
 
-  gtk_viewport_adjustment_changed (adjustment, (gpointer) viewport);
+  if (viewport->hadjustment != adjustment)
+    {
+      viewport->hadjustment = adjustment;
+      gtk_object_ref (GTK_OBJECT (viewport->hadjustment));
+      gtk_object_sink (GTK_OBJECT (viewport->hadjustment));
+      
+      gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
+                         (GtkSignalFunc) gtk_viewport_adjustment_changed,
+                         (gpointer) viewport);
+      gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+                         (GtkSignalFunc) gtk_viewport_adjustment_value_changed,
+                         (gpointer) viewport);
+
+      gtk_viewport_adjustment_changed (adjustment, viewport);
+    }
 }
 
 void
@@ -170,25 +317,46 @@ gtk_viewport_set_vadjustment (GtkViewport   *viewport,
 {
   g_return_if_fail (viewport != NULL);
   g_return_if_fail (GTK_IS_VIEWPORT (viewport));
-  g_return_if_fail (adjustment != NULL);
+  if (adjustment)
+    g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
 
-  if (viewport->vadjustment)
+  if (viewport->vadjustment && viewport->vadjustment != adjustment)
     {
-      gtk_signal_disconnect_by_data (GTK_OBJECT (viewport->vadjustment), (gpointer) viewport);
+      gtk_signal_disconnect_by_data (GTK_OBJECT (viewport->vadjustment),
+                                    (gpointer) viewport);
       gtk_object_unref (GTK_OBJECT (viewport->vadjustment));
     }
 
-  viewport->vadjustment = adjustment;
-  gtk_object_ref (GTK_OBJECT (viewport->vadjustment));
+  if (!adjustment)
+    adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0,
+                                                    0.0, 0.0, 0.0));
 
-  gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
-                     (GtkSignalFunc) gtk_viewport_adjustment_changed,
-                     (gpointer) viewport);
-  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
-                     (GtkSignalFunc) gtk_viewport_adjustment_value_changed,
-                     (gpointer) viewport);
+  if (viewport->vadjustment != adjustment)
+    {
+      viewport->vadjustment = adjustment;
+      gtk_object_ref (GTK_OBJECT (viewport->vadjustment));
+      gtk_object_sink (GTK_OBJECT (viewport->vadjustment));
+      
+      gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
+                         (GtkSignalFunc) gtk_viewport_adjustment_changed,
+                         (gpointer) viewport);
+      gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+                         (GtkSignalFunc) gtk_viewport_adjustment_value_changed,
+                         (gpointer) viewport);
+
+      gtk_viewport_adjustment_changed (adjustment, viewport);
+    }
+}
 
-  gtk_viewport_adjustment_changed (adjustment, (gpointer) viewport);
+static void
+gtk_viewport_set_scroll_adjustments (GtkViewport      *viewport,
+                                    GtkAdjustment    *hadjustment,
+                                    GtkAdjustment    *vadjustment)
+{
+  if (viewport->hadjustment != hadjustment)
+    gtk_viewport_set_hadjustment (viewport, hadjustment);
+  if (viewport->vadjustment != vadjustment)
+    gtk_viewport_set_vadjustment (viewport, vadjustment);
 }
 
 void
@@ -214,93 +382,117 @@ gtk_viewport_set_shadow_type (GtkViewport   *viewport,
 static void
 gtk_viewport_map (GtkWidget *widget)
 {
-  GtkViewport *viewport;
   GtkBin *bin;
 
   g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_VIEWPORT (widget));
 
   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
-  viewport = GTK_VIEWPORT (widget);
   bin = GTK_BIN (widget);
 
-  gdk_window_show (viewport->main_window);
-
   if (bin->child &&
       GTK_WIDGET_VISIBLE (bin->child) &&
       !GTK_WIDGET_MAPPED (bin->child))
     gtk_widget_map (bin->child);
+
+  gdk_window_show (widget->window);
 }
 
 static void
 gtk_viewport_unmap (GtkWidget *widget)
 {
-  GtkViewport *viewport;
-
   g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_VIEWPORT (widget));
 
   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
-  viewport = GTK_VIEWPORT (widget);
   
-  gdk_window_hide (viewport->main_window);
+  gdk_window_hide (widget->window);
 }
 
 static void
 gtk_viewport_realize (GtkWidget *widget)
 {
+  GtkBin *bin;
   GtkViewport *viewport;
   GdkWindowAttr attributes;
-  GtkRequisition *child_requisition;
   gint attributes_mask;
+  gint event_mask;
+  gint border_width;
 
   g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_VIEWPORT (widget));
 
+  border_width = GTK_CONTAINER (widget)->border_width;
+
+  bin = GTK_BIN (widget);
   viewport = GTK_VIEWPORT (widget);
   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
 
-  attributes.x = widget->allocation.x + GTK_CONTAINER (widget)->border_width;
-  attributes.y = widget->allocation.y + GTK_CONTAINER (widget)->border_width;
-  attributes.width = widget->allocation.width - GTK_CONTAINER (widget)->border_width * 2;
-  attributes.height = widget->allocation.height - GTK_CONTAINER (widget)->border_width * 2;
+  attributes.x = widget->allocation.x + border_width;
+  attributes.y = widget->allocation.y + border_width;
+  attributes.width = widget->allocation.width - border_width * 2;
+  attributes.height = widget->allocation.height - border_width * 2;
   attributes.window_type = GDK_WINDOW_CHILD;
   attributes.wclass = GDK_INPUT_OUTPUT;
   attributes.visual = gtk_widget_get_visual (widget);
   attributes.colormap = gtk_widget_get_colormap (widget);
-  attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
+
+  event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
+  /* We select on button_press_mask so that button 4-5 scrolls are trapped.
+   */
+  attributes.event_mask = event_mask | GDK_BUTTON_PRESS_MASK;
 
   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
 
-  viewport->main_window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
-  gdk_window_set_user_data (viewport->main_window, viewport);
+  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
+                                  &attributes, attributes_mask);
+  gdk_window_set_user_data (widget->window, viewport);
 
-  attributes.x += widget->style->klass->xthickness;
-  attributes.y += widget->style->klass->ythickness;
-  attributes.width -= widget->style->klass->xthickness * 2;
-  attributes.height -= widget->style->klass->ythickness * 2;
+  if (viewport->shadow_type != GTK_SHADOW_NONE)
+    {
+      attributes.x = widget->style->klass->xthickness;
+      attributes.y = widget->style->klass->ythickness;
+    }
+  else
+    {
+      attributes.x = 0;
+      attributes.y = 0;
+    }
+
+  attributes.width = MAX (1, (gint)widget->allocation.width - attributes.x * 2 - border_width * 2);
+  attributes.height = MAX (1, (gint)widget->allocation.height - attributes.y * 2 - border_width * 2);
+  attributes.event_mask = 0;
 
-  viewport->view_window = gdk_window_new (viewport->main_window, &attributes, attributes_mask);
+  viewport->view_window = gdk_window_new (widget->window, &attributes, attributes_mask);
   gdk_window_set_user_data (viewport->view_window, viewport);
 
   attributes.x = 0;
   attributes.y = 0;
 
-  if (GTK_BIN (viewport)->child)
+  if (bin->child)
     {
-      child_requisition = &GTK_WIDGET (GTK_BIN (viewport)->child)->requisition;
-      attributes.width = child_requisition->width;
-      attributes.height = child_requisition->height;
+      attributes.width = viewport->hadjustment->upper;
+      attributes.height = viewport->vadjustment->upper;
     }
+  
+  attributes.event_mask = event_mask;
 
-  widget->window = gdk_window_new (viewport->view_window, &attributes, attributes_mask);
-  gdk_window_set_user_data (widget->window, viewport);
+  viewport->bin_window = gdk_window_new (viewport->view_window, &attributes, attributes_mask);
+  gdk_window_set_user_data (viewport->bin_window, viewport);
 
-  widget->style = gtk_style_attach (widget->style, viewport->main_window);
-  gtk_style_set_background (widget->style, viewport->main_window, GTK_STATE_NORMAL);
+  if (bin->child)
+    gtk_widget_set_parent_window (bin->child, viewport->bin_window);
+
+  widget->style = gtk_style_attach (widget->style, widget->window);
   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
-  
-  gdk_window_show (widget->window);
+  gtk_style_set_background (widget->style, viewport->bin_window, GTK_STATE_NORMAL);
+
+   gtk_paint_flat_box(widget->style, viewport->bin_window, GTK_STATE_NORMAL,
+                     GTK_SHADOW_NONE,
+                     NULL, widget, "viewportbin",
+                     0, 0, -1, -1);
+   
+  gdk_window_show (viewport->bin_window);
   gdk_window_show (viewport->view_window);
 }
 
@@ -313,17 +505,17 @@ gtk_viewport_unrealize (GtkWidget *widget)
   g_return_if_fail (GTK_IS_VIEWPORT (widget));
 
   viewport = GTK_VIEWPORT (widget);
-  GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED | GTK_MAPPED);
 
-  gtk_style_detach (widget->style);
-
-  gdk_window_destroy (widget->window);
+  gdk_window_set_user_data (viewport->view_window, NULL);
   gdk_window_destroy (viewport->view_window);
-  gdk_window_destroy (viewport->main_window);
-
-  widget->window = NULL;
   viewport->view_window = NULL;
-  viewport->main_window = NULL;
+
+  gdk_window_set_user_data (viewport->bin_window, NULL);
+  gdk_window_destroy (viewport->bin_window);
+  viewport->bin_window = NULL;
+
+  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
 }
 
 static void
@@ -331,8 +523,6 @@ gtk_viewport_paint (GtkWidget    *widget,
                    GdkRectangle *area)
 {
   GtkViewport *viewport;
-  GtkStateType state;
-  gint x, y;
 
   g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_VIEWPORT (widget));
@@ -342,14 +532,7 @@ gtk_viewport_paint (GtkWidget    *widget,
     {
       viewport = GTK_VIEWPORT (widget);
 
-      state = widget->state;
-      if (!GTK_WIDGET_IS_SENSITIVE (widget))
-        state = GTK_STATE_INSENSITIVE;
-
-      x = GTK_CONTAINER (viewport)->border_width;
-      y = GTK_CONTAINER (viewport)->border_width;
-
-      gtk_draw_shadow (widget->style, viewport->main_window,
+      gtk_draw_shadow (widget->style, widget->window,
                       GTK_STATE_NORMAL, viewport->shadow_type,
                       0, 0, -1, -1);
     }
@@ -363,6 +546,7 @@ gtk_viewport_draw (GtkWidget    *widget,
   GtkBin *bin;
   GdkRectangle tmp_area;
   GdkRectangle child_area;
+  gint border_width;
 
   g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_VIEWPORT (widget));
@@ -373,14 +557,24 @@ gtk_viewport_draw (GtkWidget    *widget,
       viewport = GTK_VIEWPORT (widget);
       bin = GTK_BIN (widget);
 
-      gtk_viewport_paint (widget, area);
+      border_width = GTK_CONTAINER (widget)->border_width;
+      
+      tmp_area = *area;
+      tmp_area.x -= border_width;
+      tmp_area.y -= border_width;
+      
+      gtk_viewport_paint (widget, &tmp_area);
+
+      tmp_area.x += viewport->hadjustment->value - widget->style->klass->xthickness;
+      tmp_area.y += viewport->vadjustment->value - widget->style->klass->ythickness;
+      
+      gtk_paint_flat_box(widget->style, viewport->bin_window, 
+                        GTK_STATE_NORMAL, GTK_SHADOW_NONE,
+                        &tmp_area, widget, "viewportbin",
+                        0, 0, -1, -1);
 
       if (bin->child)
        {
-         tmp_area = *area;
-         tmp_area.x += viewport->hadjustment->value;
-         tmp_area.y += viewport->vadjustment->value;
-
          if (gtk_widget_intersect (bin->child, &tmp_area, &child_area))
            gtk_widget_draw (bin->child, &child_area);
        }
@@ -404,25 +598,54 @@ gtk_viewport_expose (GtkWidget      *widget,
       viewport = GTK_VIEWPORT (widget);
       bin = GTK_BIN (widget);
 
-      if (event->window == viewport->main_window)
+      if (event->window == widget->window)
        gtk_viewport_paint (widget, &event->area);
+      else if (event->window == viewport->bin_window)
+       {
+         child_event = *event;
+
+         gtk_paint_flat_box(widget->style, viewport->bin_window, 
+                            GTK_STATE_NORMAL, GTK_SHADOW_NONE,
+                            &event->area, widget, "viewportbin",
+                            0, 0, -1, -1);
+         
+         if ((bin->child != NULL) &&
+             GTK_WIDGET_NO_WINDOW (bin->child) &&
+             gtk_widget_intersect (bin->child, &event->area, &child_event.area))
+           gtk_widget_event (bin->child, (GdkEvent*) &child_event);
+       }
+       
 
-      child_event = *event;
-      if (bin->child &&
-         GTK_WIDGET_NO_WINDOW (bin->child) &&
-         gtk_widget_intersect (bin->child, &event->area, &child_event.area))
-       gtk_widget_event (bin->child, (GdkEvent*) &child_event);
     }
 
   return FALSE;
 }
 
+static void
+gtk_viewport_add (GtkContainer *container,
+                 GtkWidget    *child)
+{
+  GtkBin *bin;
+
+  g_return_if_fail (container != NULL);
+  g_return_if_fail (GTK_IS_VIEWPORT (container));
+  g_return_if_fail (child != NULL);
+
+  bin = GTK_BIN (container);
+  g_return_if_fail (bin->child == NULL);
+
+  gtk_widget_set_parent_window (child, GTK_VIEWPORT (bin)->bin_window);
+
+  GTK_CONTAINER_CLASS (parent_class)->add (container, child);
+}
+
 static void
 gtk_viewport_size_request (GtkWidget      *widget,
                           GtkRequisition *requisition)
 {
   GtkViewport *viewport;
   GtkBin *bin;
+  GtkRequisition child_requisition;
 
   g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_VIEWPORT (widget));
@@ -438,7 +661,11 @@ gtk_viewport_size_request (GtkWidget      *widget,
                         GTK_WIDGET (widget)->style->klass->ythickness) * 2 + 5;
 
   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
-    gtk_widget_size_request (bin->child, &bin->child->requisition);
+    {
+      gtk_widget_size_request (bin->child, &child_requisition);
+      requisition->width += child_requisition.width;
+      requisition->height += child_requisition.height;
+    }
 }
 
 static void
@@ -449,6 +676,7 @@ gtk_viewport_size_allocate (GtkWidget     *widget,
   GtkBin *bin;
   GtkAllocation child_allocation;
   gint hval, vval;
+  gint border_width;
 
   g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_VIEWPORT (widget));
@@ -458,19 +686,27 @@ gtk_viewport_size_allocate (GtkWidget     *widget,
   viewport = GTK_VIEWPORT (widget);
   bin = GTK_BIN (widget);
 
-  child_allocation.x = GTK_WIDGET (viewport)->style->klass->xthickness;
-  child_allocation.width = allocation->width - child_allocation.x * 2;
+  border_width = GTK_CONTAINER (widget)->border_width;
 
-  child_allocation.y = GTK_WIDGET (viewport)->style->klass->ythickness;
-  child_allocation.height = allocation->height - child_allocation.y * 2;
+  child_allocation.x = 0;
+  child_allocation.y = 0;
+
+  if (viewport->shadow_type != GTK_SHADOW_NONE)
+    {
+      child_allocation.x = GTK_WIDGET (viewport)->style->klass->xthickness;
+      child_allocation.y = GTK_WIDGET (viewport)->style->klass->ythickness;
+    }
+
+  child_allocation.width = MAX (1, allocation->width - child_allocation.x * 2 - border_width * 2);
+  child_allocation.height = MAX (1, allocation->height - child_allocation.y * 2 - border_width * 2);
 
   if (GTK_WIDGET_REALIZED (widget))
     {
-      gdk_window_move_resize (viewport->main_window,
-                             allocation->x + GTK_CONTAINER (viewport)->border_width,
-                             allocation->y + GTK_CONTAINER (viewport)->border_width,
-                             allocation->width - GTK_CONTAINER (viewport)->border_width * 2,
-                             allocation->height - GTK_CONTAINER (viewport)->border_width * 2);
+      gdk_window_move_resize (widget->window,
+                             allocation->x + border_width,
+                             allocation->y + border_width,
+                             allocation->width - border_width * 2,
+                             allocation->height - border_width * 2);
 
       gdk_window_move_resize (viewport->view_window,
                              child_allocation.x,
@@ -492,8 +728,11 @@ gtk_viewport_size_allocate (GtkWidget     *widget,
 
   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
     {
+      GtkRequisition child_requisition;
+      gtk_widget_get_child_requisition (bin->child, &child_requisition);
+      
       viewport->hadjustment->lower = 0;
-      viewport->hadjustment->upper = MAX (bin->child->requisition.width,
+      viewport->hadjustment->upper = MAX (child_requisition.width,
                                          child_allocation.width);
 
       hval = CLAMP (hval, 0,
@@ -501,7 +740,7 @@ gtk_viewport_size_allocate (GtkWidget     *widget,
                    viewport->hadjustment->page_size);
 
       viewport->vadjustment->lower = 0;
-      viewport->vadjustment->upper = MAX (bin->child->requisition.height,
+      viewport->vadjustment->upper = MAX (child_requisition.height,
                                          child_allocation.height);
 
       vval = CLAMP (vval, 0,
@@ -517,12 +756,10 @@ gtk_viewport_size_allocate (GtkWidget     *widget,
       child_allocation.width = viewport->hadjustment->upper;
       child_allocation.height = viewport->vadjustment->upper;
 
-      if (!GTK_WIDGET_REALIZED (widget))
-        gtk_widget_realize (widget);
-
-      gdk_window_resize (widget->window,
-                        child_allocation.width,
-                        child_allocation.height);
+      if (GTK_WIDGET_REALIZED (widget))
+       gdk_window_resize (viewport->bin_window,
+                          child_allocation.width,
+                          child_allocation.height);
 
       child_allocation.x = 0;
       child_allocation.y = 0;
@@ -543,27 +780,6 @@ gtk_viewport_size_allocate (GtkWidget     *widget,
     }
 }
 
-static gint
-gtk_viewport_need_resize (GtkContainer *container)
-{
-  GtkBin *bin;
-
-  g_return_val_if_fail (container != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_VIEWPORT (container), FALSE);
-
-  if (GTK_WIDGET_REALIZED (container))
-    {
-      bin = GTK_BIN (container);
-
-      gtk_widget_size_request (bin->child, &bin->child->requisition);
-
-      gtk_widget_size_allocate (GTK_WIDGET (container),
-                               &(GTK_WIDGET (container)->allocation));
-    }
-
-  return FALSE;
-}
-
 static void
 gtk_viewport_adjustment_changed (GtkAdjustment *adjustment,
                                 gpointer       data)
@@ -584,7 +800,6 @@ gtk_viewport_adjustment_value_changed (GtkAdjustment *adjustment,
   GtkViewport *viewport;
   GtkBin *bin;
   GtkAllocation child_allocation;
-  gint width, height;
 
   g_return_if_fail (adjustment != NULL);
   g_return_if_fail (data != NULL);
@@ -595,8 +810,6 @@ gtk_viewport_adjustment_value_changed (GtkAdjustment *adjustment,
 
   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
     {
-      gdk_window_get_size (viewport->view_window, &width, &height);
-
       child_allocation.x = 0;
       child_allocation.y = 0;
 
@@ -609,8 +822,24 @@ gtk_viewport_adjustment_value_changed (GtkAdjustment *adjustment,
        child_allocation.y = viewport->vadjustment->lower - viewport->vadjustment->value;
 
       if (GTK_WIDGET_REALIZED (viewport))
-       gdk_window_move (GTK_WIDGET (viewport)->window,
+       gdk_window_move (viewport->bin_window,
                         child_allocation.x,
                         child_allocation.y);
     }
 }
+
+static void
+gtk_viewport_style_set (GtkWidget *widget,
+                       GtkStyle  *previous_style)
+{
+   GtkViewport *viewport;
+   
+   if (GTK_WIDGET_REALIZED (widget) &&
+       !GTK_WIDGET_NO_WINDOW (widget))
+     {
+       viewport = GTK_VIEWPORT (widget);
+       
+       gtk_style_set_background (widget->style, viewport->bin_window, GTK_STATE_NORMAL);
+       gtk_style_set_background (widget->style, widget->window, widget->state);
+     }
+}