]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtktreeview.c
modify and free tmp instead of path ... (patch from #97927).
[~andy/gtk] / gtk / gtktreeview.c
index bb9c29702672d636521f0e6fe7ff8232a634cdbd..8ebf772f1988d876841cdc40fc629831415a3fde 100644 (file)
  */
 
 
+#include <string.h>
+#include <gdk/gdkkeysyms.h>
+
 #include "gtktreeview.h"
 #include "gtkrbtree.h"
 #include "gtktreednd.h"
 #include "gtktreeprivate.h"
 #include "gtkcellrenderer.h"
-#include "gtksignal.h"
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
 #include "gtkbutton.h"
 #include "gtkentry.h"
 #include "gtktreemodelsort.h"
 
-#include <string.h>
-#include <gdk/gdkkeysyms.h>
-
 #define GTK_TREE_VIEW_SEARCH_DIALOG_KEY "gtk-tree-view-search-dialog"
 #define GTK_TREE_VIEW_PRIORITY_VALIDATE (GDK_PRIORITY_REDRAW + 5)
-#define GTK_TREE_VIEW_NUM_ROWS_PER_IDLE 50
+#define GTK_TREE_VIEW_PRIORITY_SCROLL_SYNC (GTK_TREE_VIEW_PRIORITY_VALIDATE + 2)
+#define GTK_TREE_VIEW_NUM_ROWS_PER_IDLE 500
 #define SCROLL_EDGE_SIZE 15
 #define EXPANDER_EXTRA_PADDING 4
 
@@ -100,6 +100,7 @@ enum
   CURSOR_CHANGED,
   MOVE_CURSOR,
   SELECT_ALL,
+  UNSELECT_ALL,
   SELECT_CURSOR_ROW,
   TOGGLE_CURSOR_ROW,
   EXPAND_COLLAPSE_CURSOR_ROW,
@@ -120,7 +121,7 @@ enum {
   PROP_REORDERABLE,
   PROP_RULES_HINT,
   PROP_ENABLE_SEARCH,
-  PROP_SEARCH_COLUMN,
+  PROP_SEARCH_COLUMN
 };
 
 static void     gtk_tree_view_class_init           (GtkTreeViewClass *klass);
@@ -164,12 +165,11 @@ static gboolean gtk_tree_view_button_release       (GtkWidget        *widget,
                                                    GdkEventButton   *event);
 static void     gtk_tree_view_set_focus_child      (GtkContainer     *container,
                                                    GtkWidget        *child);
-static gint     gtk_tree_view_focus_in             (GtkWidget        *widget,
-                                                   GdkEventFocus    *event);
 static gint     gtk_tree_view_focus_out            (GtkWidget        *widget,
                                                    GdkEventFocus    *event);
 static gint     gtk_tree_view_focus                (GtkWidget        *widget,
                                                    GtkDirectionType  direction);
+static void     gtk_tree_view_grab_focus           (GtkWidget        *widget);
 static void     gtk_tree_view_style_set            (GtkWidget        *widget,
                                                    GtkStyle         *previous_style);
 
@@ -220,10 +220,11 @@ static void     gtk_tree_view_drag_data_received (GtkWidget        *widget,
 static void gtk_tree_view_set_adjustments                 (GtkTreeView     *tree_view,
                                                           GtkAdjustment   *hadj,
                                                           GtkAdjustment   *vadj);
-static void gtk_tree_view_real_move_cursor                (GtkTreeView     *tree_view,
+static gboolean gtk_tree_view_real_move_cursor            (GtkTreeView     *tree_view,
                                                           GtkMovementStep  step,
                                                           gint             count);
 static void gtk_tree_view_real_select_all                 (GtkTreeView     *tree_view);
+static void gtk_tree_view_real_unselect_all               (GtkTreeView     *tree_view);
 static void gtk_tree_view_real_select_cursor_row          (GtkTreeView     *tree_view,
                                                           gboolean         start_editing);
 static void gtk_tree_view_real_toggle_cursor_row          (GtkTreeView     *tree_view);
@@ -261,9 +262,12 @@ 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 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);
 
 
 /* Internal functions */
@@ -340,13 +344,21 @@ static gboolean gtk_tree_view_real_expand_row                (GtkTreeView
                                                              gboolean           animate);
 static void     gtk_tree_view_real_set_cursor                (GtkTreeView       *tree_view,
                                                              GtkTreePath       *path,
-                                                             gboolean           clear_and_select);
+                                                             gboolean           clear_and_select,
+                                                             gboolean           clamp_node);
+static gboolean gtk_tree_view_has_special_cell               (GtkTreeView       *tree_view);
 
 /* interactive search */
 static void     gtk_tree_view_search_dialog_destroy     (GtkWidget        *search_dialog,
                                                         GtkTreeView      *tree_view);
 static void     gtk_tree_view_search_position_func      (GtkTreeView      *tree_view,
                                                         GtkWidget        *search_dialog);
+static void     gtk_tree_view_search_disable_popdown    (GtkEntry         *entry,
+                                                        GtkMenu          *menu,
+                                                        gpointer          data);
+static gboolean gtk_tree_view_real_search_enable_popdown(gpointer          data);
+static void     gtk_tree_view_search_enable_popdown     (GtkWidget        *widget,
+                                                        gpointer          data);
 static gboolean gtk_tree_view_search_delete_event       (GtkWidget        *widget,
                                                         GdkEventAny      *event,
                                                         GtkTreeView      *tree_view);
@@ -390,6 +402,9 @@ static void gtk_tree_view_real_start_editing (GtkTreeView       *tree_view,
 static void gtk_tree_view_stop_editing                  (GtkTreeView *tree_view,
                                                         gboolean     cancel_editing);
 static void gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view);
+static GtkTreeViewColumn *gtk_tree_view_get_drop_column (GtkTreeView       *tree_view,
+                                                        GtkTreeViewColumn *column,
+                                                        gint               drop_position);
 
 
 static GtkContainerClass *parent_class = NULL;
@@ -400,10 +415,10 @@ static guint tree_view_signals [LAST_SIGNAL] = { 0 };
 /* GType Methods
  */
 
-GtkType
+GType
 gtk_tree_view_get_type (void)
 {
-  static GtkType tree_view_type = 0;
+  static GType tree_view_type = 0;
 
   if (!tree_view_type)
     {
@@ -420,7 +435,9 @@ gtk_tree_view_get_type (void)
         (GInstanceInitFunc) gtk_tree_view_init
       };
 
-      tree_view_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkTreeView", &tree_view_info, 0);
+      tree_view_type =
+       g_type_register_static (GTK_TYPE_CONTAINER, "GtkTreeView",
+                               &tree_view_info, 0);
     }
 
   return tree_view_type;
@@ -464,7 +481,6 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   widget_class->key_press_event = gtk_tree_view_key_press;
   widget_class->enter_notify_event = gtk_tree_view_enter_notify;
   widget_class->leave_notify_event = gtk_tree_view_leave_notify;
-  widget_class->focus_in_event = gtk_tree_view_focus_in;
   widget_class->focus_out_event = gtk_tree_view_focus_out;
   widget_class->drag_begin = gtk_tree_view_drag_begin;
   widget_class->drag_end = gtk_tree_view_drag_end;
@@ -475,6 +491,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   widget_class->drag_drop = gtk_tree_view_drag_drop;
   widget_class->drag_data_received = gtk_tree_view_drag_data_received;
   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;
 
   /* GtkContainer signals */
@@ -485,6 +502,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   class->set_scroll_adjustments = gtk_tree_view_set_adjustments;
   class->move_cursor = gtk_tree_view_real_move_cursor;
   class->select_all = gtk_tree_view_real_select_all;
+  class->unselect_all = gtk_tree_view_real_unselect_all;
   class->select_cursor_row = gtk_tree_view_real_select_cursor_row;
   class->toggle_cursor_row = gtk_tree_view_real_toggle_cursor_row;
   class->expand_collapse_cursor_row = gtk_tree_view_real_expand_collapse_cursor_row;
@@ -522,7 +540,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                                    g_param_spec_boolean ("headers_visible",
                                                         _("Visible"),
                                                         _("Show the column header buttons"),
-                                                        FALSE,
+                                                        TRUE,
                                                         G_PARAM_READWRITE));
 
   g_object_class_install_property (o_class,
@@ -583,7 +601,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_int ("expander_size",
                                                             _("Expander Size"),
-                                                            _("Size of the expander arrow."),
+                                                            _("Size of the expander arrow"),
                                                             0,
                                                             G_MAXINT,
                                                             _TREE_VIEW_EXPANDER_SIZE,
@@ -592,7 +610,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_int ("vertical_separator",
                                                             _("Vertical Separator Width"),
-                                                            _("Vertical space between cells.  Must be an even number."),
+                                                            _("Vertical space between cells.  Must be an even number"),
                                                             0,
                                                             G_MAXINT,
                                                             _TREE_VIEW_VERTICAL_SEPARATOR,
@@ -601,7 +619,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_int ("horizontal_separator",
                                                             _("Horizontal Separator Width"),
-                                                            _("Horizontal space between cells.  Must be an even number."),
+                                                            _("Horizontal space between cells.  Must be an even number"),
                                                             0,
                                                             G_MAXINT,
                                                             _TREE_VIEW_HORIZONTAL_SEPARATOR,
@@ -610,161 +628,193 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_boolean ("allow_rules",
                                                                 _("Allow Rules"),
-                                                                _("Allow drawing of alternating color rows."),
+                                                                _("Allow drawing of alternating color rows"),
                                                                 TRUE,
                                                                 G_PARAM_READABLE));
 
   gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_boolean ("indent_expanders",
                                                                 _("Indent Expanders"),
-                                                                _("Make the expanders indented."),
+                                                                _("Make the expanders indented"),
                                                                 TRUE,
                                                                 G_PARAM_READABLE));
+
+  gtk_widget_class_install_style_property (widget_class,
+                                           g_param_spec_boxed ("even_row_color",
+                                                               _("Even Row Color"),
+                                                               _("Color to use for even rows"),
+                                                              GDK_TYPE_COLOR,
+G_PARAM_READABLE));
+
+  gtk_widget_class_install_style_property (widget_class,
+                                           g_param_spec_boxed ("odd_row_color",
+                                                               _("Odd Row Color"),
+                                                               _("Color to use for odd rows"),
+                                                              GDK_TYPE_COLOR,
+G_PARAM_READABLE));
+
   /* Signals */
   widget_class->set_scroll_adjustments_signal =
-    gtk_signal_new ("set_scroll_adjustments",
-                   GTK_RUN_LAST,
-                   GTK_CLASS_TYPE (object_class),
-                   GTK_SIGNAL_OFFSET (GtkTreeViewClass, set_scroll_adjustments),
-                   _gtk_marshal_VOID__OBJECT_OBJECT,
-                   GTK_TYPE_NONE, 2,
-                   GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
+    g_signal_new ("set_scroll_adjustments",
+                 G_TYPE_FROM_CLASS (o_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, set_scroll_adjustments),
+                 NULL, NULL,
+                 _gtk_marshal_VOID__OBJECT_OBJECT,
+                 G_TYPE_NONE, 2,
+                 GTK_TYPE_ADJUSTMENT,
+                 GTK_TYPE_ADJUSTMENT);
 
   tree_view_signals[ROW_ACTIVATED] =
-    gtk_signal_new ("row_activated",
-                   GTK_RUN_LAST | GTK_RUN_ACTION,
-                   GTK_CLASS_TYPE (object_class),
-                   GTK_SIGNAL_OFFSET (GtkTreeViewClass, row_activated),
-                   _gtk_marshal_VOID__BOXED_OBJECT,
-                   GTK_TYPE_NONE, 2,
-                   GTK_TYPE_TREE_PATH,
-                   GTK_TYPE_TREE_VIEW_COLUMN);
+    g_signal_new ("row_activated",
+                 G_TYPE_FROM_CLASS (o_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, row_activated),
+                 NULL, NULL,
+                 _gtk_marshal_VOID__BOXED_OBJECT,
+                 G_TYPE_NONE, 2,
+                 GTK_TYPE_TREE_PATH,
+                 GTK_TYPE_TREE_VIEW_COLUMN);
 
   tree_view_signals[TEST_EXPAND_ROW] =
     g_signal_new ("test_expand_row",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, test_expand_row),
-                  _gtk_boolean_handled_accumulator, NULL,
-                  _gtk_marshal_BOOLEAN__BOXED_BOXED,
-                  G_TYPE_BOOLEAN, 2,
-                  GTK_TYPE_TREE_ITER,
-                  GTK_TYPE_TREE_PATH);
+                 G_TYPE_FROM_CLASS (o_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, test_expand_row),
+                 _gtk_boolean_handled_accumulator, NULL,
+                 _gtk_marshal_BOOLEAN__BOXED_BOXED,
+                 G_TYPE_BOOLEAN, 2,
+                 GTK_TYPE_TREE_ITER,
+                 GTK_TYPE_TREE_PATH);
 
   tree_view_signals[TEST_COLLAPSE_ROW] =
     g_signal_new ("test_collapse_row",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, test_collapse_row),
-                  _gtk_boolean_handled_accumulator, NULL,
-                  _gtk_marshal_BOOLEAN__BOXED_BOXED,
-                  G_TYPE_BOOLEAN, 2,
-                  GTK_TYPE_TREE_ITER,
-                  GTK_TYPE_TREE_PATH);
+                 G_TYPE_FROM_CLASS (o_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, test_collapse_row),
+                 _gtk_boolean_handled_accumulator, NULL,
+                 _gtk_marshal_BOOLEAN__BOXED_BOXED,
+                 G_TYPE_BOOLEAN, 2,
+                 GTK_TYPE_TREE_ITER,
+                 GTK_TYPE_TREE_PATH);
 
   tree_view_signals[ROW_EXPANDED] =
     g_signal_new ("row_expanded",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, row_expanded),
-                  NULL, NULL,
-                  _gtk_marshal_VOID__BOXED_BOXED,
-                  GTK_TYPE_NONE, 2,
-                  GTK_TYPE_TREE_ITER,
-                  GTK_TYPE_TREE_PATH);
+                 G_TYPE_FROM_CLASS (o_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, row_expanded),
+                 NULL, NULL,
+                 _gtk_marshal_VOID__BOXED_BOXED,
+                 G_TYPE_NONE, 2,
+                 GTK_TYPE_TREE_ITER,
+                 GTK_TYPE_TREE_PATH);
 
   tree_view_signals[ROW_COLLAPSED] =
     g_signal_new ("row_collapsed",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, row_collapsed),
-                  NULL, NULL,
-                  _gtk_marshal_VOID__BOXED_BOXED,
-                  GTK_TYPE_NONE, 2,
-                  GTK_TYPE_TREE_ITER,
-                  GTK_TYPE_TREE_PATH);
+                 G_TYPE_FROM_CLASS (o_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, row_collapsed),
+                 NULL, NULL,
+                 _gtk_marshal_VOID__BOXED_BOXED,
+                 G_TYPE_NONE, 2,
+                 GTK_TYPE_TREE_ITER,
+                 GTK_TYPE_TREE_PATH);
 
   tree_view_signals[COLUMNS_CHANGED] =
     g_signal_new ("columns_changed",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, columns_changed),
-                  NULL, NULL,
-                  _gtk_marshal_NONE__NONE,
-                  G_TYPE_NONE, 0);
+                 G_TYPE_FROM_CLASS (o_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, columns_changed),
+                 NULL, NULL,
+                 _gtk_marshal_NONE__NONE,
+                 G_TYPE_NONE, 0);
 
   tree_view_signals[CURSOR_CHANGED] =
     g_signal_new ("cursor_changed",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, cursor_changed),
-                  NULL, NULL,
-                  _gtk_marshal_NONE__NONE,
-                  G_TYPE_NONE, 0);
+                 G_TYPE_FROM_CLASS (o_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, cursor_changed),
+                 NULL, NULL,
+                 _gtk_marshal_NONE__NONE,
+                 G_TYPE_NONE, 0);
 
   tree_view_signals[MOVE_CURSOR] =
     g_signal_new ("move_cursor",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, move_cursor),
-                  NULL, NULL,
-                  _gtk_marshal_VOID__ENUM_INT,
-                  GTK_TYPE_NONE, 2, GTK_TYPE_MOVEMENT_STEP, GTK_TYPE_INT);
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, move_cursor),
+                 NULL, NULL,
+                 _gtk_marshal_BOOLEAN__ENUM_INT,
+                 G_TYPE_BOOLEAN, 2,
+                 GTK_TYPE_MOVEMENT_STEP,
+                 G_TYPE_INT);
 
   tree_view_signals[SELECT_ALL] =
     g_signal_new ("select_all",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, select_all),
-                  NULL, NULL,
-                  _gtk_marshal_NONE__NONE,
-                  GTK_TYPE_NONE, 0);
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, select_all),
+                 NULL, NULL,
+                 _gtk_marshal_NONE__NONE,
+                 G_TYPE_NONE, 0);
+
+  tree_view_signals[UNSELECT_ALL] =
+    g_signal_new ("unselect_all",
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, unselect_all),
+                 NULL, NULL,
+                 _gtk_marshal_NONE__NONE,
+                 G_TYPE_NONE, 0);
 
   tree_view_signals[SELECT_CURSOR_ROW] =
     g_signal_new ("select_cursor_row",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_row),
-                  NULL, NULL,
-                  _gtk_marshal_VOID__BOOLEAN,
-                  GTK_TYPE_NONE, 1,
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_row),
+                 NULL, NULL,
+                 _gtk_marshal_VOID__BOOLEAN,
+                 G_TYPE_NONE, 1,
                  G_TYPE_BOOLEAN);
 
   tree_view_signals[TOGGLE_CURSOR_ROW] =
     g_signal_new ("toggle_cursor_row",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, toggle_cursor_row),
-                  NULL, NULL,
-                  _gtk_marshal_NONE__NONE,
-                  GTK_TYPE_NONE, 0);
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, toggle_cursor_row),
+                 NULL, NULL,
+                 _gtk_marshal_NONE__NONE,
+                 G_TYPE_NONE, 0);
 
   tree_view_signals[EXPAND_COLLAPSE_CURSOR_ROW] =
     g_signal_new ("expand_collapse_cursor_row",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, expand_collapse_cursor_row),
-                  NULL, NULL,
-                  _gtk_marshal_VOID__BOOLEAN_BOOLEAN_BOOLEAN,
-                  GTK_TYPE_NONE, 3, GTK_TYPE_BOOL, GTK_TYPE_BOOL, GTK_TYPE_BOOL);
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, expand_collapse_cursor_row),
+                 NULL, NULL,
+                 _gtk_marshal_VOID__BOOLEAN_BOOLEAN_BOOLEAN,
+                 G_TYPE_NONE, 3,
+                 G_TYPE_BOOLEAN,
+                 G_TYPE_BOOLEAN,
+                 G_TYPE_BOOLEAN);
 
   tree_view_signals[SELECT_CURSOR_PARENT] =
     g_signal_new ("select_cursor_parent",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_parent),
