e1248b8c180aa8911bc3e86b1c3d995e99a6b765
diff --git a/gtk/gtktreeprivate.h b/gtk/gtktreeprivate.h
index 9d49f39..d47c1f7 100644
--- a/gtk/gtktreeprivate.h
+++ b/gtk/gtktreeprivate.h
@@ -77,6 +77,8 @@ enum
   */
 #define TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER(tree_view) (10*TREE_VIEW_HEADER_HEIGHT(tree_view))
 
+#define GTK_TREE_VIEW_COLUMN_GET_PRIVATE(column) (G_TYPE_INSTANCE_GET_PRIVATE ((column), GTK_TYPE_TREE_VIEW_COLUMN, GtkTreeViewColumnPrivate))
+
 typedef struct _GtkTreeViewColumnReorder GtkTreeViewColumnReorder;
 struct _GtkTreeViewColumnReorder
 {
@@ -268,6 +270,11 @@ struct _GtkTreeViewPrivate
   gint tooltip_column;
 };
 
+struct _GtkTreeViewColumnPrivate
+{
+  gint natural_width;
+};
+
 #ifdef __GNUC__
 
 #define TREE_VIEW_INTERNAL_ASSERT(expr, ret)     G_STMT_START{          \
diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c
index 5b393a3..6a79ec6 100644
--- a/gtk/gtktreeview.c
+++ b/gtk/gtktreeview.c
@@ -43,6 +43,7 @@
 #include "gtkframe.h"
 #include "gtktreemodelsort.h"
 #include "gtktooltip.h"
+#include "gtkextendedlayout.h"
 #include "gtkprivate.h"
 #include "gtkalias.h"
 
@@ -470,6 +471,9 @@ static void gtk_tree_view_buildable_add_child (GtkBuildable *tree_view,
 					       const gchar *type);
 static void gtk_tree_view_buildable_init      (GtkBuildableIface *iface);
 
+/* GtkExtendedLayout */
+static void gtk_tree_view_extended_layout_init (GtkExtendedLayoutIface *iface);
+
 
 static gboolean scroll_row_timeout                   (gpointer     data);
 static void     add_scroll_timeout                   (GtkTreeView *tree_view);
@@ -484,7 +488,9 @@ static guint tree_view_signals [LAST_SIGNAL] = { 0 };
 
 G_DEFINE_TYPE_WITH_CODE (GtkTreeView, gtk_tree_view, GTK_TYPE_CONTAINER,
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
-						gtk_tree_view_buildable_init))
+						gtk_tree_view_buildable_init)
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_EXTENDED_LAYOUT,
+						gtk_tree_view_extended_layout_init))
 
 static void
 gtk_tree_view_class_init (GtkTreeViewClass *class)
@@ -2157,6 +2163,31 @@ gtk_tree_view_get_real_requested_width_from_column (GtkTreeView       *tree_view
   return real_requested_width;
 }
 
+static gint
+gtk_tree_view_get_real_natural_width_from_column (GtkTreeView       *tree_view,
+                                                  GtkTreeViewColumn *column)
+{
+  GtkTreeViewColumnPrivate *column_priv;
+  GtkRequisition button_natural_size;
+  gint column_natural_width;
+
+  column_priv = GTK_TREE_VIEW_COLUMN_GET_PRIVATE (column);
+  column_natural_width = column_priv->natural_width;
+
+  if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE))
+    {
+      if (GTK_EXTENDED_LAYOUT_HAS_NATURAL_SIZE (column->button))
+        gtk_extended_layout_get_natural_size (GTK_EXTENDED_LAYOUT (column->button),
+                                              &button_natural_size);
+      else
+        button_natural_size.width = column->button_request;
+
+      column_natural_width = MAX (column_natural_width, button_natural_size.width);
+    }
+
+  return column_natural_width;
+}
+
 /* GtkWidget::size_allocate helper */
 static void
 gtk_tree_view_size_allocate_columns (GtkWidget *widget)
@@ -2165,9 +2196,10 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
   GList *list, *first_column, *last_column;
   GtkTreeViewColumn *column;
   GtkAllocation allocation;
-  gint width = 0;
-  gint extra, extra_per_column;
+  gint width = 0, natural_width;
+  gint extra_width, extra_per_column;
   gint full_requested_width = 0;
