]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtktreeview.c
Use the slice allocator for many small allocations.
[~andy/gtk] / gtk / gtktreeview.c
index 2f401ebaeb736dcae3d16e42a03d3e87a72d695b..4de65e394fa8495697666b9fd41aaa1fe55a62fd 100644 (file)
@@ -22,7 +22,6 @@
 #include <string.h>
 #include <gdk/gdkkeysyms.h>
 
-#include "gtkalias.h"
 #include "gtktreeview.h"
 #include "gtkrbtree.h"
 #include "gtktreednd.h"
@@ -42,6 +41,8 @@
 #include "gtkentry.h"
 #include "gtkframe.h"
 #include "gtktreemodelsort.h"
+#include "gtkprivate.h"
+#include "gtkalias.h"
 
 #define GTK_TREE_VIEW_PRIORITY_VALIDATE (GDK_PRIORITY_REDRAW + 5)
 #define GTK_TREE_VIEW_PRIORITY_SCROLL_SYNC (GTK_TREE_VIEW_PRIORITY_VALIDATE + 2)
@@ -176,6 +177,8 @@ static gboolean gtk_tree_view_button_press         (GtkWidget        *widget,
                                                    GdkEventButton   *event);
 static gboolean gtk_tree_view_button_release       (GtkWidget        *widget,
                                                    GdkEventButton   *event);
+static gboolean gtk_tree_view_grab_broken          (GtkWidget          *widget,
+                                                   GdkEventGrabBroken *event);
 #if 0
 static gboolean gtk_tree_view_configure            (GtkWidget         *widget,
                                                    GdkEventConfigure *event);
@@ -190,6 +193,10 @@ static gint     gtk_tree_view_focus                (GtkWidget        *widget,
 static void     gtk_tree_view_grab_focus           (GtkWidget        *widget);
 static void     gtk_tree_view_style_set            (GtkWidget        *widget,
                                                    GtkStyle         *previous_style);
+static void     gtk_tree_view_grab_notify          (GtkWidget        *widget,
+                                                   gboolean          was_grabbed);
+static void     gtk_tree_view_state_changed        (GtkWidget        *widget,
+                                                   GtkStateType      previous_state);
 
 /* container signals */
 static void     gtk_tree_view_remove               (GtkContainer     *container,
@@ -280,13 +287,15 @@ static gboolean validate_row             (GtkTreeView *tree_view,
                                          GtkTreePath *path);
 static void     validate_visible_area    (GtkTreeView *tree_view);
 static gboolean validate_rows_handler    (GtkTreeView *tree_view);
+static gboolean do_validate_rows         (GtkTreeView *tree_view,
+                                         gboolean     size_request);
 static gboolean validate_rows            (GtkTreeView *tree_view);
 static gboolean presize_handler_callback (gpointer     data);
 static void     install_presize_handler  (GtkTreeView *tree_view);
 static void     install_scroll_sync_handler (GtkTreeView *tree_view);
 static void    gtk_tree_view_dy_to_top_row (GtkTreeView *tree_view);
 static void     gtk_tree_view_top_row_to_dy (GtkTreeView *tree_view);
-
+static void     invalidate_empty_focus      (GtkTreeView *tree_view);
 
 /* Internal functions */
 static gboolean gtk_tree_view_is_expander_column             (GtkTreeView       *tree_view,
@@ -393,6 +402,9 @@ static gboolean gtk_tree_view_search_delete_event       (GtkWidget        *widge
 static gboolean gtk_tree_view_search_button_press_event (GtkWidget        *widget,
                                                         GdkEventButton   *event,
                                                         GtkTreeView      *tree_view);
+static gboolean gtk_tree_view_search_scroll_event       (GtkWidget        *entry,
+                                                        GdkEventScroll   *event,
+                                                        GtkTreeView      *tree_view);
 static gboolean gtk_tree_view_search_key_press_event    (GtkWidget        *entry,
                                                         GdkEventKey      *event,
                                                         GtkTreeView      *tree_view);
@@ -472,7 +484,7 @@ gtk_tree_view_get_type (void)
       };
 
       tree_view_type =
-       g_type_register_static (GTK_TYPE_CONTAINER, "GtkTreeView",
+       g_type_register_static (GTK_TYPE_CONTAINER, I_("GtkTreeView"),
                                &tree_view_info, 0);
     }
 
@@ -512,6 +524,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   widget_class->size_allocate = gtk_tree_view_size_allocate;
   widget_class->button_press_event = gtk_tree_view_button_press;
   widget_class->button_release_event = gtk_tree_view_button_release;
+  widget_class->grab_broken_event = gtk_tree_view_grab_broken;
   /*widget_class->configure_event = gtk_tree_view_configure;*/
   widget_class->motion_notify_event = gtk_tree_view_motion;
   widget_class->expose_event = gtk_tree_view_expose;
@@ -531,6 +544,8 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   widget_class->focus = gtk_tree_view_focus;
   widget_class->grab_focus = gtk_tree_view_grab_focus;
   widget_class->style_set = gtk_tree_view_style_set;
+  widget_class->grab_notify = gtk_tree_view_grab_notify;
+  widget_class->state_changed = gtk_tree_view_state_changed;
 
   /* GtkContainer signals */
   container_class->remove = gtk_tree_view_remove;
@@ -555,7 +570,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                                                        P_("TreeView Model"),
                                                        P_("The model for the tree view"),
                                                        GTK_TYPE_TREE_MODEL,
-                                                       G_PARAM_READWRITE));
+                                                       GTK_PARAM_READWRITE));
 
   g_object_class_install_property (o_class,
                                    PROP_HADJUSTMENT,
@@ -563,7 +578,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                                                        P_("Horizontal Adjustment"),
                                                         P_("Horizontal Adjustment for the widget"),
                                                         GTK_TYPE_ADJUSTMENT,
-                                                        G_PARAM_READWRITE));
+                                                        GTK_PARAM_READWRITE));
 
   g_object_class_install_property (o_class,
                                    PROP_VADJUSTMENT,
@@ -571,31 +586,31 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                                                        P_("Vertical Adjustment"),
                                                         P_("Vertical Adjustment for the widget"),
                                                         GTK_TYPE_ADJUSTMENT,
-                                                        G_PARAM_READWRITE));
+                                                        GTK_PARAM_READWRITE));
 
   g_object_class_install_property (o_class,
                                    PROP_HEADERS_VISIBLE,
-                                   g_param_spec_boolean ("headers_visible",
-                                                        P_("Visible"),
+                                   g_param_spec_boolean ("headers-visible",
+                                                        P_("Headers Visible"),
                                                         P_("Show the column header buttons"),
                                                         TRUE,
-                                                        G_PARAM_READWRITE));
+                                                        GTK_PARAM_READWRITE));
 
   g_object_class_install_property (o_class,
                                    PROP_HEADERS_CLICKABLE,
-                                   g_param_spec_boolean ("headers_clickable",
+                                   g_param_spec_boolean ("headers-clickable",
                                                         P_("Headers Clickable"),
                                                         P_("Column headers respond to click events"),
                                                         FALSE,
-                                                        G_PARAM_WRITABLE));
+                                                        GTK_PARAM_READWRITE));
 
   g_object_class_install_property (o_class,
                                    PROP_EXPANDER_COLUMN,
-                                   g_param_spec_object ("expander_column",
+                                   g_param_spec_object ("expander-column",
                                                        P_("Expander Column"),
                                                        P_("Set the column for the expander column"),
                                                        GTK_TYPE_TREE_VIEW_COLUMN,
-                                                       G_PARAM_READWRITE));
+                                                       GTK_PARAM_READWRITE));
 
   g_object_class_install_property (o_class,
                                    PROP_REORDERABLE,
@@ -603,33 +618,33 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                                                         P_("Reorderable"),
                                                         P_("View is reorderable"),
                                                         FALSE,
-                                                        G_PARAM_READWRITE));
+                                                        GTK_PARAM_READWRITE));
 
   g_object_class_install_property (o_class,
                                    PROP_RULES_HINT,
-                                   g_param_spec_boolean ("rules_hint",
+                                   g_param_spec_boolean ("rules-hint",
                                                         P_("Rules Hint"),
                                                         P_("Set a hint to the theme engine to draw rows in alternating colors"),
                                                         FALSE,
-                                                        G_PARAM_READWRITE));
+                                                        GTK_PARAM_READWRITE));
 
     g_object_class_install_property (o_class,
                                     PROP_ENABLE_SEARCH,
-                                    g_param_spec_boolean ("enable_search",
+                                    g_param_spec_boolean ("enable-search",
                                                           P_("Enable Search"),
                                                           P_("View allows user to search through columns interactively"),
                                                           TRUE,
-                                                          G_PARAM_READWRITE));
+                                                          GTK_PARAM_READWRITE));
 
     g_object_class_install_property (o_class,
                                     PROP_SEARCH_COLUMN,
-                                    g_param_spec_int ("search_column",
+                                    g_param_spec_int ("search-column",
                                                       P_("Search Column"),
                                                       P_("Model column to search through when searching through code"),
                                                       -1,
                                                       G_MAXINT,
                                                       -1,
-                                                      G_PARAM_READWRITE));
+                                                      GTK_PARAM_READWRITE));
 
     /**
      * GtkTreeView:fixed-height-mode:
@@ -644,11 +659,11 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
      **/
     g_object_class_install_property (o_class,
                                      PROP_FIXED_HEIGHT_MODE,
-                                     g_param_spec_boolean ("fixed_height_mode",
+                                     g_param_spec_boolean ("fixed-height-mode",
                                                            P_("Fixed Height Mode"),
                                                            P_("Speeds up GtkTreeView by assuming that all rows have the same height"),
                                                            FALSE,
-                                                           G_PARAM_READWRITE));
+                                                           GTK_PARAM_READWRITE));
     
     /**
      * GtkTreeView:hover-selection:
@@ -665,11 +680,11 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
      */
     g_object_class_install_property (o_class,
                                      PROP_HOVER_SELECTION,
-                                     g_param_spec_boolean ("hover_selection",
+                                     g_param_spec_boolean ("hover-selection",
                                                            P_("Hover Selection"),
                                                            P_("Whether the selection should follow the pointer"),
                                                            FALSE,
-                                                           G_PARAM_READWRITE));
+                                                           GTK_PARAM_READWRITE));
 
     /**
      * GtkTreeView:hover-expand:
@@ -685,11 +700,11 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
      */
     g_object_class_install_property (o_class,
                                      PROP_HOVER_EXPAND,
-                                     g_param_spec_boolean ("hover_expand",
+                                     g_param_spec_boolean ("hover-expand",
                                                            P_("Hover Expand"),
-                                                           P_("Whether rows should be expanded/collaped when the pointer moves over them"),
+                                                           P_("Whether rows should be expanded/collapsed when the pointer moves over them"),
                                                            FALSE,
-                                                           G_PARAM_READWRITE));
+                                                           GTK_PARAM_READWRITE));
 
   /* Style properties */
 #define _TREE_VIEW_EXPANDER_SIZE 12
@@ -697,63 +712,63 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
 #define _TREE_VIEW_HORIZONTAL_SEPARATOR 2
     
   gtk_widget_class_install_style_property (widget_class,
-                                          g_param_spec_int ("expander_size",
+                                          g_param_spec_int ("expander-size",
                                                             P_("Expander Size"),
                                                             P_("Size of the expander arrow"),
                                                             0,
                                                             G_MAXINT,
                                                             _TREE_VIEW_EXPANDER_SIZE,
-                                                            G_PARAM_READABLE));
+                                                            GTK_PARAM_READABLE));
 
   gtk_widget_class_install_style_property (widget_class,
-                                          g_param_spec_int ("vertical_separator",
+                                          g_param_spec_int ("vertical-separator",
                                                             P_("Vertical Separator Width"),
                                                             P_("Vertical space between cells.  Must be an even number"),
                                                             0,
                                                             G_MAXINT,
                                                             _TREE_VIEW_VERTICAL_SEPARATOR,
-                                                            G_PARAM_READABLE));
+                                                            GTK_PARAM_READABLE));
 
   gtk_widget_class_install_style_property (widget_class,
-                                          g_param_spec_int ("horizontal_separator",
+                                          g_param_spec_int ("horizontal-separator",
                                                             P_("Horizontal Separator Width"),
                                                             P_("Horizontal space between cells.  Must be an even number"),
                                                             0,
                                                             G_MAXINT,
                                                             _TREE_VIEW_HORIZONTAL_SEPARATOR,
-                                                            G_PARAM_READABLE));
+                                                            GTK_PARAM_READABLE));
 
   gtk_widget_class_install_style_property (widget_class,
-                                          g_param_spec_boolean ("allow_rules",
+                                          g_param_spec_boolean ("allow-rules",
                                                                 P_("Allow Rules"),
                                                                 P_("Allow drawing of alternating color rows"),
                                                                 TRUE,
-                                                                G_PARAM_READABLE));
+                                                                GTK_PARAM_READABLE));
 
   gtk_widget_class_install_style_property (widget_class,
-                                          g_param_spec_boolean ("indent_expanders",
+                                          g_param_spec_boolean ("indent-expanders",
                                                                 P_("Indent Expanders"),
                                                                 P_("Make the expanders indented"),
                                                                 TRUE,
-                                                                G_PARAM_READABLE));
+                                                                GTK_PARAM_READABLE));
 
   gtk_widget_class_install_style_property (widget_class,
-                                           g_param_spec_boxed ("even_row_color",
+                                           g_param_spec_boxed ("even-row-color",
                                                                P_("Even Row Color"),
                                                                P_("Color to use for even rows"),
                                                               GDK_TYPE_COLOR,
-G_PARAM_READABLE));
+                                                              GTK_PARAM_READABLE));
 
   gtk_widget_class_install_style_property (widget_class,
-                                           g_param_spec_boxed ("odd_row_color",
+                                           g_param_spec_boxed ("odd-row-color",
                                                                P_("Odd Row Color"),
                                                                P_("Color to use for odd rows"),
                                                               GDK_TYPE_COLOR,
-G_PARAM_READABLE));
+                                                              GTK_PARAM_READABLE));
 
   /* Signals */
   widget_class->set_scroll_adjustments_signal =