-                  NULL, NULL,
-                  _gtk_marshal_NONE__NONE,
-                  GTK_TYPE_NONE, 0);
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_parent),
+                 NULL, NULL,
+                 _gtk_marshal_NONE__NONE,
+                 G_TYPE_NONE, 0);
 
   tree_view_signals[START_INTERACTIVE_SEARCH] =
     g_signal_new ("start_interactive_search",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
-                  G_STRUCT_OFFSET (GtkTreeViewClass, start_interactive_search),
-                  NULL, NULL,
-                  _gtk_marshal_NONE__NONE,
-                  GTK_TYPE_NONE, 0);
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                 G_STRUCT_OFFSET (GtkTreeViewClass, start_interactive_search),
+                 NULL, NULL,
+                 _gtk_marshal_NONE__NONE,
+                 G_TYPE_NONE, 0);
 
   /* Key bindings */
   gtk_tree_view_add_move_binding (binding_set, GDK_Up, 0,
@@ -792,100 +842,96 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                                  GTK_MOVEMENT_PAGES, 1);
 
   gtk_binding_entry_add_signal (binding_set, GDK_Right, 0, "move_cursor", 2,
-                               GTK_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
-                               GTK_TYPE_INT, 1);
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, 1);
 
   gtk_binding_entry_add_signal (binding_set, GDK_Left, 0, "move_cursor", 2,
-                               GTK_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
-                               GTK_TYPE_INT, -1);
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, -1);
 
   gtk_binding_entry_add_signal (binding_set, GDK_Right, GDK_CONTROL_MASK, "move_cursor", 2,
-                               GTK_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
-                               GTK_TYPE_INT, 1);
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, 1);
 
   gtk_binding_entry_add_signal (binding_set, GDK_Left, GDK_CONTROL_MASK, "move_cursor", 2,
-                               GTK_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
-                               GTK_TYPE_INT, -1);
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, -1);
 
   gtk_binding_entry_add_signal (binding_set, GDK_Right, GDK_CONTROL_MASK|GDK_SHIFT_MASK, "move_cursor", 2,
-                               GTK_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
-                               GTK_TYPE_INT, 1);
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, 1);
 
   gtk_binding_entry_add_signal (binding_set, GDK_Left, GDK_CONTROL_MASK|GDK_SHIFT_MASK, "move_cursor", 2,
-                               GTK_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
-                               GTK_TYPE_INT, -1);
-
-  gtk_binding_entry_add_signal (binding_set, GDK_f, GDK_CONTROL_MASK, "move_cursor", 2,
-                               GTK_TYPE_ENUM, GTK_MOVEMENT_LOGICAL_POSITIONS,
-                               GTK_TYPE_INT, 1);
-
-  gtk_binding_entry_add_signal (binding_set, GDK_b, GDK_CONTROL_MASK, "move_cursor", 2,
-                               GTK_TYPE_ENUM, GTK_MOVEMENT_LOGICAL_POSITIONS,
-                               GTK_TYPE_INT, -1);
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, -1);
 
   gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK, "toggle_cursor_row", 0);
 
   gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK, "select_all", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_slash, GDK_CONTROL_MASK, "select_all", 0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_A, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "unselect_all", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_backslash, GDK_CONTROL_MASK, "unselect_all", 0);
 
   gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_SHIFT_MASK, "select_cursor_row", 1,
-                               GTK_TYPE_BOOL, TRUE);
+                               G_TYPE_BOOLEAN, TRUE);
 
   gtk_binding_entry_add_signal (binding_set, GDK_space, 0, "select_cursor_row", 1,
-                               GTK_TYPE_BOOL, TRUE);
+                               G_TYPE_BOOLEAN, TRUE);
 
   /* expand and collapse rows */
   gtk_binding_entry_add_signal (binding_set, GDK_plus, 0, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, TRUE,
-                               GTK_TYPE_BOOL, FALSE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, FALSE);
   /* Not doable on US keyboards */
   gtk_binding_entry_add_signal (binding_set, GDK_plus, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, TRUE,
-                               GTK_TYPE_BOOL, TRUE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE);
   gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, 0, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, TRUE,
-                               GTK_TYPE_BOOL, FALSE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, FALSE);
   gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, TRUE,
-                               GTK_TYPE_BOOL, TRUE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE);
   gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, TRUE,
-                               GTK_TYPE_BOOL, TRUE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE);
   gtk_binding_entry_add_signal (binding_set, GDK_Right, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, TRUE,
-                               GTK_TYPE_BOOL, TRUE,
-                               GTK_TYPE_BOOL, TRUE);
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE);
 
   gtk_binding_entry_add_signal (binding_set, GDK_minus, 0, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, FALSE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE);
   gtk_binding_entry_add_signal (binding_set, GDK_minus, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, TRUE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE);
   gtk_binding_entry_add_signal (binding_set, GDK_KP_Subtract, 0, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, FALSE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE);
   gtk_binding_entry_add_signal (binding_set, GDK_KP_Subtract, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, TRUE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE);
   gtk_binding_entry_add_signal (binding_set, GDK_Left, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, FALSE,
-                               GTK_TYPE_BOOL, TRUE);
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               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_s, GDK_CONTROL_MASK, "start_interactive_search", 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_S, GDK_CONTROL_MASK, "start_interactive_search", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_F, GDK_CONTROL_MASK, "start_interactive_search", 0);
 }
 
 static void
@@ -894,6 +940,8 @@ gtk_tree_view_init (GtkTreeView *tree_view)
   tree_view->priv = g_new0 (GtkTreeViewPrivate, 1);
   GTK_WIDGET_SET_FLAGS (tree_view, GTK_CAN_FOCUS);
 
+  gtk_widget_set_redraw_on_allocate (GTK_WIDGET (tree_view), FALSE);
+
   tree_view->priv->flags = GTK_TREE_VIEW_IS_LIST | GTK_TREE_VIEW_SHOW_EXPANDERS | GTK_TREE_VIEW_DRAW_KEYFOCUS | GTK_TREE_VIEW_HEADERS_VISIBLE;
 
   /* We need some padding */
@@ -908,6 +956,8 @@ gtk_tree_view_init (GtkTreeView *tree_view)
   tree_view->priv->press_start_y = -1;
   tree_view->priv->reorderable = FALSE;
   tree_view->priv->presize_handler_timer = 0;
+  tree_view->priv->scroll_sync_timer = 0;
+  tree_view->priv->fixed_height_check = 0;
   gtk_tree_view_set_adjustments (tree_view, NULL, NULL);
   tree_view->priv->selection = _gtk_tree_selection_new_with_tree_view (tree_view);
   tree_view->priv->enable_search = TRUE;
@@ -956,6 +1006,7 @@ gtk_tree_view_set_property (GObject         *object,
       break;
     case PROP_RULES_HINT:
       gtk_tree_view_set_rules_hint (tree_view, g_value_get_boolean (value));
+      break;
     case PROP_ENABLE_SEARCH:
       gtk_tree_view_set_enable_search (tree_view, g_value_get_boolean (value));
       break;
@@ -1066,7 +1117,7 @@ gtk_tree_view_destroy (GtkObject *object)
 
   if (tree_view->priv->scroll_to_path != NULL)
     {
-      gtk_tree_path_free (tree_view->priv->scroll_to_path);
+      gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
       tree_view->priv->scroll_to_path = NULL;
     }
 
@@ -1076,6 +1127,18 @@ gtk_tree_view_destroy (GtkObject *object)
       tree_view->priv->drag_dest_row = NULL;
     }
 
+  if (tree_view->priv->last_button_press != NULL)
+    {
+      gtk_tree_row_reference_free (tree_view->priv->last_button_press);
+      tree_view->priv->last_button_press = NULL;
+    }
+
+  if (tree_view->priv->last_button_press_2 != NULL)
+    {
+      gtk_tree_row_reference_free (tree_view->priv->last_button_press_2);
+      tree_view->priv->last_button_press_2 = NULL;
+    }
+
   if (tree_view->priv->top_row != NULL)
     {
       gtk_tree_row_reference_free (tree_view->priv->top_row);
@@ -1103,8 +1166,8 @@ gtk_tree_view_destroy (GtkObject *object)
   tree_view->priv->anchor = NULL;
 
   /* destroy interactive search dialog */
-  search_dialog = gtk_object_get_data (GTK_OBJECT (tree_view),
-                                      GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
+  search_dialog = g_object_get_data (G_OBJECT (tree_view),
+                                    GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
   if (search_dialog)
     gtk_tree_view_search_dialog_destroy (search_dialog,
                                         tree_view);
@@ -1327,6 +1390,12 @@ gtk_tree_view_unrealize (GtkWidget *widget)
       tree_view->priv->validate_rows_timer = 0;
     }
 
+  if (tree_view->priv->scroll_sync_timer != 0)
+    {
+      gtk_timeout_remove (tree_view->priv->scroll_sync_timer);
+      tree_view->priv->scroll_sync_timer = 0;
+    }
+
   for (list = tree_view->priv->columns; list; list = list->next)
     _gtk_tree_view_column_unrealize_button (GTK_TREE_VIEW_COLUMN (list->data));
 
@@ -1452,7 +1521,7 @@ gtk_tree_view_size_request (GtkWidget      *widget,
 
   /* we validate 50 rows initially just to make sure we have some size */
   /* in practice, with a lot of static lists, this should get a good width */
-  validate_rows_handler (tree_view);
+  validate_rows (tree_view);
   gtk_tree_view_size_request_columns (tree_view);
   gtk_tree_view_update_size (GTK_TREE_VIEW (widget));
 
@@ -1507,11 +1576,13 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
       if (column == tree_view->priv->drag_column)
        {
          GtkAllocation drag_allocation;
-         gdk_window_get_size (tree_view->priv->drag_window,
-                              &(drag_allocation.width), &(drag_allocation.height));
+         gdk_drawable_get_size (tree_view->priv->drag_window,
+                                &(drag_allocation.width),
+                                &(drag_allocation.height));
          drag_allocation.x = 0;
          drag_allocation.y = 0;
-         gtk_widget_size_allocate (tree_view->priv->drag_column->button, &drag_allocation);
+         gtk_widget_size_allocate (tree_view->priv->drag_column->button,
+                                   &drag_allocation);
          width += drag_allocation.width;
          continue;
        }
@@ -1559,15 +1630,52 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
     }
 }
 
+static void
+invalidate_last_column (GtkTreeView *tree_view)
+{
+  GList *list, *last_column;
+  gint last_column_x;
+  GtkWidget *widget = GTK_WIDGET (tree_view);
+
+  for (last_column = g_list_last (tree_view->priv->columns);
+       last_column && !(GTK_TREE_VIEW_COLUMN (last_column->data)->visible);
+       last_column = last_column->prev)
+    ;
+  
+  last_column_x = 0;
+  for (list = tree_view->priv->columns; list; list = list->next)
+    {
+      GtkTreeViewColumn *column = list->data;
+      if (list == last_column)
+       {
+         GdkRectangle invalid_rect;
+         
+         invalid_rect.x = last_column_x;
+         invalid_rect.y = 0;
+         invalid_rect.width = column->width;
+         invalid_rect.height = widget->allocation.height;
+         
+         gdk_window_invalidate_rect (widget->window, &invalid_rect, TRUE);
+         break;
+       }
+      
+      last_column_x += column->width;
+    }
+}
+
 static void
 gtk_tree_view_size_allocate (GtkWidget     *widget,
                             GtkAllocation *allocation)
 {
   GList *tmp_list;
   GtkTreeView *tree_view;
+  gboolean width_changed = FALSE;
 
   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
 
+  if (allocation->width != widget->allocation.width)
+    width_changed = TRUE;
+  
   widget->allocation = *allocation;
 
   tree_view = GTK_TREE_VIEW (widget);
@@ -1591,22 +1699,22 @@ gtk_tree_view_size_allocate (GtkWidget     *widget,
 
 
   tree_view->priv->hadjustment->page_size = allocation->width;
-  tree_view->priv->hadjustment->page_increment = allocation->width;
-  tree_view->priv->hadjustment->step_increment = allocation->width / 10;
+  tree_view->priv->hadjustment->page_increment = allocation->width * 0.9;
+  tree_view->priv->hadjustment->step_increment = allocation->width * 0.1;
   tree_view->priv->hadjustment->lower = 0;
-  tree_view->priv->hadjustment->upper = tree_view->priv->width;
+  tree_view->priv->hadjustment->upper = MAX (tree_view->priv->hadjustment->page_size, tree_view->priv->width);
 
   if (tree_view->priv->hadjustment->value + allocation->width > tree_view->priv->width)
     tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
   gtk_adjustment_changed (tree_view->priv->hadjustment);
 
   tree_view->priv->vadjustment->page_size = allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view);
-  tree_view->priv->vadjustment->step_increment = (tree_view->priv->vadjustment->page_size) / 10;
-  tree_view->priv->vadjustment->page_increment = (allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view)) / 2;
+  tree_view->priv->vadjustment->step_increment = tree_view->priv->vadjustment->page_size * 0.1;
+  tree_view->priv->vadjustment->page_increment = tree_view->priv->vadjustment->page_size * 0.9;
   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->priv->height)
+  if (tree_view->priv->vadjustment->value + allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view) > tree_view->priv->height)
     gtk_adjustment_set_value (tree_view->priv->vadjustment,
                              MAX (tree_view->priv->height - tree_view->priv->vadjustment->page_size, 0));
   gtk_adjustment_changed (tree_view->priv->vadjustment);
@@ -1629,23 +1737,9 @@ gtk_tree_view_size_allocate (GtkWidget     *widget,
     }
 
   gtk_tree_view_size_allocate_columns (widget);
-  
-  if (tree_view->priv->scroll_to_path != NULL ||
-      tree_view->priv->scroll_to_column != NULL)
-    {
-      gtk_tree_view_scroll_to_cell (tree_view,
-                                   tree_view->priv->scroll_to_path,
-                                   tree_view->priv->scroll_to_column,
-                                   tree_view->priv->scroll_to_use_align,
-                                   tree_view->priv->scroll_to_row_align,
-                                   tree_view->priv->scroll_to_col_align);
-      if (tree_view->priv->scroll_to_path)
-       {
-         gtk_tree_path_free (tree_view->priv->scroll_to_path);
-         tree_view->priv->scroll_to_path = NULL;
-       }
-      tree_view->priv->scroll_to_column = NULL;
-    }
+
+  if (GTK_WIDGET_REALIZED (widget) && width_changed)
+    invalidate_last_column (tree_view);
 }
 
 static gboolean
@@ -1684,7 +1778,9 @@ gtk_tree_view_button_press (GtkWidget      *widget,
       gint dval;
       gint pre_val, aft_val;
       GtkTreeViewColumn *column = NULL;
+      GtkCellRenderer *focus_cell = NULL;
       gint column_handled_click = FALSE;
+      gboolean emit_row_activated = FALSE;
 
       if (!GTK_WIDGET_HAS_FOCUS (widget))
        gtk_widget_grab_focus (widget);
@@ -1758,24 +1854,101 @@ gtk_tree_view_button_press (GtkWidget      *widget,
        }
 
       if (column == NULL)
-       return FALSE;
+       {
+         gtk_tree_path_free (path);
+
+         return FALSE;
+       }
 
+      /* decide if we edit */
+      if (event->type == GDK_BUTTON_PRESS &&
+         !(event->state & gtk_accelerator_get_default_mod_mask ()))
+       {
+         GtkTreePath *anchor;
+         GtkTreeIter iter;
+
+         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);
+           }
+         else
+           anchor = NULL;
+
+         if ((anchor && !gtk_tree_path_compare (anchor, path))
+             || !_gtk_tree_view_column_has_editable_cell (column))
+           {
+             GtkCellEditable *cell_editable = NULL;
+
+             /* FIXME: get the right flags */
+             guint flags = 0;
+
+             path_string = gtk_tree_path_to_string (path);
+
+             if (_gtk_tree_view_column_cell_event (column,
+                                                   &cell_editable,
+                                                   (GdkEvent *)event,
+                                                   path_string,
+                                                   &background_area,
+                                                   &cell_area, flags))
+               {
+                 if (cell_editable != NULL)
+                   {
+                     gint left, right;
+                     GdkRectangle area;
+
+                     area = cell_area;
+                     _gtk_tree_view_column_get_neighbor_sizes (column, _gtk_tree_view_column_get_edited_cell (column), &left, &right);
+
+                     area.x += left;
+                     area.width -= right + left;
+
+                     gtk_tree_view_real_start_editing (tree_view,
+                                                       column,
+                                                       path,
+                                                       cell_editable,
+                                                       &area,
+                                                       (GdkEvent *)event,
+                                                       flags);
+                     g_free (path_string);
+                     gtk_tree_path_free (path);
+                     gtk_tree_path_free (anchor);
+                     return TRUE;
+                   }
+                 column_handled_click = TRUE;
+               }
+             g_free (path_string);
+           }
+         if (anchor)
+           gtk_tree_path_free (anchor);
+       }
+
+      /* select */
       pre_val = tree_view->priv->vadjustment->value;
 
       tree_view->priv->focus_column = column;
+      focus_cell = _gtk_tree_view_column_get_cell_at_pos (column, event->x - background_area.x);
+      if (focus_cell)
+        gtk_tree_view_column_focus_cell (column, focus_cell);
+
       if (event->state & GDK_CONTROL_MASK)
        {
-         gtk_tree_view_real_set_cursor (tree_view, path, FALSE);
+         gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
          gtk_tree_view_real_toggle_cursor_row (tree_view);
        }
       else if (event->state & GDK_SHIFT_MASK)
        {
-         gtk_tree_view_real_set_cursor (tree_view, path, FALSE);
+         gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
          gtk_tree_view_real_select_cursor_row (tree_view, FALSE);
        }
       else
        {
-         gtk_tree_view_real_set_cursor (tree_view, path, TRUE);
+         gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
        }
 
       /* the treeview may have been scrolled because of _set_cursor,
@@ -1788,46 +1961,6 @@ gtk_tree_view_button_press (GtkWidget      *widget,
       cell_area.y += dval;
       background_area.y += dval;
 
-      if (event->type == GDK_BUTTON_PRESS &&
-         !(event->state & gtk_accelerator_get_default_mod_mask ()))
-       {
-         GtkCellEditable *cell_editable = NULL;
-         /* FIXME: get the right flags */
-         guint flags = 0;
-         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);
-
-         path_string = gtk_tree_path_to_string (path);
-
-         if (_gtk_tree_view_column_cell_event (column,
-                                               &cell_editable,
-                                               (GdkEvent *)event,
-                                               path_string,
-                                               &background_area,
-                                               &cell_area, flags))
-           {
-             if (cell_editable != NULL)
-               {
-                 gtk_tree_view_real_start_editing (tree_view,
-                                                   column,
-                                                   path,
-                                                   cell_editable,
-                                                   &cell_area,
-                                                   (GdkEvent *)event,
-                                                   flags);
-
-               }
-             column_handled_click = TRUE;
-           }
-         g_free (path_string);
-       }
-
       /* Save press to possibly begin a drag
        */
       if (!column_handled_click &&
@@ -1838,22 +1971,45 @@ gtk_tree_view_button_press (GtkWidget      *widget,
           tree_view->priv->press_start_y = event->y;
         }
 
-      if (event->button == 1 && event->type == GDK_2BUTTON_PRESS)
+      if (event->button == 1 && event->type == GDK_2BUTTON_PRESS &&
+         tree_view->priv->last_button_press)
        {
-         if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT))
+         GtkTreePath *lsc;
+
+         lsc = gtk_tree_row_reference_get_path (tree_view->priv->last_button_press);
+
+         if (tree_view->priv->last_button_press)
+           gtk_tree_row_reference_free (tree_view->priv->last_button_press);
+         if (tree_view->priv->last_button_press_2)
+           gtk_tree_row_reference_free (tree_view->priv->last_button_press_2);
+         tree_view->priv->last_button_press = NULL;
+         tree_view->priv->last_button_press_2 = NULL;
+
+         if (lsc)
            {
-             if (node->children == NULL)
-               gtk_tree_view_real_expand_row (tree_view, path,
-                                              tree, node, FALSE, TRUE);
-             else
-               gtk_tree_view_real_collapse_row (GTK_TREE_VIEW (widget), path,
-                                                tree, node, TRUE);
+             if (!gtk_tree_path_compare (lsc, path))
+               emit_row_activated = TRUE;
+             gtk_tree_path_free (lsc);
            }
+       }
+      else if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
+        {
+         if (tree_view->priv->last_button_press)
+           gtk_tree_row_reference_free (tree_view->priv->last_button_press);
+         tree_view->priv->last_button_press = tree_view->priv->last_button_press_2;
+         tree_view->priv->last_button_press_2 = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
+       }
+
+      GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
 
+      if (emit_row_activated)
+       {
+         gtk_grab_remove (widget);
          gtk_tree_view_row_activated (tree_view, path, column);
        }
-      GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
+
       gtk_tree_path_free (path);
+
       return TRUE;
     }
 
