]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtktreeview.c
modify and free tmp instead of path ... (patch from #97927).
[~andy/gtk] / gtk / gtktreeview.c
index 94f02634cb3568a73c753aefc72ee4dc1fbeba33..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_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
@@ -169,6 +169,7 @@ 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);
 
@@ -261,8 +262,10 @@ 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);
 
@@ -341,9 +344,9 @@ 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);
-static void     gtk_tree_view_column_autosize                (GtkTreeView       *tree_view,
-                                                             GtkTreeViewColumn *tree_column);
+                                                             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,
@@ -412,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)
     {
@@ -432,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;
@@ -486,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 */
@@ -595,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,
@@ -604,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,
@@ -613,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,
@@ -622,170 +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 | GTK_RUN_ACTION,
+                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTreeViewClass, unselect_all),
                  NULL, NULL,
                  _gtk_marshal_NONE__NONE,
-                 GTK_TYPE_NONE, 0);
+                 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,
@@ -813,28 +842,28 @@ 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);
+                               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);
 
@@ -845,58 +874,58 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   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);
 
@@ -911,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 */
@@ -925,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;
@@ -1094,16 +1127,16 @@ gtk_tree_view_destroy (GtkObject *object)
       tree_view->priv->drag_dest_row = NULL;
     }
 
-  if (tree_view->priv->last_single_clicked != NULL)
+  if (tree_view->priv->last_button_press != NULL)
     {
-      gtk_tree_row_reference_free (tree_view->priv->last_single_clicked);
-      tree_view->priv->last_single_clicked = NULL;
+      gtk_tree_row_reference_free (tree_view->priv->last_button_press);
+      tree_view->priv->last_button_press = NULL;
     }
 
-  if (tree_view->priv->last_single_clicked_2 != NULL)
+  if (tree_view->priv->last_button_press_2 != NULL)
     {
-      gtk_tree_row_reference_free (tree_view->priv->last_single_clicked_2);
-      tree_view->priv->last_single_clicked_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)
@@ -1133,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);
@@ -1357,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));
 
@@ -1482,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));
 
@@ -1537,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;
        }
@@ -1589,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);
@@ -1636,7 +1714,7 @@ gtk_tree_view_size_allocate (GtkWidget     *widget,
   tree_view->priv->vadjustment->lower = 0;
   tree_view->priv->vadjustment->upper = MAX (tree_view->priv->vadjustment->page_size, tree_view->priv->height);
 
-  if (tree_view->priv->vadjustment->value + allocation->height > tree_view->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);
@@ -1659,6 +1737,9 @@ gtk_tree_view_size_allocate (GtkWidget     *widget,
     }
 
   gtk_tree_view_size_allocate_columns (widget);
+
+  if (GTK_WIDGET_REALIZED (widget) && width_changed)
+    invalidate_last_column (tree_view);
 }
 
 static gboolean
@@ -1697,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);
@@ -1771,74 +1854,101 @@ gtk_tree_view_button_press (GtkWidget      *widget,
        }
 
       if (column == NULL)
-       return FALSE;
+       {
+         gtk_tree_path_free (path);
 
-      /* decide to edit */
+         return FALSE;
+       }
+
+      /* decide if we edit */
       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;
+         GtkTreePath *anchor;
          GtkTreeIter iter;
 