-    g_signal_new ("set_scroll_adjustments",
+    g_signal_new (I_("set_scroll_adjustments"),
                  G_TYPE_FROM_CLASS (o_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, set_scroll_adjustments),
@@ -763,8 +778,23 @@ G_PARAM_READABLE));
                  GTK_TYPE_ADJUSTMENT,
                  GTK_TYPE_ADJUSTMENT);
 
+  /**
+   * GtkTreeView::row-activated:
+   * @tree_view: the object on which the signal is emitted
+   * @path: the #GtkTreePath for the activated row
+   * @column: the #GtkTreeViewColumn in which the activation occurred
+   *
+   * The "row-activated" signal is emitted when the method
+   * gtk_tree_view_row_activated() is called or the user double clicks 
+   * a treeview row. It is also emitted when a non-editable row is 
+   * selected and one of the keys: Space, Shift+Space, Return or 
+   * Enter is pressed.
+   * 
+   * For selection handling refer to the <link linkend="TreeWidget">tree 
+   * widget conceptual overview</link> as well as #GtkTreeSelection.
+   */
   tree_view_signals[ROW_ACTIVATED] =
-    g_signal_new ("row_activated",
+    g_signal_new (I_("row_activated"),
                  G_TYPE_FROM_CLASS (o_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, row_activated),
@@ -775,7 +805,7 @@ G_PARAM_READABLE));
                  GTK_TYPE_TREE_VIEW_COLUMN);
 
   tree_view_signals[TEST_EXPAND_ROW] =
-    g_signal_new ("test_expand_row",
+    g_signal_new (I_("test_expand_row"),
                  G_TYPE_FROM_CLASS (o_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkTreeViewClass, test_expand_row),
@@ -786,7 +816,7 @@ G_PARAM_READABLE));
                  GTK_TYPE_TREE_PATH);
 
   tree_view_signals[TEST_COLLAPSE_ROW] =
-    g_signal_new ("test_collapse_row",
+    g_signal_new (I_("test_collapse_row"),
                  G_TYPE_FROM_CLASS (o_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkTreeViewClass, test_collapse_row),
@@ -797,7 +827,7 @@ G_PARAM_READABLE));
                  GTK_TYPE_TREE_PATH);
 
   tree_view_signals[ROW_EXPANDED] =
-    g_signal_new ("row_expanded",
+    g_signal_new (I_("row_expanded"),
                  G_TYPE_FROM_CLASS (o_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkTreeViewClass, row_expanded),
@@ -808,7 +838,7 @@ G_PARAM_READABLE));
                  GTK_TYPE_TREE_PATH);
 
   tree_view_signals[ROW_COLLAPSED] =
-    g_signal_new ("row_collapsed",
+    g_signal_new (I_("row_collapsed"),
                  G_TYPE_FROM_CLASS (o_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkTreeViewClass, row_collapsed),
@@ -819,7 +849,7 @@ G_PARAM_READABLE));
                  GTK_TYPE_TREE_PATH);
 
   tree_view_signals[COLUMNS_CHANGED] =
-    g_signal_new ("columns_changed",
+    g_signal_new (I_("columns_changed"),
                  G_TYPE_FROM_CLASS (o_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkTreeViewClass, columns_changed),
@@ -828,7 +858,7 @@ G_PARAM_READABLE));
                  G_TYPE_NONE, 0);
 
   tree_view_signals[CURSOR_CHANGED] =
-    g_signal_new ("cursor_changed",
+    g_signal_new (I_("cursor_changed"),
                  G_TYPE_FROM_CLASS (o_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkTreeViewClass, cursor_changed),
@@ -837,7 +867,7 @@ G_PARAM_READABLE));
                  G_TYPE_NONE, 0);
 
   tree_view_signals[MOVE_CURSOR] =
-    g_signal_new ("move_cursor",
+    g_signal_new (I_("move_cursor"),
                  G_TYPE_FROM_CLASS (object_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, move_cursor),
@@ -848,7 +878,7 @@ G_PARAM_READABLE));
                  G_TYPE_INT);
 
   tree_view_signals[SELECT_ALL] =
-    g_signal_new ("select_all",
+    g_signal_new (I_("select_all"),
                  G_TYPE_FROM_CLASS (object_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, select_all),
@@ -857,7 +887,7 @@ G_PARAM_READABLE));
                  G_TYPE_BOOLEAN, 0);
 
   tree_view_signals[UNSELECT_ALL] =
-    g_signal_new ("unselect_all",
+    g_signal_new (I_("unselect_all"),
                  G_TYPE_FROM_CLASS (object_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, unselect_all),
@@ -866,7 +896,7 @@ G_PARAM_READABLE));
                  G_TYPE_BOOLEAN, 0);
 
   tree_view_signals[SELECT_CURSOR_ROW] =
-    g_signal_new ("select_cursor_row",
+    g_signal_new (I_("select_cursor_row"),
                  G_TYPE_FROM_CLASS (object_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_row),
@@ -876,7 +906,7 @@ G_PARAM_READABLE));
                  G_TYPE_BOOLEAN);
 
   tree_view_signals[TOGGLE_CURSOR_ROW] =
-    g_signal_new ("toggle_cursor_row",
+    g_signal_new (I_("toggle_cursor_row"),
                  G_TYPE_FROM_CLASS (object_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, toggle_cursor_row),
@@ -885,7 +915,7 @@ G_PARAM_READABLE));
                  G_TYPE_BOOLEAN, 0);
 
   tree_view_signals[EXPAND_COLLAPSE_CURSOR_ROW] =
-    g_signal_new ("expand_collapse_cursor_row",
+    g_signal_new (I_("expand_collapse_cursor_row"),
                  G_TYPE_FROM_CLASS (object_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, expand_collapse_cursor_row),
@@ -897,7 +927,7 @@ G_PARAM_READABLE));
                  G_TYPE_BOOLEAN);
 
   tree_view_signals[SELECT_CURSOR_PARENT] =
-    g_signal_new ("select_cursor_parent",
+    g_signal_new (I_("select_cursor_parent"),
                  G_TYPE_FROM_CLASS (object_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_parent),
@@ -906,7 +936,7 @@ G_PARAM_READABLE));
                  G_TYPE_BOOLEAN, 0);
 
   tree_view_signals[START_INTERACTIVE_SEARCH] =
-    g_signal_new ("start_interactive_search",
+    g_signal_new (I_("start_interactive_search"),
                  G_TYPE_FROM_CLASS (object_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, start_interactive_search),
@@ -1116,16 +1146,20 @@ G_PARAM_READABLE));
                                G_TYPE_BOOLEAN, TRUE);
 
   gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0, "select_cursor_parent", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, GDK_CONTROL_MASK, "select_cursor_parent", 0);
 
   gtk_binding_entry_add_signal (binding_set, GDK_f, GDK_CONTROL_MASK, "start_interactive_search", 0);
 
   gtk_binding_entry_add_signal (binding_set, GDK_F, GDK_CONTROL_MASK, "start_interactive_search", 0);
