Index: gtk+-2.12.1/gtk/gtktreeview.c
===================================================================
--- gtk+-2.12.1.orig/gtk/gtktreeview.c	2007-10-16 15:20:39.000000000 +0200
+++ gtk+-2.12.1/gtk/gtktreeview.c	2007-11-15 20:06:34.282370218 +0100
@@ -2158,19 +2158,21 @@ gtk_tree_view_get_real_requested_width_f
 }
 
 /* GtkWidget::size_allocate helper */
-static void
-gtk_tree_view_size_allocate_columns (GtkWidget *widget)
+static gboolean
+gtk_tree_view_size_allocate_columns (GtkWidget *widget,
+				     gboolean width_changed)
 {
   GtkTreeView *tree_view;
   GList *list, *first_column, *last_column;
   GtkTreeViewColumn *column;
   GtkAllocation allocation;
   gint width = 0;
-  gint extra, extra_per_column;
+  gint extra, extra_per_column, extra_for_last;
   gint full_requested_width = 0;
   gint number_of_expand_columns = 0;
   gboolean column_changed = FALSE;
   gboolean rtl;
+  gboolean update_expand;
   
   tree_view = GTK_TREE_VIEW (widget);
 
@@ -2179,7 +2181,7 @@ gtk_tree_view_size_allocate_columns (Gtk
        last_column = last_column->prev)
     ;
   if (last_column == NULL)
-    return;
+    return width_changed;
 
   for (first_column = g_list_first (tree_view->priv->columns);
        first_column && !(GTK_TREE_VIEW_COLUMN (first_column->data)->visible);
@@ -2205,12 +2207,38 @@ gtk_tree_view_size_allocate_columns (Gtk
 	number_of_expand_columns++;
     }
 
-  extra = MAX (widget->allocation.width - full_requested_width, 0);
+  /* Only update the expand value if the width of the widget changed,
+   * the number of expand columns are if there are no expand
+   * columns.
+   */
+  update_expand = width_changed ||
+                  number_of_expand_columns != tree_view->priv->last_number_of_expand_columns ||
+		  number_of_expand_columns == 0;
+
+  if (!update_expand)
+    {
+      extra = tree_view->priv->last_extra_space;
+      extra_for_last = MAX (widget->allocation.width - full_requested_width - extra, 0);
+    }
+  else
+    {
+      extra = MAX (widget->allocation.width - full_requested_width, 0);
+      extra_for_last = 0;
+
+      tree_view->priv->last_extra_space = extra;
+    }
+
   if (number_of_expand_columns > 0)
     extra_per_column = extra/number_of_expand_columns;
   else
     extra_per_column = 0;
 
+  if (update_expand)
+    {
+      tree_view->priv->last_extra_space_per_column = extra_per_column;
+      tree_view->priv->last_number_of_expand_columns = number_of_expand_columns;
+    }
+
   for (list = (rtl ? last_column : first_column); 
        list != (rtl ? first_column->prev : last_column->next);
        list = (rtl ? list->prev : list->next)) 
@@ -2266,6 +2294,12 @@ gtk_tree_view_size_allocate_columns (Gtk
 	  column->width += extra;
 	}
 
+      /* In addition to expand, the last column can get even more
+       * extra space so all available space is filled up.
+       */
+      if (extra_for_last > 0 && list == last_column)
+	column->width += extra_for_last;
+
       g_object_notify (G_OBJECT (column), "width");
 
       allocation.width = column->width;
@@ -2283,8 +2317,17 @@ gtk_tree_view_size_allocate_columns (Gtk
                                 TREE_VIEW_DRAG_WIDTH, allocation.height);
     }
 
+  /* We change the width here.  The user has been dragging columns,
+   * and we do need more width than allocated to properly display.
+   * The scrolled window should handle this, if the application
+   * doesn't have one, the tree view can't fit.
+   */
+  tree_view->priv->width = width;
+
   if (column_changed)
     gtk_widget_queue_draw (GTK_WIDGET (tree_view));
+
+  return TRUE;
 }
 
 