@@ -1868,6 +2024,13 @@ gtk_tree_view_button_press (GtkWidget      *widget,
        {
          gpointer drag_data;
 
+         if (event->type == GDK_2BUTTON_PRESS &&
+             gtk_tree_view_column_get_sizing (column) != GTK_TREE_VIEW_COLUMN_AUTOSIZE)
+           {
+             _gtk_tree_view_column_autosize (tree_view, column);
+             break;
+           }
+
          if (gdk_pointer_grab (column->window, FALSE,
                                GDK_POINTER_MOTION_HINT_MASK |
                                GDK_BUTTON1_MOTION_MASK |
@@ -1881,9 +2044,12 @@ gtk_tree_view_button_press (GtkWidget      *widget,
          column->use_resized_width = TRUE;
 
          /* block attached dnd signal handler */
-         drag_data = gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data");
+         drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
          if (drag_data)
-           gtk_signal_handler_block_by_data (GTK_OBJECT (widget), drag_data);
+           g_signal_handlers_block_matched (widget,
+                                            G_SIGNAL_MATCH_DATA,
+                                            0, 0, NULL, NULL,
+                                            drag_data);
 
          if (!GTK_WIDGET_HAS_FOCUS (widget))
            gtk_widget_grab_focus (widget);
@@ -1905,8 +2071,8 @@ gtk_tree_view_button_release_drag_column (GtkWidget      *widget,
 
   tree_view = GTK_TREE_VIEW (widget);
 
-  gdk_pointer_ungrab (GDK_CURRENT_TIME);
-  gdk_keyboard_ungrab (GDK_CURRENT_TIME);
+  gdk_display_pointer_ungrab (gtk_widget_get_display (widget), GDK_CURRENT_TIME);
+  gdk_display_keyboard_ungrab (gtk_widget_get_display (widget), GDK_CURRENT_TIME);
 
   /* Move the button back */
   g_object_ref (tree_view->priv->drag_column->button);
@@ -1961,15 +2127,18 @@ gtk_tree_view_button_release_column_resize (GtkWidget      *widget,
   tree_view->priv->drag_pos = -1;
 
       /* unblock attached dnd signal handler */
-  drag_data = gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data");
+  drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
   if (drag_data)
-    gtk_signal_handler_unblock_by_data (GTK_OBJECT (widget), drag_data);
+    g_signal_handlers_unblock_matched (widget,
+                                      G_SIGNAL_MATCH_DATA,
+                                      0, 0, NULL, NULL,
+                                      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_pointer_ungrab (event->time);
-
+  gdk_display_pointer_ungrab (gdk_drawable_get_display (event->window),
+                             event->time);
   return TRUE;
 }
 
@@ -2190,9 +2359,12 @@ gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
 
       if (tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ORIGINAL)
        {
-
          if (tree_view->priv->drag_highlight_window)
-           gdk_window_destroy (tree_view->priv->drag_highlight_window);
+           {
+             gdk_window_set_user_data (tree_view->priv->drag_highlight_window,
+                                       NULL);
+             gdk_window_destroy (tree_view->priv->drag_highlight_window);
+           }
 
          attributes.window_type = GDK_WINDOW_CHILD;
          attributes.wclass = GDK_INPUT_OUTPUT;
@@ -2216,11 +2388,11 @@ gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
          col.pixel = 0;
          gdk_gc_set_foreground(gc, &col);
          gdk_draw_rectangle (mask, gc, TRUE, 2, 2, width - 4, height - 4);
-         gdk_gc_destroy (gc);
+         g_object_unref (gc);
 
          gdk_window_shape_combine_mask (tree_view->priv->drag_highlight_window,
                                         mask, 0, 0);
-         if (mask) gdk_pixmap_unref (mask);
+         if (mask) g_object_unref (mask);
          tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_ORIGINAL;
        }
     }
@@ -2251,7 +2423,11 @@ gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
       if (tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ARROW)
        {
          if (tree_view->priv->drag_highlight_window)
-           gdk_window_destroy (tree_view->priv->drag_highlight_window);
+           {
+             gdk_window_set_user_data (tree_view->priv->drag_highlight_window,
+                                       NULL);
+             gdk_window_destroy (tree_view->priv->drag_highlight_window);
+           }
 
          attributes.window_type = GDK_WINDOW_TEMP;
          attributes.wclass = GDK_INPUT_OUTPUT;
@@ -2261,7 +2437,8 @@ gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
          attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
          attributes.width = width;
          attributes.height = height;
-         tree_view->priv->drag_highlight_window = gdk_window_new (NULL, &attributes, attributes_mask);
+         tree_view->priv->drag_highlight_window = gdk_window_new (gtk_widget_get_root_window (widget),
+                                                                  &attributes, attributes_mask);
          gdk_window_set_user_data (tree_view->priv->drag_highlight_window, GTK_WIDGET (tree_view));
 
          mask = gdk_pixmap_new (tree_view->priv->drag_highlight_window, width, height, 1);
@@ -2283,10 +2460,10 @@ gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
              else
                j--;
            }
-         gdk_gc_destroy (gc);
+         g_object_unref (gc);
          gdk_window_shape_combine_mask (tree_view->priv->drag_highlight_window,
                                         mask, 0, 0);
-         if (mask) gdk_pixmap_unref (mask);
+         if (mask) g_object_unref (mask);
        }
 
       tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_ARROW;
@@ -2320,7 +2497,11 @@ gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
          tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
        {
          if (tree_view->priv->drag_highlight_window)
-           gdk_window_destroy (tree_view->priv->drag_highlight_window);
+           {
+             gdk_window_set_user_data (tree_view->priv->drag_highlight_window,
+                                       NULL);
+             gdk_window_destroy (tree_view->priv->drag_highlight_window);
+           }
 
          attributes.window_type = GDK_WINDOW_TEMP;
          attributes.wclass = GDK_INPUT_OUTPUT;
@@ -2355,10 +2536,10 @@ gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
              gdk_draw_line (mask, gc, k, height, k, height - tree_view->priv->expander_size + j);
              j--;
            }
-         gdk_gc_destroy (gc);
+         g_object_unref (gc);
          gdk_window_shape_combine_mask (tree_view->priv->drag_highlight_window,
                                         mask, 0, 0);
-         if (mask) gdk_pixmap_unref (mask);
+         if (mask) g_object_unref (mask);
        }
 
       tree_view->priv->drag_column_window_state = arrow_type;
@@ -2431,6 +2612,33 @@ gtk_tree_view_update_current_reorder (GtkTreeView *tree_view)
   gtk_tree_view_motion_draw_column_motion_arrow (tree_view);
 }
 
+static void
+gtk_tree_view_vertical_autoscroll (GtkTreeView *tree_view)
+{
+  GdkRectangle visible_rect;
+  gint y;
+  gint offset;
+  gfloat value;
+
+  gdk_window_get_pointer (tree_view->priv->bin_window, NULL, &y, NULL);
+  y += tree_view->priv->dy;
+
+  gtk_tree_view_get_visible_rect (tree_view, &visible_rect);
+
+  /* see if we are near the edge. */
+  offset = y - (visible_rect.y + 2 * SCROLL_EDGE_SIZE);
+  if (offset > 0)
+    {
+      offset = y - (visible_rect.y + visible_rect.height - 2 * SCROLL_EDGE_SIZE);
+      if (offset < 0)
+       return;
+    }
+
+  value = CLAMP (tree_view->priv->vadjustment->value + offset, 0.0,
+                tree_view->priv->vadjustment->upper - tree_view->priv->vadjustment->page_size);
+  gtk_adjustment_set_value (tree_view->priv->vadjustment, value);
+}
+
 static gboolean
 gtk_tree_view_horizontal_autoscroll (GtkTreeView *tree_view)
 {
@@ -2615,7 +2823,9 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
   GList *last_column;
   gint vertical_separator;
   gint horizontal_separator;
+  gint focus_line_width;
   gboolean allow_rules;
+  gboolean has_special_cell;
 
   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
 
@@ -2625,6 +2835,7 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                        "horizontal_separator", &horizontal_separator,
                        "vertical_separator", &vertical_separator,
                        "allow_rules", &allow_rules,
+                       "focus-line-width", &focus_line_width,
                        NULL);
 
   if (tree_view->priv->tree == NULL)
@@ -2710,6 +2921,8 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
 
       parity = _gtk_rbtree_node_find_parity (tree, node);
 
+      has_special_cell = gtk_tree_view_has_special_cell (tree_view);
+
       for (list = tree_view->priv->columns; list; list = list->next)
        {
          GtkTreeViewColumn *column = list->data;
@@ -2731,13 +2944,6 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
           else
             flags &= ~GTK_CELL_RENDERER_SORTED;
 
-         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);
-
-
          background_area.x = cell_offset;
          background_area.width = column->width;
 
@@ -2747,6 +2953,18 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
           cell_area.height -= vertical_separator;
          cell_area.width -= horizontal_separator;
 
+         if (gdk_region_rect_in (event->region, &background_area) == GDK_OVERLAP_RECTANGLE_OUT)
+           {
+             cell_offset += column->width;
+             continue;
+           }
+
+         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);
+
           /* Select the detail for drawing the cell.  relevant
            * factors are parity, sortedness, and whether to
            * display rules.
@@ -2817,12 +3035,12 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                * level of the tree we're dropping at.
                */
               highlight_x = cell_area.x;
-             gtk_tree_view_column_cell_render (column,
-                                               event->window,
-                                               &background_area,
-                                               &cell_area,
-                                               &event->area,
-                                               flags);
+             _gtk_tree_view_column_cell_render (column,
+                                                event->window,
+                                                &background_area,
+                                                &cell_area,
+                                                &event->area,
+                                                flags);
              if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT)
                {
                  gint x, y;
@@ -2835,30 +3053,29 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
            }
          else
            {
-             gtk_tree_view_column_cell_render (column,
-                                               event->window,
-                                               &background_area,
-                                               &cell_area,
-                                               &event->area,
-                                               flags);
+             _gtk_tree_view_column_cell_render (column,
+                                                event->window,
+                                                &background_area,
+                                                &cell_area,
+                                                &event->area,
+                                                flags);
            }
-         if (node == cursor &&
+         if (node == cursor && has_special_cell &&
              ((column == tree_view->priv->focus_column &&
                GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS) &&
                GTK_WIDGET_HAS_FOCUS (widget)) ||
               (column == tree_view->priv->edited_column)))
            {
-             gtk_tree_view_column_cell_draw_focus (column,
-                                                   event->window,
-                                                   &background_area,
-                                                   &cell_area,
-                                                   &event->area,
-                                                   flags);
+             _gtk_tree_view_column_cell_draw_focus (column,
+                                                    event->window,
+                                                    &background_area,
+                                                    &cell_area,
+                                                    &event->area,
+                                                    flags);
            }
          cell_offset += column->width;
        }
 