+
+  g_type_class_add_private (o_class, sizeof (GtkTreeViewPrivate));
 }
 
 static void
 gtk_tree_view_init (GtkTreeView *tree_view)
 {
-  tree_view->priv = g_new0 (GtkTreeViewPrivate, 1);
+  tree_view->priv = G_TYPE_INSTANCE_GET_PRIVATE (tree_view, GTK_TYPE_TREE_VIEW, GtkTreeViewPrivate);
+
   GTK_WIDGET_SET_FLAGS (tree_view, GTK_CAN_FOCUS);
 
   gtk_widget_set_redraw_on_allocate (GTK_WIDGET (tree_view), FALSE);
@@ -1249,6 +1283,9 @@ gtk_tree_view_get_property (GObject    *object,
     case PROP_HEADERS_VISIBLE:
       g_value_set_boolean (value, gtk_tree_view_get_headers_visible (tree_view));
       break;
+    case PROP_HEADERS_CLICKABLE:
+      g_value_set_boolean (value, gtk_tree_view_get_headers_clickable (tree_view));
+      break;
     case PROP_EXPANDER_COLUMN:
       g_value_set_object (value, tree_view->priv->expander_column);
       break;
@@ -1282,10 +1319,6 @@ gtk_tree_view_get_property (GObject    *object,
 static void
 gtk_tree_view_finalize (GObject *object)
 {
-  GtkTreeView *tree_view = (GtkTreeView *) object;
-
-  g_free (tree_view->priv);
-
   (* G_OBJECT_CLASS (parent_class)->finalize) (object);
 }
 
@@ -1294,6 +1327,20 @@ gtk_tree_view_finalize (GObject *object)
 /* GtkObject Methods
  */
 
+static void
+gtk_tree_view_free_rbtree (GtkTreeView *tree_view)
+{
+  _gtk_rbtree_free (tree_view->priv->tree);
+  
+  tree_view->priv->tree = NULL;
+  tree_view->priv->button_pressed_node = NULL;
+  tree_view->priv->button_pressed_tree = NULL;
+  tree_view->priv->prelight_tree = NULL;
+  tree_view->priv->prelight_node = NULL;
+  tree_view->priv->expanded_collapsed_node = NULL;
+  tree_view->priv->expanded_collapsed_tree = NULL;
+}
+
 static void
 gtk_tree_view_destroy (GtkObject *object)
 {
@@ -1318,8 +1365,8 @@ gtk_tree_view_destroy (GtkObject *object)
   if (tree_view->priv->tree != NULL)
     {
       gtk_tree_view_unref_and_check_selection_tree (tree_view, tree_view->priv->tree);
-      _gtk_rbtree_free (tree_view->priv->tree);
-      tree_view->priv->tree = NULL;
+
+      gtk_tree_view_free_rbtree (tree_view);
     }
 
   if (tree_view->priv->selection != NULL)
@@ -1385,15 +1432,20 @@ gtk_tree_view_destroy (GtkObject *object)
       gtk_widget_destroy (tree_view->priv->search_window);
       tree_view->priv->search_window = NULL;
       tree_view->priv->search_entry = NULL;
+      if (tree_view->priv->typeselect_flush_timeout)
+       {
+         g_source_remove (tree_view->priv->typeselect_flush_timeout);
+         tree_view->priv->typeselect_flush_timeout = 0;
+       }
     }
 
-  if (tree_view->priv->search_destroy)
+  if (tree_view->priv->search_destroy && tree_view->priv->search_user_data)
     {
       (* tree_view->priv->search_destroy) (tree_view->priv->search_user_data);
       tree_view->priv->search_user_data = NULL;
     }
 
-  if (tree_view->priv->row_separator_destroy)
+  if (tree_view->priv->row_separator_destroy && tree_view->priv->row_separator_data)
     {
       (* tree_view->priv->row_separator_destroy) (tree_view->priv->row_separator_data);
       tree_view->priv->row_separator_data = NULL;
@@ -1493,7 +1545,6 @@ gtk_tree_view_realize (GtkWidget *widget)
 {
   GList *tmp_list;
   GtkTreeView *tree_view;
-  GdkGCValues values;
   GdkWindowAttr attributes;
   gint attributes_mask;
 
@@ -1555,12 +1606,6 @@ gtk_tree_view_realize (GtkWidget *widget)
                                                   &attributes, attributes_mask);
   gdk_window_set_user_data (tree_view->priv->header_window, widget);
 
-
-  values.foreground = (widget->style->white.pixel==0 ?
-                      widget->style->black:widget->style->white);
-  values.function = GDK_XOR;
-  values.subwindow_mode = GDK_INCLUDE_INFERIORS;
-
   /* Add them all up. */
   widget->style = gtk_style_attach (widget->style, widget->window);
   gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
@@ -1764,7 +1809,7 @@ gtk_tree_view_size_request (GtkWidget      *widget,
    * sure we have some size. In practice, with a lot of static lists, this
    * should get a good width.
    */
-  validate_rows (tree_view);
+  do_validate_rows (tree_view, FALSE);
   gtk_tree_view_size_request_columns (tree_view);
   gtk_tree_view_update_size (GTK_TREE_VIEW (widget));
 
@@ -1886,6 +1931,7 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
   gint extra, extra_per_column;
   gint full_requested_width = 0;
   gint number_of_expand_columns = 0;
+  gboolean column_changed = FALSE;
   gboolean rtl;
   
   tree_view = GTK_TREE_VIEW (widget);
@@ -1988,7 +2034,7 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
       width += column->width;
 
       if (column->width > old_width)
-       invalidate_column (tree_view, column);
+        column_changed = TRUE;
 
       gtk_widget_size_allocate (column->button, &allocation);
 
@@ -1998,6 +2044,9 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
                                allocation.y,
                                 TREE_VIEW_DRAG_WIDTH, allocation.height);
     }
+
+  if (column_changed)
+    gtk_widget_queue_draw (GTK_WIDGET (tree_view));
 }
 
 
@@ -2008,7 +2057,6 @@ gtk_tree_view_size_allocate (GtkWidget     *widget,
   GList *tmp_list;
   GtkTreeView *tree_view;
   gboolean width_changed = FALSE;
-  gboolean dy_changed = FALSE;
   gint old_width = widget->allocation.width;           
 
   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
@@ -2076,16 +2124,15 @@ gtk_tree_view_size_allocate (GtkWidget     *widget,
   tree_view->priv->vadjustment->lower = 0;
   tree_view->priv->vadjustment->upper = MAX (tree_view->priv->vadjustment->page_size, tree_view->priv->height);
 
-  if (tree_view->priv->vadjustment->value + allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view) > tree_view->priv->height)
-    {
-      double before = tree_view->priv->vadjustment->value;
-      gtk_adjustment_set_value (tree_view->priv->vadjustment,
-                               MAX (tree_view->priv->height - tree_view->priv->vadjustment->page_size, 0));
-      if (before != tree_view->priv->vadjustment->value)
-        dy_changed = TRUE;
-    }
-
   gtk_adjustment_changed (tree_view->priv->vadjustment);
+
+  /* now the adjustments and window sizes are in sync, we can sync toprow/dy again */
+  if (tree_view->priv->height <= tree_view->priv->vadjustment->page_size)
+    gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment), 0);
+  else if (gtk_tree_row_reference_valid (tree_view->priv->top_row))
+    gtk_tree_view_top_row_to_dy (tree_view);
+  else
+    gtk_tree_view_dy_to_top_row (tree_view);
   
   if (GTK_WIDGET_REALIZED (widget))
     {
@@ -2106,6 +2153,9 @@ gtk_tree_view_size_allocate (GtkWidget     *widget,
 
   gtk_tree_view_size_allocate_columns (widget);
 
+  if (tree_view->priv->tree == NULL)
+    invalidate_empty_focus (tree_view);
+
   if (GTK_WIDGET_REALIZED (widget))
     {
       gboolean has_expand_column = FALSE;
@@ -2127,9 +2177,6 @@ gtk_tree_view_size_allocate (GtkWidget     *widget,
          else
            gtk_widget_queue_draw (widget);
        }
-      
-      if (dy_changed)
-       gtk_widget_queue_draw (widget);
     }
 }
 
@@ -2163,8 +2210,8 @@ gtk_tree_view_button_press (GtkWidget      *widget,
   rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
   gtk_tree_view_stop_editing (tree_view, FALSE);
   gtk_widget_style_get (widget,
-                       "vertical_separator", &vertical_separator,
-                       "horizontal_separator", &horizontal_separator,
+                       "vertical-separator", &vertical_separator,
+                       "horizontal-separator", &horizontal_separator,
                        NULL);
 
 
@@ -2242,12 +2289,12 @@ gtk_tree_view_button_press (GtkWidget      *widget,
       for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
           list; list = (rtl ? list->prev : list->next))
        {
-         column = list->data;
+         GtkTreeViewColumn *candidate = list->data;
 
-         if (!column->visible)
+         if (!candidate->visible)
            continue;
 
-         background_area.width = column->width;
+         background_area.width = candidate->width;
          if ((background_area.x > (gint) event->x) ||
              (background_area.x + background_area.width <= (gint) event->x))
            {
@@ -2256,6 +2303,7 @@ gtk_tree_view_button_press (GtkWidget      *widget,
            }
 
          /* we found the focus column */
+         column = candidate;
          cell_area = background_area;
          cell_area.width -= horizontal_separator;
          cell_area.height -= vertical_separator;
@@ -2286,16 +2334,15 @@ gtk_tree_view_button_press (GtkWidget      *widget,
          GtkTreePath *anchor;
          GtkTreeIter iter;
 
+         gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
+         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);
+
          if (tree_view->priv->anchor)
-           {
-             anchor = gtk_tree_row_reference_get_path (tree_view->priv->anchor);
-             gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
-             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);
-           }
+           anchor = gtk_tree_row_reference_get_path (tree_view->priv->anchor);
          else
            anchor = NULL;
 
@@ -2475,6 +2522,7 @@ gtk_tree_view_button_press (GtkWidget      *widget,
          if (event->type == GDK_2BUTTON_PRESS &&
              gtk_tree_view_column_get_sizing (column) != GTK_TREE_VIEW_COLUMN_AUTOSIZE)
            {
+             column->use_resized_width = FALSE;
              _gtk_tree_view_column_autosize (tree_view, column);
              return TRUE;
            }
@@ -2489,7 +2537,6 @@ gtk_tree_view_button_press (GtkWidget      *widget,
          gtk_grab_add (widget);
          GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE);
          column->resized_width = column->width;
-         column->use_resized_width = TRUE;
 
          /* block attached dnd signal handler */
          drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
@@ -2581,15 +2628,12 @@ gtk_tree_view_button_release_column_resize (GtkWidget      *widget,
 {
   GtkTreeView *tree_view;
   gpointer drag_data;
-  gint x;
-  gint i;
 
   tree_view = GTK_TREE_VIEW (widget);
 
-  i = tree_view->priv->drag_pos;
   tree_view->priv->drag_pos = -1;
 
-      /* unblock attached dnd signal handler */
+  /* unblock attached dnd signal handler */
   drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
   if (drag_data)
     g_signal_handlers_unblock_matched (widget,
@@ -2598,7 +2642,6 @@ gtk_tree_view_button_release_column_resize (GtkWidget      *widget,
                                       drag_data);
 
   GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE);
-  gtk_widget_get_pointer (widget, &x, NULL);
   gtk_grab_remove (widget);
   gdk_display_pointer_ungrab (gdk_drawable_get_display (event->window),
                              event->time);
@@ -2659,6 +2702,26 @@ gtk_tree_view_button_release (GtkWidget      *widget,
   return TRUE;
 }
 
+static gboolean
+gtk_tree_view_grab_broken (GtkWidget          *widget,
+                          GdkEventGrabBroken *event)
+{
+  GtkTreeView *tree_view;
+
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  tree_view = GTK_TREE_VIEW (widget);
+
+  if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG))
+    gtk_tree_view_button_release_drag_column (widget, (GdkEventButton *)event);
+
+  if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE))
+    gtk_tree_view_button_release_column_resize (widget, (GdkEventButton *)event);
+
+  return TRUE;
+}
+
 #if 0
 static gboolean
 gtk_tree_view_configure (GtkWidget *widget,
@@ -3177,8 +3240,9 @@ gtk_tree_view_motion_resize_column (GtkWidget      *widget,
   new_width = gtk_tree_view_new_column_width (tree_view,
                                              tree_view->priv->drag_pos, &x);
   if (x != tree_view->priv->x_drag &&
-      (new_width != column->fixed_width));
+      (new_width != column->fixed_width))
     {
+      column->use_resized_width = TRUE;
       column->resized_width = new_width;
       gtk_widget_queue_resize (widget);
     }
@@ -3351,6 +3415,23 @@ gtk_tree_view_motion (GtkWidget      *widget,
   return FALSE;
 }
 
+/* Invalidate the focus rectangle near the edge of the bin_window; used when
+ * the tree is empty.
+ */
+static void
+invalidate_empty_focus (GtkTreeView *tree_view)
+{
+  GdkRectangle area;
+
+  if (!GTK_WIDGET_HAS_FOCUS (tree_view))
+    return;
+
+  area.x = 0;
+  area.y = 0;
+  gdk_drawable_get_size (tree_view->priv->bin_window, &area.width, &area.height);
+  gdk_window_invalidate_rect (tree_view->priv->bin_window, &area, FALSE);
+}
+
 /* Draws a focus rectangle near the edge of the bin_window; used when the tree
  * is empty.
  */
@@ -3398,7 +3479,7 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
   GtkRBTree *drag_highlight_tree = NULL;
   GtkTreeIter iter;
   gint new_y;
-  gint y_offset, x_offset, cell_offset;
+  gint y_offset, cell_offset;
   gint max_height;
   gint depth;
   GdkRectangle background_area;
@@ -3406,6 +3487,7 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
   guint flags;
   gint highlight_x;
   gint bin_window_width;
+  gint bin_window_height;
   GtkTreePath *cursor_path;
   GtkTreePath *drag_dest_path;
   GList *last_column;
@@ -3416,6 +3498,8 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
   gboolean has_special_cell;
   gboolean rtl;
   gint n_visible_columns;
+  gint pointer_x, pointer_y;
+  gboolean got_pointer = FALSE;
 
   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
 
@@ -3424,9 +3508,9 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
   tree_view = GTK_TREE_VIEW (widget);
 
   gtk_widget_style_get (widget,
-                       "horizontal_separator", &horizontal_separator,
-                       "vertical_separator", &vertical_separator,
-                       "allow_rules", &allow_rules,
+                       "horizontal-separator", &horizontal_separator,
+                       "vertical-separator", &vertical_separator,
+                       "allow-rules", &allow_rules,
                        "focus-line-width", &focus_line_width,
                        NULL);
 
@@ -3447,6 +3531,21 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
   if (new_y < 0)
     new_y = 0;
   y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
+  gdk_drawable_get_size (tree_view->priv->bin_window,
+                         &bin_window_width, &bin_window_height);
+
+  if (tree_view->priv->height < bin_window_height)
+    {
+      gtk_paint_flat_box (widget->style,
+                          event->window,
+                          widget->state,
+                          GTK_SHADOW_NONE,
+                          &event->area,
+                          widget,
+                          "cell_even",
+                          0, tree_view->priv->height,
+                          bin_window_width, bin_window_height);
+    }
 
   if (node == NULL)
     return TRUE;
@@ -3478,9 +3577,6 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
     _gtk_tree_view_find_node (tree_view, drag_dest_path,
                               &drag_highlight_tree, &drag_highlight);
 
-  gdk_drawable_get_size (tree_view->priv->bin_window,
-                         &bin_window_width, NULL);
-
   
   n_visible_columns = 0;
   for (list = tree_view->priv->columns; list; list = list->next)
@@ -3517,7 +3613,6 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
 
       max_height = ROW_HEIGHT (tree_view, BACKGROUND_HEIGHT (node));
 
-      x_offset = -event->area.x;
       cell_offset = 0;
       highlight_x = 0; /* should match x coord of first cell */
 
@@ -3534,6 +3629,22 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
 
       parity = _gtk_rbtree_node_find_parity (tree, node);
 
+      /* we *need* to set cell data on all cells before the call
+       * to _has_special_cell, else _has_special_cell() does not
+       * return a correct value.
+       */
+      for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
+          list;
+          list = (rtl ? list->prev : list->next))
+        {
+         GtkTreeViewColumn *column = list->data;
+         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);
+        }
+
       has_special_cell = gtk_tree_view_has_special_cell (tree_view);
 
       for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
@@ -3628,7 +3739,9 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
 
           g_assert (detail);
 
-         if (flags & GTK_CELL_RENDERER_SELECTED)
+         if (widget->state == GTK_STATE_INSENSITIVE)
+           state = GTK_STATE_INSENSITIVE;          
+         else if (flags & GTK_CELL_RENDERER_SELECTED)
            state = GTK_STATE_SELECTED;
          else
            state = GTK_STATE_NORMAL;
@@ -3677,12 +3790,17 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                                                   flags);
              if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT)
                {
-                 gint x, y;
-                 gdk_window_get_pointer (tree_view->priv->bin_window, &x, &y, 0);
+                 if (!got_pointer)
+                   {
+                     gdk_window_get_pointer (tree_view->priv->bin_window, 
+                                             &pointer_x, &pointer_y, NULL);
+                     got_pointer = TRUE;
+                   }
+
                  gtk_tree_view_draw_arrow (GTK_TREE_VIEW (widget),
-                                            tree,
+                                           tree,
                                            node,
-                                           x, y);
+                                           pointer_x, pointer_y);
                }
            }
          else
@@ -3729,7 +3847,6 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
          GtkRBTree *tree = NULL;
          GtkRBNode *node = NULL;
          gint width;
-         gint focus_line_width;
 
           switch (tree_view->priv->drag_dest_pos)
             {
@@ -3751,7 +3868,6 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                break;
              gdk_drawable_get_size (tree_view->priv->bin_window,
                                     &width, NULL);
-             gtk_widget_style_get (widget, "focus-line-width", &focus_line_width, NULL);
              gtk_paint_focus (widget->style,
                               tree_view->priv->bin_window,
                               GTK_WIDGET_STATE (widget),
@@ -3980,7 +4096,7 @@ gtk_tree_view_get_drop_column (GtkTreeView       *tree_view,
                continue;
              }
 
-           return cur_column;
+           return left_column;
          }
 
        if (!tree_view->priv->column_drop_func)
@@ -4031,7 +4147,7 @@ gtk_tree_view_get_drop_column (GtkTreeView       *tree_view,
                continue;
              }
 
-           return cur_column;
+           return left_column;
          }
 
        if (!tree_view->priv->column_drop_func)