@@ -2299,13 +2342,13 @@ gtk_tree_view_size_allocate (GtkWidget  
 
   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
 
-  if (allocation->width != widget->allocation.width)
-    width_changed = TRUE;
-  
   widget->allocation = *allocation;
 
   tree_view = GTK_TREE_VIEW (widget);
 
+  if (allocation->width != old_width || tree_view->priv->width != tree_view->priv->prev_width)
+    width_changed = TRUE;
+
   tmp_list = tree_view->priv->children;
 
   while (tmp_list)
@@ -2323,6 +2366,7 @@ gtk_tree_view_size_allocate (GtkWidget  
       gtk_widget_size_allocate (child->widget, &allocation);
     }
 
+  width_changed = gtk_tree_view_size_allocate_columns (widget, width_changed);
 
   tree_view->priv->hadjustment->page_size = allocation->width;
   tree_view->priv->hadjustment->page_increment = allocation->width * 0.9;
@@ -2331,28 +2375,30 @@ gtk_tree_view_size_allocate (GtkWidget  
   tree_view->priv->hadjustment->upper = MAX (tree_view->priv->hadjustment->page_size, tree_view->priv->width);
 
   if (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL)   
-     {
+    {
       if (allocation->width < tree_view->priv->width)
-         {
-         if (tree_view->priv->init_hadjust_value)
-           {
-           tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
-           tree_view->priv->init_hadjust_value = FALSE;
-           }
-         else if(allocation->width != old_width)
-           tree_view->priv->hadjustment->value = CLAMP(tree_view->priv->hadjustment->value - allocation->width + old_width, 0, tree_view->priv->width - allocation->width);
-         else
-           tree_view->priv->hadjustment->value = CLAMP(tree_view->priv->width - (tree_view->priv->prev_width - tree_view->priv->hadjustment->value), 0, tree_view->priv->width - allocation->width);
-         }
-      else
-         {
-         tree_view->priv->hadjustment->value = 0;
-         tree_view->priv->init_hadjust_value = TRUE;
-         }
-     }
+        {
+	  if (tree_view->priv->init_hadjust_value)
+	    {
+	      tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
+	      tree_view->priv->init_hadjust_value = FALSE;
+	    }
+	  else if (allocation->width != old_width)
+	    {
+	      tree_view->priv->hadjustment->value = CLAMP (tree_view->priv->hadjustment->value - allocation->width + old_width, 0, tree_view->priv->width - allocation->width);
+	    }
+	  else
+	    tree_view->priv->hadjustment->value = CLAMP (tree_view->priv->width - (tree_view->priv->prev_width - tree_view->priv->hadjustment->value), 0, tree_view->priv->width - allocation->width);
+	}
+      else
+        {
+	  tree_view->priv->hadjustment->value = 0;
+	  tree_view->priv->init_hadjust_value = TRUE;
+	}
+    }
   else
-     if (tree_view->priv->hadjustment->value + allocation->width > tree_view->priv->width)
-        tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
+    if (tree_view->priv->hadjustment->value + allocation->width > tree_view->priv->width)
+      tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
 
   gtk_adjustment_changed (tree_view->priv->hadjustment);
 
@@ -2392,8 +2438,6 @@ gtk_tree_view_size_allocate (GtkWidget  
 			      allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view));
     }
 
-  gtk_tree_view_size_allocate_columns (widget);
-
   if (tree_view->priv->tree == NULL)
     invalidate_empty_focus (tree_view);
 
@@ -2837,7 +2881,7 @@ gtk_tree_view_button_press (GtkWidget   
 
 	  gtk_grab_add (widget);
 	  GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE);
-	  column->resized_width = column->width;
+	  column->resized_width = column->width - tree_view->priv->last_extra_space_per_column;
 
 	  /* block attached dnd signal handler */
 	  drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
@@ -3546,6 +3590,8 @@ gtk_tree_view_motion_resize_column (GtkW
     {
       column->use_resized_width = TRUE;
       column->resized_width = new_width;
+      if (column->expand)
+	column->resized_width -= tree_view->priv->last_extra_space_per_column;
       gtk_widget_queue_resize (widget);
     }
 
@@ -11479,7 +11525,7 @@ gtk_tree_view_move_column_after (GtkTree
   if (GTK_WIDGET_REALIZED (tree_view))
     {
       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
-      gtk_tree_view_size_allocate_columns (GTK_WIDGET (tree_view));
+      gtk_tree_view_size_allocate_columns (GTK_WIDGET (tree_view), FALSE);
     }
 
   g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
Index: gtk+-2.12.1/gtk/gtktreeviewcolumn.c
===================================================================
--- gtk+-2.12.1.orig/gtk/gtktreeviewcolumn.c	2007-10-16 15:20:39.000000000 +0200
+++ gtk+-2.12.1/gtk/gtktreeviewcolumn.c	2007-11-15 19:58:41.667437428 +0100
@@ -2142,6 +2142,7 @@ gtk_tree_view_column_set_expand (GtkTree
       tree_column->tree_view != NULL &&
       GTK_WIDGET_REALIZED (tree_column->tree_view))
     {
+      tree_column->use_resized_width = FALSE;
       gtk_widget_queue_resize (tree_column->tree_view);
     }
 
Index: gtk+-2.12.1/gtk/gtktreeprivate.h
===================================================================
--- gtk+-2.12.1.orig/gtk/gtktreeprivate.h	2007-10-16 15:20:39.000000000 +0200
+++ gtk+-2.12.1/gtk/gtktreeprivate.h	2007-11-15 19:58:41.667437428 +0100
@@ -266,6 +266,10 @@ struct _GtkTreeViewPrivate
   GdkGC *tree_line_gc;
 
   gint tooltip_column;
+
+  gint last_extra_space;
+  gint last_extra_space_per_column;
+  gint last_number_of_expand_columns;
 };
 
 #ifdef __GNUC__