-         gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
-         gtk_tree_view_column_cell_set_cell_data (column,
-                                                  tree_view->priv->model,
-                                                  &iter,
-                                                  GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
-                                                  node->children?TRUE:FALSE);
-
-         path_string = gtk_tree_path_to_string (path);
+         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 (_gtk_tree_view_column_cell_event (column,
-                                               &cell_editable,
-                                               (GdkEvent *)event,
-                                               path_string,
-                                               &background_area,
-                                               &cell_area, flags) &&
-             tree_view->priv->cursor)
+         if ((anchor && !gtk_tree_path_compare (anchor, path))
+             || !_gtk_tree_view_column_has_editable_cell (column))
            {
-             GtkTreePath *cursor = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
+             GtkCellEditable *cell_editable = NULL;
 
-             if (cell_editable != NULL && cursor &&
-                 !gtk_tree_path_compare (cursor, path))
-               {
-                 gtk_tree_view_real_start_editing (tree_view,
-                                                   column,
-                                                   path,
-                                                   cell_editable,
-                                                   &cell_area,
+             /* 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,
-                                                   flags);
-                 gtk_tree_path_free (path);
-                 gtk_tree_path_free (cursor);
-                 return TRUE;
+                                                   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;
                }
-             if (cursor)
-               gtk_tree_path_free (cursor);
-             column_handled_click = TRUE;
+             g_free (path_string);
            }
-         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,
@@ -1862,34 +1972,44 @@ gtk_tree_view_button_press (GtkWidget      *widget,
         }
 
       if (event->button == 1 && event->type == GDK_2BUTTON_PRESS &&
-         tree_view->priv->last_single_clicked)
+         tree_view->priv->last_button_press)
        {
-         GtkTreePath *lsc = gtk_tree_row_reference_get_path (tree_view->priv->last_single_clicked);
+         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 (!gtk_tree_path_compare (lsc, path))
-               gtk_tree_view_row_activated (tree_view, path, column);
+               emit_row_activated = TRUE;
              gtk_tree_path_free (lsc);
            }
-
-         if (tree_view->priv->last_single_clicked)
-           gtk_tree_row_reference_free (tree_view->priv->last_single_clicked);
-         if (tree_view->priv->last_single_clicked_2)
-           gtk_tree_row_reference_free (tree_view->priv->last_single_clicked_2);
-         tree_view->priv->last_single_clicked = NULL;
-         tree_view->priv->last_single_clicked_2 = NULL;
        }
       else if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
         {
-         if (tree_view->priv->last_single_clicked)
-           gtk_tree_row_reference_free (tree_view->priv->last_single_clicked);
-         tree_view->priv->last_single_clicked = tree_view->priv->last_single_clicked_2;
-         tree_view->priv->last_single_clicked_2 = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
+         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_path_free (path);
+
       return TRUE;
     }
 
@@ -1904,9 +2024,10 @@ gtk_tree_view_button_press (GtkWidget      *widget,
        {
          gpointer drag_data;
 
-         if (event->type == GDK_2BUTTON_PRESS)
+         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);
+             _gtk_tree_view_column_autosize (tree_view, column);
              break;
            }
 
@@ -1923,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);
@@ -1947,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);
@@ -2003,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;
 }
 
@@ -2232,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;
@@ -2258,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;
        }
     }
@@ -2293,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;
@@ -2303,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);
@@ -2325,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;
@@ -2362,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;
@@ -2397,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;
@@ -2684,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);
 
@@ -2694,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)
@@ -2779,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;
@@ -2800,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;
 
@@ -2816,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.
@@ -2911,7 +3060,7 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                                                 &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)) ||
@@ -2927,7 +3076,6 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
          cell_offset += column->width;
        }
 
-
       if (node == drag_highlight)
         {
           /* Draw indicator for the drop
@@ -2984,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)
        {
@@ -3539,7 +3716,7 @@ gtk_tree_view_leave_notify (GtkWidget        *widget,
 
   ensure_unprelighted (tree_view);
 
-return TRUE;
+  return TRUE;
 }
 
 
@@ -3552,8 +3729,8 @@ gtk_tree_view_focus_out (GtkWidget     *widget,
   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));
 
@@ -3608,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);
 
@@ -3646,7 +3824,7 @@ validate_visible_area (GtkTreeView *tree_view)
   GtkRBNode *node = NULL;
   gboolean need_redraw = FALSE;
   gboolean size_changed = FALSE;
-  gboolean modify_dy = FALSE;
+  gboolean update_dy = FALSE;
   gint total_height;
   gint area_above = 0;
   gint area_below = 0;
@@ -3656,10 +3834,13 @@ validate_visible_area (GtkTreeView *tree_view)
 
   if (! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID) &&
       tree_view->priv->scroll_to_path == NULL)
-      return;
+    return;
 
   total_height = GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
 
+  if (total_height == 0)
+    return;
+
   /* First, we check to see if we need to scroll anywhere
    */
   if (tree_view->priv->scroll_to_path)
@@ -3686,10 +3867,11 @@ validate_visible_area (GtkTreeView *tree_view)
            }
          else
            {
-             /* FIXME: */
-             g_warning ("non use_align not implemented yet");
-             gtk_tree_path_free (path);
-             path = NULL;
+             /* FIXME: temporary solution, just validate a complete height
+              * and all will be fine...
+              */
+             area_above = total_height;
+             area_below = total_height;
            }
        }
       else
@@ -3844,11 +4026,35 @@ validate_visible_area (GtkTreeView *tree_view)
            size_changed = TRUE;
        }
       area_above -= MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