+  gint full_natural_width = 0;
   gint number_of_expand_columns = 0;
   gboolean column_changed = FALSE;
   gboolean rtl;
@@ -2200,14 +2232,19 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
 	continue;
 
       full_requested_width += gtk_tree_view_get_real_requested_width_from_column (tree_view, column);
+      full_natural_width += gtk_tree_view_get_real_natural_width_from_column (tree_view, column);
 
       if (column->expand)
 	number_of_expand_columns++;
     }
 
-  extra = MAX (widget->allocation.width - full_requested_width, 0);
+  full_natural_width -= full_requested_width;
+  extra_width = MAX (0, widget->allocation.width - full_requested_width);
+  natural_width = MIN (extra_width, full_natural_width);
+  extra_width -= natural_width;
+
   if (number_of_expand_columns > 0)
-    extra_per_column = extra/number_of_expand_columns;
+    extra_per_column = extra_width/number_of_expand_columns;
   else
     extra_per_column = 0;
 
@@ -2216,6 +2253,7 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
        list = (rtl ? list->prev : list->next)) 
     {
       gint real_requested_width = 0;
+      gint real_natural_width = 0;
       gint old_width;
 
       column = list->data;
@@ -2241,29 +2279,34 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
 	}
 
       real_requested_width = gtk_tree_view_get_real_requested_width_from_column (tree_view, column);
+      real_natural_width = gtk_tree_view_get_real_natural_width_from_column (tree_view, column);
+      real_natural_width -= real_requested_width;
 
       allocation.x = width;
       column->width = real_requested_width;
 
+      if (full_natural_width > 0)
+        column->width += natural_width * real_natural_width / full_natural_width;
+
       if (column->expand)
 	{
 	  if (number_of_expand_columns == 1)
 	    {
 	      /* We add the remander to the last column as
 	       * */
-	      column->width += extra;
+	      column->width += extra_width;
 	    }
 	  else
 	    {
 	      column->width += extra_per_column;
-	      extra -= extra_per_column;
+	      extra_width -= extra_per_column;
 	      number_of_expand_columns --;
 	    }
 	}
       else if (number_of_expand_columns == 0 &&
 	       list == last_column)
 	{
-	  column->width += extra;
+	  column->width += extra_width;
 	}
 
       g_object_notify (G_OBJECT (column), "width");