-
       if (node == drag_highlight)
         {
           /* Draw indicator for the drop
@@ -2872,11 +3089,13 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
           switch (tree_view->priv->drag_dest_pos)
             {
             case GTK_TREE_VIEW_DROP_BEFORE:
-              highlight_y = background_area.y - vertical_separator/2;
+              highlight_y = background_area.y - 1;
+             if (highlight_y < 0)
+                     highlight_y = 0;
               break;
 
             case GTK_TREE_VIEW_DROP_AFTER:
-              highlight_y = background_area.y + background_area.height + vertical_separator/2;
+              highlight_y = background_area.y + background_area.height - 1;
               break;
 
             case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
@@ -2913,6 +3132,35 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
             }
         }
 
+      /* draw the big row-spanning focus rectangle, if needed */
+      if (!has_special_cell && node == cursor &&
+         GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS) &&
+         GTK_WIDGET_HAS_FOCUS (widget))
+        {
+         gint width;
+         GtkStateType focus_rect_state;
+
+         focus_rect_state =
+           flags & GTK_CELL_RENDERER_SELECTED ? GTK_STATE_SELECTED :
+           (flags & GTK_CELL_RENDERER_PRELIT ? GTK_STATE_PRELIGHT :
+            (flags & GTK_CELL_RENDERER_INSENSITIVE ? GTK_STATE_INSENSITIVE :
+             GTK_STATE_NORMAL));
+
+         gdk_drawable_get_size (tree_view->priv->bin_window,
+                                &width, NULL);
+         gtk_paint_focus (widget->style,
+                          tree_view->priv->bin_window,
+                          focus_rect_state,
+                          NULL,
+                          widget,
+                          "treeview",
+                          0,
+                          BACKGROUND_FIRST_PIXEL (tree_view, tree, node),
+                          width,
+                          MAX (BACKGROUND_HEIGHT (node),
+                               tree_view->priv->expander_size));
+       }
+
       y_offset += max_height;
       if (node->children)
        {
@@ -3020,11 +3268,222 @@ gtk_tree_view_expose (GtkWidget      *widget,
   return TRUE;
 }
 
+enum
+{
+  DROP_HOME,
+  DROP_RIGHT,
+  DROP_LEFT,
+  DROP_END
+};
+
+/* returns 0x1 when no column has been found -- yes it's hackish */
+static GtkTreeViewColumn *
+gtk_tree_view_get_drop_column (GtkTreeView       *tree_view,
+                              GtkTreeViewColumn *column,
+                              gint               drop_position)
+{
+  GtkTreeViewColumn *left_column = NULL;
+  GtkTreeViewColumn *cur_column = NULL;
+  GList *tmp_list;
+
+  if (!column->reorderable)
+    return (GtkTreeViewColumn *)0x1;
+
+  switch (drop_position)
+    {
+      case DROP_HOME:
+       /* find first column where we can drop */
+       tmp_list = tree_view->priv->columns;
+       if (column == GTK_TREE_VIEW_COLUMN (tmp_list->data))
+         return (GtkTreeViewColumn *)0x1;
+
+       while (tmp_list)
+         {
+           g_assert (tmp_list);
+
+           cur_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
+           tmp_list = tmp_list->next;
+
+           if (left_column && left_column->visible == FALSE)
+             continue;
+
+           if (!tree_view->priv->column_drop_func)
+             return left_column;
+
+           if (!(*tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
+             {
+               left_column = cur_column;
+               continue;
+             }
+
+           return cur_column;
+         }
+
+       if (!tree_view->priv->column_drop_func)
+         return left_column;
+
+       if ((*tree_view->priv->column_drop_func) (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data))
+         return left_column;
+       else
+         return (GtkTreeViewColumn *)0x1;
+       break;
+
+      case DROP_RIGHT:
+       /* find first column after column where we can drop */
+       tmp_list = tree_view->priv->columns;
+
+       for (; tmp_list; tmp_list = tmp_list->next)
+         if (GTK_TREE_VIEW_COLUMN (tmp_list->data) == column)
+           break;
+
+       if (!tmp_list || !tmp_list->next)
+         return (GtkTreeViewColumn *)0x1;
+
+       tmp_list = tmp_list->next;
+       left_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
+       tmp_list = tmp_list->next;
+
+       while (tmp_list)
+         {
+           g_assert (tmp_list);
+
+           cur_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
+           tmp_list = tmp_list->next;
+
+           if (left_column && left_column->visible == FALSE)
+             {
+               left_column = cur_column;
+               if (tmp_list)
+                 tmp_list = tmp_list->next;
+               continue;
+             }
+
+           if (!tree_view->priv->column_drop_func)
+             return left_column;
+
+           if (!(*tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
+             {
+               left_column = cur_column;
+               continue;
+             }
+
+           return cur_column;
+         }
+
+       if (!tree_view->priv->column_drop_func)
+         return left_column;
+
+       if ((*tree_view->priv->column_drop_func) (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data))
+         return left_column;
+       else
+         return (GtkTreeViewColumn *)0x1;
+       break;
+
+      case DROP_LEFT:
+       /* find first column before column where we can drop */
+       tmp_list = tree_view->priv->columns;
+
+       for (; tmp_list; tmp_list = tmp_list->next)
+         if (GTK_TREE_VIEW_COLUMN (tmp_list->data) == column)
+           break;
+
+       if (!tmp_list || !tmp_list->prev)
+         return (GtkTreeViewColumn *)0x1;
+
+       tmp_list = tmp_list->prev;
+       cur_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
+       tmp_list = tmp_list->prev;
+
+       while (tmp_list)
+         {
+           g_assert (tmp_list);
+
+           left_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
+
+           if (left_column && !left_column->visible)
+             {
+               /*if (!tmp_list->prev)
+                 return (GtkTreeViewColumn *)0x1;
+                 */
+/*
+               cur_column = GTK_TREE_VIEW_COLUMN (tmp_list->prev->data);
+               tmp_list = tmp_list->prev->prev;
+               continue;*/
+
+               cur_column = left_column;
+               if (tmp_list)
+                 tmp_list = tmp_list->prev;
+               continue;
+             }
+
+           if (!tree_view->priv->column_drop_func)
+             return left_column;
+
+           if ((*tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
+             return left_column;
+
+           cur_column = left_column;
+           tmp_list = tmp_list->prev;
+         }
+
+       if (!tree_view->priv->column_drop_func)
+         return NULL;
+
+       if ((*tree_view->priv->column_drop_func) (tree_view, column, NULL, cur_column, tree_view->priv->column_drop_func_data))
+         return NULL;
+       else
+         return (GtkTreeViewColumn *)0x1;
+       break;
+
+      case DROP_END:
+       /* same as DROP_HOME case, but doing it backwards */
+       tmp_list = g_list_last (tree_view->priv->columns);
+       cur_column = NULL;
+
+       if (column == GTK_TREE_VIEW_COLUMN (tmp_list->data))
+         return (GtkTreeViewColumn *)0x1;
+
+       while (tmp_list)
+         {
+           g_assert (tmp_list);
+
+           left_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
+
+           if (left_column && !left_column->visible)
+             {
+               cur_column = left_column;
+               tmp_list = tmp_list->prev;
+             }
+
+           if (!tree_view->priv->column_drop_func)
+             return left_column;
+
+           if ((*tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
+             return left_column;
+
+           cur_column = left_column;
+           tmp_list = tmp_list->prev;
+         }
+
+       if (!tree_view->priv->column_drop_func)
+         return NULL;
+
+       if ((*tree_view->priv->column_drop_func) (tree_view, column, NULL, cur_column, tree_view->priv->column_drop_func_data))
+         return NULL;
+       else
+         return (GtkTreeViewColumn *)0x1;
+       break;
+    }
+
+  return (GtkTreeViewColumn *)0x1;
+}
+
 static gboolean
 gtk_tree_view_key_press (GtkWidget   *widget,
                         GdkEventKey *event)
 {
   GtkTreeView *tree_view = (GtkTreeView *) widget;
+  GList *list;
 
   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG))
     {
@@ -3036,6 +3495,157 @@ gtk_tree_view_key_press (GtkWidget   *widget,
       return TRUE;
     }
 
+  /* FIXME: this is prolly broken when we go bidi */
+  if (tree_view->priv->columns && (event->state & GDK_SHIFT_MASK)
+      && (event->keyval == GDK_Left || event->keyval == GDK_Right))
+    {
+      list = tree_view->priv->columns;
+      while (list)
+        {
+         GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (list->data);
+         if (GTK_WIDGET_HAS_FOCUS (column->button))
+           {
+             if (!column->resizable)
+               return TRUE;
+
+             if (event->keyval == GDK_Left)
+               {
+                 column->resized_width = MAX (column->resized_width,
+                                              column->width);
+                 column->resized_width -= 2;
+                 if (column->resized_width < 0)
+                   column->resized_width = 0;
+
+                 if (column->min_width == -1)
+                   column->resized_width = MAX (column->button->requisition.width, column->resized_width);
+                 else
+                   column->resized_width = MAX (column->min_width, column->resized_width);
+
+                 if (column->max_width != -1)
+                   column->resized_width = MIN (column->resized_width, column->max_width);
+
+                 column->use_resized_width = TRUE;
+                 gtk_widget_queue_resize (widget);
+                 return TRUE;
+               }
+             else if (event->keyval == GDK_Right)
+               {
+                 column->resized_width = MAX (column->resized_width,
+                                              column->width);
+                 column->resized_width += 2;
+
+                 if (column->max_width != -1)
+                   column->resized_width = MIN (column->resized_width, column->max_width);
+
+                 column->use_resized_width = TRUE;
+                 gtk_widget_queue_resize (widget);
+                 return TRUE;
+               }
+           }
+         list = list->next;
+       }
+    }
+
+  /* FIXME: broken when we go bidi? */
+  if (tree_view->priv->columns && (event->state & GDK_CONTROL_MASK) &&
+      (event->keyval == GDK_Left || event->keyval == GDK_Right
+       || event->keyval == GDK_Home || event->keyval == GDK_End))
+    {
+      list = tree_view->priv->columns;
+      while (list)
+        {
+         GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (list->data);
+         if (GTK_WIDGET_HAS_FOCUS (column->button))
+           {
+             if (event->keyval == GDK_Left)
+               {
+                 GtkTreeViewColumn *col;
+                 col = gtk_tree_view_get_drop_column (tree_view, column, DROP_LEFT);
+                 if (col != (GtkTreeViewColumn *)0x1)
+                   gtk_tree_view_move_column_after (tree_view, column, col);
+                 return TRUE;
+               }
+             else if (event->keyval == GDK_Right)
+               {
+                 GtkTreeViewColumn *col;
+                 col = gtk_tree_view_get_drop_column (tree_view, column, DROP_RIGHT);
+                 if (col != (GtkTreeViewColumn *)0x1)
+                   gtk_tree_view_move_column_after (tree_view, column, col);
+                 return TRUE;
+               }
+             else if (event->keyval == GDK_Home)
+               {
+                 GtkTreeViewColumn *col;
+                 col = gtk_tree_view_get_drop_column (tree_view, column, DROP_HOME);
+                 if (col != (GtkTreeViewColumn *)0x1)
+                   gtk_tree_view_move_column_after (tree_view, column, col);
+                 return TRUE;
+               }
+             else if (event->keyval == GDK_End)
+               {
+                 GtkTreeViewColumn *col;
+                 col = gtk_tree_view_get_drop_column (tree_view, column, DROP_END);
+                 if (col != (GtkTreeViewColumn *)0x1)
+                   gtk_tree_view_move_column_after (tree_view, column, col);
+                 return TRUE;
+               }
+           }
+         list = list->next;
+       }
+    }
+
+  /* FIXME: this is prolly broken when we go bidi */
+  if (tree_view->priv->columns &&
+      (event->keyval == GDK_Left || event->keyval == GDK_Right))
+    {
+      gint width = 0;
+      list = tree_view->priv->columns;
+      while (list)
+       {
+         GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (list->data);
+         if (GTK_WIDGET_HAS_FOCUS (column->button))
+           {
+             if (event->keyval == GDK_Left && list->prev)
+               {
+                 GList *tmp;
+
+                 for (tmp = list->prev; tmp; tmp = tmp->prev)
+                   if (GTK_TREE_VIEW_COLUMN (tmp->data)->visible)
+                     break;
+
+                 if (!tmp)
+                   return FALSE;
+
+                 tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (tmp->data);
+                 gtk_widget_grab_focus (tree_view->priv->focus_column->button);
+                 width -= tree_view->priv->focus_column->width;
+                 gtk_adjustment_set_value (tree_view->priv->hadjustment, CLAMP (width, tree_view->priv->hadjustment->lower, tree_view->priv->hadjustment->upper - tree_view->priv->hadjustment->page_size));
+                 return TRUE;
+               }
+             else if (event->keyval == GDK_Right && list->next)
+               {
+                 GList *tmp;
+
+                 for (tmp = list->next; tmp; tmp = tmp->next)
+                   if (GTK_TREE_VIEW_COLUMN (tmp->data)->visible)
+                     break;
+
+                 if (!tmp)
+                   return FALSE;
+
+                 tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (tmp->data);
+
+                 gtk_widget_grab_focus (tree_view->priv->focus_column->button);
+                 width += tree_view->priv->focus_column->width;
+                 gtk_adjustment_set_value (tree_view->priv->hadjustment, CLAMP (width, tree_view->priv->hadjustment->lower, tree_view->priv->hadjustment->upper - tree_view->priv->hadjustment->page_size));
+                 return TRUE;
+               }
+           }
+         width += GTK_TREE_VIEW_COLUMN (list->data)->width;
+         list = list->next;
+       }
+    }
+
   return (* GTK_WIDGET_CLASS (parent_class)->key_press_event) (widget, event);
 }
 
@@ -3106,26 +3716,7 @@ gtk_tree_view_leave_notify (GtkWidget        *widget,
 
   ensure_unprelighted (tree_view);
 
-return TRUE;
-}
-
-
-static gint
-gtk_tree_view_focus_in (GtkWidget     *widget,
-                       GdkEventFocus *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);
-
-  GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
-
-  gtk_widget_queue_draw (widget);
-
-  return FALSE;
+  return TRUE;
 }
 
 
@@ -3135,16 +3726,11 @@ gtk_tree_view_focus_out (GtkWidget     *widget,
 {
   GtkWidget   *search_dialog;
 
-  g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
-
-  GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
-
   gtk_widget_queue_draw (widget);
 
   /* destroy interactive search dialog */
-  search_dialog = gtk_object_get_data (GTK_OBJECT (widget),
-                                      GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
+  search_dialog = g_object_get_data (G_OBJECT (widget),
+                                    GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
   if (search_dialog)
     gtk_tree_view_search_dialog_destroy (search_dialog, GTK_TREE_VIEW (widget));
 
@@ -3199,6 +3785,7 @@ validate_row (GtkTreeView *tree_view,
       gtk_tree_view_column_cell_get_size (column,
                                          NULL, NULL, NULL,
                                          &tmp_width, &tmp_height);
+
       height = MAX (height, tmp_height);
       height = MAX (height, tree_view->priv->expander_size);
 
@@ -3230,49 +3817,121 @@ validate_row (GtkTreeView *tree_view,
 static void
 validate_visible_area (GtkTreeView *tree_view)
 {
-  GtkTreePath *path;
+  GtkTreePath *path = NULL;
+  GtkTreePath *above_path = NULL;
   GtkTreeIter iter;
-  GtkRBTree *tree;
-  GtkRBNode *node;
-  gint y, height, offset;
-  gboolean validated_area = FALSE;
+  GtkRBTree *tree = NULL;
+  GtkRBNode *node = NULL;
+  gboolean need_redraw = FALSE;
   gboolean size_changed = FALSE;
-  
+  gboolean update_dy = FALSE;
+  gint total_height;
+  gint area_above = 0;
+  gint area_below = 0;
+
   if (tree_view->priv->tree == NULL)
     return;
-  
-  if (! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID))
+
+  if (! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID) &&
+      tree_view->priv->scroll_to_path == NULL)
     return;
-  
-  height = GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
 
-  y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, 0);
+  total_height = GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
 
-  offset = _gtk_rbtree_find_offset (tree_view->priv->tree, y,
-                                   &tree, &node);
-  if (node == NULL)
-    {
-      path = gtk_tree_path_new_root ();
-      _gtk_tree_view_find_node (tree_view, path, &tree, &node);
-    }
-  else
+  if (total_height == 0)
+    return;
+
+  /* First, we check to see if we need to scroll anywhere
+   */
+  if (tree_view->priv->scroll_to_path)
     {
-      path = _gtk_tree_view_find_path (tree_view, tree, node);
-      height += offset;
+      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))
+       {
+         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))
+           {
+             need_redraw = TRUE;
+             if (validate_row (tree_view, tree, node, &iter, path))
+               size_changed = TRUE;
+           }
+         if (tree_view->priv->scroll_to_use_align)
+           {
+             gint height = MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
+             area_above = (total_height - height) *
+               tree_view->priv->scroll_to_row_align;
+             area_below = total_height - area_above - height;
+             area_above = MAX (area_above, 0);
+             area_below = MAX (area_below, 0);
+           }
+         else
+           {
+             /* FIXME: temporary solution, just validate a complete height
+              * and all will be fine...
+              */
+             area_above = total_height;
+             area_below = total_height;
+           }
+       }
+      else
+       /* the scroll to isn't valid; ignore it.
+        */
+       {
+         if (tree_view->priv->scroll_to_path && !path)
+           {
+             gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
+             tree_view->priv->scroll_to_path = NULL;
+           }
+         if (path)
+           gtk_tree_path_free (path);
+         path = NULL;
+       }      
     }
 
-  gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
-  do
+  /* We didn't have a scroll_to set, so we just handle things normally
+   */
+  if (path == NULL)
     {
+      gint offset;
+
+      offset = _gtk_rbtree_find_offset (tree_view->priv->tree,
+                                       TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, 0),
+                                       &tree, &node);
+      if (node == NULL)
+       {
+         /* In this case, nothing has been validated */
+         path = gtk_tree_path_new_first ();
+         _gtk_tree_view_find_node (tree_view, path, &tree, &node);
+       }
+      else
+       {
+         path = _gtk_tree_view_find_path (tree_view, tree, node);
+         total_height += offset;
+       }
+
+      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))
        {
-         validated_area = TRUE;
+         need_redraw = TRUE;
          if (validate_row (tree_view, tree, node, &iter, path))
            size_changed = TRUE;
        }
-      height -= MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
+      area_above = 0;
+      area_below = total_height - MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
+    }
+
+  above_path = gtk_tree_path_copy (path);
 
+  /* 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
+   * fill out the top.
+   */
+  while (node && area_below > 0)
+    {
       if (node->children)
        {
          GtkTreeIter parent = iter;
@@ -3289,7 +3948,7 @@ validate_visible_area (GtkTreeView *tree_view)
                                                    &iter,
                                                    &parent);
          TREE_VIEW_INTERNAL_ASSERT_VOID (has_child);
-         gtk_tree_path_append_index (path, 0);
+         gtk_tree_path_down (path);
        }
       else
        {
@@ -3301,6 +3960,7 @@ validate_visible_area (GtkTreeView *tree_view)
                {
                  gboolean has_next = gtk_tree_model_iter_next (tree_view->priv->model, &iter);
                  done = TRUE;
+                 gtk_tree_path_next (path);
 
                  /* Sanity Check! */
                  TREE_VIEW_INTERNAL_ASSERT_VOID (has_next);
@@ -3317,6 +3977,7 @@ validate_visible_area (GtkTreeView *tree_view)
                  has_parent = gtk_tree_model_iter_parent (tree_view->priv->model,
                                                           &iter,
                                                           &parent_iter);
+                 gtk_tree_path_up (path);
 
                  /* Sanity check */
                  TREE_VIEW_INTERNAL_ASSERT_VOID (has_parent);
@@ -3324,17 +3985,108 @@ validate_visible_area (GtkTreeView *tree_view)
            }
          while (!done);
        }
+      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;
+       }
+      if (node)
+       area_below -= MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
+    }
+  gtk_tree_path_free (path);
+
+  /* If we ran out of tree, and have extra area_below left, we need to remove it
+   * from the area_above */
+  if (area_below > 0)
+    area_above += area_below;
+
+  _gtk_tree_view_find_node (tree_view, above_path, &tree, &node);
+
+  /* We walk backwards */
+  while (area_above > 0)
+    {
+      _gtk_rbtree_prev_full (tree, node, &tree, &node);
+      if (! gtk_tree_path_prev (above_path) && node != NULL)
+       {
+         gtk_tree_path_free (above_path);
+         above_path = _gtk_tree_view_find_path (tree_view, tree, node);
+       }
+      gtk_tree_model_get_iter (tree_view->priv->model, &iter, above_path);
+
+      if (node == NULL)
+       break;
+
+      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, above_path))
+           size_changed = TRUE;
+       }
+      area_above -= MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
+      update_dy = TRUE;
     }
-  while (node && height > 0);
 
   if (size_changed)
-    gtk_widget_queue_resize (GTK_WIDGET (tree_view));
-  if (validated_area)
+    {
+      GtkRequisition requisition;
+      /* 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. */
+      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 we scroll at all, always update dy and kill the top_row */
+  if (tree_view->priv->scroll_to_path)
+    {
+      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);
+      tree_view->priv->scroll_to_path = NULL;
+    }
+
+  if (above_path)
+    gtk_tree_path_free (above_path);
+
+  if (tree_view->priv->scroll_to_column)
+    {
+      tree_view->priv->scroll_to_column = NULL;
+    }
+  if (need_redraw)
     gtk_widget_queue_draw (GTK_WIDGET (tree_view));
-  if (path)
-    gtk_tree_path_free (path);
 }
 
+
 /* Our strategy for finding nodes to validate is a little convoluted.  We find
  * the left-most uninvalidated node.  We then try walking right, validating
  * nodes.  Once we find a valid node, we repeat the previous process of finding
@@ -3342,7 +4094,7 @@ validate_visible_area (GtkTreeView *tree_view)
  */
 
 static gboolean
-validate_rows_handler (GtkTreeView *tree_view)
+do_validate_rows (GtkTreeView *tree_view)
 {
   GtkRBTree *tree = NULL;
   GtkRBNode *node = NULL;
@@ -3351,19 +4103,17 @@ validate_rows_handler (GtkTreeView *tree_view)
   GtkTreePath *path = NULL;
   GtkTreeIter iter;
   gint i = 0;
-  g_assert (tree_view);
 
-  GDK_THREADS_ENTER ();
+  gint prev_height = -1;
+  gboolean fixed_height = TRUE;
+
+  g_assert (tree_view);
 
   if (tree_view->priv->tree == NULL)
-    {
-      tree_view->priv->validate_rows_timer = 0;
       return FALSE;
-    }
 
   do
     {
-
       if (! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID))
        {
          retval = FALSE;
@@ -3423,29 +4173,90 @@ validate_rows_handler (GtkTreeView *tree_view)
          gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
        }
       validated_area = validate_row (tree_view, tree, node, &iter, path) | validated_area;
+
+      if (!tree_view->priv->fixed_height_check)
+        {
+         gint height;
+
+         height = MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
+         if (prev_height < 0)
+           prev_height = height;
+         else if (prev_height != height)
+           fixed_height = FALSE;
+       }
+
       i++;
     }
   while (i < GTK_TREE_VIEW_NUM_ROWS_PER_IDLE);
+
+  if (!tree_view->priv->fixed_height_check)
+   {
+     if (fixed_height)
+       _gtk_rbtree_set_fixed_height (tree_view->priv->tree, prev_height);
+
+     tree_view->priv->fixed_height_check = 1;
+   }
   
  done:
-  if (path) gtk_tree_path_free (path);
   if (validated_area)
-    gtk_widget_queue_resize (GTK_WIDGET (tree_view));
-  if (! retval)
-    tree_view->priv->validate_rows_timer = 0;
+    {
+      GtkRequisition requisition;
+      /* 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));
+    }
 
-  GDK_THREADS_LEAVE ();
+  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 (path) gtk_tree_path_free (path);
 
   return retval;
 }
 
 static gboolean
-presize_handler_callback (gpointer data)
+validate_rows (GtkTreeView *tree_view)
 {
-  GtkTreeView *tree_view = GTK_TREE_VIEW (data);
+  gboolean retval;
+  
+  retval = do_validate_rows (tree_view);
+  
+  if (! retval && tree_view->priv->validate_rows_timer)
+    {
+      g_source_remove (tree_view->priv->validate_rows_timer);
+      tree_view->priv->validate_rows_timer = 0;
+    }
+  
+  return retval;
+}
+
+static gboolean
+validate_rows_handler (GtkTreeView *tree_view)
+{
+  gboolean retval;
 
   GDK_THREADS_ENTER ();
 
+  retval = do_validate_rows (tree_view);
+  if (! retval)
+    tree_view->priv->validate_rows_timer = 0;
+
+  GDK_THREADS_LEAVE ();
+
+  return retval;
+}
+
+static gboolean
+do_presize_handler (GtkTreeView *tree_view)
+{
   if (tree_view->priv->mark_rows_col_dirty)
     {
       if (tree_view->priv->tree)
@@ -3455,6 +4266,16 @@ presize_handler_callback (gpointer data)
   validate_visible_area (tree_view);
   tree_view->priv->presize_handler_timer = 0;
                   
+  return FALSE;
+}
+
+static gboolean
+presize_handler_callback (gpointer data)
+{
+  GDK_THREADS_ENTER ();
+
+  do_presize_handler (GTK_TREE_VIEW (data));
+                  
   GDK_THREADS_LEAVE ();
 
   return FALSE;
@@ -3478,6 +4299,37 @@ install_presize_handler (GtkTreeView *tree_view)
     }
 }
 
+static gboolean
+scroll_sync_handler (GtkTreeView *tree_view)
+{
+
+  GDK_THREADS_ENTER ();
+
+  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);
+
+  tree_view->priv->scroll_sync_timer = 0;
+
+  GDK_THREADS_LEAVE ();
+
+  return FALSE;
+}
+
+static void
+install_scroll_sync_handler (GtkTreeView *tree_view)
+{
+  if (! GTK_WIDGET_REALIZED (tree_view))
+    return;
+
+  if (!tree_view->priv->scroll_sync_timer)
+    {
+      tree_view->priv->scroll_sync_timer =
+       g_idle_add_full (GTK_TREE_VIEW_PRIORITY_SCROLL_SYNC, (GSourceFunc) scroll_sync_handler, tree_view, NULL);
+    }
+}
+
 /* Always call this iff dy is in the visible range.  If the tree is empty, then
  * it's set to be NULL, and top_row_dy is 0;
  */
@@ -3507,6 +4359,52 @@ gtk_tree_view_dy_to_top_row (GtkTreeView *tree_view)
   gtk_tree_path_free (path);
 }
 
+static void
+gtk_tree_view_top_row_to_dy (GtkTreeView *tree_view)
+{
+  GtkTreePath *path;
+  GtkRBTree *tree;
+  GtkRBNode *node;
+
+  if (tree_view->priv->top_row)
+    path = gtk_tree_row_reference_get_path (tree_view->priv->top_row);
+  else
+    path = NULL;
+
+  if (!path)
+    tree = NULL;
+  else
+    _gtk_tree_view_find_node (tree_view, path, &tree, &node);
+
+  if (path)
+    gtk_tree_path_free (path);
+
+  if (tree == NULL)
+    {
+      /* keep dy and set new toprow */
+      gtk_tree_row_reference_free (tree_view->priv->top_row);
+      tree_view->priv->top_row = NULL;
+      tree_view->priv->top_row_dy = 0;
+      /* DO NOT install the idle handler */
+      gtk_tree_view_dy_to_top_row (tree_view);
+      return;
+    }
+
+  if (MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size)
+      < tree_view->priv->top_row_dy)
+    {
+      /* new top row -- do NOT install the idle handler */
+      gtk_tree_view_dy_to_top_row (tree_view);
+      return;
+    }
+
+  tree_view->priv->dy = _gtk_rbtree_node_find_offset (tree, node);
+  tree_view->priv->dy += tree_view->priv->top_row_dy;
+  gtk_adjustment_set_value (tree_view->priv->vadjustment,
+                           (gdouble)tree_view->priv->dy);
+}
+
+
 void
 _gtk_tree_view_install_mark_rows_col_dirty (GtkTreeView *tree_view)
 {
@@ -3515,6 +4413,28 @@ _gtk_tree_view_install_mark_rows_col_dirty (GtkTreeView *tree_view)
   install_presize_handler (tree_view);
 }
 
+/*
+ * This function works synchronously (due to the while (validate_rows...)
+ * loop).
+ *
+ * There was a check for column_type != GTK_TREE_VIEW_COLUMN_AUTOSIZE
+ * here. You now need to check that yourself.
+ */
+void
+_gtk_tree_view_column_autosize (GtkTreeView *tree_view,
+                               GtkTreeViewColumn *column)
+{
+  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+  g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (column));
+
+  _gtk_tree_view_column_cell_set_dirty (column, FALSE);
+
+  do_presize_handler (tree_view);
+  while (validate_rows (tree_view));
+
+  gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+}
+
 /* Drag-and-drop */
 
 static void