-      modify_dy = TRUE;
+      update_dy = TRUE;
+    }
+
+  if (size_changed)
+    {
+      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 (modify_dy)
+  if (update_dy)
     {
       gint dy;
       if (node != NULL)
@@ -3876,8 +4082,6 @@ validate_visible_area (GtkTreeView *tree_view)
     {
       tree_view->priv->scroll_to_column = NULL;
     }
-  if (size_changed)
-    gtk_widget_queue_resize (GTK_WIDGET (tree_view));
   if (need_redraw)
     gtk_widget_queue_draw (GTK_WIDGET (tree_view));
 }
@@ -3899,16 +4103,17 @@ do_validate_rows (GtkTreeView *tree_view)
   GtkTreePath *path = NULL;
   GtkTreeIter iter;
   gint i = 0;
+
+  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;
@@ -3968,25 +4173,71 @@ do_validate_rows (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 (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 when we call top_row_to_dy. */
+      gtk_widget_size_request (GTK_WIDGET (tree_view), &requisition);
+      tree_view->priv->hadjustment->upper = MAX (tree_view->priv->hadjustment->upper, (gfloat)requisition.width);
+      tree_view->priv->vadjustment->upper = MAX (tree_view->priv->vadjustment->upper, (gfloat)requisition.height);
+      gtk_adjustment_changed (tree_view->priv->hadjustment);
+      gtk_adjustment_changed (tree_view->priv->vadjustment);
+      gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+    }
+
   if (gtk_tree_row_reference_valid (tree_view->priv->top_row))
     gtk_tree_view_top_row_to_dy (tree_view);
   else
     gtk_tree_view_dy_to_top_row (tree_view);
 
   if (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;
 
   return retval;
 }
 
+static gboolean
+validate_rows (GtkTreeView *tree_view)
+{
+  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)
 {
@@ -3995,7 +4246,9 @@ validate_rows_handler (GtkTreeView *tree_view)
   GDK_THREADS_ENTER ();
 
   retval = do_validate_rows (tree_view);
-  
+  if (! retval)
+    tree_view->priv->validate_rows_timer = 0;
+
   GDK_THREADS_LEAVE ();
 
   return retval;
@@ -4046,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;
  */
@@ -4101,6 +4385,7 @@ gtk_tree_view_top_row_to_dy (GtkTreeView *tree_view)
       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;
     }
@@ -4108,7 +4393,7 @@ gtk_tree_view_top_row_to_dy (GtkTreeView *tree_view)
   if (MAX (BACKGROUND_HEIGHT (node), tree_view->priv->expander_size)
       < tree_view->priv->top_row_dy)
     {
-      /* new top row */
+      /* new top row -- do NOT install the idle handler */
       gtk_tree_view_dy_to_top_row (tree_view);
       return;
     }
@@ -4116,9 +4401,10 @@ gtk_tree_view_top_row_to_dy (GtkTreeView *tree_view)
   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,
-                           tree_view->priv->dy);
+                           (gdouble)tree_view->priv->dy);
 }
 
+
 void
 _gtk_tree_view_install_mark_rows_col_dirty (GtkTreeView *tree_view)
 {
@@ -4127,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
@@ -4326,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 "
@@ -4641,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);
@@ -5072,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
  */
@@ -5271,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;
        }
     }
@@ -5292,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;
     }
 
@@ -5306,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)
@@ -5378,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;
     }
 
@@ -5549,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)
@@ -5833,15 +6175,12 @@ gtk_tree_view_row_deleted (GtkTreeModel *model,
       _gtk_rbtree_remove_node (tree, node);
     }
 
-  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);
+  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");
 }
 
 
@@ -6157,28 +6496,20 @@ gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view,
                                  GtkRBTree   *tree,
                                  GtkRBNode   *node)
 {
-  GdkRectangle cell_rect;
-  GdkRectangle vis_rect;
-  gint dest_y;
+  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))
     return;
 
-  gdk_window_process_updates (tree_view->priv->bin_window, TRUE);
-  cell_rect.y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, BACKGROUND_FIRST_PIXEL (tree_view, tree, node));
-  cell_rect.height = BACKGROUND_HEIGHT (node);
-  gtk_tree_view_get_visible_rect (tree_view, &vis_rect);
-
-  dest_y = vis_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;
-  if (cell_rect.y < vis_rect.y)
-    dest_y = cell_rect.y;
+  path = _gtk_tree_view_find_path (tree_view, tree, node);
 
-  gtk_tree_view_scroll_to_point (tree_view, -1, dest_y);
+  if (path)
+    {
+      gtk_tree_view_scroll_to_cell (tree_view, path, NULL, FALSE, 0.0, 0.0);
+      gtk_tree_path_free (path);
+    }
 }
 
 static void
@@ -6319,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
@@ -6367,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);
        }
 
@@ -6499,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);
        }
     }
@@ -6509,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);
 
@@ -6538,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,
@@ -6590,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 ())
@@ -6765,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)
@@ -6778,11 +7114,13 @@ gtk_tree_view_focus_to_cursor (GtkTreeView *tree_view)
       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;
@@ -6807,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? */
@@ -6830,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
@@ -6851,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
@@ -6878,10 +7222,13 @@ gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
              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);
 }