@@ -4162,9 +4278,10 @@ gtk_tree_view_key_press (GtkWidget   *widget,
       return TRUE;
     }
 
-  if (tree_view->priv->columns && (event->state & GDK_SHIFT_MASK)
-      && (event->keyval == GDK_Left || event->keyval == GDK_KP_Left
-          || event->keyval == GDK_Right || event->keyval == GDK_KP_Right))
+  if (tree_view->priv->columns && 
+      (event->state & GDK_SHIFT_MASK) && (event->state & GDK_MOD1_MASK) &&
+      (event->keyval == GDK_Left || event->keyval == GDK_KP_Left
+       || event->keyval == GDK_Right || event->keyval == GDK_KP_Right))
     {
       list = tree_view->priv->columns;
       while (list)
@@ -4214,7 +4331,7 @@ gtk_tree_view_key_press (GtkWidget   *widget,
        }
     }
 
-  if (tree_view->priv->columns && (event->state & GDK_CONTROL_MASK) &&
+  if (tree_view->priv->columns && (event->state & GDK_MOD1_MASK) &&
       (event->keyval == GDK_Left || event->keyval == GDK_KP_Left
        || event->keyval == GDK_Right || event->keyval == GDK_KP_Right
        || event->keyval == GDK_Home || event->keyval == GDK_KP_Home
@@ -4336,15 +4453,21 @@ gtk_tree_view_key_press (GtkWidget   *widget,
       const char *new_text;
       gboolean retval;
       GdkScreen *screen;
+      gboolean text_modified;
+      gulong popup_menu_id;
 
       gtk_tree_view_ensure_interactive_directory (tree_view);
 
       /* Make a copy of the current text */
       old_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (tree_view->priv->search_entry)));
       new_event = gdk_event_copy ((GdkEvent *) event);
-      ((GdkEventKey *) new_event)->window = tree_view->priv->search_entry->window;
+      g_object_unref (((GdkEventKey *) new_event)->window);
+      ((GdkEventKey *) new_event)->window = g_object_ref (tree_view->priv->search_window->window);
       gtk_widget_realize (tree_view->priv->search_window);
 
+      popup_menu_id = g_signal_connect (tree_view->priv->search_entry, 
+                                       "popup_menu", G_CALLBACK (gtk_true), NULL);
+
       /* Move the entry off screen */
       screen = gtk_widget_get_screen (GTK_WIDGET (tree_view));
       gtk_window_move (GTK_WINDOW (tree_view->priv->search_window),
@@ -4355,17 +4478,22 @@ gtk_tree_view_key_press (GtkWidget   *widget,
       /* Send the event to the window.  If the preedit_changed signal is emitted
        * during this event, we will set priv->imcontext_changed  */
       tree_view->priv->imcontext_changed = FALSE;
-      retval = gtk_widget_event (tree_view->priv->search_entry, new_event);
+      retval = gtk_widget_event (tree_view->priv->search_window, new_event);
+      gdk_event_free (new_event);
       gtk_widget_hide (tree_view->priv->search_window);
 
+      g_signal_handler_disconnect (tree_view->priv->search_entry, 
+                                  popup_menu_id);
+
       /* We check to make sure that the entry tried to handle the text, and that
        * the text has changed.
        */
       new_text = gtk_entry_get_text (GTK_ENTRY (tree_view->priv->search_entry));
+      text_modified = strcmp (old_text, new_text) != 0;
+      g_free (old_text);
       if (tree_view->priv->imcontext_changed ||    /* we're in a preedit */
-         (retval && strcmp (old_text, new_text))) /* ...or the text was modified */
+         (retval && text_modified))               /* ...or the text was modified */
        {
-         g_free (old_text);
          if (gtk_tree_view_real_start_interactive_search (tree_view, FALSE))
            {
              gtk_widget_grab_focus (GTK_WIDGET (tree_view));
@@ -4431,11 +4559,11 @@ gtk_tree_view_leave_notify (GtkWidget        *widget,
 {
   GtkTreeView *tree_view;
 
-  g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
+  tree_view = GTK_TREE_VIEW (widget);
+  tree_view->priv->pressed_button = -1;
 
   if (event->mode == GDK_CROSSING_GRAB)
     return TRUE;
-  tree_view = GTK_TREE_VIEW (widget);
 
   if (tree_view->priv->prelight_node)
     _gtk_tree_view_queue_draw_node (tree_view,
@@ -4485,7 +4613,7 @@ gtk_tree_view_node_queue_redraw (GtkTreeView *tree_view,
 
   gtk_widget_queue_draw_area (GTK_WIDGET (tree_view),
                              0, y,
-                             GTK_WIDGET (tree_view)->requisition.width,
+                             GTK_WIDGET (tree_view)->allocation.width,
                              GTK_RBNODE_GET_HEIGHT (node));
 }
 
@@ -4502,11 +4630,13 @@ validate_row (GtkTreeView *tree_view,
   GList *list;
   gint height = 0;
   gint horizontal_separator;
+  gint vertical_separator;
+  gint focus_line_width;
   gint depth = gtk_tree_path_get_depth (path);
   gboolean retval = FALSE;
   gboolean is_separator = FALSE;
   gint focus_pad;
-      
+
   /* double check the row needs validating */
   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) &&
       ! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
@@ -4521,7 +4651,9 @@ validate_row (GtkTreeView *tree_view,
 
   gtk_widget_style_get (GTK_WIDGET (tree_view),
                        "focus-padding", &focus_pad,
-                       "horizontal_separator", &horizontal_separator,
+                       "focus-line-width", &focus_line_width,
+                       "horizontal-separator", &horizontal_separator,
+                       "vertical-separator", &vertical_separator,
                        NULL);
   
   for (list = tree_view->priv->columns; list; list = list->next)
@@ -4546,6 +4678,7 @@ validate_row (GtkTreeView *tree_view,
 
       if (!is_separator)
        {
+          tmp_height += vertical_separator;
          height = MAX (height, tmp_height);
          height = MAX (height, tree_view->priv->expander_size);
        }
@@ -4611,6 +4744,9 @@ validate_visible_area (GtkTreeView *tree_view)
       path = gtk_tree_row_reference_get_path (tree_view->priv->scroll_to_path);
       if (path && !_gtk_tree_view_find_node (tree_view, path, &tree, &node))
        {
+          /* we are going to scroll, and will update dy */
+         update_dy = TRUE;
+
          gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
          if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
              GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
@@ -4641,8 +4777,8 @@ validate_visible_area (GtkTreeView *tree_view)
              dy = _gtk_rbtree_node_find_offset (tree, node);
 
              if (dy >= tree_view->priv->vadjustment->value &&
-                 dy < (tree_view->priv->vadjustment->value
-                       + tree_view->priv->vadjustment->page_size))
+                 dy + height <= (tree_view->priv->vadjustment->value
+                                 + tree_view->priv->vadjustment->page_size))
                {
                  /* row visible: keep the row at the same position */
                  area_above = dy - tree_view->priv->vadjustment->value;
@@ -4740,6 +4876,42 @@ validate_visible_area (GtkTreeView *tree_view)
 
   above_path = gtk_tree_path_copy (path);
 
+  /* if we do not validate any row above the new top_row, we will make sure
+   * that the row immediately above top_row has been validated. (if we do not
+   * do this, _gtk_rbtree_find_offset will find the row above top_row, because
+   * when invalidated that row's height will be zero. and this will mess up
+   * scrolling).
+   */
+  if (area_above == 0)
+    {
+      GtkRBTree *tree;
+      GtkRBNode *node;
+      GtkTreePath *tmppath;
+      GtkTreeIter iter;
+
+      _gtk_tree_view_find_node (tree_view, above_path, &tree, &node);
+
+      tmppath = gtk_tree_path_copy (above_path);
+
+      _gtk_rbtree_prev_full (tree, node, &tree, &node);
+      if (! gtk_tree_path_prev (tmppath) && node != NULL)
+        {
+          gtk_tree_path_free (tmppath);
+          tmppath = _gtk_tree_view_find_path (tree_view, tree, node);
+        }
+      gtk_tree_model_get_iter (tree_view->priv->model, &iter, tmppath);
+
+      if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
+          GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
+        {
+          need_redraw = TRUE;
+          if (validate_row (tree_view, tree, node, &iter, path))
+            size_changed = TRUE;
+        }
+
+      gtk_tree_path_free (tmppath);
+    }
+
   /* Now, we walk forwards and backwards, measuring rows. Unfortunately,
    * backwards is much slower then forward, as there is no iter_prev function.
    * We go forwards first in case we run out of tree.  Then we go backwards to
@@ -4870,6 +5042,35 @@ validate_visible_area (GtkTreeView *tree_view)
       update_dy = TRUE;
     }
 
+  /* if we scrolled to a path, we need to set the dy here,
+   * and sync the top row accordingly
+   */
+  if (tree_view->priv->scroll_to_path)
+    {
+      gint dy;
+
+      if (node != NULL)
+       dy = _gtk_rbtree_node_find_offset (tree, node) - area_above;
+      else
+       dy = 0;
+
+      gtk_adjustment_set_value (tree_view->priv->vadjustment, dy);
+      gtk_tree_view_dy_to_top_row (tree_view);
+
+      need_redraw = TRUE;
+    }
+  else if (tree_view->priv->height <= tree_view->priv->vadjustment->page_size)
+    {
+      /* when we are not scrolling, we should never set dy to something
+       * else than zero. we update top_row to be in sync with dy = 0.
+       */
+      gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment), 0);
+      gtk_tree_view_dy_to_top_row (tree_view);
+    }
+  else
+    gtk_tree_view_top_row_to_dy (tree_view);
+
+  /* update width/height and queue a resize */
   if (size_changed)
     {
       GtkRequisition requisition;
@@ -4877,6 +5078,7 @@ validate_visible_area (GtkTreeView *tree_view)
       /* We temporarily guess a size, under the assumption that it will be the
        * same when we get our next size_allocate.  If we don't do this, we'll be
        * in an inconsistent state if we call top_row_to_dy. */
+
       gtk_widget_size_request (GTK_WIDGET (tree_view), &requisition);
       tree_view->priv->hadjustment->upper = MAX (tree_view->priv->hadjustment->upper, (gfloat)requisition.width);
       tree_view->priv->vadjustment->upper = MAX (tree_view->priv->vadjustment->upper, (gfloat)requisition.height);
@@ -4885,35 +5087,6 @@ validate_visible_area (GtkTreeView *tree_view)
       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
     }
 
-  /* if we scroll at all, always update dy and kill the top_row */
-  if (tree_view->priv->scroll_to_path &&
-      ! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID))
-    {
-      update_dy = TRUE;
-      if (tree_view->priv->top_row)
-        {
-         gtk_tree_row_reference_free (tree_view->priv->top_row);
-         tree_view->priv->top_row = NULL;
-       }
-    }
-
-  /* if we walk backwards at all, then we need to reset our dy. */
-  if (update_dy)
-    {
-      gint dy;
-      if (node != NULL)
-       {
-         dy = _gtk_rbtree_node_find_offset (tree, node) - area_above;
-       }
-      else
-       {
-         dy = 0;
-       }
-
-      gtk_adjustment_set_value (tree_view->priv->vadjustment, dy);
-      need_redraw = TRUE;
-    }
-
   if (tree_view->priv->scroll_to_path)
     {
       gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
@@ -4959,7 +5132,7 @@ initialize_fixed_height_mode (GtkTreeView *tree_view)
     }
 
    _gtk_rbtree_set_fixed_height (tree_view->priv->tree,
-                                 tree_view->priv->fixed_height);
+                                 tree_view->priv->fixed_height, TRUE);
 }
 
 /* Our strategy for finding nodes to validate is a little convoluted.  We find
@@ -4969,7 +5142,7 @@ initialize_fixed_height_mode (GtkTreeView *tree_view)
  */
 
 static gboolean
-do_validate_rows (GtkTreeView *tree_view)
+do_validate_rows (GtkTreeView *tree_view, gboolean queue_resize)
 {
   GtkRBTree *tree = NULL;
   GtkRBNode *node = NULL;
@@ -5077,7 +5250,7 @@ do_validate_rows (GtkTreeView *tree_view)
   if (!tree_view->priv->fixed_height_check)
    {
      if (fixed_height)
-       _gtk_rbtree_set_fixed_height (tree_view->priv->tree, prev_height);
+       _gtk_rbtree_set_fixed_height (tree_view->priv->tree, prev_height, FALSE);
 
      tree_view->priv->fixed_height_check = 1;
    }
@@ -5089,18 +5262,16 @@ do_validate_rows (GtkTreeView *tree_view)
       /* We temporarily guess a size, under the assumption that it will be the
        * same when we get our next size_allocate.  If we don't do this, we'll be
        * in an inconsistent state when we call top_row_to_dy. */
+
       gtk_widget_size_request (GTK_WIDGET (tree_view), &requisition);
       tree_view->priv->hadjustment->upper = MAX (tree_view->priv->hadjustment->upper, (gfloat)requisition.width);
       tree_view->priv->vadjustment->upper = MAX (tree_view->priv->vadjustment->upper, (gfloat)requisition.height);
       gtk_adjustment_changed (tree_view->priv->hadjustment);
       gtk_adjustment_changed (tree_view->priv->vadjustment);
-      gtk_widget_queue_resize (GTK_WIDGET (tree_view));
-    }
 
-  if (gtk_tree_row_reference_valid (tree_view->priv->top_row))
-    gtk_tree_view_top_row_to_dy (tree_view);
-  else
-    gtk_tree_view_dy_to_top_row (tree_view);
+      if (queue_resize)
+        gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+    }
 
   if (path) gtk_tree_path_free (path);
 
@@ -5112,7 +5283,7 @@ validate_rows (GtkTreeView *tree_view)
 {
   gboolean retval;
   
-  retval = do_validate_rows (tree_view);
+  retval = do_validate_rows (tree_view, TRUE);
   
   if (! retval && tree_view->priv->validate_rows_timer)
     {
@@ -5130,7 +5301,7 @@ validate_rows_handler (GtkTreeView *tree_view)
 
   GDK_THREADS_ENTER ();
 
-  retval = do_validate_rows (tree_view);
+  retval = do_validate_rows (tree_view, TRUE);
   if (! retval && tree_view->priv->validate_rows_timer)
     {
       g_source_remove (tree_view->priv->validate_rows_timer);
@@ -5153,6 +5324,19 @@ do_presize_handler (GtkTreeView *tree_view)
     }
   validate_visible_area (tree_view);
   tree_view->priv->presize_handler_timer = 0;
+
+  if (tree_view->priv->fixed_height_mode)
+    {
+      GtkRequisition requisition;
+
+      gtk_widget_size_request (GTK_WIDGET (tree_view), &requisition);
+
+      tree_view->priv->hadjustment->upper = MAX (tree_view->priv->hadjustment->upper, (gfloat)requisition.width);
+      tree_view->priv->vadjustment->upper = MAX (tree_view->priv->vadjustment->upper, (gfloat)requisition.height);
+      gtk_adjustment_changed (tree_view->priv->hadjustment);
+      gtk_adjustment_changed (tree_view->priv->vadjustment);
+      gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+    }
                   
   return FALSE;
 }
@@ -5193,7 +5377,9 @@ scroll_sync_handler (GtkTreeView *tree_view)
 
   GDK_THREADS_ENTER ();
 
-  if (gtk_tree_row_reference_valid (tree_view->priv->top_row))
+  if (tree_view->priv->height <= tree_view->priv->vadjustment->page_size)
+    gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment), 0);
+  else if (gtk_tree_row_reference_valid (tree_view->priv->top_row))
     gtk_tree_view_top_row_to_dy (tree_view);
   else
     gtk_tree_view_dy_to_top_row (tree_view);
@@ -5331,7 +5517,7 @@ set_source_row (GdkDragContext *context,
                 GtkTreePath    *source_row)
 {
   g_object_set_data_full (G_OBJECT (context),
-                          "gtk-tree-view-source-row",
+                          I_("gtk-tree-view-source-row"),
                           source_row ? gtk_tree_row_reference_new (model, source_row) : NULL,
                           (GDestroyNotify) (source_row ? gtk_tree_row_reference_free : NULL));
 }
@@ -5379,7 +5565,7 @@ set_dest_row (GdkDragContext *context,
 
   if (!dest_row)
     {
-      g_object_set_data_full (G_OBJECT (context), "gtk-tree-view-dest-row",
+      g_object_set_data_full (G_OBJECT (context), I_("gtk-tree-view-dest-row"),
                               NULL, NULL);
       return;
     }
@@ -5391,7 +5577,7 @@ set_dest_row (GdkDragContext *context,
   dr->empty_view_drop = empty_view_drop;
   dr->drop_append_mode = drop_append_mode;
 
-  g_object_set_data_full (G_OBJECT (context), "gtk-tree-view-dest-row",
+  g_object_set_data_full (G_OBJECT (context), I_("gtk-tree-view-dest-row"),
                           dr, (GDestroyNotify) dest_row_free);
 }
 
@@ -5434,7 +5620,7 @@ set_status_pending (GdkDragContext *context,
                     GdkDragAction   suggested_action)
 {
   g_object_set_data (G_OBJECT (context),
-                     "gtk-tree-view-status-pending",
+                     I_("gtk-tree-view-status-pending"),
                      GINT_TO_POINTER (suggested_action));
 }
 
@@ -5489,7 +5675,7 @@ ensure_info (GtkTreeView *tree_view)
       di = g_new0 (TreeViewDragInfo, 1);
 
       g_object_set_data_full (G_OBJECT (tree_view),
-                              "gtk-tree-view-drag-info",
+                              I_("gtk-tree-view-drag-info"),
                               di,
                               (GDestroyNotify) destroy_info);
     }
@@ -5500,7 +5686,7 @@ ensure_info (GtkTreeView *tree_view)
 static void
 remove_info (GtkTreeView *tree_view)
 {
-  g_object_set_data (G_OBJECT (tree_view), "gtk-tree-view-drag-info", NULL);
+  g_object_set_data (G_OBJECT (tree_view), I_("gtk-tree-view-drag-info"), NULL);
 }
 
 #if 0
@@ -5884,9 +6070,8 @@ gtk_tree_view_maybe_begin_dragging_row (GtkTreeView      *tree_view,
                                           path))
     goto out;
 
-  /* FIXME Check whether we're a start button, if not return FALSE and
-   * free path
-   */
+  if (!(GDK_BUTTON1_MASK << (button - 1) & di->start_button_mask))
+    goto out;
 
   /* Now we can begin the drag */
 
@@ -5997,7 +6182,7 @@ gtk_tree_view_drag_data_get (GtkWidget        *widget,
     goto done;
 
   /* If drag_data_get does nothing, try providing row data. */
-  if (selection_data->target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
+  if (selection_data->target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
     {
       gtk_tree_set_row_drag_data (selection_data,
                                  model,
@@ -6047,10 +6232,6 @@ gtk_tree_view_drag_leave (GtkWidget      *widget,
                           GdkDragContext *context,
                           guint             time)
 {
-  TreeViewDragInfo *di;
-
-  di = get_info (GTK_TREE_VIEW (widget));
-
   /* unset any highlight row */
   gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
                                    NULL,
@@ -6070,7 +6251,6 @@ gtk_tree_view_drag_motion (GtkWidget        *widget,
 {
   gboolean empty;
   GtkTreePath *path = NULL;
-  GtkTreeModel *model;
   GtkTreeViewDropPosition pos;
   GtkTreeView *tree_view;
   GdkDragAction suggested_action = 0;
@@ -6084,7 +6264,6 @@ gtk_tree_view_drag_motion (GtkWidget        *widget,
   gtk_tree_view_get_drag_dest_row (tree_view, &path, &pos);
 
   /* we only know this *after* set_desination_row */
-  model = gtk_tree_view_get_model (tree_view);
   empty = tree_view->priv->empty_view_drop;
 
   if (path == NULL && !empty)
@@ -6107,7 +6286,7 @@ gtk_tree_view_drag_motion (GtkWidget        *widget,
            g_timeout_add (150, scroll_row_timeout, tree_view);
        }
 
-      if (target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
+      if (target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
         {
           /* Request data so we can use the source row when
            * determining whether to accept the drop
@@ -6433,7 +6612,7 @@ column_sizing_notify (GObject    *object,
 
   if (gtk_tree_view_column_get_sizing (c) != GTK_TREE_VIEW_COLUMN_FIXED)
     /* disable fixed height mode */
-    g_object_set (data, "fixed_height_mode", FALSE, NULL);
+    g_object_set (data, "fixed-height-mode", FALSE, NULL);
 }
 
 /**
@@ -6517,7 +6696,6 @@ gtk_tree_view_header_focus (GtkTreeView      *tree_view,
                            GtkDirectionType  dir)
 {
   GtkWidget *focus_child;
-  GtkContainer *container;
 
   GList *last_column, *first_column;
   GList *tmp_list;
@@ -6527,7 +6705,6 @@ gtk_tree_view_header_focus (GtkTreeView      *tree_view,
     return FALSE;
 
   focus_child = GTK_CONTAINER (tree_view)->focus_child;
-  container = GTK_CONTAINER (tree_view);
 
   first_column = tree_view->priv->columns;
   while (first_column)
@@ -6768,7 +6945,7 @@ gtk_tree_view_style_set (GtkWidget *widget,
     }
 
   gtk_widget_style_get (widget,
-                       "expander_size", &tree_view->priv->expander_size,
+                       "expander-size", &tree_view->priv->expander_size,
                        NULL);
   tree_view->priv->expander_size += EXPANDER_EXTRA_PADDING;
 
@@ -6841,8 +7018,7 @@ gtk_tree_view_set_adjustments (GtkTreeView   *tree_view,
   if (tree_view->priv->hadjustment != hadj)
     {
       tree_view->priv->hadjustment = hadj;
-      g_object_ref (tree_view->priv->hadjustment);
-      gtk_object_sink (GTK_OBJECT (tree_view->priv->hadjustment));
+      g_object_ref_sink (tree_view->priv->hadjustment);
 
       g_signal_connect (tree_view->priv->hadjustment, "value_changed",
                        G_CALLBACK (gtk_tree_view_adjustment_changed),
@@ -6853,8 +7029,7 @@ gtk_tree_view_set_adjustments (GtkTreeView   *tree_view,
   if (tree_view->priv->vadjustment != vadj)
     {
       tree_view->priv->vadjustment = vadj;
-      g_object_ref (tree_view->priv->vadjustment);
-      gtk_object_sink (GTK_OBJECT (tree_view->priv->vadjustment));
+      g_object_ref_sink (tree_view->priv->vadjustment);
 
       g_signal_connect (tree_view->priv->vadjustment, "value_changed",
                        G_CALLBACK (gtk_tree_view_adjustment_changed),
@@ -7005,6 +7180,7 @@ gtk_tree_view_row_changed (GtkTreeModel *model,
   gboolean free_path = FALSE;
   gint vertical_separator;
   GList *list;
+  GtkTreePath *cursor_path;
 
   g_return_if_fail (path != NULL || iter != NULL);
 
@@ -7013,10 +7189,19 @@ gtk_tree_view_row_changed (GtkTreeModel *model,
      */
     return;
 
-  if (tree_view->priv->edited_column)
+  if (tree_view->priv->cursor != NULL)
+    cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
+  else
+    cursor_path = NULL;
+
+  if (tree_view->priv->edited_column &&
+      (cursor_path == NULL || gtk_tree_path_compare (cursor_path, path) == 0))
     gtk_tree_view_stop_editing (tree_view, TRUE);
 
-  gtk_widget_style_get (GTK_WIDGET (data), "vertical_separator", &vertical_separator, NULL);
+  if (cursor_path != NULL)
+    gtk_tree_path_free (cursor_path);
+
+  gtk_widget_style_get (GTK_WIDGET (data), "vertical-separator", &vertical_separator, NULL);
 
   if (path == NULL)
     {
@@ -7158,11 +7343,15 @@ gtk_tree_view_row_inserted (GtkTreeModel *model,
     {
       tmpnode = _gtk_rbtree_find_count (tree, indices[depth - 1]);
       _gtk_rbtree_insert_after (tree, tmpnode, height, FALSE);
-    } 
+    }
 
  done:
   if (height > 0)
-    gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+    {
+      if (tree)
+        _gtk_rbtree_node_mark_valid (tree, tmpnode);
+      gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+    }
   else
     install_presize_handler (tree_view);
   if (free_path)
@@ -7505,7 +7694,7 @@ gtk_tree_view_get_arrow_xrange (GtkTreeView *tree_view,
     }
 
   gtk_widget_style_get (GTK_WIDGET (tree_view),
-                       "indent_expanders", &indent_expanders,
+                       "indent-expanders", &indent_expanders,
                        NULL);
 
   if (indent_expanders)
@@ -7549,6 +7738,15 @@ gtk_tree_view_build_tree (GtkTreeView *tree_view,
       gtk_tree_model_ref_node (tree_view->priv->model, iter);
       temp = _gtk_rbtree_insert_after (tree, temp, 0, FALSE);
 
+      if (tree_view->priv->fixed_height > 0)
+        {
+          if (GTK_RBNODE_FLAG_SET (temp, GTK_RBNODE_INVALID))
+           {
+              _gtk_rbtree_node_set_height (tree, temp, tree_view->priv->fixed_height);
+             _gtk_rbtree_node_mark_valid (tree, temp);
+           }
+        }
+
       if (is_list)
         continue;
 
@@ -7590,7 +7788,7 @@ gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view,
   gint horizontal_separator;
 
   gtk_widget_style_get (GTK_WIDGET (tree_view),
-                       "horizontal_separator", &horizontal_separator,
+                       "horizontal-separator", &horizontal_separator,
                        NULL);
 
   if (height)
@@ -7701,13 +7899,22 @@ gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view,
                                  GtkRBTree   *tree,
                                  GtkRBNode   *node)
 {
+  gint node_dy, height;
   GtkTreePath *path = NULL;
 
   if (!GTK_WIDGET_REALIZED (tree_view))
     return;
 
-  path = _gtk_tree_view_find_path (tree_view, tree, node);
+  /* just return if the node is visible, avoiding a costly expose */
+  node_dy = _gtk_rbtree_node_find_offset (tree, node);
+  height = ROW_HEIGHT (tree_view, GTK_RBNODE_GET_HEIGHT (node));
+  if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID)
+      && node_dy >= tree_view->priv->vadjustment->value
+      && node_dy + height <= (tree_view->priv->vadjustment->value
+                              + tree_view->priv->vadjustment->page_size))
+    return;
 
+  path = _gtk_tree_view_find_path (tree_view, tree, node);
   if (path)
     {
       /* We process updates because we want to clear old selected items when we scroll.
@@ -7997,7 +8204,7 @@ gtk_tree_view_set_column_drag_info (GtkTreeView       *tree_view,
   /* Add the last one */
   if (tree_view->priv->column_drop_func == NULL ||
       ((left_column != column) &&
-       (* tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data)))
+       (* tree_view->priv->column_drop_func) (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data)))
     {
       reorder = g_new (GtkTreeViewColumnReorder, 1);
       reorder->left_column = left_column;
@@ -8091,7 +8298,7 @@ _gtk_tree_view_column_start_drag (GtkTreeView       *tree_view,
 
   send_event = gdk_event_new (GDK_LEAVE_NOTIFY);
   send_event->crossing.send_event = TRUE;
-  send_event->crossing.window = g_object_ref (column->button->window);
+  send_event->crossing.window = g_object_ref (GTK_BUTTON (column->button)->event_window);
   send_event->crossing.subwindow = NULL;
   send_event->crossing.detail = GDK_NOTIFY_ANCESTOR;
   send_event->crossing.time = GDK_CURRENT_TIME;
@@ -8248,7 +8455,7 @@ gtk_tree_view_draw_arrow (GtkTreeView *tree_view,
   GtkExpanderStyle expander_style;
 
   gtk_widget_style_get (GTK_WIDGET (tree_view),
-                       "vertical_separator", &vertical_separator,
+                       "vertical-separator", &vertical_separator,
                        NULL);
   expander_size = tree_view->priv->expander_size - EXPANDER_EXTRA_PADDING;
 
@@ -8264,7 +8471,11 @@ gtk_tree_view_draw_arrow (GtkTreeView *tree_view,
   area.width = expander_size + 2;
   area.height = MAX (CELL_HEIGHT (node, vertical_separator), (expander_size - vertical_separator));
 
-  if (node == tree_view->priv->button_pressed_node)
+  if (GTK_WIDGET_STATE (tree_view) == GTK_STATE_INSENSITIVE)
+    {
+      state = GTK_STATE_INSENSITIVE;
+    }
+  else if (node == tree_view->priv->button_pressed_node)
     {
       if (x >= area.x && x <= (area.x + area.width) &&
          y >= area.y && y <= (area.y + area.height))
@@ -8319,7 +8530,22 @@ gtk_tree_view_focus_to_cursor (GtkTreeView *tree_view)
 
   if (cursor_path == NULL)
     {
-      cursor_path = gtk_tree_path_new_first ();
+      /* Consult the selection before defaulting to the first element */
+      GtkTreeSelection *selection;
+      GtkTreeModel     *model;
+      GList            *selected_rows;
+
+      selection = gtk_tree_view_get_selection (tree_view);
+      selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
+      if (selected_rows)
+       {
+          cursor_path = gtk_tree_path_copy((const GtkTreePath *)(selected_rows->data));
+         g_list_foreach (selected_rows, (GFunc)gtk_tree_path_free, NULL);
+         g_list_free (selected_rows);
+        }
+      else
+       cursor_path = gtk_tree_path_new_first ();
+
       gtk_tree_row_reference_free (tree_view->priv->cursor);
       tree_view->priv->cursor = NULL;
 
@@ -8425,6 +8651,7 @@ gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
   GtkRBNode *cursor_node = NULL;
   GtkTreePath *cursor_path = NULL;
   gint y;
+  gint window_y;
   gint vertical_separator;
 
   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
@@ -8436,7 +8663,7 @@ gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
     /* This is sorta weird.  Focus in should give us a cursor */
     return;
 
-  gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical_separator", &vertical_separator, NULL);
+  gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical-separator", &vertical_separator, NULL);
   _gtk_tree_view_find_node (tree_view, cursor_path,
                            &cursor_tree, &cursor_node);
 
@@ -8448,22 +8675,21 @@ gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
   g_return_if_fail (cursor_node != NULL);
 
   y = _gtk_rbtree_node_find_offset (cursor_tree, cursor_node);
-  y += count * tree_view->priv->vadjustment->page_size;
-  if (count > 0)
-    y -= ROW_HEIGHT (tree_view, GTK_RBNODE_GET_HEIGHT (cursor_node));
-  else if (count < 0)
-    y += ROW_HEIGHT (tree_view, GTK_RBNODE_GET_HEIGHT (cursor_node));
+  window_y = RBTREE_Y_TO_TREE_WINDOW_Y (tree_view, y);
+  y += count * (int)tree_view->priv->vadjustment->page_increment;
   y = CLAMP (y, (gint)tree_view->priv->vadjustment->lower,  (gint)tree_view->priv->vadjustment->upper - vertical_separator);
 
   if (y >= tree_view->priv->height)
     y = tree_view->priv->height - 1;
 
-  _gtk_rbtree_find_offset (tree_view->priv->tree, y, &cursor_tree, &cursor_node);
+  y -= _gtk_rbtree_find_offset (tree_view->priv->tree, y, &cursor_tree, &cursor_node);
   cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
   g_return_if_fail (cursor_path != NULL);
-  gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, TRUE);
-  gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
+  gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, FALSE);
   gtk_tree_path_free (cursor_path);
+
+  y -= window_y;
+  gtk_tree_view_scroll_to_point (tree_view, -1, y);
 }
 
 static void
@@ -8768,6 +8994,7 @@ gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
   GtkRBTree *cursor_tree = NULL;
   GtkRBNode *cursor_node = NULL;
   GtkTreePath *cursor_path = NULL;
+  GdkModifierType state;
 
   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
     return FALSE;
@@ -8787,6 +9014,12 @@ gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
       return FALSE;
     }
 
+  if (gtk_get_current_event_state (&state))
+    {
+      if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
+        tree_view->priv->ctrl_pressed = TRUE;
+    }
+
   if (cursor_tree->parent_node)
     {
       gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
@@ -8794,14 +9027,8 @@ gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
       cursor_tree = cursor_tree->parent_tree;
 
       gtk_tree_path_up (cursor_path);
-      gtk_tree_row_reference_free (tree_view->priv->cursor);
-      tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, cursor_path);
-      _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
-                                               cursor_node,
-                                               cursor_tree,
-                                               cursor_path,
-                                                0,
-                                               FALSE);
+
+      gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, FALSE);
     }
 
   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
@@ -8810,6 +9037,8 @@ gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
   gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
   gtk_tree_path_free (cursor_path);
 
+  tree_view->priv->ctrl_pressed = FALSE;
+
   return TRUE;
 }
 static gboolean
@@ -8822,7 +9051,7 @@ gtk_tree_view_search_entry_flush_timeout (GtkTreeView *tree_view)
 
   GDK_THREADS_LEAVE ();
 
-  return TRUE;
+  return FALSE;
 }
 
 /* Cut and paste from gtkwindow.c */
@@ -8845,7 +9074,7 @@ send_focus_change (GtkWidget *widget,
   
   gtk_widget_event (widget, fevent);
   
-  g_object_notify (G_OBJECT (widget), "has_focus");
+  g_object_notify (G_OBJECT (widget), "has-focus");
 
   g_object_unref (widget);
   gdk_event_free (fevent);
@@ -8854,13 +9083,27 @@ send_focus_change (GtkWidget *widget,
 static void
 gtk_tree_view_ensure_interactive_directory (GtkTreeView *tree_view)
 {
-  GtkWidget *frame, *vbox;
+  GtkWidget *frame, *vbox, *toplevel;
 
-  if (tree_view->priv->search_window != NULL)
-    return;
+  toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tree_view));
 
+   if (tree_view->priv->search_window != NULL)
+     {
+       if (GTK_WINDOW (toplevel)->group)
+        gtk_window_group_add_window (GTK_WINDOW (toplevel)->group,
+                                     GTK_WINDOW (tree_view->priv->search_window));
+       else if (GTK_WINDOW (tree_view->priv->search_window)->group)
+        gtk_window_group_remove_window (GTK_WINDOW (tree_view->priv->search_window)->group,
+                                        GTK_WINDOW (tree_view->priv->search_window));
+       return;
+     }
+   
   tree_view->priv->search_window = gtk_window_new (GTK_WINDOW_POPUP);
 
+  if (GTK_WINDOW (toplevel)->group)
+    gtk_window_group_add_window (GTK_WINDOW (toplevel)->group,
+                                GTK_WINDOW (tree_view->priv->search_window));
+
   gtk_window_set_modal (GTK_WINDOW (tree_view->priv->search_window), TRUE);
   g_signal_connect (tree_view->priv->search_window, "delete_event",
                    G_CALLBACK (gtk_tree_view_search_delete_event),
@@ -8871,6 +9114,9 @@ gtk_tree_view_ensure_interactive_directory (GtkTreeView *tree_view)
   g_signal_connect (tree_view->priv->search_window, "button_press_event",
                    G_CALLBACK (gtk_tree_view_search_button_press_event),
                    tree_view);
+  g_signal_connect (tree_view->priv->search_window, "scroll_event",
+                   G_CALLBACK (gtk_tree_view_search_scroll_event),
+                   tree_view);
 
   frame = gtk_frame_new (NULL);
   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
@@ -8916,7 +9162,11 @@ gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view,
   gboolean found_focus = FALSE;
   GtkWidgetClass *entry_parent_class;
   
-  if (GTK_WIDGET_VISIBLE (tree_view->priv->search_window))
+  if (!tree_view->priv->enable_search && !keybinding)
+    return FALSE;
+
+  if (tree_view->priv->search_window != NULL &&
+      GTK_WIDGET_VISIBLE (tree_view->priv->search_window))
     return TRUE;
 
   for (list = tree_view->priv->columns; list; list = list->next)
@@ -8937,19 +9187,16 @@ gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view,
   if (GTK_WIDGET_HAS_FOCUS (tree_view))
     found_focus = TRUE;
 
-  if (! found_focus)
+  if (!found_focus)
     return FALSE;
 
-  if (tree_view->priv->enable_search == FALSE ||
-      tree_view->priv->search_column < 0)
+  if (tree_view->priv->search_column < 0)
     return FALSE;
 
   gtk_tree_view_ensure_interactive_directory (tree_view);
 
   if (keybinding)
-    {
-      gtk_entry_set_text (GTK_ENTRY (tree_view->priv->search_entry), "");
-    }
+    gtk_entry_set_text (GTK_ENTRY (tree_view->priv->search_entry), "");
 
   /* done, show it */
   tree_view->priv->search_dialog_position_func (tree_view, tree_view->priv->search_window);
@@ -8961,13 +9208,11 @@ gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view,
                          G_CALLBACK (gtk_tree_view_search_init),
                          tree_view);
     }
-  if (! keybinding)
-    {
-      tree_view->priv->typeselect_flush_timeout =
-       g_timeout_add (GTK_TREE_VIEW_SEARCH_DIALOG_TIMEOUT,
-                      (GSourceFunc) gtk_tree_view_search_entry_flush_timeout,
-                      tree_view);
-    }
+
+  tree_view->priv->typeselect_flush_timeout =
+    g_timeout_add (GTK_TREE_VIEW_SEARCH_DIALOG_TIMEOUT,
+                  (GSourceFunc) gtk_tree_view_search_entry_flush_timeout,
+                  tree_view);
 
   /* Grab focus will select all the text.  We don't want that to happen, so we
    * call the parent instance and bypass the selection change.  This is probably
@@ -8987,7 +9232,7 @@ gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view,
 static gboolean
 gtk_tree_view_start_interactive_search (GtkTreeView *tree_view)
 {
-  return gtk_tree_view_real_start_interactive_search (tree_view, FALSE);
+  return gtk_tree_view_real_start_interactive_search (tree_view, TRUE);
 }
 /* this function returns the new width of the column being resized given
  * the column and x position of the cursor; the x cursor position is passed
@@ -9017,7 +9262,7 @@ gtk_tree_view_new_column_width (GtkTreeView *tree_view,
     width = MAX (column->min_width,
                 width);
   if (column->max_width != -1)
-    width = MIN (width, column->max_width != -1);
+    width = MIN (width, column->max_width);
 
   *x = rtl ? (column->button->allocation.x + column->button->allocation.width - width) : (column->button->allocation.x + width);
  
@@ -9181,7 +9426,7 @@ gtk_tree_view_new_with_model (GtkTreeModel *model)
  * gtk_tree_view_get_model:
  * @tree_view: a #GtkTreeView
  *
- * Returns the model the the #GtkTreeView is based on.  Returns %NULL if the
+ * Returns the model the #GtkTreeView is based on.  Returns %NULL if the
  * model is unset.
  *
  * Return value: A #GtkTreeModel, or %NULL if none is currently being used.
@@ -9215,6 +9460,12 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
   if (model == tree_view->priv->model)
     return;
 
+  if (tree_view->priv->scroll_to_path)
+    {
+      gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
+      tree_view->priv->scroll_to_path = NULL;
+    }
+
   if (tree_view->priv->model)
     {
       GList *tmplist = tree_view->priv->columns;
@@ -9243,15 +9494,7 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
                                           tree_view->priv->model);
 
       if (tree_view->priv->tree)
-       {
-         _gtk_rbtree_free (tree_view->priv->tree);
-         tree_view->priv->tree = NULL;
-       }
-
-      tree_view->priv->prelight_node = NULL;
-      tree_view->priv->prelight_tree = NULL;
-      tree_view->priv->button_pressed_node = NULL;
-      tree_view->priv->button_pressed_tree = NULL;
+       gtk_tree_view_free_rbtree (tree_view);
 
       gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
       tree_view->priv->drag_dest_row = NULL;
@@ -9280,7 +9523,6 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
 
   tree_view->priv->model = model;
 
-
   if (tree_view->priv->model)
     {
       gint i;
@@ -9344,6 +9586,9 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
 
   g_object_notify (G_OBJECT (tree_view), "model");
 
+  if (tree_view->priv->selection)
+  _gtk_tree_selection_emit_changed (tree_view->priv->selection);
+
   if (GTK_WIDGET_REALIZED (tree_view))
     gtk_widget_queue_resize (GTK_WIDGET (tree_view));
 }
@@ -9467,7 +9712,7 @@ gtk_tree_view_get_headers_visible (GtkTreeView *tree_view)
  * @tree_view: A #GtkTreeView.
  * @headers_visible: %TRUE if the headers are visible
  *
- * Sets the the visibility state of the headers.
+ * Sets the visibility state of the headers.
  **/
 void
 gtk_tree_view_set_headers_visible (GtkTreeView *tree_view,
@@ -9520,7 +9765,7 @@ gtk_tree_view_set_headers_visible (GtkTreeView *tree_view,
 
   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
 
-  g_object_notify (G_OBJECT (tree_view), "headers_visible");
+  g_object_notify (G_OBJECT (tree_view), "headers-visible");
 }
 
 /**
@@ -9566,15 +9811,36 @@ gtk_tree_view_set_headers_clickable (GtkTreeView *tree_view,
   GList *list;
 
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
-  g_return_if_fail (tree_view->priv->model != NULL);
 
   for (list = tree_view->priv->columns; list; list = list->next)
     gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (list->data), setting);
 
-  g_object_notify (G_OBJECT (tree_view), "headers_clickable");
+  g_object_notify (G_OBJECT (tree_view), "headers-clickable");
 }
 
 
+/**
+ * gtk_tree_view_get_headers_clickable:
+ * @tree_view: A #GtkTreeView.
+ *
+ * Return value: %TRUE if all header columns are clickable, otherwise %FALSE
+ *
+ * Since: 2.10
+ **/
+gboolean 
+gtk_tree_view_get_headers_clickable (GtkTreeView *tree_view)
+{
+  GList *list;
+  
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
+
+  for (list = tree_view->priv->columns; list; list = list->next)
+    if (!GTK_TREE_VIEW_COLUMN (list->data)->clickable)
+      return FALSE;
+
+  return TRUE;
+}
+
 /**
  * gtk_tree_view_set_rules_hint
  * @tree_view: a #GtkTreeView
@@ -9608,7 +9874,7 @@ gtk_tree_view_set_rules_hint (GtkTreeView  *tree_view,
       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
     }
 
-  g_object_notify (G_OBJECT (tree_view), "rules_hint");
+  g_object_notify (G_OBJECT (tree_view), "rules-hint");
 }
 
 /**
@@ -9636,7 +9902,7 @@ gtk_tree_view_get_rules_hint (GtkTreeView  *tree_view)
  * @column: The #GtkTreeViewColumn to add.
  *
  * Appends @column to the list of columns. If @tree_view has "fixed_height"
- * mode enbabled, then @column must have its "sizing" property set to be
+ * mode enabled, then @column must have its "sizing" property set to be
  * GTK_TREE_VIEW_COLUMN_FIXED.
  *
  * Return value: The number of columns in @tree_view after appending.
@@ -9743,8 +10009,7 @@ gtk_tree_view_insert_column (GtkTreeView       *tree_view,
     g_return_val_if_fail (gtk_tree_view_column_get_sizing (column)
                           == GTK_TREE_VIEW_COLUMN_FIXED, -1);
 
-  g_object_ref (column);
-  gtk_object_sink (GTK_OBJECT (column));
+  g_object_ref_sink (column);
 
   if (tree_view->priv->n_columns == 0 &&
       GTK_WIDGET_REALIZED (tree_view) &&
@@ -9982,9 +10247,12 @@ gtk_tree_view_move_column_after (GtkTreeView       *tree_view,
  * @tree_view: A #GtkTreeView
  * @column: %NULL, or the column to draw the expander arrow at.
  *
- * Sets the column to draw the expander arrow at. It must be in @tree_view.  If
- * @column is %NULL, then the expander arrow is always at the first visible
- * column.
+ * Sets the column to draw the expander arrow at. It must be in @tree_view.  
+ * If @column is %NULL, then the expander arrow is always at the first 
+ * visible column.
+ *
+ * If you do not want expander arrow to appear in your tree, set the 
+ * expander column to a hidden column.
  **/
 void
 gtk_tree_view_set_expander_column (GtkTreeView       *tree_view,
@@ -10008,7 +10276,7 @@ gtk_tree_view_set_expander_column (GtkTreeView       *tree_view,
        }
 
       tree_view->priv->expander_column = column;
-      g_object_notify (G_OBJECT (tree_view), "expander_column");
+      g_object_notify (G_OBJECT (tree_view), "expander-column");
     }
 }
 
@@ -10155,7 +10423,9 @@ gtk_tree_view_scroll_to_cell (GtkTreeView       *tree_view,
    * scrolling code, we short-circuit validate_visible_area's immplementation as
    * it is much slower than just going to the point.
    */
-  if (! GTK_WIDGET_REALIZED (tree_view) ||
+  if (! GTK_WIDGET_VISIBLE (tree_view) ||
+      ! GTK_WIDGET_REALIZED (tree_view) ||
+      GTK_WIDGET_ALLOC_NEEDED (tree_view) || 
       GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID))
     {
       if (tree_view->priv->scroll_to_path)
@@ -10269,48 +10539,6 @@ gtk_tree_view_expand_all_emission_helper (GtkRBTree *tree,
                           gtk_tree_view_expand_all_emission_helper,
                           tree_view);
 }
-
-static void
-gtk_tree_view_expand_all_helper (GtkRBTree  *tree,
-                                GtkRBNode  *node,
-                                gpointer  data)
-{
-  GtkTreeView *tree_view = data;
-
-  if (node->children)
-    _gtk_rbtree_traverse (node->children,
-                         node->children->root,
-                         G_PRE_ORDER,
-                         gtk_tree_view_expand_all_helper,
-                         data);
-  else if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT && node->children == NULL)
-    {
-      GtkTreePath *path;
-      GtkTreeIter iter;
-      GtkTreeIter child;
-
-      node->children = _gtk_rbtree_new ();
-      node->children->parent_tree = tree;
-      node->children->parent_node = node;
-      path = _gtk_tree_view_find_path (tree_view, tree, node);
-      gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
-      gtk_tree_model_iter_children (tree_view->priv->model, &child, &iter);
-      gtk_tree_view_build_tree (tree_view,
-                               node->children,
-                               &child,
-                               gtk_tree_path_get_depth (path) + 1,
-                               TRUE);
-
-      g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
-      _gtk_rbtree_traverse (node->children,
-                            node->children->root,
-                            G_PRE_ORDER,
-                            gtk_tree_view_expand_all_emission_helper,
-                            tree_view);
-      gtk_tree_path_free (path);
-    }
-}
-
 /**
  * gtk_tree_view_expand_all:
  * @tree_view: A #GtkTreeView.
@@ -10320,16 +10548,26 @@ gtk_tree_view_expand_all_helper (GtkRBTree  *tree,
 void
 gtk_tree_view_expand_all (GtkTreeView *tree_view)
 {
+  GtkTreePath *path;
+  GtkRBTree *tree;
+  GtkRBNode *node;
+
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
 
   if (tree_view->priv->tree == NULL)
     return;
 
-  _gtk_rbtree_traverse (tree_view->priv->tree,
-                       tree_view->priv->tree->root,
-                       G_PRE_ORDER,
-                       gtk_tree_view_expand_all_helper,
-                       tree_view);
+  path = gtk_tree_path_new_first ();
+  _gtk_tree_view_find_node (tree_view, path, &tree, &node);
+
+  while (node)
+    {
+      gtk_tree_view_real_expand_row (tree_view, path, tree, node, TRUE, FALSE);
+      node = _gtk_rbtree_next (tree, node);
+      gtk_tree_path_next (path);
+  }
+
+  gtk_tree_path_free (path);
 }
 
 /* Timeout to animate the expander during expands and collapses */
@@ -10587,6 +10825,14 @@ gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
   install_presize_handler (tree_view);
 
   g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
+  if (open_all)
+    {
+      _gtk_rbtree_traverse (node->children,
+                            node->children->root,
+                            G_PRE_ORDER,
+                            gtk_tree_view_expand_all_emission_helper,
+                            tree_view);
+    }
   return TRUE;
 }
 
@@ -10637,7 +10883,6 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
   gboolean collapse;
   gint x, y;
   GList *list;
-  GdkDisplay *display;
   GdkWindow *child, *parent;
 
   remove_auto_expand_timeout (tree_view);
@@ -10745,6 +10990,14 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
       gtk_tree_path_free (lsc);
     }
 
+  if (tree_view->priv->expanded_collapsed_node != NULL)
+    {
+      GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_EXPANDED);
+      GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_COLLAPSED);
+      
+      tree_view->priv->expanded_collapsed_node = NULL;
+    }
+
   if (gtk_tree_view_unref_and_check_selection_tree (tree_view, node->children))
     {
       _gtk_rbtree_remove (node->children);
@@ -10759,14 +11012,6 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
       tree_view->priv->expand_collapse_timeout = 0;
     }
   
-  if (tree_view->priv->expanded_collapsed_node != NULL)
-    {
-      GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_EXPANDED);
-      GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_COLLAPSED);
-      
-      tree_view->priv->expanded_collapsed_node = NULL;
-    }
-
   if (animate)
     {
       tree_view->priv->expand_collapse_timeout = g_timeout_add (50, expand_collapse_timeout, tree_view);
@@ -10788,7 +11033,6 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
       /* now that we've collapsed all rows, we want to try to set the prelight
        * again. To do this, we fake a motion event and send it to ourselves. */
 
-      display = gdk_drawable_get_display (tree_view->priv->bin_window);
       child = tree_view->priv->bin_window;
       parent = gdk_window_get_parent (child);
 
@@ -11267,8 +11511,12 @@ gtk_tree_view_get_path_at_pos (GtkTreeView        *tree_view,
       GList *list;
       gint remaining_x = x;
       gboolean found = FALSE;
+      gboolean rtl;
 
-      for (list = tree_view->priv->columns; list; list = list->next)
+      rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
+      for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
+          list;
+          list = (rtl ? list->prev : list->next))
        {
          tmp_column = list->data;
 
@@ -11363,8 +11611,8 @@ gtk_tree_view_get_cell_area (GtkTreeView        *tree_view,
   g_return_if_fail (GTK_WIDGET_REALIZED (tree_view));
 
   gtk_widget_style_get (GTK_WIDGET (tree_view),
-                       "vertical_separator", &vertical_separator,
-                       "horizontal_separator", &horizontal_separator,
+                       "vertical-separator", &vertical_separator,
+                       "horizontal-separator", &horizontal_separator,
                        NULL);
 
   rect->x = 0;
@@ -11560,6 +11808,58 @@ gtk_tree_view_tree_to_widget_coords (GtkTreeView *tree_view,
     *wy = ty - tree_view->priv->dy;
 }
 
+/**
+ * gtk_tree_view_get_visible_range:
+ * @tree_view: A #GtkTreeView
+ * @start_path: Return location for start of region, or %NULL.
+ * @end_path: Return location for end of region, or %NULL.
+ *
+ * Sets @start_path and @end_path to be the first and last visible path.
+ * Note that there may be invisible paths in between.
+ *
+ * The paths should be freed with gtk_tree_path_free() after use.
+ *
+ * Returns: %TRUE, if valid paths were placed in @start_path and @end_path.
+ *
+ * Since: 2.8
+ **/
+gboolean
+gtk_tree_view_get_visible_range (GtkTreeView  *tree_view,
+                                 GtkTreePath **start_path,
+                                 GtkTreePath **end_path)
+{
+  GtkRBTree *tree;
+  GtkRBNode *node;
+
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
+
+  if (!tree_view->priv->tree)
+    return FALSE;
+
+  if (start_path)
+    {
+      _gtk_rbtree_find_offset (tree_view->priv->tree,
+                               TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, 0),
+                               &tree, &node);
+      *start_path = _gtk_tree_view_find_path (tree_view, tree, node);
+    }
+
+  if (end_path)
+    {
+      gint y;
+
+      if (tree_view->priv->height < tree_view->priv->vadjustment->page_size)
+        y = tree_view->priv->height - 1;
+      else
+        y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, tree_view->priv->vadjustment->page_size) - 1;
+
+      _gtk_rbtree_find_offset (tree_view->priv->tree, y, &tree, &node);
+      *end_path = _gtk_tree_view_find_path (tree_view, tree, node);
+    }
+
+  return TRUE;
+}
+
 static void
 unset_reorderable (GtkTreeView *tree_view)
 {
@@ -11594,8 +11894,8 @@ gtk_tree_view_enable_model_drag_source (GtkTreeView              *tree_view,
 
   gtk_drag_source_set (GTK_WIDGET (tree_view),
                       0,
-                      NULL,
-                      0,
+                      targets,
+                      n_targets,
                       actions);
 
   di = ensure_info (tree_view);
@@ -11632,8 +11932,8 @@ gtk_tree_view_enable_model_drag_dest (GtkTreeView              *tree_view,
 
   gtk_drag_dest_set (GTK_WIDGET (tree_view),
                      0,
-                     NULL,
-                     0,
+                     targets,
+                     n_targets,
                      actions);
 
   di = ensure_info (tree_view);
@@ -11829,7 +12129,7 @@ gtk_tree_view_get_drag_dest_row (GtkTreeView              *tree_view,
  * 
  * Determines the destination row for a given position.
  * 
- * Return value: whether there is a row at the given postiion,
+ * Return value: whether there is a row at the given position.
  **/
 gboolean
 gtk_tree_view_get_dest_row_at_pos (GtkTreeView             *tree_view,
@@ -11920,8 +12220,8 @@ gtk_tree_view_get_dest_row_at_pos (GtkTreeView             *tree_view,
  * @tree_view: a #GtkTreeView
  * @path: a #GtkTreePath in @tree_view
  *
- * Creates a #GdkPixmap representation of the row at @path.  This image is used
- * for a drag icon.
+ * Creates a #GdkPixmap representation of the row at @path.  
+ * This image is used for a drag icon.
  *
  * Return value: a newly-allocated pixmap of the drag icon.
  **/
@@ -11944,8 +12244,14 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
   gint bin_window_width;
   gboolean is_separator = FALSE;
 
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
+  g_return_val_if_fail (path != NULL, NULL);
+
   widget = GTK_WIDGET (tree_view);
 
+  if (!GTK_WIDGET_REALIZED (tree_view))
+    return NULL;
+
   depth = gtk_tree_path_get_depth (path);
 
   _gtk_tree_view_find_node (tree_view,
@@ -12011,7 +12317,7 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
 
       cell_area = background_area;
 
-      gtk_widget_style_get (widget, "vertical_separator", &vertical_separator, NULL);
+      gtk_widget_style_get (widget, "vertical-separator", &vertical_separator, NULL);
       cell_area.y += vertical_separator / 2;
       cell_area.height -= vertical_separator;
 
@@ -12094,7 +12400,10 @@ gtk_tree_view_set_destroy_count_func (GtkTreeView             *tree_view,
  * @enable_search: %TRUE, if the user can search interactively
  *
  * If @enable_search is set, then the user can type in text to search through
- * the tree interactively.
+ * the tree interactively (this is sometimes called "typeahead find").
+ * 
+ * Note that even if this is %FALSE, the user can still initiate a search 
+ * using the "start-interactive-search" key binding.
  */
 void
 gtk_tree_view_set_enable_search (GtkTreeView *tree_view,
@@ -12107,7 +12416,7 @@ gtk_tree_view_set_enable_search (GtkTreeView *tree_view,
   if (tree_view->priv->enable_search != enable_search)
     {
        tree_view->priv->enable_search = enable_search;
-       g_object_notify (G_OBJECT (tree_view), "enable_search");
+       g_object_notify (G_OBJECT (tree_view), "enable-search");
     }
 }
 
@@ -12115,7 +12424,8 @@ gtk_tree_view_set_enable_search (GtkTreeView *tree_view,
  * gtk_tree_view_get_enable_search:
  * @tree_view: A #GtkTreeView
  *
- * Returns whether or not the tree allows interactive searching.
+ * Returns whether or not the tree allows to start interactive searching 
+ * by typing in text.
  *
  * Return value: whether or not to let the user search interactively
  */
@@ -12139,7 +12449,7 @@ gtk_tree_view_get_enable_search (GtkTreeView *tree_view)
 gint
 gtk_tree_view_get_search_column (GtkTreeView *tree_view)
 {
-  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), 0);
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
 
   return (tree_view->priv->search_column);
 }
@@ -12147,24 +12457,29 @@ gtk_tree_view_get_search_column (GtkTreeView *tree_view)
 /**
  * gtk_tree_view_set_search_column:
  * @tree_view: A #GtkTreeView
- * @column: the column of the model to search in
+ * @column: the column of the model to search in, or -1 to disable searching
  *
  * Sets @column as the column where the interactive search code should
- * search in.  Additionally, turns on interactive searching. Note that
- * @column refers to a column of the model.
+ * search in. 
+ * 
+ * If the sort column is set, users can use the "start-interactive-search"
+ * key binding to bring up search popup. The enable-search property controls
+ * whether simply typing text will also start an interactive search.
+ *
+ * Note that @column refers to a column of the model. 
  */
 void
 gtk_tree_view_set_search_column (GtkTreeView *tree_view,
                                 gint         column)
 {
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
-  g_return_if_fail (column >= 0);
+  g_return_if_fail (column >= -1);
 
   if (tree_view->priv->search_column == column)
     return;
 
   tree_view->priv->search_column = column;
-  g_object_notify (G_OBJECT (tree_view), "search_column");
+  g_object_notify (G_OBJECT (tree_view), "search-column");
 }
 
 /**
@@ -12249,6 +12564,11 @@ gtk_tree_view_search_position_func (GtkTreeView *tree_view,
   GdkWindow *tree_window = GTK_WIDGET (tree_view)->window;
   GdkScreen *screen = gdk_drawable_get_screen (tree_window);
   GtkRequisition requisition;
+  gint monitor_num;
+  GdkRectangle monitor;
+
+  monitor_num = gdk_screen_get_monitor_at_window (screen, tree_window);
+  gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
 
   gtk_widget_realize (search_dialog);
 
@@ -12310,7 +12630,7 @@ static void
 gtk_tree_view_search_activate (GtkEntry    *entry,
                               GtkTreeView *tree_view)
 {
-  GtkTreePath *path = NULL;
+  GtkTreePath *path;
   GtkRBNode *node;
   GtkRBTree *tree;
 
@@ -12320,15 +12640,16 @@ gtk_tree_view_search_activate (GtkEntry    *entry,
   /* If we have a row selected and it's the cursor row, we activate
    * the row XXX */
   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
-    path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
-
-  _gtk_tree_view_find_node (tree_view, path, &tree, &node);
-
-  if (node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
-    gtk_tree_view_row_activated (tree_view, path, tree_view->priv->focus_column);
-
-  if (path)
-    gtk_tree_path_free (path);
+    {
+      path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
+      
+      _gtk_tree_view_find_node (tree_view, path, &tree, &node);
+      
+      if (node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
+       gtk_tree_view_row_activated (tree_view, path, tree_view->priv->focus_column);
+      
+      gtk_tree_path_free (path);
+    }
 }
 
 static gboolean
@@ -12373,9 +12694,33 @@ gtk_tree_view_search_button_press_event (GtkWidget *widget,
 
   gtk_tree_view_search_dialog_hide (widget, tree_view);
 
+  if (event->window == tree_view->priv->bin_window)
+    gtk_tree_view_button_press (GTK_WIDGET (tree_view), event);
+
   return TRUE;
 }
 
+static gboolean
+gtk_tree_view_search_scroll_event (GtkWidget *widget,
+                                  GdkEventScroll *event,
+                                  GtkTreeView *tree_view)
+{
+  gboolean retval = FALSE;
+
+  if (event->direction == GDK_SCROLL_UP)
+    {
+      gtk_tree_view_search_move (widget, tree_view, TRUE);
+      retval = TRUE;
+    }
+  else if (event->direction == GDK_SCROLL_DOWN)
+    {
+      gtk_tree_view_search_move (widget, tree_view, FALSE);
+      retval = TRUE;
+    }
+
+  return retval;
+}
+
 static gboolean
 gtk_tree_view_search_key_press_event (GtkWidget *widget,
                                      GdkEventKey *event,
@@ -12388,7 +12733,9 @@ gtk_tree_view_search_key_press_event (GtkWidget *widget,
 
   /* close window and cancel the search */
   if (event->keyval == GDK_Escape ||
-      event->keyval == GDK_Tab)
+      event->keyval == GDK_Tab ||
+         event->keyval == GDK_KP_Tab ||
+         event->keyval == GDK_ISO_Left_Tab)
     {
       gtk_tree_view_search_dialog_hide (widget, tree_view);
       return TRUE;
@@ -12401,6 +12748,13 @@ gtk_tree_view_search_key_press_event (GtkWidget *widget,
       retval = TRUE;
     }
 
+  if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == (GDK_CONTROL_MASK | GDK_SHIFT_MASK))
+      && (event->keyval == GDK_g || event->keyval == GDK_G))
+    {
+      gtk_tree_view_search_move (widget, tree_view, TRUE);
+      retval = TRUE;
+    }
+
   /* select next matching iter */
   if (event->keyval == GDK_Down || event->keyval == GDK_KP_Down)
     {
@@ -12408,6 +12762,13 @@ gtk_tree_view_search_key_press_event (GtkWidget *widget,
       retval = TRUE;
     }
 
+  if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK)
+      && (event->keyval == GDK_g || event->keyval == GDK_G))
+    {
+      gtk_tree_view_search_move (widget, tree_view, FALSE);
+      retval = TRUE;
+    }
+
   /* renew the flush timeout */
   if (retval && tree_view->priv->typeselect_flush_timeout)
     {
@@ -12451,7 +12812,8 @@ gtk_tree_view_search_move (GtkWidget   *window,
 
   /* search */
   gtk_tree_selection_unselect_all (selection);
-  gtk_tree_model_get_iter_first (model, &iter);
+  if (!gtk_tree_model_get_iter_first (model, &iter))
+    return;
 
   ret = gtk_tree_view_search_iter (model, selection, &iter, text,
                                   &count, up?((tree_view->priv->selected_iter) - 1):((tree_view->priv->selected_iter + 1)));
@@ -12554,8 +12916,8 @@ gtk_tree_view_search_iter (GtkTreeModel     *model,
             {
               gtk_tree_view_scroll_to_cell (tree_view, path, NULL,
                                            TRUE, 0.5, 0.0);
-              gtk_tree_selection_select_iter (selection, iter);
              gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
+              gtk_tree_selection_select_iter (selection, iter);
 
              if (path)
                gtk_tree_path_free (path);
@@ -12644,7 +13006,6 @@ gtk_tree_view_search_init (GtkWidget   *entry,
   gint len;
   gint count = 0;
   const gchar *text;
-  GtkWidget *window;
   GtkTreeIter iter;
   GtkTreeModel *model;
   GtkTreeSelection *selection;
@@ -12652,7 +13013,6 @@ gtk_tree_view_search_init (GtkWidget   *entry,
   g_return_if_fail (GTK_IS_ENTRY (entry));
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
 
-  window = gtk_widget_get_parent (entry);
   text = gtk_entry_get_text (GTK_ENTRY (entry));
   len = strlen (text);
   model = gtk_tree_view_get_model (tree_view);
@@ -12696,8 +13056,13 @@ gtk_tree_view_remove_widget (GtkCellEditable *cell_editable,
   if (GTK_WIDGET_HAS_FOCUS (cell_editable))
     gtk_widget_grab_focus (GTK_WIDGET (tree_view));
 
+  g_signal_handlers_disconnect_by_func (cell_editable,
+                                       gtk_tree_view_remove_widget,
+                                       tree_view);
+
   gtk_container_remove (GTK_CONTAINER (tree_view),
                        GTK_WIDGET (cell_editable));  
+
   /* FIXME should only redraw a single node */
   gtk_widget_queue_draw (GTK_WIDGET (tree_view));
 }
@@ -12820,6 +13185,7 @@ gtk_tree_view_stop_editing (GtkTreeView *tree_view,
                            gboolean     cancel_editing)
 {
   GtkTreeViewColumn *column;
+  GtkCellRenderer *cell;
 
   if (tree_view->priv->edited_column == NULL)
     return;
@@ -12837,7 +13203,10 @@ gtk_tree_view_stop_editing (GtkTreeView *tree_view,
   column = tree_view->priv->edited_column;
   tree_view->priv->edited_column = NULL;
 
-  if (! cancel_editing)
+  cell = _gtk_tree_view_column_get_edited_cell (column);
+  gtk_cell_renderer_stop_editing (cell, cancel_editing);
+
+  if (!cancel_editing)
     gtk_cell_editable_editing_done (column->editable_widget);
 
   tree_view->priv->edited_column = column;
@@ -12977,4 +13346,30 @@ gtk_tree_view_set_row_separator_func (GtkTreeView                *tree_view,
 }
 
   
+static void
+gtk_tree_view_grab_notify (GtkWidget *widget,
+                          gboolean   was_grabbed)
+{
+  GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
+
+  if (!was_grabbed)
+    tree_view->priv->pressed_button = -1;
+}
+
+static void
+gtk_tree_view_state_changed (GtkWidget      *widget,
+                            GtkStateType    previous_state)
+{
+  GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
+
+  if (GTK_WIDGET_REALIZED (widget))
+    {
+      gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
+      gdk_window_set_background (tree_view->priv->bin_window, &widget->style->base[widget->state]);
+    }
+
+  gtk_widget_queue_draw (widget);
+}
 
+#define __GTK_TREE_VIEW_C__
+#include "gtkaliasdef.c"