@@ -3714,7 +4634,7 @@ check_model_dnd (GtkTreeModel *model,
                  "on GtkTreeView when using models that don't support "
                  "the %s interface and enabling drag-and-drop. The simplest way to do this "
                  "is to connect to '%s' and call "
-                 "gtk_signal_emit_stop_by_name() in your signal handler to prevent "
+                 "g_signal_stop_emission_by_name() in your signal handler to prevent "
                  "the default handler from running. Look at the source code "
                  "for the default handler in gtktreeview.c to get an idea what "
                  "your handler should do. (gtktreeview.c is in the GTK source "
@@ -3774,6 +4694,20 @@ open_row_timeout (gpointer data)
   return result;
 }
 
+static gint
+scroll_row_timeout (gpointer data)
+{
+  GtkTreeView *tree_view = data;
+
+  GDK_THREADS_ENTER ();
+
+  gtk_tree_view_vertical_autoscroll (tree_view);
+
+  GDK_THREADS_LEAVE ();
+
+  return TRUE;
+}
+
 /* Returns TRUE if event should not be propagated to parent widgets */
 static gboolean
 set_destination_row (GtkTreeView    *tree_view,
@@ -3831,6 +4765,9 @@ set_destination_row (GtkTreeView    *tree_view,
                                        NULL,
                                        GTK_TREE_VIEW_DROP_BEFORE);
 
+      if (path)
+       gtk_tree_path_free (path);
+
       /* don't propagate to parent though */
       return TRUE;
     }
@@ -3883,6 +4820,9 @@ set_destination_row (GtkTreeView    *tree_view,
                                        GTK_TREE_VIEW_DROP_BEFORE);
     }
 
+  if (path)
+    gtk_tree_path_free (path);
+
   return TRUE;
 }
 static GtkTreePath*
@@ -3904,12 +4844,26 @@ get_logical_dest_row (GtkTreeView *tree_view)
            pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
     {
       /* get first child, drop before it */
-      gtk_tree_path_append_index (path, 0);
+      gtk_tree_path_down (path);
     }
   else
     {
+      GtkTreeIter iter;
+      GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
+
       g_assert (pos == GTK_TREE_VIEW_DROP_AFTER);
-      gtk_tree_path_next (path);
+
+      gtk_tree_model_get_iter (model, &iter, path);
+
+      if (!gtk_tree_model_iter_next (model, &iter))
+       g_object_set_data (G_OBJECT (model), "gtk-tree-model-drop-append",
+                          GINT_TO_POINTER (1));
+      else
+        {
+         g_object_set_data (G_OBJECT (model), "gtk-tree-model-drop-append",
+                            NULL);
+         gtk_tree_path_next (path);
+       }
     }
 
   return path;
@@ -3995,7 +4949,7 @@ gtk_tree_view_maybe_begin_dragging_row (GtkTreeView      *tree_view,
                               tree_view->priv->press_start_x + 1,
                               cell_y + 1);
 
-    gdk_pixmap_unref (row_pix);
+    g_object_unref (row_pix);
   }
 
   set_source_row (context, model, path);
@@ -4162,6 +5116,11 @@ gtk_tree_view_drag_motion (GtkWidget        *widget,
           tree_view->priv->open_dest_timeout =
             gtk_timeout_add (500, open_row_timeout, tree_view);
         }
+      else if (tree_view->priv->scroll_timeout == 0)
+        {
+         tree_view->priv->scroll_timeout =
+           gtk_timeout_add (150, scroll_row_timeout, tree_view);
+       }
 
       if (target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
         {
@@ -4421,6 +5380,25 @@ gtk_tree_view_forall (GtkContainer *container,
     }
 }
 
+/* Returns TRUE if the treeview contains no "special" (editable or activatable)
+ * cells. If so we draw one big row-spanning focus rectangle.
+ */
+static gboolean
+gtk_tree_view_has_special_cell (GtkTreeView *tree_view)
+{
+  GList *list;
+
+  for (list = tree_view->priv->columns; list; list = list->next)
+    {
+      if (!((GtkTreeViewColumn *)list->data)->visible)
+       continue;
+      if (_gtk_tree_view_column_count_special_cells (list->data))
+       return TRUE;
+    }
+
+  return FALSE;
+}
+
 /* Returns TRUE if the focus is within the headers, after the focus operation is
  * done
  */
@@ -4440,33 +5418,34 @@ gtk_tree_view_header_focus (GtkTreeView      *tree_view,
   focus_child = GTK_CONTAINER (tree_view)->focus_child;
   container = GTK_CONTAINER (tree_view);
 
-  last_column = g_list_last (tree_view->priv->columns);
-  while (last_column)
+  first_column = tree_view->priv->columns;
+  while (first_column)
     {
-      if (GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (last_column->data)->button) &&
-         GTK_TREE_VIEW_COLUMN (last_column->data)->clickable &&
-         GTK_TREE_VIEW_COLUMN (last_column->data)->reorderable &&
-         GTK_TREE_VIEW_COLUMN (last_column->data)->visible)
+      if (GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (first_column->data)->button) &&
+         GTK_TREE_VIEW_COLUMN (first_column->data)->visible &&
+         (GTK_TREE_VIEW_COLUMN (first_column->data)->clickable ||
+          GTK_TREE_VIEW_COLUMN (first_column->data)->reorderable))
        break;
-      last_column = last_column->prev;
+      first_column = first_column->next;
     }
 
   /* No headers are visible, or are focusable.  We can't focus in or out.
    */
-  if (last_column == NULL)
+  if (first_column == NULL)
     return FALSE;
 
-  first_column = tree_view->priv->columns;
-  while (first_column)
+  last_column = g_list_last (tree_view->priv->columns);
+  while (last_column)
     {
-      if (GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (first_column->data)->button) &&
-         GTK_TREE_VIEW_COLUMN (first_column->data)->clickable &&
-         GTK_TREE_VIEW_COLUMN (last_column->data)->reorderable &&
-         GTK_TREE_VIEW_COLUMN (first_column->data)->visible)
+      if (GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (last_column->data)->button) &&
+         GTK_TREE_VIEW_COLUMN (last_column->data)->visible &&
+         (GTK_TREE_VIEW_COLUMN (last_column->data)->clickable ||
+          GTK_TREE_VIEW_COLUMN (last_column->data)->reorderable))
        break;
-      first_column = first_column->next;
+      last_column = last_column->prev;
     }
 
+
   switch (dir)
     {
     case GTK_DIR_TAB_BACKWARD:
@@ -4619,7 +5598,7 @@ gtk_tree_view_focus (GtkWidget        *widget,
        case GTK_DIR_DOWN:
          if (tree_view->priv->tree == NULL)
            return FALSE;
-         gtk_tree_view_focus_to_cursor (tree_view);
+         gtk_widget_grab_focus (widget);
          return TRUE;
        }
     }
@@ -4640,7 +5619,7 @@ gtk_tree_view_focus (GtkWidget        *widget,
 
       if (tree_view->priv->tree == NULL)
        return FALSE;
-      gtk_tree_view_focus_to_cursor (tree_view);
+      gtk_widget_grab_focus (widget);
       return TRUE;
     }
 
@@ -4654,10 +5633,18 @@ gtk_tree_view_focus (GtkWidget        *widget,
     return FALSE;
 
   /* Other directions caught by the keybindings */
-  gtk_tree_view_focus_to_cursor (tree_view);
+  gtk_widget_grab_focus (widget);
   return TRUE;
 }
 
+static void
+gtk_tree_view_grab_focus (GtkWidget *widget)
+{
+  (* GTK_WIDGET_CLASS (parent_class)->grab_focus) (widget);
+
+  gtk_tree_view_focus_to_cursor (GTK_TREE_VIEW (widget));
+}
+
 static void
 gtk_tree_view_style_set (GtkWidget *widget,
                         GtkStyle *previous_style)
@@ -4678,7 +5665,7 @@ gtk_tree_view_style_set (GtkWidget *widget,
   for (list = tree_view->priv->columns; list; list = list->next)
     {
       column = list->data;
-      gtk_tree_view_column_cell_set_dirty (column);
+      _gtk_tree_view_column_cell_set_dirty (column, TRUE);
     }
 
   _gtk_rbtree_mark_invalid (tree_view->priv->tree);
@@ -4726,37 +5713,41 @@ gtk_tree_view_set_adjustments (GtkTreeView   *tree_view,
 
   if (tree_view->priv->hadjustment && (tree_view->priv->hadjustment != hadj))
     {
-      gtk_signal_disconnect_by_data (GTK_OBJECT (tree_view->priv->hadjustment), tree_view);
-      gtk_object_unref (GTK_OBJECT (tree_view->priv->hadjustment));
+      g_signal_handlers_disconnect_by_func (tree_view->priv->hadjustment,
+                                           gtk_tree_view_adjustment_changed,
+                                           tree_view);
+      g_object_unref (tree_view->priv->hadjustment);
     }
 
   if (tree_view->priv->vadjustment && (tree_view->priv->vadjustment != vadj))
     {
-      gtk_signal_disconnect_by_data (GTK_OBJECT (tree_view->priv->vadjustment), tree_view);
-      gtk_object_unref (GTK_OBJECT (tree_view->priv->vadjustment));
+      g_signal_handlers_disconnect_by_func (tree_view->priv->vadjustment,
+                                           gtk_tree_view_adjustment_changed,
+                                           tree_view);
+      g_object_unref (tree_view->priv->vadjustment);
     }
 
   if (tree_view->priv->hadjustment != hadj)
     {
       tree_view->priv->hadjustment = hadj;
-      gtk_object_ref (GTK_OBJECT (tree_view->priv->hadjustment));
+      g_object_ref (tree_view->priv->hadjustment);
       gtk_object_sink (GTK_OBJECT (tree_view->priv->hadjustment));
 
-      gtk_signal_connect (GTK_OBJECT (tree_view->priv->hadjustment), "value_changed",
-                         (GtkSignalFunc) gtk_tree_view_adjustment_changed,
-                         tree_view);
+      g_signal_connect (tree_view->priv->hadjustment, "value_changed",
+                       G_CALLBACK (gtk_tree_view_adjustment_changed),
+                       tree_view);
       need_adjust = TRUE;
     }
 
   if (tree_view->priv->vadjustment != vadj)
     {
       tree_view->priv->vadjustment = vadj;
-      gtk_object_ref (GTK_OBJECT (tree_view->priv->vadjustment));
+      g_object_ref (tree_view->priv->vadjustment);
       gtk_object_sink (GTK_OBJECT (tree_view->priv->vadjustment));
 
-      gtk_signal_connect (GTK_OBJECT (tree_view->priv->vadjustment), "value_changed",
-                         (GtkSignalFunc) gtk_tree_view_adjustment_changed,
-                         tree_view);
+      g_signal_connect (tree_view->priv->vadjustment, "value_changed",
+                       G_CALLBACK (gtk_tree_view_adjustment_changed),
+                       tree_view);
       need_adjust = TRUE;
     }
 
@@ -4765,20 +5756,23 @@ gtk_tree_view_set_adjustments (GtkTreeView   *tree_view,
 }
 
 
-static void
+static gboolean
 gtk_tree_view_real_move_cursor (GtkTreeView       *tree_view,
                                GtkMovementStep    step,
                                gint               count)
 {
-  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
-  g_return_if_fail (step == GTK_MOVEMENT_LOGICAL_POSITIONS ||
-                   step == GTK_MOVEMENT_VISUAL_POSITIONS ||
-                   step == GTK_MOVEMENT_DISPLAY_LINES ||
-                   step == GTK_MOVEMENT_PAGES ||
-                   step == GTK_MOVEMENT_BUFFER_ENDS);
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
+  g_return_val_if_fail (step == GTK_MOVEMENT_LOGICAL_POSITIONS ||
+                       step == GTK_MOVEMENT_VISUAL_POSITIONS ||
+                       step == GTK_MOVEMENT_DISPLAY_LINES ||
+                       step == GTK_MOVEMENT_PAGES ||
+                       step == GTK_MOVEMENT_BUFFER_ENDS, FALSE);
 
   if (tree_view->priv->tree == NULL)
-    return;
+    return FALSE;
+  if (!GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (tree_view)))
+    return FALSE;
+
   gtk_tree_view_stop_editing (tree_view, FALSE);
   GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
@@ -4802,6 +5796,8 @@ gtk_tree_view_real_move_cursor (GtkTreeView       *tree_view,
     default:
       g_assert_not_reached ();
     }
+
+  return TRUE;
 }
 
 static void
@@ -4892,6 +5888,9 @@ gtk_tree_view_row_changed (GtkTreeModel *model,
      */
     return;
 
+  if (tree_view->priv->edited_column)
+    gtk_tree_view_stop_editing (tree_view, TRUE);
+
   gtk_widget_style_get (GTK_WIDGET (data), "vertical_separator", &vertical_separator, NULL);
 
   if (path == NULL)
@@ -4923,7 +5922,7 @@ gtk_tree_view_row_changed (GtkTreeModel *model,
 
       if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
        {
-         gtk_tree_view_column_cell_set_dirty (column);
+         _gtk_tree_view_column_cell_set_dirty (column, TRUE);
        }
     }
 
@@ -5083,7 +6082,7 @@ gtk_tree_view_row_has_child_toggled (GtkTreeModel *model,
            if (GTK_TREE_VIEW_COLUMN (list->data)->visible)
              {
                GTK_TREE_VIEW_COLUMN (list->data)->dirty = TRUE;
-               gtk_tree_view_column_cell_set_dirty (GTK_TREE_VIEW_COLUMN (list->data));
+               _gtk_tree_view_column_cell_set_dirty (GTK_TREE_VIEW_COLUMN (list->data), TRUE);
                break;
              }
        }
@@ -5136,7 +6135,7 @@ gtk_tree_view_row_deleted (GtkTreeModel *model,
   for (list = tree_view->priv->columns; list; list = list->next)
     if (((GtkTreeViewColumn *)list->data)->visible &&
        ((GtkTreeViewColumn *)list->data)->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
-      gtk_tree_view_column_cell_set_dirty ((GtkTreeViewColumn *)list->data);
+      _gtk_tree_view_column_cell_set_dirty ((GtkTreeViewColumn *)list->data, TRUE);
 
   /* Ensure we don't have a dangling pointer to a dead node */
   ensure_unprelighted (tree_view);
@@ -5176,10 +6175,12 @@ gtk_tree_view_row_deleted (GtkTreeModel *model,
       _gtk_rbtree_remove_node (tree, node);
     }
 
+  install_scroll_sync_handler (tree_view);
+
   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
 
   if (selection_changed)
-    g_signal_emit_by_name (G_OBJECT (tree_view->priv->selection), "changed");
+    g_signal_emit_by_name (tree_view->priv->selection, "changed");
 }
 
 
@@ -5226,6 +6227,8 @@ gtk_tree_view_rows_reordered (GtkTreeModel *model,
   _gtk_rbtree_reorder (tree, new_order, len);
 
   gtk_widget_queue_draw (GTK_WIDGET (tree_view));
+
+  gtk_tree_view_dy_to_top_row (tree_view);
 }
 
 
@@ -5422,7 +6425,7 @@ gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view,
        {
          if (depth * tree_view->priv->expander_size + horizontal_separator + width > column->requested_width)
            {
-             gtk_tree_view_column_cell_set_dirty (column);
+             _gtk_tree_view_column_cell_set_dirty (column, TRUE);
              retval = TRUE;
            }
        }
@@ -5430,7 +6433,7 @@ gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view,
        {
          if (horizontal_separator + width > column->requested_width)
            {
-             gtk_tree_view_column_cell_set_dirty (column);
+             _gtk_tree_view_column_cell_set_dirty (column, TRUE);
              retval = TRUE;
            }
        }
@@ -5493,31 +6496,20 @@ gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view,
                                  GtkRBTree   *tree,
                                  GtkRBNode   *node)
 {
-  gint offset;
-  gint real_height;
+  GtkTreePath *path = NULL;
 
   /* We process updates because we want to clear old selected items when we scroll.
    * if this is removed, we get a "selection streak" at the bottom. */
-  if (GTK_WIDGET_REALIZED (tree_view))
-    gdk_window_process_updates (tree_view->priv->bin_window, TRUE);
-
-  real_height = MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
-
-  offset = _gtk_rbtree_node_find_offset (tree, node);
+  if (!GTK_WIDGET_REALIZED (tree_view))
+    return;
 
-  /* we reverse the order, b/c in the unusual case of the
-   * node's height being taller then the visible area, we'd rather
-   * have the node flush to the top
-   */
-  if (offset + real_height >
-      tree_view->priv->vadjustment->value + tree_view->priv->vadjustment->page_size)
-    gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment),
-                             offset + real_height -
-                             tree_view->priv->vadjustment->page_size);
-  if (offset < tree_view->priv->vadjustment->value)
-    gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment),
-                             offset);
+  path = _gtk_tree_view_find_path (tree_view, tree, node);
 
+  if (path)
+    {
+      gtk_tree_view_scroll_to_cell (tree_view, path, NULL, FALSE, 0.0, 0.0);
+      gtk_tree_path_free (path);
+    }
 }
 
 static void
@@ -5658,29 +6650,29 @@ gtk_tree_view_add_move_binding (GtkBindingSet  *binding_set,
                                GtkMovementStep step,
                                gint            count)
 {
-
+  
   gtk_binding_entry_add_signal (binding_set, keyval, modmask,
                                 "move_cursor", 2,
-                                GTK_TYPE_ENUM, step,
-                                GTK_TYPE_INT, count);
+                                G_TYPE_ENUM, step,
+                                G_TYPE_INT, count);
 
   gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
                                 "move_cursor", 2,
-                                GTK_TYPE_ENUM, step,
-                                GTK_TYPE_INT, count);
+                                G_TYPE_ENUM, step,
+                                G_TYPE_INT, count);
 
   if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
    return;
 
   gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
                                 "move_cursor", 2,
-                                GTK_TYPE_ENUM, step,
-                                GTK_TYPE_INT, count);
+                                G_TYPE_ENUM, step,
+                                G_TYPE_INT, count);
 
   gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK,
                                 "move_cursor", 2,
-                                GTK_TYPE_ENUM, step,
-                                GTK_TYPE_INT, count);
+                                G_TYPE_ENUM, step,
+                                G_TYPE_INT, count);
 }
 
 static gint
@@ -5706,7 +6698,9 @@ gtk_tree_view_unref_tree_helper (GtkTreeModel *model,
          while (new_node && new_node->left != new_tree->nil)
            new_node = new_node->left;
 
-         g_return_val_if_fail (gtk_tree_model_iter_children (model, &child, iter), FALSE);
+         if (!gtk_tree_model_iter_children (model, &child, iter))
+           return FALSE;
+
          retval = retval || gtk_tree_view_unref_tree_helper (model, &child, new_tree, new_node);
        }
 
@@ -5838,7 +6832,7 @@ gtk_tree_view_set_column_drag_info (GtkTreeView       *tree_view,
        {
          gint width;
 
-         gdk_window_get_size (tree_view->priv->header_window, &width, NULL);
+         gdk_drawable_get_size (tree_view->priv->header_window, &width, NULL);
          reorder->right_align = width + TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER (tree_view);
        }
     }
@@ -5848,9 +6842,11 @@ void
 _gtk_tree_view_column_start_drag (GtkTreeView       *tree_view,
                                  GtkTreeViewColumn *column)
 {
-  GdkEvent send_event;
+  GdkEvent *send_event;
   GtkAllocation allocation;
   gint x, y, width, height;
+  GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (tree_view));
+  GdkDisplay *display = gdk_screen_get_display (screen);
 
   g_return_if_fail (tree_view->priv->column_drag_info == NULL);
 
@@ -5877,34 +6873,36 @@ _gtk_tree_view_column_start_drag (GtkTreeView       *tree_view,
       gdk_window_set_user_data (tree_view->priv->drag_window, GTK_WIDGET (tree_view));
     }
 
-  gdk_pointer_ungrab (GDK_CURRENT_TIME);
-  gdk_keyboard_ungrab (GDK_CURRENT_TIME);
+  gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
+  gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
 
   gtk_grab_remove (column->button);
 