@@ -6898,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
@@ -6934,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;
@@ -6949,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);
 }
@@ -6966,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)
@@ -6993,13 +7349,16 @@ gtk_tree_view_move_cursor_start_end (GtkTreeView *tree_view,
     }
 
   path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
-  gtk_tree_view_real_set_cursor (tree_view, path, TRUE);
+  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);
@@ -7008,6 +7367,9 @@ gtk_tree_view_real_select_all (GtkTreeView *tree_view)
 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);
@@ -7023,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);
 
@@ -7054,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);
 
@@ -7074,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);
@@ -7093,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);
 
@@ -7114,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);
@@ -7142,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);
@@ -7170,7 +7546,8 @@ 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);
@@ -7180,13 +7557,41 @@ gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
   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");
+
+  g_object_unref (widget);
+  gdk_event_free (fevent);
+}
+
 static void
 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)
@@ -7202,22 +7607,23 @@ 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 (G_OBJECT (entry), "populate_popup",
+  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);
@@ -7228,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 */
 
@@ -7319,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);
 }
 
 /**
@@ -7337,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
@@ -7385,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);
@@ -7418,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;
@@ -7649,31 +8057,13 @@ 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");
 }
 
-static 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));
-
-  if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
-    return;
-
-  _gtk_tree_view_column_cell_set_dirty (column, FALSE);
-
-  do_presize_handler (tree_view);
-  while (do_validate_rows (tree_view));
-
-  gtk_widget_queue_resize (GTK_WIDGET (tree_view));
-}
-
 /**
  * gtk_tree_view_columns_autosize:
  * @tree_view: A #GtkTreeView.
@@ -7848,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;
 }
@@ -7874,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 &&
@@ -7905,7 +8295,7 @@ gtk_tree_view_insert_column (GtkTreeView       *tree_view,
       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;
 }
@@ -7927,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,
                                             ...)
 {
@@ -7981,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,
@@ -8098,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);
 }
 
 /**
@@ -8361,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);
 }
 
 
@@ -8502,7 +8892,7 @@ 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));
 
@@ -8529,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.
@@ -8547,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;
 
@@ -8557,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;
@@ -8599,7 +9053,7 @@ gtk_tree_view_real_expand_row (GtkTreeView *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;
 }
 
@@ -8650,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;
@@ -8707,9 +9162,60 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
       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)
     {
@@ -8739,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;
@@ -8838,10 +9319,10 @@ gtk_tree_view_map_expanded_rows_helper (GtkTreeView            *tree_view,
     {
       if (node->children)
        {
+         (* 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);
        }
       gtk_tree_path_next (path);
       node = _gtk_rbtree_next (tree, node);
@@ -8977,7 +9458,8 @@ gtk_tree_view_set_reorderable (GtkTreeView *tree_view,
 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;
@@ -9003,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);
 }
 
 /**
@@ -9063,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)
     {
@@ -9084,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
@@ -9271,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);
@@ -9332,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);
@@ -9805,7 +10328,6 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
                                           &cell_area,
                                           &expose_area,
                                           0);
-
       cell_offset += column->width;
     }
 
@@ -9911,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,
@@ -9987,11 +10510,8 @@ gtk_tree_view_search_dialog_destroy (GtkWidget   *search_dialog,
 
   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 */
@@ -10016,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
@@ -10051,7 +10572,7 @@ gtk_tree_view_search_disable_popdown (GtkEntry *entry,
   GtkTreeView *tree_view = (GtkTreeView *)data;
 
   tree_view->priv->disable_popdown = 1;
-  g_signal_connect (G_OBJECT (menu), "hide",
+  g_signal_connect (menu, "hide",
                    G_CALLBACK (gtk_tree_view_search_enable_popdown), data);
 }
 
@@ -10235,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);
@@ -10248,10 +10767,10 @@ gtk_tree_view_search_iter (GtkTreeModel     *model,
           (*count)++;
           if (*count == n)
             {
-              gtk_tree_view_scroll_to_cell (tree_view, path, column,
-                                           TRUE, 0.5, 0.5);
+              gtk_tree_view_scroll_to_cell (tree_view, path, NULL,
+                                           TRUE, 0.5, 0.0);
               gtk_tree_selection_select_iter (selection, iter);
-             gtk_tree_view_real_set_cursor (tree_view, path, FALSE);
+             gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
 
              if (path)
                gtk_tree_path_free (path);
@@ -10329,9 +10848,6 @@ gtk_tree_view_search_iter (GtkTreeModel     *model,
     }
   while (1);
 
-  if (path)
-    gtk_tree_path_free (path);
-
   return FALSE;
 }
 
@@ -10451,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);
        }
@@ -10474,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),
@@ -10484,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);
 }