@@ -5592,10 +5635,13 @@ validate_row (GtkTreeView *tree_view,
 
   for (list = tree_view->priv->columns; list; list = list->next)
     {
-      gint tmp_width;
-      gint tmp_height;
+      GtkTreeViewColumnPrivate *column_priv;
+      GtkRequisition requested_size;
+      GtkRequisition natural_size;
+      gint padding;
 
       column = list->data;
+      column_priv =  GTK_TREE_VIEW_COLUMN_GET_PRIVATE (column);
 
       if (! column->visible)
 	continue;
@@ -5606,14 +5652,19 @@ validate_row (GtkTreeView *tree_view,
       gtk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, iter,
 					       GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
 					       node->children?TRUE:FALSE);
-      gtk_tree_view_column_cell_get_size (column,
-					  NULL, NULL, NULL,
-					  &tmp_width, &tmp_height);
+      gtk_tree_view_column_cell_get_size (column, NULL, NULL, NULL,
+					  &requested_size.width,
+                                          &requested_size.height);
+      if (GTK_EXTENDED_LAYOUT_HAS_NATURAL_SIZE (column))
+        gtk_extended_layout_get_natural_size (GTK_EXTENDED_LAYOUT (column),
+                                              &natural_size);
+      else
+        natural_size = requested_size;
 
       if (!is_separator)
 	{
-          tmp_height += vertical_separator;
-	  height = MAX (height, tmp_height);
+          requested_size.height += vertical_separator;
+	  height = MAX (height, requested_size.height);
 	  height = MAX (height, tree_view->priv->expander_size);
 	}
       else
@@ -5621,26 +5672,31 @@ validate_row (GtkTreeView *tree_view,
 
       if (gtk_tree_view_is_expander_column (tree_view, column))
         {
-	  tmp_width = tmp_width + horizontal_separator + (depth - 1) * tree_view->priv->level_indentation;
+	  padding = horizontal_separator + (depth - 1) * tree_view->priv->level_indentation;
 
 	  if (TREE_VIEW_DRAW_EXPANDERS (tree_view))
-	    tmp_width += depth * tree_view->priv->expander_size;
+	    padding += depth * tree_view->priv->expander_size;
 	}
       else
-	tmp_width = tmp_width + horizontal_separator;
+	padding = horizontal_separator;
 
       if (draw_vgrid_lines)
         {
 	  if (list->data == first_column || list->data == last_column)
-	    tmp_width += grid_line_width / 2.0;
+	    padding += grid_line_width / 2;
 	  else
-	    tmp_width += grid_line_width;
+	    padding += grid_line_width;
 	}
 
-      if (tmp_width > column->requested_width)
+      requested_size.width += padding;
+      natural_size.width += padding;
+
+      if (requested_size.width > column->requested_width ||
+          natural_size.width > column_priv->natural_width)
 	{
 	  retval = TRUE;
-	  column->requested_width = tmp_width;
+	  column->requested_width = requested_size.width;
+          column_priv->natural_width = natural_size.width;
 	}
     }
 
@@ -15146,7 +15202,7 @@ gtk_tree_view_set_grid_lines (GtkTreeView           *tree_view,
 	  !priv->grid_line_gc)
 	{
 	  gint line_width;
-	  guint8 *dash_list;
+	  gint8 *dash_list;
 
 	  gtk_widget_style_get (widget,
 				"grid-line-width", &line_width,
@@ -15232,7 +15288,7 @@ gtk_tree_view_set_enable_tree_lines (GtkTreeView *tree_view,
       if (enabled && !priv->tree_line_gc)
 	{
 	  gint line_width;
-	  guint8 *dash_list;
+	  gint8 *dash_list;
 	  gtk_widget_style_get (widget,
 				"tree-line-width", &line_width,
 				"tree-line-pattern", (gchar *)&dash_list,
@@ -15647,5 +15703,43 @@ gtk_tree_view_get_tooltip_column (GtkTreeView *tree_view)
   return tree_view->priv->tooltip_column;
 }
 
+static GtkExtendedLayoutFeatures
+gtk_tree_view_extended_layout_get_features (GtkExtendedLayout *layout)
+{
+  return GTK_EXTENDED_LAYOUT_NATURAL_SIZE;
+}
+
+static void
+gtk_tree_view_extended_layout_get_natural_size (GtkExtendedLayout *layout,
+                                                GtkRequisition    *requisition)
+{
+  GtkTreeView *tree_view;
+  gint natural_width = 0;
+  GList *column_iter;
+
+  tree_view = GTK_TREE_VIEW (layout);
+
+  gtk_widget_size_request (GTK_WIDGET (layout), requisition);
+
+  for (column_iter = tree_view->priv->columns; column_iter; column_iter = column_iter->next)
+    {
+      GtkTreeViewColumn *column = column_iter->data;
+
+      if (!column->visible)
+	continue;
+
+      natural_width += gtk_tree_view_get_real_natural_width_from_column (tree_view, column);
+    }
+
+  requisition->width = natural_width;
+}
+
+static void
+gtk_tree_view_extended_layout_init (GtkExtendedLayoutIface *iface)
+{
+  iface->get_features = gtk_tree_view_extended_layout_get_features;
+  iface->get_natural_size = gtk_tree_view_extended_layout_get_natural_size;
+}
+
 #define __GTK_TREE_VIEW_C__
 #include "gtkaliasdef.c"
diff --git a/gtk/gtktreeviewcolumn.c b/gtk/gtktreeviewcolumn.c
index ea8adbb..b495d6b 100644
--- a/gtk/gtktreeviewcolumn.c
+++ b/gtk/gtktreeviewcolumn.c
@@ -29,6 +29,7 @@
 #include "gtkhbox.h"
 #include "gtkmarshalers.h"
 #include "gtkarrow.h"
+#include "gtkextendedlayout.h"
 #include "gtkprivate.h"
 #include "gtkintl.h"
 #include "gtkalias.h"
@@ -152,7 +153,10 @@ static GList *gtk_tree_view_column_cell_prev                   (GtkTreeViewColum
 static void gtk_tree_view_column_clear_attributes_by_info      (GtkTreeViewColumn      *tree_column,
 					                        GtkTreeViewColumnCellInfo *info);
 /* GtkBuildable implementation */
-static void gtk_tree_view_column_buildable_init                 (GtkBuildableIface     *iface);
+static void gtk_tree_view_column_buildable_init                (GtkBuildableIface      *iface);
+
+/* GtkExtendedLayout implementation */
+static void gtk_tree_view_column_extended_layout_init          (GtkExtendedLayoutIface *iface);
 
 static guint tree_column_signals[LAST_SIGNAL] = { 0 };
 
@@ -160,7 +164,9 @@ G_DEFINE_TYPE_WITH_CODE (GtkTreeViewColumn, gtk_tree_view_column, GTK_TYPE_OBJEC
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
 						gtk_tree_view_column_cell_layout_init)
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
-						gtk_tree_view_column_buildable_init))
+						gtk_tree_view_column_buildable_init)
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_EXTENDED_LAYOUT,
+						gtk_tree_view_column_extended_layout_init))
 
 
 static void
@@ -175,6 +181,8 @@ gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class)
   object_class->finalize = gtk_tree_view_column_finalize;
   object_class->set_property = gtk_tree_view_column_set_property;
   object_class->get_property = gtk_tree_view_column_get_property;
+
+  g_type_class_add_private (class, sizeof (GtkTreeViewColumnPrivate));
   
   tree_column_signals[CLICKED] =
     g_signal_new (I_("clicked"),
@@ -2556,26 +2564,16 @@ gtk_tree_view_column_cell_set_cell_data (GtkTreeViewColumn *tree_column,
 
 }
 
-/**
- * gtk_tree_view_column_cell_get_size:
- * @tree_column: A #GtkTreeViewColumn.
- * @cell_area: The area a cell in the column will be allocated, or %NULL
- * @x_offset: location to return x offset of a cell relative to @cell_area, or %NULL
- * @y_offset: location to return y offset of a cell relative to @cell_area, or %NULL
- * @width: location to return width needed to render a cell, or %NULL
- * @height: location to return height needed to render a cell, or %NULL
- * 
- * Obtains the width and height needed to render the column.  This is used
- * primarily by the #GtkTreeView.
- **/
 void
-gtk_tree_view_column_cell_get_size (GtkTreeViewColumn *tree_column,
-				    GdkRectangle      *cell_area,
-				    gint              *x_offset,
-				    gint              *y_offset,
-				    gint              *width,
-				    gint              *height)
+gtk_tree_view_column_cell_get_real_size (GtkTreeViewColumn *tree_column,
+                                         GdkRectangle      *cell_area,
+                                         gint              *x_offset,
+                                         gint              *y_offset,
+                                         gint              *width,
+                                         gint              *height,
+                                         gboolean           consider_natural_size)
 {
+
   GList *list;
   gboolean first_cell = TRUE;
   gint focus_line_width;
@@ -2583,43 +2581,77 @@ gtk_tree_view_column_cell_get_size (GtkTreeViewColumn *tree_column,
   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
 
   if (height)
-    * height = 0;
+    *height = 0;
   if (width)
-    * width = 0;
+    *width = 0;
 
   gtk_widget_style_get (tree_column->tree_view, "focus-line-width", &focus_line_width, NULL);
   
   for (list = tree_column->cell_list; list; list = list->next)
     {
       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
+      GtkRequisition req = { 0, 0 };
       gboolean visible;
-      gint new_height = 0;
-      gint new_width = 0;
+
       g_object_get (info->cell, "visible", &visible, NULL);
 
       if (visible == FALSE)
-	continue;
+        continue;
 
       if (first_cell == FALSE && width)
-	*width += tree_column->spacing;
+        *width += tree_column->spacing;
 
-      gtk_cell_renderer_get_size (info->cell,
-				  tree_column->tree_view,
-				  cell_area,
-				  x_offset,
-				  y_offset,
-				  &new_width,
-				  &new_height);
+      if (consider_natural_size && GTK_EXTENDED_LAYOUT_HAS_NATURAL_SIZE (info->cell))
+        gtk_extended_layout_get_natural_size (GTK_EXTENDED_LAYOUT (info->cell), &req);
+      else
+        gtk_cell_renderer_get_size (info->cell, tree_column->tree_view,
+                                    cell_area, x_offset, y_offset,
+                                    &req.width, &req.height);
+
+      req.width += focus_line_width * 2;
+      req.height += focus_line_width * 2;
+
+      if (!consider_natural_size)
+        {
+          req.width = MAX (info->requested_width, req.width);
+          req.height = MAX (0, req.height);
+
+          info->requested_width = req.width;
+        }
 
-      if (height)
-	* height = MAX (*height, new_height + focus_line_width * 2);
-      info->requested_width = MAX (info->requested_width, new_width + focus_line_width * 2);
       if (width)
-	* width += info->requested_width;
+        *width = req.width;
+      if (height)
+        *height = req.height;
+
       first_cell = FALSE;
     }
 }
 
+/**
+ * gtk_tree_view_column_cell_get_size:
+ * @tree_column: A #GtkTreeViewColumn.
+ * @cell_area: The area a cell in the column will be allocated, or %NULL
+ * @x_offset: location to return x offset of a cell relative to @cell_area, or %NULL
+ * @y_offset: location to return y offset of a cell relative to @cell_area, or %NULL
+ * @width: location to return width needed to render a cell, or %NULL
+ * @height: location to return height needed to render a cell, or %NULL
+ *
+ * Obtains the width and height needed to render the column.  This is used
+ * primarily by the #GtkTreeView.
+ **/
+void
+gtk_tree_view_column_cell_get_size (GtkTreeViewColumn *tree_column,
+				    GdkRectangle      *cell_area,
+				    gint              *x_offset,
+				    gint              *y_offset,
+				    gint              *width,
+				    gint              *height)
+{
+  gtk_tree_view_column_cell_get_real_size (tree_column, cell_area,
+                                           x_offset, y_offset, width, height, FALSE);
+}
+
 /* rendering, event handling and rendering focus are somewhat complicated, and
  * quite a bit of code.  Rather than duplicate them, we put them together to
  * keep the code in one place.
@@ -3745,5 +3777,29 @@ gtk_tree_view_column_get_tree_view (GtkTreeViewColumn *tree_column)
   return tree_column->tree_view;
 }
 
+static GtkExtendedLayoutFeatures
+gtk_tree_view_column_extended_layout_get_features (GtkExtendedLayout *layout)
+{
+  return GTK_EXTENDED_LAYOUT_NATURAL_SIZE;
+}
+
+static void
+gtk_tree_view_column_extended_layout_get_natural_size (GtkExtendedLayout *layout,
+                                                       GtkRequisition    *requisition)
+{
+  gtk_tree_view_column_cell_get_real_size (GTK_TREE_VIEW_COLUMN (layout),
+                                           NULL, NULL, NULL,
+                                           &requisition->width,
+                                           &requisition->height,
+                                           TRUE);
+}
+
+static void
+gtk_tree_view_column_extended_layout_init (GtkExtendedLayoutIface *iface)
+{
+  iface->get_features = gtk_tree_view_column_extended_layout_get_features;
+  iface->get_natural_size = gtk_tree_view_column_extended_layout_get_natural_size;
+}
+
 #define __GTK_TREE_VIEW_COLUMN_C__
 #include "gtkaliasdef.c"
diff --git a/gtk/gtktreeviewcolumn.h b/gtk/gtktreeviewcolumn.h
index d7f14cb..b045648 100644
--- a/gtk/gtktreeviewcolumn.h
+++ b/gtk/gtktreeviewcolumn.h
@@ -46,8 +46,9 @@ typedef enum
   GTK_TREE_VIEW_COLUMN_FIXED
 } GtkTreeViewColumnSizing;
 
-typedef struct _GtkTreeViewColumn      GtkTreeViewColumn;
-typedef struct _GtkTreeViewColumnClass GtkTreeViewColumnClass;
+typedef struct _GtkTreeViewColumn        GtkTreeViewColumn;
+typedef struct _GtkTreeViewColumnClass   GtkTreeViewColumnClass;
+typedef struct _GtkTreeViewColumnPrivate GtkTreeViewColumnPrivate;
 
 typedef void (* GtkTreeCellDataFunc) (GtkTreeViewColumn *tree_column,
 				      GtkCellRenderer   *cell,