-  send_event.crossing.type = GDK_LEAVE_NOTIFY;
-  send_event.crossing.send_event = TRUE;
-  send_event.crossing.window = column->button->window;
-  send_event.crossing.subwindow = NULL;
-  send_event.crossing.detail = GDK_NOTIFY_ANCESTOR;
-  send_event.crossing.time = GDK_CURRENT_TIME;
-
-  gtk_propagate_event (column->button, &send_event);
-
-  send_event.button.type = GDK_BUTTON_RELEASE;
-  send_event.button.window = GDK_ROOT_PARENT ();
-  send_event.button.send_event = TRUE;
-  send_event.button.time = GDK_CURRENT_TIME;
-  send_event.button.x = -1;
-  send_event.button.y = -1;
-  send_event.button.axes = NULL;
-  send_event.button.state = 0;
-  send_event.button.button = 1;
-  send_event.button.device = gdk_device_get_core_pointer ();
-  send_event.button.x_root = 0;
-  send_event.button.y_root = 0;
-
-  gtk_propagate_event (column->button, &send_event);
+  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.subwindow = NULL;
+  send_event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+  send_event->crossing.time = GDK_CURRENT_TIME;
+
+  gtk_propagate_event (column->button, send_event);
+  gdk_event_free (send_event);
+
+  send_event = gdk_event_new (GDK_BUTTON_RELEASE);
+  send_event->button.window = g_object_ref (gdk_screen_get_root_window (screen));
+  send_event->button.send_event = TRUE;
+  send_event->button.time = GDK_CURRENT_TIME;
+  send_event->button.x = -1;
+  send_event->button.y = -1;
+  send_event->button.axes = NULL;
+  send_event->button.state = 0;
+  send_event->button.button = 1;
+  send_event->button.device = gdk_display_get_core_pointer (display);
+  send_event->button.x_root = 0;
+  send_event->button.y_root = 0;
+
+  gtk_propagate_event (column->button, send_event);
+  gdk_event_free (send_event);
 
   gdk_window_move_resize (tree_view->priv->drag_window,
                          column->button->allocation.x,
@@ -5929,7 +6927,7 @@ _gtk_tree_view_column_start_drag (GtkTreeView       *tree_view,
   gdk_window_show (tree_view->priv->drag_window);
 
   gdk_window_get_origin (tree_view->priv->header_window, &x, &y);
-  gdk_window_get_size (tree_view->priv->header_window, &width, &height);
+  gdk_drawable_get_size (tree_view->priv->header_window, &width, &height);
 
   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
   while (gtk_events_pending ())
@@ -6104,7 +7102,6 @@ gtk_tree_view_focus_to_cursor (GtkTreeView *tree_view)
     return;
 
   GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
-  gtk_widget_grab_focus (GTK_WIDGET (tree_view));
 
   cursor_path = NULL;
   if (tree_view->priv->cursor)
@@ -6112,16 +7109,18 @@ gtk_tree_view_focus_to_cursor (GtkTreeView *tree_view)
 
   if (cursor_path == NULL)
     {
-      cursor_path = gtk_tree_path_new_root ();
+      cursor_path = gtk_tree_path_new_first ();
       gtk_tree_row_reference_free (tree_view->priv->cursor);
       tree_view->priv->cursor = NULL;
 
       if (tree_view->priv->selection->type == GTK_SELECTION_MULTIPLE)
-       gtk_tree_view_real_set_cursor (tree_view, cursor_path, FALSE);
+       gtk_tree_view_real_set_cursor (tree_view, cursor_path, FALSE, FALSE);
       else
-       gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE);
+       gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, FALSE);
     }
+  gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
   gtk_tree_path_free (cursor_path);
+
   if (tree_view->priv->focus_column == NULL)
     {
       GList *list;
@@ -6146,6 +7145,9 @@ gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view,
   GtkRBNode *new_cursor_node = NULL;
   GtkTreePath *cursor_path = NULL;
 
+  if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+    return;
+
   cursor_path = NULL;
   if (!gtk_tree_row_reference_valid (tree_view->priv->cursor))
     /* FIXME: we lost the cursor; should we get the first? */
@@ -6169,7 +7171,7 @@ gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view,
   if (new_cursor_node)
     {
       cursor_path = _gtk_tree_view_find_path (tree_view, new_cursor_tree, new_cursor_node);
-      gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE);
+      gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, TRUE);
       gtk_tree_path_free (cursor_path);
     }
   else
@@ -6190,6 +7192,9 @@ gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
   gint y;
   gint vertical_separator;
 
+  if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+    return;
+
   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
   else
@@ -6209,12 +7214,22 @@ gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
 
   y = _gtk_rbtree_node_find_offset (cursor_tree, cursor_node);
   y += count * tree_view->priv->vadjustment->page_size;
+  if (count > 0)
+    y -= MAX (GTK_RBNODE_GET_HEIGHT (cursor_node),
+             tree_view->priv->expander_size);
+  else if (count < 0)
+    y += MAX (GTK_RBNODE_GET_HEIGHT (cursor_node),
+             tree_view->priv->expander_size);
   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);
   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);
+  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_path_free (cursor_path);
 }
 
@@ -6230,6 +7245,9 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
   GList *list;
   gboolean found_column = FALSE;
 
+  if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+    return;
+
   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
   else
@@ -6266,7 +7284,9 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
                                               &iter,
                                               GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT),
                                               cursor_node->children?TRUE:FALSE);
-      if (gtk_tree_view_column_cell_focus (column, count))
+      if (_gtk_tree_view_column_cell_focus (column, count,
+                                           list->prev?TRUE:FALSE,
+                                           list->next?TRUE:FALSE))
        {
          tree_view->priv->focus_column = column;
          found_column = TRUE;
@@ -6281,11 +7301,12 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
 
   if (found_column)
     {
-      _gtk_tree_view_queue_draw_node (tree_view,
-                                    cursor_tree,
-                                    cursor_node,
-                                    NULL);
-      g_signal_emit (G_OBJECT (tree_view), tree_view_signals[CURSOR_CHANGED], 0);
+      if (!gtk_tree_view_has_special_cell (tree_view))
+       _gtk_tree_view_queue_draw_node (tree_view,
+                                       cursor_tree,
+                                       cursor_node,
+                                       NULL);
+      g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
     }
   gtk_tree_view_clamp_column_visible (tree_view, tree_view->priv->focus_column);
 }
@@ -6298,6 +7319,9 @@ gtk_tree_view_move_cursor_start_end (GtkTreeView *tree_view,
   GtkRBNode *cursor_node;
   GtkTreePath *path;
 
+  if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+    return;
+
   g_return_if_fail (tree_view->priv->tree != NULL);
 
   if (count == -1)
@@ -6325,25 +7349,32 @@ gtk_tree_view_move_cursor_start_end (GtkTreeView *tree_view,
     }
 
   path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
-  _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
-                                           cursor_node,
-                                           cursor_tree,
-                                           path,
-                                           FALSE?GDK_SHIFT_MASK:0);
-
-  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, path);
-  gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
+  gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
+  gtk_tree_path_free (path);
 }
 
 static void
 gtk_tree_view_real_select_all (GtkTreeView *tree_view)
 {
+  if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+    return;
+
   if (tree_view->priv->selection->type != GTK_SELECTION_MULTIPLE)
     return;
   gtk_tree_selection_select_all (tree_view->priv->selection);
 }
 
+static void
+gtk_tree_view_real_unselect_all (GtkTreeView *tree_view)
+{
+  if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+    return;
+
+  if (tree_view->priv->selection->type != GTK_SELECTION_MULTIPLE)
+    return;
+  gtk_tree_selection_unselect_all (tree_view->priv->selection);
+}
+
 static void
 gtk_tree_view_real_select_cursor_row (GtkTreeView *tree_view,
                                      gboolean     start_editing)
@@ -6354,6 +7385,9 @@ gtk_tree_view_real_select_cursor_row (GtkTreeView *tree_view,
   GdkModifierType state = 0;
   cursor_path = NULL;
 
+  if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+    return;
+
   if (tree_view->priv->cursor)
     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
 
@@ -6385,7 +7419,8 @@ gtk_tree_view_real_select_cursor_row (GtkTreeView *tree_view,
                                            cursor_node,
                                            cursor_tree,
                                            cursor_path,
-                                           state);
+                                           state,
+                                           FALSE);
 
   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
 
@@ -6405,6 +7440,9 @@ gtk_tree_view_real_toggle_cursor_row (GtkTreeView *tree_view)
   GtkRBNode *cursor_node = NULL;
   GtkTreePath *cursor_path = NULL;
 
+  if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+    return;
+
   cursor_path = NULL;
   if (tree_view->priv->cursor)
     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
@@ -6424,7 +7462,8 @@ gtk_tree_view_real_toggle_cursor_row (GtkTreeView *tree_view)
                                            cursor_node,
                                            cursor_tree,
                                            cursor_path,
-                                           GDK_CONTROL_MASK);
+                                           GDK_CONTROL_MASK,
+                                           FALSE);
 
   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
 
@@ -6445,6 +7484,9 @@ gtk_tree_view_real_expand_collapse_cursor_row (GtkTreeView *tree_view,
   GtkRBTree *tree;
   GtkRBNode *node;
 
+  if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+    return;
+
   cursor_path = NULL;
   if (tree_view->priv->cursor)
     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
@@ -6473,6 +7515,9 @@ gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
   GtkRBNode *cursor_node = NULL;
   GtkTreePath *cursor_path = NULL;
 
+  if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+    return;
+
   cursor_path = NULL;
   if (tree_view->priv->cursor)
     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
@@ -6501,14 +7546,41 @@ gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
                                                cursor_node,
                                                cursor_tree,
                                                cursor_path,
-                                               0);
+                                               0,
+                                               FALSE);
     }
 
-  gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
+  gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
+
+  gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+  gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
+  gtk_tree_path_free (cursor_path);
+}
+
+/* Cut and paste from gtkwindow.c */
+static void
+send_focus_change (GtkWidget *widget,
+                  gboolean   in)
+{
+  GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
+
+  g_object_ref (widget);
+   
+ if (in)
+    GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
+  else
+    GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
+
+  fevent->focus_change.type = GDK_FOCUS_CHANGE;
+  fevent->focus_change.window = g_object_ref (widget->window);
+  fevent->focus_change.in = in;
+  
+  gtk_widget_event (widget, fevent);
+  
+  g_object_notify (G_OBJECT (widget), "has_focus");
 
-  gtk_widget_grab_focus (GTK_WIDGET (tree_view));
-  gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
-  gtk_tree_path_free (cursor_path);
+  g_object_unref (widget);
+  gdk_event_free (fevent);
 }
 
 static void
@@ -6517,7 +7589,9 @@ gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view)
   GtkWidget *window;
   GtkWidget *entry;
   GtkWidget *search_dialog;
-  GdkEventFocus focus_event;
+
+  if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+    return;
 
   if (tree_view->priv->enable_search == FALSE ||
       tree_view->priv->search_column < 0)
@@ -6533,21 +7607,25 @@ gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view)
   gtk_window_set_title (GTK_WINDOW (window), "search dialog");
   gtk_container_set_border_width (GTK_CONTAINER (window), 3);
   gtk_window_set_modal (GTK_WINDOW (window), TRUE);
-  g_signal_connect (G_OBJECT (window), "delete_event",
+  g_signal_connect (window, "delete_event",
                    G_CALLBACK (gtk_tree_view_search_delete_event),
                    tree_view);
-  g_signal_connect (G_OBJECT (window), "key_press_event",
+  g_signal_connect (window, "key_press_event",
                    G_CALLBACK (gtk_tree_view_search_key_press_event),
                    tree_view);
-  g_signal_connect (G_OBJECT (window), "button_press_event",
+  g_signal_connect (window, "button_press_event",
                    G_CALLBACK (gtk_tree_view_search_button_press_event),
                    tree_view);
 
   /* add entry */
   entry = gtk_entry_new ();
   gtk_widget_show (entry);
-  g_signal_connect (G_OBJECT (entry), "changed",
-                   G_CALLBACK (gtk_tree_view_search_init), tree_view);
+  g_signal_connect (entry, "changed",
+                   G_CALLBACK (gtk_tree_view_search_init),
+                   tree_view);
+  g_signal_connect (entry, "populate_popup",
+                   G_CALLBACK (gtk_tree_view_search_disable_popdown),
+                   tree_view);
   gtk_container_add (GTK_CONTAINER (window), entry);
 
   /* done, show it */
@@ -6556,9 +7634,7 @@ gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view)
   gtk_widget_grab_focus (entry);
 
   /* send focus-in event */
-  focus_event.type = GDK_FOCUS_CHANGE;
-  focus_event.in = TRUE;
-  gtk_widget_event (entry, (GdkEvent *) &focus_event);
+  send_focus_change (entry, TRUE);
 
   /* position window */
 
@@ -6647,11 +7723,7 @@ gtk_tree_view_adjustment_changed (GtkAdjustment *adjustment,
 GtkWidget *
 gtk_tree_view_new (void)
 {
-  GtkTreeView *tree_view;
-
-  tree_view = GTK_TREE_VIEW (gtk_type_new (gtk_tree_view_get_type ()));
-
-  return GTK_WIDGET (tree_view);
+  return g_object_new (GTK_TYPE_TREE_VIEW, NULL);
 }
 
 /**
@@ -6665,12 +7737,7 @@ gtk_tree_view_new (void)
 GtkWidget *
 gtk_tree_view_new_with_model (GtkTreeModel *model)
 {
-  GtkTreeView *tree_view;
-
-  tree_view = GTK_TREE_VIEW (gtk_type_new (gtk_tree_view_get_type ()));
-  gtk_tree_view_set_model (tree_view, model);
-
-  return GTK_WIDGET (tree_view);
+  return g_object_new (GTK_TYPE_TREE_VIEW, "model", model, NULL);
 }
 
 /* Public Accessors
@@ -6713,18 +7780,30 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
 
   if (tree_view->priv->model)
     {
+      GList *tmplist = tree_view->priv->columns;
+
       gtk_tree_view_unref_and_check_selection_tree (tree_view, tree_view->priv->tree);
 
-      g_signal_handlers_disconnect_by_func (G_OBJECT (tree_view->priv->model),
-                                           gtk_tree_view_row_changed, tree_view);
-      g_signal_handlers_disconnect_by_func (G_OBJECT (tree_view->priv->model),
-                                           gtk_tree_view_row_inserted, tree_view);
-      g_signal_handlers_disconnect_by_func (G_OBJECT (tree_view->priv->model),
-                                           gtk_tree_view_row_has_child_toggled, tree_view);
-      g_signal_handlers_disconnect_by_func (G_OBJECT (tree_view->priv->model),
-                                           gtk_tree_view_row_deleted, tree_view);
-      g_signal_handlers_disconnect_by_func (G_OBJECT (tree_view->priv->model),
-                                           gtk_tree_view_rows_reordered, tree_view);
+      g_signal_handlers_disconnect_by_func (tree_view->priv->model,
+                                           gtk_tree_view_row_changed,
+                                           tree_view);
+      g_signal_handlers_disconnect_by_func (tree_view->priv->model,
+                                           gtk_tree_view_row_inserted,
+                                           tree_view);
+      g_signal_handlers_disconnect_by_func (tree_view->priv->model,
+                                           gtk_tree_view_row_has_child_toggled,
+                                           tree_view);
+      g_signal_handlers_disconnect_by_func (tree_view->priv->model,
+                                           gtk_tree_view_row_deleted,
+                                           tree_view);
+      g_signal_handlers_disconnect_by_func (tree_view->priv->model,
+                                           gtk_tree_view_rows_reordered,
+                                           tree_view);
+
+      for (; tmplist; tmplist = tmplist->next)
+       _gtk_tree_view_column_unset_model (tmplist->data,
+                                          tree_view->priv->model);
+
       if (tree_view->priv->tree)
        {
          _gtk_rbtree_free (tree_view->priv->tree);
@@ -6746,6 +7825,7 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
       g_object_unref (tree_view->priv->model);
       tree_view->priv->search_column = -1;
       GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_IS_LIST);
+      tree_view->priv->fixed_height_check = 0;
     }
 
   tree_view->priv->model = model;
@@ -6791,7 +7871,7 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
                        G_CALLBACK (gtk_tree_view_rows_reordered),
                        tree_view);
 
-      path = gtk_tree_path_new_root ();
+      path = gtk_tree_path_new_first ();
       if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, path))
        {
          tree_view->priv->tree = _gtk_rbtree_new ();
@@ -6800,6 +7880,7 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
       gtk_tree_path_free (path);
 
       /*  FIXME: do I need to do this? gtk_tree_view_create_buttons (tree_view); */
+      install_presize_handler (tree_view);
     }
 
   g_object_notify (G_OBJECT (tree_view), "model");
@@ -6954,7 +8035,7 @@ gtk_tree_view_set_headers_visible (GtkTreeView *tree_view,
       gdk_window_get_position (tree_view->priv->bin_window, &x, &y);
       if (headers_visible)
        {
-         gdk_window_move_resize (tree_view->priv->bin_window, x + TREE_VIEW_HEADER_HEIGHT (tree_view), y, tree_view->priv->width, GTK_WIDGET (tree_view)->allocation.height -  + TREE_VIEW_HEADER_HEIGHT (tree_view));
+         gdk_window_move_resize (tree_view->priv->bin_window, x, y  + TREE_VIEW_HEADER_HEIGHT (tree_view), tree_view->priv->width, GTK_WIDGET (tree_view)->allocation.height -  + TREE_VIEW_HEADER_HEIGHT (tree_view));
 
           if (GTK_WIDGET_MAPPED (tree_view))
             gtk_tree_view_map_buttons (tree_view);
@@ -6976,19 +8057,19 @@ gtk_tree_view_set_headers_visible (GtkTreeView *tree_view,
   tree_view->priv->vadjustment->page_increment = (GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view)) / 2;
   tree_view->priv->vadjustment->lower = 0;
   tree_view->priv->vadjustment->upper = tree_view->priv->height;
-  gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->vadjustment), "changed");
+  gtk_adjustment_changed (tree_view->priv->vadjustment);
 
   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
 
   g_object_notify (G_OBJECT (tree_view), "headers_visible");
 }
 
-
 /**
  * gtk_tree_view_columns_autosize:
  * @tree_view: A #GtkTreeView.
  *
- * Resizes all columns to their optimal width.
+ * Resizes all columns to their optimal width. Only works after the
+ * treeview has been realized.
  **/
 void
 gtk_tree_view_columns_autosize (GtkTreeView *tree_view)
@@ -7004,7 +8085,7 @@ gtk_tree_view_columns_autosize (GtkTreeView *tree_view)
       column = list->data;
       if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
        continue;
-      gtk_tree_view_column_cell_set_dirty (column);
+      _gtk_tree_view_column_cell_set_dirty (column, TRUE);
       dirty = TRUE;
     }
 
@@ -7147,7 +8228,7 @@ gtk_tree_view_remove_column (GtkTreeView       *tree_view,
 
          tmp_column = GTK_TREE_VIEW_COLUMN (list->data);
          if (tmp_column->visible)
-           gtk_tree_view_column_cell_set_dirty (tmp_column);
+           _gtk_tree_view_column_cell_set_dirty (tmp_column, TRUE);
        }
 
       if (tree_view->priv->n_columns == 0 &&
@@ -7157,8 +8238,8 @@ gtk_tree_view_remove_column (GtkTreeView       *tree_view,
       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
     }
 
-  g_object_unref (G_OBJECT (column));
-  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[COLUMNS_CHANGED], 0);
+  g_object_unref (column);
+  g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
 
   return tree_view->priv->n_columns;
 }
@@ -7183,7 +8264,7 @@ gtk_tree_view_insert_column (GtkTreeView       *tree_view,
   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
   g_return_val_if_fail (column->tree_view == NULL, -1);
 
-  g_object_ref (G_OBJECT (column));
+  g_object_ref (column);
   gtk_object_sink (GTK_OBJECT (column));
 
   if (tree_view->priv->n_columns == 0 &&
@@ -7209,12 +8290,12 @@ gtk_tree_view_insert_column (GtkTreeView       *tree_view,
        {
          column = GTK_TREE_VIEW_COLUMN (list->data);
          if (column->visible)
-           gtk_tree_view_column_cell_set_dirty (column);
+           _gtk_tree_view_column_cell_set_dirty (column, TRUE);
        }
       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
     }
 
-  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[COLUMNS_CHANGED], 0);
+  g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
 
   return tree_view->priv->n_columns;
 }
@@ -7236,7 +8317,7 @@ gtk_tree_view_insert_column (GtkTreeView       *tree_view,
 gint
 gtk_tree_view_insert_column_with_attributes (GtkTreeView     *tree_view,
                                             gint             position,
-                                            gchar           *title,
+                                            const gchar     *title,
                                             GtkCellRenderer *cell,
                                             ...)
 {
@@ -7290,7 +8371,7 @@ gtk_tree_view_insert_column_with_attributes (GtkTreeView     *tree_view,
 gint
 gtk_tree_view_insert_column_with_data_func  (GtkTreeView               *tree_view,
                                              gint                       position,
-                                             gchar                     *title,
+                                             const gchar               *title,
                                              GtkCellRenderer           *cell,
                                              GtkTreeCellDataFunc        func,
                                              gpointer                   data,
@@ -7407,7 +8488,7 @@ gtk_tree_view_move_column_after (GtkTreeView       *tree_view,
       gtk_tree_view_size_allocate_columns (GTK_WIDGET (tree_view));
     }
 
-  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[COLUMNS_CHANGED], 0);
+  g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
 }
 
 /**
@@ -7504,14 +8585,16 @@ gtk_tree_view_set_column_drag_function (GtkTreeView               *tree_view,
 /**
  * gtk_tree_view_scroll_to_point:
  * @tree_view: a #GtkTreeView
- * @tree_x: X coordinate of new top-left pixel of visible area
- * @tree_y: Y coordinate of new top-left pixel of visible area
+ * @tree_x: X coordinate of new top-left pixel of visible area, or -1
+ * @tree_y: Y coordinate of new top-left pixel of visible area, or -1
  *
  * Scrolls the tree view such that the top-left corner of the visible
  * area is @tree_x, @tree_y, where @tree_x and @tree_y are specified
  * in tree window coordinates.  The @tree_view must be realized before
  * this function is called.  If it isn't, you probably want to be
  * using gtk_tree_view_scroll_to_cell().
+ *
+ * If either @tree_x or @tree_y are -1, then that direction isn't scrolled.
  **/
 void
 gtk_tree_view_scroll_to_point (GtkTreeView *tree_view,
@@ -7527,8 +8610,10 @@ gtk_tree_view_scroll_to_point (GtkTreeView *tree_view,
   hadj = tree_view->priv->hadjustment;
   vadj = tree_view->priv->vadjustment;
 
-  gtk_adjustment_set_value (hadj, CLAMP (tree_x, hadj->lower, hadj->upper - hadj->page_size));
-  gtk_adjustment_set_value (vadj, CLAMP (tree_y, vadj->lower, vadj->upper - vadj->page_size));
+  if (tree_x != -1)
+    gtk_adjustment_set_value (hadj, CLAMP (tree_x, hadj->lower, hadj->upper - hadj->page_size));
+  if (tree_y != -1)
+    gtk_adjustment_set_value (vadj, CLAMP (tree_y, vadj->lower, vadj->upper - vadj->page_size));
 }
 
 /**
@@ -7542,12 +8627,20 @@ gtk_tree_view_scroll_to_point (GtkTreeView *tree_view,
  *
  * Moves the alignments of @tree_view to the position specified by @column and
  * @path.  If @column is %NULL, then no horizontal scrolling occurs.  Likewise,
- * if @path is %NULL no vertical scrolling occurs.  @row_align determines where
- * the row is placed, and @col_align determines where @column is placed.  Both
- * are expected to be between 0.0 and 1.0. 0.0 means left/top alignment, 1.0
- * means right/bottom alignment, 0.5 means center.  If @use_align is %FALSE,
- * then the alignment arguments are ignored, and the tree does the minimum
- * amount of work to scroll the cell onto the screen.
+ * if @path is %NULL no vertical scrolling occurs.  At a minimum, one of @column
+ * or @path need to be non-%NULL.  @row_align determines where the row is
+ * placed, and @col_align determines where @column is placed.  Both are expected
+ * to be between 0.0 and 1.0. 0.0 means left/top alignment, 1.0 means
+ * right/bottom alignment, 0.5 means center.
+ *
+ * If @use_align is %FALSE, then the alignment arguments are ignored, and the
+ * tree does the minimum amount of work to scroll the cell onto the screen.
+ * This means that the cell will be scrolled to the edge closest to it's current
+ * position.  If the cell is currently visible on the screen, nothing is done.
+ *
+ * This function only works if the model is set, and @path is a valid row on the
+ * model.  If the model changes before the @tree_view is realized, the centered
+ * path will be modified to reflect this change.
  **/
 void
 gtk_tree_view_scroll_to_cell (GtkTreeView       *tree_view,
@@ -7557,76 +8650,92 @@ gtk_tree_view_scroll_to_cell (GtkTreeView       *tree_view,
                               gfloat             row_align,
                               gfloat             col_align)
 {
-  GdkRectangle cell_rect;
-  GdkRectangle vis_rect;
-  gint dest_x, dest_y;
-  gfloat within_margin = 0;
-
-  /* FIXME work on unmapped/unrealized trees? maybe implement when
-   * we do incremental reflow for trees
-   */
-
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+  g_return_if_fail (tree_view->priv->model != NULL);
+  g_return_if_fail (tree_view->priv->tree != NULL);
   g_return_if_fail (row_align >= 0.0 && row_align <= 1.0);
   g_return_if_fail (col_align >= 0.0 && col_align <= 1.0);
   g_return_if_fail (path != NULL || column != NULL);
 
+#if 0
+  g_print ("gtk_tree_view_scroll_to_cell:\npath: %s\ncolumn: %s\nuse_align: %d\nrow_align: %f\ncol_align: %f\n",
+          gtk_tree_path_to_string (path), column?"non-null":"null", use_align, row_align, col_align);
+#endif
   row_align = CLAMP (row_align, 0.0, 1.0);
   col_align = CLAMP (col_align, 0.0, 1.0);
 
-  if (! GTK_WIDGET_REALIZED (tree_view))
+
+  /* Note: Despite the benefits that come from having one code path for the
+   * 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) ||
+      GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID))
     {
+      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;
+      tree_view->priv->scroll_to_column = NULL;
+
       if (path)
-       tree_view->priv->scroll_to_path = gtk_tree_path_copy (path);
+       tree_view->priv->scroll_to_path = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
       if (column)
        tree_view->priv->scroll_to_column = column;
       tree_view->priv->scroll_to_use_align = use_align;
       tree_view->priv->scroll_to_row_align = row_align;
       tree_view->priv->scroll_to_col_align = col_align;
 
-      return;
+      install_presize_handler (tree_view);
     }
+  else
+    {
+      GdkRectangle cell_rect;
+      GdkRectangle vis_rect;
+      gint dest_x, dest_y;
 
-  gtk_tree_view_get_cell_area (tree_view, path, column, &cell_rect);
-  gtk_tree_view_get_visible_rect (tree_view, &vis_rect);
+      gtk_tree_view_get_cell_area (tree_view, path, column, &cell_rect);
+      gtk_tree_view_widget_to_tree_coords (tree_view, cell_rect.x, cell_rect.y, &(cell_rect.x), &(cell_rect.y));
+      gtk_tree_view_get_visible_rect (tree_view, &vis_rect);
 
-  dest_x = vis_rect.x;
-  dest_y = vis_rect.y;
+      dest_x = vis_rect.x;
+      dest_y = vis_rect.y;
 
-  if (column)
-    {
-      if (use_align)
-       {
-         dest_x = cell_rect.x + cell_rect.width * row_align - vis_rect.width * row_align;
-       }
-      else
+      if (column)
        {
-         if (cell_rect.x < vis_rect.x)
-           dest_x = cell_rect.x - vis_rect.width * within_margin;
-         else if (cell_rect.x + cell_rect.width > vis_rect.x + vis_rect.width)
-           dest_x = cell_rect.x + cell_rect.width - vis_rect.width * (1 - within_margin);
+         if (use_align)
+           {
+             dest_x = cell_rect.x - ((vis_rect.width - cell_rect.width) * col_align);
+           }
+         else
+           {
+             if (cell_rect.x < vis_rect.x)
+               dest_x = cell_rect.x;
+             if (cell_rect.x + cell_rect.width > vis_rect.x + vis_rect.width)
+               dest_x = cell_rect.x + cell_rect.width - vis_rect.width;
+           }
        }
-    }
 
-  if (path)
-    {
-      if (use_align)
-       {
-         dest_y = cell_rect.y + cell_rect.height * col_align - vis_rect.height * col_align;
-       }
-      else
+      if (path)
        {
-         if (cell_rect.y < vis_rect.y)
-           dest_y = cell_rect.y - vis_rect.height * within_margin;
-         else if (cell_rect.y + cell_rect.height > vis_rect.y + vis_rect.height)
-           dest_y = cell_rect.y + cell_rect.height - vis_rect.height * (1 - within_margin);
+         if (use_align)
+           {
+             dest_y = cell_rect.y - ((vis_rect.height - cell_rect.height) * row_align);
+             dest_y = MAX (dest_y, 0);
+           }
+         else
+           {
+             if (cell_rect.y < vis_rect.y)
+               dest_y = cell_rect.y;
+             if (cell_rect.y + cell_rect.height > vis_rect.y + vis_rect.height)
+               dest_y = cell_rect.y + cell_rect.height - vis_rect.height;
+           }
        }
-    }
 
-  gtk_tree_view_scroll_to_point (tree_view, dest_x, dest_y);
+      gtk_tree_view_scroll_to_point (tree_view, dest_x, dest_y);
+    }
 }
 
-
 /**
  * gtk_tree_view_row_activated:
  * @tree_view: A #GtkTreeView
@@ -7642,7 +8751,7 @@ gtk_tree_view_row_activated (GtkTreeView       *tree_view,
 {
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
 
-  g_signal_emit (G_OBJECT(tree_view), tree_view_signals[ROW_ACTIVATED], 0, path, column);
+  g_signal_emit (tree_view, tree_view_signals[ROW_ACTIVATED], 0, path, column);
 }
 
 
@@ -7690,7 +8799,9 @@ void
 gtk_tree_view_expand_all (GtkTreeView *tree_view)
 {
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
-  g_return_if_fail (tree_view->priv->tree != NULL);
+
+  if (tree_view->priv->tree == NULL)
+    return;
 
   _gtk_rbtree_traverse (tree_view->priv->tree,
                        tree_view->priv->tree->root,
@@ -7781,13 +8892,15 @@ gtk_tree_view_collapse_all (GtkTreeView *tree_view)
   GtkRBTree *tree;
   GtkRBNode *node;
   GtkTreePath *path;
-  guint *indices;
+  gint *indices;
 
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
-  g_return_if_fail (tree_view->priv->tree != NULL);
+
+  if (tree_view->priv->tree == NULL)
+    return;
 
   path = gtk_tree_path_new ();
-  gtk_tree_path_append_index (path, 0);
+  gtk_tree_path_down (path);
   indices = gtk_tree_path_get_indices (path);
 
   tree = tree_view->priv->tree;
@@ -7806,6 +8919,40 @@ gtk_tree_view_collapse_all (GtkTreeView *tree_view)
   gtk_tree_path_free (path);
 }
 
+/**
+ * gtk_tree_view_expand_to_path:
+ * @tree_view: A #GtkTreeView.
+ * @path: path to a row.
+ *
+ * Expands the row at @path. This will also expand all parent rows of
+ * @path as necessary.
+ **/
+void
+gtk_tree_view_expand_to_path (GtkTreeView *tree_view,
+                             GtkTreePath *path)
+{
+  gint i, depth;
+  gint *indices;
+  GtkTreePath *tmp;
+
+  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+  g_return_if_fail (path != NULL);
+
+  depth = gtk_tree_path_get_depth (path);
+  indices = gtk_tree_path_get_indices (path);
+
+  tmp = gtk_tree_path_new ();
+  g_return_if_fail (tmp != NULL);
+
+  for (i = 0; i < depth; i++)
+    {
+      gtk_tree_path_append_index (tmp, indices[i]);
+      gtk_tree_view_expand_row (tree_view, tmp, FALSE);
+    }
+
+  gtk_tree_path_free (tmp);
+}
+
 /* FIXME the bool return values for expand_row and collapse_row are
  * not analagous; they should be TRUE if the row had children and
  * was not already in the requested state.
@@ -7824,9 +8971,9 @@ gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
   GtkTreeIter temp;
   gboolean expand;
 
+  if (node->children && !open_all)
+    return FALSE;
 
-  if (node->children)
-    return TRUE;
   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT))
     return FALSE;
 
@@ -7834,7 +8981,37 @@ gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
   if (! gtk_tree_model_iter_has_child (tree_view->priv->model, &iter))
     return FALSE;
 
-  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[TEST_EXPAND_ROW], 0, &iter, path, &expand);
+
+   if (node->children && open_all)
+    {
+      gboolean retval = FALSE;
+      GtkTreePath *tmp_path = gtk_tree_path_copy (path);
+
+      gtk_tree_path_append_index (tmp_path, 0);
+      tree = node->children;
+      node = tree->root;
+      while (node->left != tree->nil)
+       node = node->left;
+      /* try to expand the children */
+      do
+        {
+         gboolean t;
+        t = gtk_tree_view_real_expand_row (tree_view, tmp_path, tree, node,
+                                           TRUE, animate);
+         if (t)
+           retval = TRUE;
+
+         gtk_tree_path_next (tmp_path);
+        node = _gtk_rbtree_next (tree, node);
+       }
+      while (node != NULL);
+
+      gtk_tree_path_free (tmp_path);
+
+      return retval;
+    }
+
+  g_signal_emit (tree_view, tree_view_signals[TEST_EXPAND_ROW], 0, &iter, path, &expand);
 
   if (expand)
     return FALSE;
@@ -7874,10 +9051,9 @@ gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
       GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_COLLAPSED);
     }
 
-  if (GTK_WIDGET_MAPPED (tree_view))
-    install_presize_handler (tree_view);
+  install_presize_handler (tree_view);
 
-  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[ROW_EXPANDED], 0, &iter, path);
+  g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
   return TRUE;
 }
 
@@ -7928,13 +9104,14 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
   gboolean collapse;
   gint x, y;
   GList *list;
+  GdkDisplay *display;
 
   if (node->children == NULL)
     return FALSE;
 
   gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
 
-  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[TEST_COLLAPSE_ROW], 0, &iter, path, &collapse);
+  g_signal_emit (tree_view, tree_view_signals[TEST_COLLAPSE_ROW], 0, &iter, path, &collapse);
 
   if (collapse)
     return FALSE;
@@ -7970,7 +9147,7 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
       if (column->visible == FALSE)
        continue;
       if (gtk_tree_view_column_get_sizing (column) == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
-       gtk_tree_view_column_cell_set_dirty (column);
+       _gtk_tree_view_column_cell_set_dirty (column, TRUE);
     }
 
   if (tree_view->priv->destroy_count_func)
@@ -7978,16 +9155,67 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
       GtkTreePath *child_path;
       gint child_count = 0;
       child_path = gtk_tree_path_copy (path);
-      gtk_tree_path_append_index (child_path, 0);
+      gtk_tree_path_down (child_path);
       if (node->children)
        _gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, count_children_helper, &child_count);
       (* tree_view->priv->destroy_count_func) (tree_view, child_path, child_count, tree_view->priv->destroy_count_data);
       gtk_tree_path_free (child_path);
     }
 
+  if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
+    {
+      GtkTreePath *cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
+
+      if (gtk_tree_path_is_ancestor (path, 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,
+                                                                     path);
+       }
+      gtk_tree_path_free (cursor_path);
+    }
+
+  if (gtk_tree_row_reference_valid (tree_view->priv->anchor))
+    {
+      GtkTreePath *anchor_path = gtk_tree_row_reference_get_path (tree_view->priv->anchor);
+      if (gtk_tree_path_is_ancestor (path, anchor_path))
+       {
+         gtk_tree_row_reference_free (tree_view->priv->anchor);
+         tree_view->priv->anchor = NULL;
+       }
+      gtk_tree_path_free (anchor_path);
+    }
+
+  if (gtk_tree_row_reference_valid (tree_view->priv->last_button_press))
+    {
+      GtkTreePath *lsc = gtk_tree_row_reference_get_path (tree_view->priv->last_button_press);
+      if (gtk_tree_path_is_ancestor (path, lsc))
+        {
+         gtk_tree_row_reference_free (tree_view->priv->last_button_press);
+         tree_view->priv->last_button_press = NULL;
+       }
+      gtk_tree_path_free (lsc);
+    }
+
+  if (gtk_tree_row_reference_valid (tree_view->priv->last_button_press_2))
+    {
+      GtkTreePath *lsc = gtk_tree_row_reference_get_path (tree_view->priv->last_button_press_2);
+      if (gtk_tree_path_is_ancestor (path, lsc))
+        {
+         gtk_tree_row_reference_free (tree_view->priv->last_button_press_2);
+         tree_view->priv->last_button_press_2 = NULL;
+       }
+      gtk_tree_path_free (lsc);
+    }
+
   if (gtk_tree_view_unref_and_check_selection_tree (tree_view, node->children))
-    g_signal_emit_by_name (G_OBJECT (tree_view->priv->selection), "changed", 0);
-  _gtk_rbtree_remove (node->children);
+    {
+      _gtk_rbtree_remove (node->children);
+      g_signal_emit_by_name (tree_view->priv->selection, "changed");
+    }
+  else
+    _gtk_rbtree_remove (node->children);
 
   if (tree_view->priv->expand_collapse_timeout)
     {
@@ -8017,38 +9245,13 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
     }
 
-  if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
-    {
-      GtkTreePath *cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
-
-      if (gtk_tree_path_is_ancestor (path, 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,
-                                                                     path);
-       }
-      gtk_tree_path_free (cursor_path);
-    }
-
-  if (gtk_tree_row_reference_valid (tree_view->priv->anchor))
-      {
-      GtkTreePath *anchor_path = gtk_tree_row_reference_get_path (tree_view->priv->anchor);
-      if (gtk_tree_path_is_ancestor (path, anchor_path))
-       {
-         gtk_tree_row_reference_free (tree_view->priv->anchor);
-         tree_view->priv->anchor = NULL;
-       }
-      gtk_tree_path_free (anchor_path);
-
-    }
-
-  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[ROW_COLLAPSED], 0, &iter, path);
+  g_signal_emit (tree_view, tree_view_signals[ROW_COLLAPSED], 0, &iter, path);
 
   /* 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. */
 
-  if (gdk_window_at_pointer (&x, &y) == tree_view->priv->bin_window)
+  display = gdk_drawable_get_display (tree_view->priv->bin_window);
+  if (gdk_display_get_window_at_pointer (display, &x, &y) == tree_view->priv->bin_window)
     {
       GdkEventMotion event;
       event.window = tree_view->priv->bin_window;
@@ -8103,18 +9306,12 @@ gtk_tree_view_map_expanded_rows_helper (GtkTreeView            *tree_view,
                                        gpointer                user_data)
 {
   GtkRBNode *node;
-  gint *indices;
-  gint depth;
-  gint i = 0;
 
   if (tree == NULL || tree->root == NULL)
     return;
 
   node = tree->root;
 
-  indices = gtk_tree_path_get_indices (path);
-  depth = gtk_tree_path_get_depth (path);
-
   while (node && node->left != tree->nil)
     node = node->left;
 
@@ -8122,13 +9319,12 @@ gtk_tree_view_map_expanded_rows_helper (GtkTreeView            *tree_view,
     {
       if (node->children)
        {
-         gtk_tree_path_append_index (path, 0);
+         (* func) (tree_view, path, user_data);
+         gtk_tree_path_down (path);
          gtk_tree_view_map_expanded_rows_helper (tree_view, node->children, path, func, user_data);
          gtk_tree_path_up (path);
-         (* func) (tree_view, path, user_data);
        }
-      i++;
-      indices[depth -1] = i;
+      gtk_tree_path_next (path);
       node = _gtk_rbtree_next (tree, node);
     }
 }
@@ -8151,7 +9347,7 @@ gtk_tree_view_map_expanded_rows (GtkTreeView            *tree_view,
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
   g_return_if_fail (func != NULL);
 
-  path = gtk_tree_path_new_root ();
+  path = gtk_tree_path_new_first ();
 
   gtk_tree_view_map_expanded_rows_helper (tree_view,
                                          tree_view->priv->tree,
@@ -8217,7 +9413,7 @@ gtk_tree_view_get_reorderable (GtkTreeView *tree_view)
  * This function is a convenience function to allow you to reorder models that
  * support the #GtkDragSourceIface and the #GtkDragDestIface.  Both
  * #GtkTreeStore and #GtkListStore support these.  If @reorderable is %TRUE, then
- * the user can reorder the model by dragging and dropping columns.  The
+ * the user can reorder the model by dragging and dropping rows.  The
  * developer can listen to these changes by connecting to the model's
  * signals.
  *
@@ -8236,8 +9432,6 @@ gtk_tree_view_set_reorderable (GtkTreeView *tree_view,
   if (tree_view->priv->reorderable == reorderable)
     return;
 
-  tree_view->priv->reorderable = reorderable;
-
   if (reorderable)
     {
       gtk_tree_view_enable_model_drag_source (tree_view,
@@ -8256,13 +9450,16 @@ gtk_tree_view_set_reorderable (GtkTreeView *tree_view,
       gtk_tree_view_unset_rows_drag_dest (tree_view);
     }
 
+  tree_view->priv->reorderable = reorderable;
+
   g_object_notify (G_OBJECT (tree_view), "reorderable");
 }
 
 static void
 gtk_tree_view_real_set_cursor (GtkTreeView     *tree_view,
                               GtkTreePath     *path,
-                              gboolean         clear_and_select)
+                              gboolean         clear_and_select,
+                              gboolean         clamp_node)
 {
   GtkRBTree *tree = NULL;
   GtkRBNode *node = NULL;
@@ -8288,12 +9485,15 @@ gtk_tree_view_real_set_cursor (GtkTreeView     *tree_view,
       if (clear_and_select && !((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK))
        _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
                                                  node, tree, path,
-                                                 state);
-      gtk_tree_view_clamp_node_visible (tree_view, tree, node);
-      _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
+                                                 state, FALSE);
+      if (clamp_node)
+        {
+         gtk_tree_view_clamp_node_visible (tree_view, tree, node);
+         _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
+       }
     }
 
-  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[CURSOR_CHANGED], 0);
+  g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
 }
 
 /**
@@ -8348,13 +9548,49 @@ gtk_tree_view_set_cursor (GtkTreeView       *tree_view,
                          GtkTreePath       *path,
                          GtkTreeViewColumn *focus_column,
                          gboolean           start_editing)
+{
+  gtk_tree_view_set_cursor_on_cell (tree_view, path, focus_column,
+                                   NULL, start_editing);
+}
+
+/**
+ * gtk_tree_view_set_cursor_on_cell:
+ * @tree_view: A #GtkTreeView
+ * @path: A #GtkTreePath
+ * @focus_column: A #GtkTreeViewColumn, or %NULL
+ * @focus_cell: A #GtkCellRenderer, or %NULL
+ * @start_editing: %TRUE if the specified cell should start being edited.
+ *
+ * Sets the current keyboard focus to be at @path, and selects it.  This is
+ * useful when you want to focus the user's attention on a particular row.  If
+ * @focus_column is not %NULL, then focus is given to the column specified by
+ * it. If @focus_column and @focus_cell are not %NULL, and @focus_column
+ * contains 2 or more editable or activatable cells, then focus is given to
+ * the cell specified by @focus_cell. Additionally, if @focus_column is
+ * specified, and @start_editing is %TRUE, then editing should be started in
+ * the specified cell.  This function is often followed by
+ * @gtk_widget_grab_focus (@tree_view) in order to give keyboard focus to the
+ * widget.  Please note that editing can only happen when the widget is
+ * realized.
+ **/
+void
+gtk_tree_view_set_cursor_on_cell (GtkTreeView       *tree_view,
+                                 GtkTreePath       *path,
+                                 GtkTreeViewColumn *focus_column,
+                                 GtkCellRenderer   *focus_cell,
+                                 gboolean           start_editing)
 {
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
   g_return_if_fail (path != NULL);
   if (focus_column)
     g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (focus_column));
+  if (focus_cell)
+    {
+      g_return_if_fail (focus_column);
+      g_return_if_fail (GTK_IS_CELL_RENDERER (focus_cell));
+    }
 
-  gtk_tree_view_real_set_cursor (tree_view, path, TRUE);
+  gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
 
   if (focus_column && focus_column->visible)
     {
@@ -8369,12 +9605,13 @@ gtk_tree_view_set_cursor (GtkTreeView       *tree_view,
          }
       g_return_if_fail (column_in_tree);
       tree_view->priv->focus_column = focus_column;
+      if (focus_cell)
+       gtk_tree_view_column_focus_cell (focus_column, focus_cell);
       if (start_editing)
        gtk_tree_view_start_editing (tree_view, path);
     }
 }
 
-
 /**
  * gtk_tree_view_get_bin_window:
  * @tree_view: A #GtkTreeView
@@ -8556,9 +9793,10 @@ gtk_tree_view_get_cell_area (GtkTreeView        *tree_view,
 
   if (path)
     {
+      gboolean ret = _gtk_tree_view_find_node (tree_view, path, &tree, &node);
+
       /* Get vertical coords */
-      if (_gtk_tree_view_find_node (tree_view, path, &tree, &node) &&
-         tree != NULL)
+      if ((!ret && tree == NULL) || ret)
        return;
 
       rect->y = CELL_FIRST_PIXEL (tree_view, tree, node, vertical_separator);
@@ -8617,8 +9855,8 @@ gtk_tree_view_get_background_area (GtkTreeView        *tree_view,
     {
       /* Get vertical coords */
 
-      if (_gtk_tree_view_find_node (tree_view, path, &tree, &node) &&
-         tree != NULL)
+      if (!_gtk_tree_view_find_node (tree_view, path, &tree, &node) &&
+         tree == NULL)
        return;
 
       rect->y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
@@ -8689,7 +9927,7 @@ gtk_tree_view_widget_to_tree_coords (GtkTreeView *tree_view,
   if (tx)
     *tx = wx + tree_view->priv->hadjustment->value;
   if (ty)
-    *ty = wy + tree_view->priv->dy - TREE_VIEW_HEADER_HEIGHT (tree_view);
+    *ty = wy + tree_view->priv->dy;
 }
 
 /**
@@ -8716,7 +9954,7 @@ gtk_tree_view_tree_to_widget_coords (GtkTreeView *tree_view,
   if (wx)
     *wx = tx - tree_view->priv->hadjustment->value;
   if (wy)
-    *wy = ty - tree_view->priv->dy + TREE_VIEW_HEADER_HEIGHT (tree_view);
+    *wy = ty - tree_view->priv->dy;
 }
 
 static void
@@ -8877,6 +10115,7 @@ gtk_tree_view_set_drag_dest_row (GtkTreeView            *tree_view,
          if (new_tree && new_node)
            _gtk_tree_view_queue_draw_node (tree_view, new_tree, new_node, NULL);
        }
+      gtk_tree_path_free (current_dest);
     }
 }
 
@@ -8908,7 +10147,7 @@ gtk_tree_view_get_dest_row_at_pos (GtkTreeView             *tree_view,
 {
   gint cell_y;
   gdouble offset_into_row;
-  gdouble quarter;
+  gdouble third;
   GdkRectangle cell;
   GtkTreeViewColumn *column = NULL;
   GtkTreePath *tmp_path = NULL;
@@ -8929,8 +10168,8 @@ gtk_tree_view_get_dest_row_at_pos (GtkTreeView             *tree_view,
   if (tree_view->priv->tree == NULL)
     return FALSE;
 
-  /* If in the top quarter of a row, we drop before that row; if
-   * in the bottom quarter, drop after that row; if in the middle,
+  /* If in the top third of a row, we drop before that row; if
+   * in the bottom third, drop after that row; if in the middle,
    * and the row has children, drop into the row.
    */
 
@@ -8955,19 +10194,19 @@ gtk_tree_view_get_dest_row_at_pos (GtkTreeView             *tree_view,
 
   tmp_path = NULL;
 
-  quarter = cell.height / 4.0;
+  third = cell.height / 3.0;
 
   if (pos)
     {
-      if (offset_into_row < quarter)
+      if (offset_into_row < third)
         {
           *pos = GTK_TREE_VIEW_DROP_BEFORE;
         }
-      else if (offset_into_row < quarter * 2)
+      else if (offset_into_row < (cell.height / 2.0))
         {
           *pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE;
         }
-      else if (offset_into_row < quarter * 3)
+      else if (offset_into_row < third * 2.0)
         {
           *pos = GTK_TREE_VIEW_DROP_INTO_OR_AFTER;
         }
@@ -9083,13 +10322,12 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
         }
 
       if (gtk_tree_view_column_cell_is_visible (column))
-       gtk_tree_view_column_cell_render (column,
-                                         drawable,
-                                         &background_area,
-                                         &cell_area,
-                                         &expose_area,
-                                         0);
-
+       _gtk_tree_view_column_cell_render (column,
+                                          drawable,
+                                          &background_area,
+                                          &cell_area,
+                                          &expose_area,
+                                          0);
       cell_offset += column->width;
     }
 
@@ -9195,10 +10433,11 @@ gtk_tree_view_get_search_column (GtkTreeView *tree_view)
 /**
  * gtk_tree_view_set_search_column:
  * @tree_view: A #GtkTreeView
- * @column: the column to search in
+ * @column: the column of the model to search in
  *
- * Sets @column as the column where the interactive search code should search
- * in.  Additionally, turns on interactive 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.
  */
 void
 gtk_tree_view_set_search_column (GtkTreeView *tree_view,
@@ -9215,7 +10454,7 @@ gtk_tree_view_set_search_column (GtkTreeView *tree_view,
 }
 
 /**
- * gtk_tree_view_search_get_search_equal_func:
+ * gtk_tree_view_get_search_equal_func:
  * @tree_view: A #GtkTreeView
  *
  * Returns the compare function currently in use.
@@ -9266,13 +10505,13 @@ gtk_tree_view_search_dialog_destroy (GtkWidget   *search_dialog,
   GtkEntry *entry = (GtkEntry *)(gtk_container_get_children (GTK_CONTAINER (search_dialog)))->data;
   gint *selected_iter;
 
+  if (tree_view->priv->disable_popdown)
+    return;
+
   if (entry)
     {
-      GdkEventFocus focus_event;
-
-      focus_event.type = GDK_FOCUS_CHANGE;
-      focus_event.in = FALSE;
-      gtk_widget_event (GTK_WIDGET (entry), (GdkEvent *) &focus_event);
+      /* send focus-in event */
+      send_focus_change (GTK_WIDGET (entry), FALSE);
     }
 
   /* remove data from tree_view */
@@ -9297,25 +10536,26 @@ gtk_tree_view_search_position_func (GtkTreeView *tree_view,
   gint tree_x, tree_y;
   gint tree_width, tree_height;
   GdkWindow *tree_window = GTK_WIDGET (tree_view)->window;
+  GdkScreen *screen = gdk_drawable_get_screen (tree_window);
   GtkRequisition requisition;
 
   gtk_widget_realize (search_dialog);
 
   gdk_window_get_origin (tree_window, &tree_x, &tree_y);
-  gdk_window_get_size (tree_window,
-                      &tree_width,
-                      &tree_height);
+  gdk_drawable_get_size (tree_window,
+                        &tree_width,
+                        &tree_height);
   gtk_widget_size_request (search_dialog, &requisition);
 
-  if (tree_x + tree_width - requisition.width > gdk_screen_width ())
-    x = gdk_screen_width () - requisition.width;
+  if (tree_x + tree_width - requisition.width > gdk_screen_get_width (screen))
+    x = gdk_screen_get_width (screen) - requisition.width;
   else if (tree_x + tree_width - requisition.width < 0)
     x = 0;
   else
     x = tree_x + tree_width - requisition.width;
 
-  if (tree_y + tree_height > gdk_screen_height ())
-    y = gdk_screen_height () - requisition.height;
+  if (tree_y + tree_height > gdk_screen_get_height (screen))
+    y = gdk_screen_get_height (screen) - requisition.height;
   else if (tree_y + tree_height < 0) /* isn't really possible ... */
     y = 0;
   else
@@ -9324,6 +10564,39 @@ gtk_tree_view_search_position_func (GtkTreeView *tree_view,
   gtk_window_move (GTK_WINDOW (search_dialog), x, y);
 }
 
+static void
+gtk_tree_view_search_disable_popdown (GtkEntry *entry,
+                                     GtkMenu  *menu,
+                                     gpointer  data)
+{
+  GtkTreeView *tree_view = (GtkTreeView *)data;
+
+  tree_view->priv->disable_popdown = 1;
+  g_signal_connect (menu, "hide",
+                   G_CALLBACK (gtk_tree_view_search_enable_popdown), data);
+}
+
+static gboolean
+gtk_tree_view_real_search_enable_popdown (gpointer data)
+{
+  GtkTreeView *tree_view = (GtkTreeView *)data;
+
+  GDK_THREADS_ENTER ();
+
+  tree_view->priv->disable_popdown = 0;
+
+  GDK_THREADS_LEAVE ();
+
+  return FALSE;
+}
+
+static void
+gtk_tree_view_search_enable_popdown (GtkWidget *widget,
+                                    gpointer   data)
+{
+  g_timeout_add (200, gtk_tree_view_real_search_enable_popdown, data);
+}
+
 static gboolean
 gtk_tree_view_search_delete_event (GtkWidget *widget,
                                   GdkEventAny *event,
@@ -9414,7 +10687,7 @@ gtk_tree_view_search_move (GtkWidget   *window,
 
   /* search */
   gtk_tree_selection_unselect_all (selection);
-  gtk_tree_model_get_iter_root (model, &iter);
+  gtk_tree_model_get_iter_first (model, &iter);
 
   ret = gtk_tree_view_search_iter (model, selection, &iter, text,
                                   &count, up?((*selected_iter) - 1):((*selected_iter + 1)));
@@ -9428,7 +10701,7 @@ gtk_tree_view_search_move (GtkWidget   *window,
     {
       /* return to old iter */
       count = 0;
-      gtk_tree_model_get_iter_root (model, &iter);
+      gtk_tree_model_get_iter_first (model, &iter);
       gtk_tree_view_search_iter (model, selection,
                                 &iter, text,
                                 &count, *selected_iter);
@@ -9483,8 +10756,6 @@ gtk_tree_view_search_iter (GtkTreeModel     *model,
   GtkTreePath *path;
 
   GtkTreeView *tree_view = gtk_tree_selection_get_tree_view (selection);
-  GtkTreeViewColumn *column =
-    gtk_tree_view_get_column (tree_view, tree_view->priv->search_column);
 
   path = gtk_tree_model_get_path (model, iter);
   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
@@ -9496,10 +10767,10 @@ gtk_tree_view_search_iter (GtkTreeModel     *model,
           (*count)++;
           if (*count == n)
             {
+              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_scroll_to_cell (tree_view, path, column,
-                                           TRUE, 0.5, 0.5);
-             gtk_tree_view_real_set_cursor (tree_view, path, FALSE);
+             gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
 
              if (path)
                gtk_tree_path_free (path);
@@ -9521,7 +10792,7 @@ gtk_tree_view_search_iter (GtkTreeModel     *model,
 
          tmp = *iter;
          has_child = gtk_tree_model_iter_children (model, iter, &tmp);
-         gtk_tree_path_append_index (path, 0);
+         gtk_tree_path_down (path);
 
          /* sanity check */
          TREE_VIEW_INTERNAL_ASSERT (has_child, FALSE);
@@ -9577,9 +10848,6 @@ gtk_tree_view_search_iter (GtkTreeModel     *model,
     }
   while (1);
 
-  if (path)
-    gtk_tree_path_free (path);
-
   return FALSE;
 }
 
@@ -9616,7 +10884,7 @@ gtk_tree_view_search_init (GtkWidget   *entry,
   if (len < 1)
     return;
 
-  gtk_tree_model_get_iter_root (model, &iter);
+  gtk_tree_model_get_iter_first (model, &iter);
 
   ret = gtk_tree_view_search_iter (model, selection,
                                   &iter, text,
@@ -9672,6 +10940,9 @@ gtk_tree_view_start_editing (GtkTreeView *tree_view,
 
   path_string = gtk_tree_path_to_string (cursor_path);
   gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path);
+
+  validate_row (tree_view, cursor_tree, cursor_node, &iter, cursor_path);
+
   gtk_tree_view_column_cell_set_cell_data (tree_view->priv->focus_column,
                                           tree_view->priv->model,
                                           &iter,
@@ -9696,11 +10967,22 @@ gtk_tree_view_start_editing (GtkTreeView *tree_view,
       retval = TRUE;
       if (editable_widget != NULL)
        {
+         gint left, right;
+         GdkRectangle area;
+         GtkCellRenderer *cell;
+
+         area = cell_area;
+         cell = _gtk_tree_view_column_get_edited_cell (tree_view->priv->focus_column);
+         _gtk_tree_view_column_get_neighbor_sizes (tree_view->priv->focus_column, cell, &left, &right);
+
+         area.x += left;
+         area.width -= right + left;
+
          gtk_tree_view_real_start_editing (tree_view,
                                            tree_view->priv->focus_column,
                                            cursor_path,
                                            editable_widget,
-                                           &cell_area,
+                                           &area,
                                            NULL,
                                            flags);
        }
@@ -9719,9 +11001,15 @@ gtk_tree_view_real_start_editing (GtkTreeView       *tree_view,
                                  GdkEvent          *event,
                                  guint              flags)
 {
+  gint pre_val = tree_view->priv->vadjustment->value;
+
   tree_view->priv->edited_column = column;
   _gtk_tree_view_column_start_editing (column, GTK_CELL_EDITABLE (cell_editable));
-  gtk_tree_view_real_set_cursor (tree_view, path, FALSE);
+
+  gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
+
+  cell_area->y += pre_val - tree_view->priv->vadjustment->value;
+
   GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
   gtk_tree_view_put (tree_view,
                     GTK_WIDGET (cell_editable),
@@ -9729,18 +11017,36 @@ gtk_tree_view_real_start_editing (GtkTreeView       *tree_view,
   gtk_cell_editable_start_editing (GTK_CELL_EDITABLE (cell_editable),
                                   (GdkEvent *)event);
   gtk_widget_grab_focus (GTK_WIDGET (cell_editable));
-  g_signal_connect (cell_editable, "remove_widget", G_CALLBACK (gtk_tree_view_remove_widget), tree_view);
+  g_signal_connect (cell_editable, "remove_widget",
+                   G_CALLBACK (gtk_tree_view_remove_widget), tree_view);
 }
 
 static void
 gtk_tree_view_stop_editing (GtkTreeView *tree_view,
                            gboolean     cancel_editing)
 {
+  GtkTreeViewColumn *column;
+
   if (tree_view->priv->edited_column == NULL)
     return;
 
+  /*
+   * This is very evil. We need to do this, because
+   * gtk_cell_editable_editing_done may trigger gtk_tree_view_row_changed
+   * later on. If gtk_tree_view_row_changed notices
+   * tree_view->priv->edited_column != NULL, it'll call
+   * gtk_tree_view_stop_editing again. Bad things will happen then.
+   *
+   * Please read that again if you intend to modify anything here.
+   */
+
+  column = tree_view->priv->edited_column;
+  tree_view->priv->edited_column = NULL;
+
   if (! cancel_editing)
-    gtk_cell_editable_editing_done (tree_view->priv->edited_column->editable_widget);
+    gtk_cell_editable_editing_done (column->editable_widget);
+
+  tree_view->priv->edited_column = column;
 
-  gtk_cell_editable_remove_widget (tree_view->priv->edited_column->editable_widget);
+  gtk_cell_editable_remove_widget (column->editable_widget);
 }