]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtktreeview.c
Moved search entries into priv data.
[~andy/gtk] / gtk / gtktreeview.c
index 54ddd15c27eb961309041b333a5566929703f345..a435faea74a4785dadf2ca3f5592d151ec978feb 100644 (file)
  */
 
 
+#include <config.h>
+#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
@@ -122,7 +121,8 @@ enum {
   PROP_REORDERABLE,
   PROP_RULES_HINT,
   PROP_ENABLE_SEARCH,
-  PROP_SEARCH_COLUMN
+  PROP_SEARCH_COLUMN,
+  PROP_FIXED_HEIGHT_MODE
 };
 
 static void     gtk_tree_view_class_init           (GtkTreeViewClass *klass);
@@ -164,6 +164,11 @@ static gboolean gtk_tree_view_button_press         (GtkWidget        *widget,
                                                    GdkEventButton   *event);
 static gboolean gtk_tree_view_button_release       (GtkWidget        *widget,
                                                    GdkEventButton   *event);
+#if 0
+static gboolean gtk_tree_view_configure            (GtkWidget         *widget,
+                                                   GdkEventConfigure *event);
+#endif
+
 static void     gtk_tree_view_set_focus_child      (GtkContainer     *container,
                                                    GtkWidget        *child);
 static gint     gtk_tree_view_focus_out            (GtkWidget        *widget,
@@ -224,16 +229,16 @@ static void gtk_tree_view_set_adjustments                 (GtkTreeView     *tree
 static gboolean gtk_tree_view_real_move_cursor            (GtkTreeView     *tree_view,
                                                           GtkMovementStep  step,
                                                           gint             count);
-static void gtk_tree_view_real_select_all                 (GtkTreeView     *tree_view);
-static void gtk_tree_view_real_unselect_all               (GtkTreeView     *tree_view);
-static void gtk_tree_view_real_select_cursor_row          (GtkTreeView     *tree_view,
+static gboolean gtk_tree_view_real_select_all             (GtkTreeView     *tree_view);
+static gboolean gtk_tree_view_real_unselect_all           (GtkTreeView     *tree_view);
+static gboolean gtk_tree_view_real_select_cursor_row      (GtkTreeView     *tree_view,
                                                           gboolean         start_editing);
-static void gtk_tree_view_real_toggle_cursor_row          (GtkTreeView     *tree_view);
-static void gtk_tree_view_real_expand_collapse_cursor_row (GtkTreeView     *tree_view,
-                                                          gboolean         logical,
-                                                          gboolean         expand,
-                                                          gboolean         open_all);
-static void gtk_tree_view_real_select_cursor_parent       (GtkTreeView     *tree_view);
+static gboolean gtk_tree_view_real_toggle_cursor_row      (GtkTreeView     *tree_view);
+static gboolean gtk_tree_view_real_expand_collapse_cursor_row (GtkTreeView     *tree_view,
+                                                              gboolean         logical,
+                                                              gboolean         expand,
+                                                              gboolean         open_all);
+static gboolean gtk_tree_view_real_select_cursor_parent   (GtkTreeView     *tree_view);
 static void gtk_tree_view_row_changed                     (GtkTreeModel    *model,
                                                           GtkTreePath     *path,
                                                           GtkTreeIter     *iter,
@@ -263,7 +268,7 @@ static gboolean validate_row             (GtkTreeView *tree_view,
                                          GtkTreePath *path);
 static void     validate_visible_area    (GtkTreeView *tree_view);
 static gboolean validate_rows_handler    (GtkTreeView *tree_view);
-static gboolean do_validate_rows        (GtkTreeView *tree_view);
+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);
@@ -348,9 +353,17 @@ static void     gtk_tree_view_real_set_cursor                (GtkTreeView
                                                              gboolean           clear_and_select,
                                                              gboolean           clamp_node);
 static gboolean gtk_tree_view_has_special_cell               (GtkTreeView       *tree_view);
+static void     column_sizing_notify                         (GObject           *object,
+                                                              GParamSpec        *pspec,
+                                                              gpointer           data);
+static void     gtk_tree_view_set_fixed_height_mode          (GtkTreeView       *tree_view,
+                                                              gboolean           enable);
+
+static gboolean expand_collapse_timeout                      (gpointer           data);
+static gboolean do_expand_collapse                           (GtkTreeView       *tree_view);
 
 /* interactive search */
-static void     gtk_tree_view_search_dialog_destroy     (GtkWidget        *search_dialog,
+static void     gtk_tree_view_search_dialog_hide     (GtkWidget        *search_dialog,
                                                         GtkTreeView      *tree_view);
 static void     gtk_tree_view_search_position_func      (GtkTreeView      *tree_view,
                                                         GtkWidget        *search_dialog);
@@ -402,7 +415,7 @@ static void gtk_tree_view_real_start_editing (GtkTreeView       *tree_view,
                                              guint              flags);
 static void gtk_tree_view_stop_editing                  (GtkTreeView *tree_view,
                                                         gboolean     cancel_editing);
-static void gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view);
+static gboolean gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view);
 static GtkTreeViewColumn *gtk_tree_view_get_drop_column (GtkTreeView       *tree_view,
                                                         GtkTreeViewColumn *column,
                                                         gint               drop_position);
@@ -416,10 +429,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)
     {
@@ -436,7 +449,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;
@@ -475,6 +490,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   widget_class->size_allocate = gtk_tree_view_size_allocate;
   widget_class->button_press_event = gtk_tree_view_button_press;
   widget_class->button_release_event = gtk_tree_view_button_release;
+  /*widget_class->configure_event = gtk_tree_view_configure;*/
   widget_class->motion_notify_event = gtk_tree_view_motion;
   widget_class->expose_event = gtk_tree_view_expose;
   widget_class->key_press_event = gtk_tree_view_key_press;
@@ -513,85 +529,93 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
   g_object_class_install_property (o_class,
                                    PROP_MODEL,
                                    g_param_spec_object ("model",
-                                                       _("TreeView Model"),
-                                                       _("The model for the tree view"),
+                                                       P_("TreeView Model"),
+                                                       P_("The model for the tree view"),
                                                        GTK_TYPE_TREE_MODEL,
                                                        G_PARAM_READWRITE));
 
   g_object_class_install_property (o_class,
                                    PROP_HADJUSTMENT,
                                    g_param_spec_object ("hadjustment",
-                                                       _("Horizontal Adjustment"),
-                                                        _("Horizontal Adjustment for the widget"),
+                                                       P_("Horizontal Adjustment"),
+                                                        P_("Horizontal Adjustment for the widget"),
                                                         GTK_TYPE_ADJUSTMENT,
                                                         G_PARAM_READWRITE));
 
   g_object_class_install_property (o_class,
                                    PROP_VADJUSTMENT,
                                    g_param_spec_object ("vadjustment",
-                                                       _("Vertical Adjustment"),
-                                                        _("Vertical Adjustment for the widget"),
+                                                       P_("Vertical Adjustment"),
+                                                        P_("Vertical Adjustment for the widget"),
                                                         GTK_TYPE_ADJUSTMENT,
                                                         G_PARAM_READWRITE));
 
   g_object_class_install_property (o_class,
                                    PROP_HEADERS_VISIBLE,
                                    g_param_spec_boolean ("headers_visible",
-                                                        _("Visible"),
-                                                        _("Show the column header buttons"),
+                                                        P_("Visible"),
+                                                        P_("Show the column header buttons"),
                                                         TRUE,
                                                         G_PARAM_READWRITE));
 
   g_object_class_install_property (o_class,
                                    PROP_HEADERS_CLICKABLE,
                                    g_param_spec_boolean ("headers_clickable",
-                                                        _("Headers Clickable"),
-                                                        _("Column headers respond to click events"),
+                                                        P_("Headers Clickable"),
+                                                        P_("Column headers respond to click events"),
                                                         FALSE,
                                                         G_PARAM_WRITABLE));
 
   g_object_class_install_property (o_class,
                                    PROP_EXPANDER_COLUMN,
                                    g_param_spec_object ("expander_column",
-                                                       _("Expander Column"),
-                                                       _("Set the column for the expander column"),
+                                                       P_("Expander Column"),
+                                                       P_("Set the column for the expander column"),
                                                        GTK_TYPE_TREE_VIEW_COLUMN,
                                                        G_PARAM_READWRITE));
 
   g_object_class_install_property (o_class,
                                    PROP_REORDERABLE,
                                    g_param_spec_boolean ("reorderable",
-                                                        _("Reorderable"),
-                                                        _("View is reorderable"),
+                                                        P_("Reorderable"),
+                                                        P_("View is reorderable"),
                                                         FALSE,
                                                         G_PARAM_READWRITE));
 
   g_object_class_install_property (o_class,
                                    PROP_RULES_HINT,
                                    g_param_spec_boolean ("rules_hint",
-                                                        _("Rules Hint"),
-                                                        _("Set a hint to the theme engine to draw rows in alternating colors"),
+                                                        P_("Rules Hint"),
+                                                        P_("Set a hint to the theme engine to draw rows in alternating colors"),
                                                         FALSE,
                                                         G_PARAM_READWRITE));
 
     g_object_class_install_property (o_class,
                                     PROP_ENABLE_SEARCH,
                                     g_param_spec_boolean ("enable_search",
-                                                          _("Enable Search"),
-                                                          _("View allows user to search through columns interactively"),
+                                                          P_("Enable Search"),
+                                                          P_("View allows user to search through columns interactively"),
                                                           TRUE,
                                                           G_PARAM_READWRITE));
 
     g_object_class_install_property (o_class,
                                     PROP_SEARCH_COLUMN,
                                     g_param_spec_int ("search_column",
-                                                      _("Search Column"),
-                                                      _("Model column to search through when searching through code"),
+                                                      P_("Search Column"),
+                                                      P_("Model column to search through when searching through code"),
                                                       -1,
                                                       G_MAXINT,
                                                       0,
                                                       G_PARAM_READWRITE));
 
+    g_object_class_install_property (o_class,
+                                     PROP_FIXED_HEIGHT_MODE,
+                                     g_param_spec_boolean ("fixed_height_mode",
+                                                           P_("Fixed Height Mode"),
+                                                           P_("Speeds up GtkTreeView by assuming that all rows have the same height"),
+                                                           FALSE,
+                                                           G_PARAM_READWRITE));
+
   /* Style properties */
 #define _TREE_VIEW_EXPANDER_SIZE 10
 #define _TREE_VIEW_VERTICAL_SEPARATOR 2
@@ -599,8 +623,8 @@ 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."),
+                                                            P_("Expander Size"),
+                                                            P_("Size of the expander arrow"),
                                                             0,
                                                             G_MAXINT,
                                                             _TREE_VIEW_EXPANDER_SIZE,
@@ -608,8 +632,8 @@ 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."),
+                                                            P_("Vertical Separator Width"),
+                                                            P_("Vertical space between cells.  Must be an even number"),
                                                             0,
                                                             G_MAXINT,
                                                             _TREE_VIEW_VERTICAL_SEPARATOR,
@@ -617,8 +641,8 @@ 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."),
+                                                            P_("Horizontal Separator Width"),
+                                                            P_("Horizontal space between cells.  Must be an even number"),
                                                             0,
                                                             G_MAXINT,
                                                             _TREE_VIEW_HORIZONTAL_SEPARATOR,
@@ -626,178 +650,205 @@ 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."),
+                                                                P_("Allow Rules"),
+                                                                P_("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."),
+                                                                P_("Indent Expanders"),
+                                                                P_("Make the expanders indented"),
                                                                 TRUE,
                                                                 G_PARAM_READABLE));
+
+  gtk_widget_class_install_style_property (widget_class,
+                                           g_param_spec_boxed ("even_row_color",
+                                                               P_("Even Row Color"),
+                                                               P_("Color to use for even rows"),
+                                                              GDK_TYPE_COLOR,
+G_PARAM_READABLE));
+
+  gtk_widget_class_install_style_property (widget_class,
+                                           g_param_spec_boxed ("odd_row_color",
+                                                               P_("Odd Row Color"),
+                                                               P_("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_BOOLEAN__ENUM_INT,
-                  GTK_TYPE_BOOL, 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_BOOLEAN__NONE,
+                 G_TYPE_BOOLEAN, 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);
+                 _gtk_marshal_BOOLEAN__NONE,
+                 G_TYPE_BOOLEAN, 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_BOOLEAN__BOOLEAN,
+                 G_TYPE_BOOLEAN, 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_BOOLEAN__NONE,
+                 G_TYPE_BOOLEAN, 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_BOOLEAN__BOOLEAN_BOOLEAN_BOOLEAN,
+                 G_TYPE_BOOLEAN, 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_BOOLEAN__NONE,
+                 G_TYPE_BOOLEAN, 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_BOOLEAN__NONE,
+                 G_TYPE_BOOLEAN, 0);
 
   /* Key bindings */
   gtk_tree_view_add_move_binding (binding_set, GDK_Up, 0,
                                  GTK_MOVEMENT_DISPLAY_LINES, -1);
+  gtk_tree_view_add_move_binding (binding_set, GDK_KP_Up, 0,
+                                 GTK_MOVEMENT_DISPLAY_LINES, -1);
 
   gtk_tree_view_add_move_binding (binding_set, GDK_Down, 0,
                                  GTK_MOVEMENT_DISPLAY_LINES, 1);
+  gtk_tree_view_add_move_binding (binding_set, GDK_KP_Down, 0,
+                                 GTK_MOVEMENT_DISPLAY_LINES, 1);
 
   gtk_tree_view_add_move_binding (binding_set, GDK_p, GDK_CONTROL_MASK,
                                  GTK_MOVEMENT_DISPLAY_LINES, -1);
@@ -807,39 +858,60 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
 
   gtk_tree_view_add_move_binding (binding_set, GDK_Home, 0,
                                  GTK_MOVEMENT_BUFFER_ENDS, -1);
+  gtk_tree_view_add_move_binding (binding_set, GDK_KP_Home, 0,
+                                 GTK_MOVEMENT_BUFFER_ENDS, -1);
 
   gtk_tree_view_add_move_binding (binding_set, GDK_End, 0,
                                  GTK_MOVEMENT_BUFFER_ENDS, 1);
+  gtk_tree_view_add_move_binding (binding_set, GDK_KP_End, 0,
+                                 GTK_MOVEMENT_BUFFER_ENDS, 1);
 
   gtk_tree_view_add_move_binding (binding_set, GDK_Page_Up, 0,
                                  GTK_MOVEMENT_PAGES, -1);
+  gtk_tree_view_add_move_binding (binding_set, GDK_KP_Page_Up, 0,
+                                 GTK_MOVEMENT_PAGES, -1);
 
   gtk_tree_view_add_move_binding (binding_set, GDK_Page_Down, 0,
                                  GTK_MOVEMENT_PAGES, 1);
+  gtk_tree_view_add_move_binding (binding_set, GDK_KP_Page_Down, 0,
+                                 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_KP_Right, 0, "move_cursor", 2,
+                               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);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0, "move_cursor", 2,
+                               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,
+                               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);
+  gtk_binding_entry_add_signal (binding_set, GDK_Left, GDK_CONTROL_MASK,
+                                "move_cursor", 2,
+                               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);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, GDK_CONTROL_MASK,
+                                "move_cursor", 2,
+                               G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+                               G_TYPE_INT, 1);
 
-  gtk_binding_entry_add_signal (binding_set, GDK_Left, GDK_CONTROL_MASK|GDK_SHIFT_MASK, "move_cursor", 2,
-                               GTK_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
-                               GTK_TYPE_INT, -1);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, GDK_CONTROL_MASK,
+                                "move_cursor", 2,
+                               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);
 
@@ -850,58 +922,123 @@ 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);
+  gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "select_cursor_row", 1,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_ISO_Enter, 0, "select_cursor_row", 1,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "select_cursor_row", 1,
+                               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, TRUE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, FALSE);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_asterisk, 0,
+                                "expand_collapse_cursor_row", 3,
+                                G_TYPE_BOOLEAN, TRUE,
+                                G_TYPE_BOOLEAN, TRUE,
+                                G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Multiply, 0,
+                                "expand_collapse_cursor_row", 3,
+                                G_TYPE_BOOLEAN, TRUE,
+                                G_TYPE_BOOLEAN, TRUE,
+                                G_TYPE_BOOLEAN, TRUE);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_slash, 0,
+                                "expand_collapse_cursor_row", 3,
+                                G_TYPE_BOOLEAN, TRUE,
+                                G_TYPE_BOOLEAN, FALSE,
+                                G_TYPE_BOOLEAN, FALSE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Divide, 0,
+                                "expand_collapse_cursor_row", 3,
+                                G_TYPE_BOOLEAN, TRUE,
+                                G_TYPE_BOOLEAN, FALSE,
+                                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, TRUE,
+                               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, TRUE,
+                               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, TRUE,
+                               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);
-  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_Right, GDK_SHIFT_MASK,
+                                "expand_collapse_cursor_row", 3,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, GDK_SHIFT_MASK,
+                                "expand_collapse_cursor_row", 3,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_Right,
+                                GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+                                "expand_collapse_cursor_row", 3,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Right,
+                                GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+                                "expand_collapse_cursor_row", 3,
+                               G_TYPE_BOOLEAN, FALSE,
+                               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, TRUE,
+                               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, TRUE,
+                               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, TRUE,
+                               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);
-  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, TRUE,
+                               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,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, GDK_SHIFT_MASK,
+                                "expand_collapse_cursor_row", 3,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_Left,
+                                GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+                                "expand_collapse_cursor_row", 3,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, FALSE,
+                               G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Left,
+                                GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+                                "expand_collapse_cursor_row", 3,
+                               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);
 
@@ -918,7 +1055,9 @@ gtk_tree_view_init (GtkTreeView *tree_view)
 
   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;
+  tree_view->priv->flags =  GTK_TREE_VIEW_SHOW_EXPANDERS
+                            | GTK_TREE_VIEW_DRAW_KEYFOCUS
+                            | GTK_TREE_VIEW_HEADERS_VISIBLE;
 
   /* We need some padding */
   tree_view->priv->dy = 0;
@@ -933,6 +1072,8 @@ gtk_tree_view_init (GtkTreeView *tree_view)
   tree_view->priv->reorderable = FALSE;
   tree_view->priv->presize_handler_timer = 0;
   tree_view->priv->scroll_sync_timer = 0;
+  tree_view->priv->fixed_height = -1;
+  tree_view->priv->fixed_height_mode = 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);
@@ -940,6 +1081,8 @@ gtk_tree_view_init (GtkTreeView *tree_view)
   tree_view->priv->search_column = -1;
   tree_view->priv->search_dialog_position_func = gtk_tree_view_search_position_func;
   tree_view->priv->search_equal_func = gtk_tree_view_search_equal_func;
+  tree_view->priv->init_hadjust_value = TRUE;    
+  tree_view->priv->width = 0;                    
 }
 
 \f
@@ -989,6 +1132,9 @@ gtk_tree_view_set_property (GObject         *object,
     case PROP_SEARCH_COLUMN:
       gtk_tree_view_set_search_column (tree_view, g_value_get_int (value));
       break;
+    case PROP_FIXED_HEIGHT_MODE:
+      gtk_tree_view_set_fixed_height_mode (tree_view, g_value_get_boolean (value));
+      break;
     default:
       break;
     }
@@ -1033,6 +1179,9 @@ gtk_tree_view_get_property (GObject    *object,
     case PROP_SEARCH_COLUMN:
       g_value_set_int (value, tree_view->priv->search_column);
       break;
+    case PROP_FIXED_HEIGHT_MODE:
+      g_value_set_boolean (value, tree_view->priv->fixed_height_mode);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1142,13 +1291,14 @@ 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);
-  if (search_dialog)
-    gtk_tree_view_search_dialog_destroy (search_dialog,
-                                        tree_view);
+  if (tree_view->priv->search_window)
+    {
+      gtk_widget_destroy (tree_view->priv->search_window);
+      tree_view->priv->search_window = NULL;
+      tree_view->priv->search_entry = NULL;
+    }
 
-  if (tree_view->priv->search_user_data)
+  if (tree_view->priv->search_destroy)
     {
       (* tree_view->priv->search_destroy) (tree_view->priv->search_user_data);
       tree_view->priv->search_user_data = NULL;
@@ -1338,37 +1488,37 @@ gtk_tree_view_unrealize (GtkWidget *widget)
 
   if (tree_view->priv->scroll_timeout != 0)
     {
-      gtk_timeout_remove (tree_view->priv->scroll_timeout);
+      g_source_remove (tree_view->priv->scroll_timeout);
       tree_view->priv->scroll_timeout = 0;
     }
 
   if (tree_view->priv->open_dest_timeout != 0)
     {
-      gtk_timeout_remove (tree_view->priv->open_dest_timeout);
+      g_source_remove (tree_view->priv->open_dest_timeout);
       tree_view->priv->open_dest_timeout = 0;
     }
 
   if (tree_view->priv->expand_collapse_timeout != 0)
     {
-      gtk_timeout_remove (tree_view->priv->expand_collapse_timeout);
+      g_source_remove (tree_view->priv->expand_collapse_timeout);
       tree_view->priv->expand_collapse_timeout = 0;
     }
   
   if (tree_view->priv->presize_handler_timer != 0)
     {
-      gtk_timeout_remove (tree_view->priv->presize_handler_timer);
+      g_source_remove (tree_view->priv->presize_handler_timer);
       tree_view->priv->presize_handler_timer = 0;
     }
 
   if (tree_view->priv->validate_rows_timer != 0)
     {
-      gtk_timeout_remove (tree_view->priv->validate_rows_timer);
+      g_source_remove (tree_view->priv->validate_rows_timer);
       tree_view->priv->validate_rows_timer = 0;
     }
 
   if (tree_view->priv->scroll_sync_timer != 0)
     {
-      gtk_timeout_remove (tree_view->priv->scroll_sync_timer);
+      g_source_remove (tree_view->priv->scroll_sync_timer);
       tree_view->priv->scroll_sync_timer = 0;
     }
 
@@ -1430,6 +1580,7 @@ gtk_tree_view_size_request_columns (GtkTreeView *tree_view)
 }
 
 
+/* Called only by ::size_request */
 static void
 gtk_tree_view_update_size (GtkTreeView *tree_view)
 {
@@ -1440,10 +1591,12 @@ gtk_tree_view_update_size (GtkTreeView *tree_view)
   if (tree_view->priv->model == NULL)
     {
       tree_view->priv->width = 0;
+      tree_view->priv->prev_width = 0;                   
       tree_view->priv->height = 0;
       return;
     }
 
+  tree_view->priv->prev_width = tree_view->priv->width;  
   tree_view->priv->width = 0;
   /* keep this in sync with size_allocate below */
   for (list = tree_view->priv->columns, i = 0; list; list = list->next, i++)
@@ -1495,9 +1648,11 @@ gtk_tree_view_size_request (GtkWidget      *widget,
 
   tree_view = GTK_TREE_VIEW (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 */
-  do_validate_rows (tree_view);
+  /* we validate GTK_TREE_VIEW_NUM_ROWS_PER_IDLE 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 (tree_view);
   gtk_tree_view_size_request_columns (tree_view);
   gtk_tree_view_update_size (GTK_TREE_VIEW (widget));
 
@@ -1518,16 +1673,109 @@ gtk_tree_view_size_request (GtkWidget      *widget,
     }
 }
 
+
+static void
+invalidate_column (GtkTreeView       *tree_view,
+                   GtkTreeViewColumn *column)
+{
+  gint column_offset = 0;
+  GList *list;
+  GtkWidget *widget = GTK_WIDGET (tree_view);
+  gboolean rtl;
+
+  if (!GTK_WIDGET_REALIZED (widget))
+    return;
+
+  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
+  for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
+       list;
+       list = (rtl ? list->prev : list->next))
+    {
+      GtkTreeViewColumn *tmpcolumn = list->data;
+      if (tmpcolumn == column)
+       {
+         GdkRectangle invalid_rect;
+         
+         invalid_rect.x = column_offset;
+         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;
+       }
+      
+      column_offset += tmpcolumn->width;
+    }
+}
+
+static void
+invalidate_last_column (GtkTreeView *tree_view)
+{
+  GList *last_column;
+  gboolean rtl;
+
+  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
+
+  for (last_column = (rtl ? g_list_first (tree_view->priv->columns) : g_list_last (tree_view->priv->columns));
+       last_column;
+       last_column = (rtl ? last_column->next : last_column->prev))
+    {
+      if (GTK_TREE_VIEW_COLUMN (last_column->data)->visible)
+        {
+          invalidate_column (tree_view, last_column->data);
+          return;
+        }
+    }
+}
+
+static gint
+gtk_tree_view_get_real_requested_width_from_column (GtkTreeView       *tree_view,
+                                                    GtkTreeViewColumn *column)
+{
+  gint real_requested_width;
+
+  if (column->use_resized_width)
+    {
+      real_requested_width = column->resized_width;
+    }
+  else if (column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
+    {
+      real_requested_width = column->fixed_width;
+    }
+  else if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE))
+    {
+      real_requested_width = MAX (column->requested_width, column->button_request);
+    }
+  else
+    {
+      real_requested_width = column->requested_width;
+      if (real_requested_width < 0)
+        real_requested_width = 0;
+    }
+
+  if (column->min_width != -1)
+    real_requested_width = MAX (real_requested_width, column->min_width);
+  if (column->max_width != -1)
+    real_requested_width = MIN (real_requested_width, column->max_width);
+
+  return real_requested_width;
+}
+
 /* GtkWidget::size_allocate helper */
 static void
 gtk_tree_view_size_allocate_columns (GtkWidget *widget)
 {
   GtkTreeView *tree_view;
-  GList *list, *last_column;
+  GList *list, *first_column, *last_column;
   GtkTreeViewColumn *column;
   GtkAllocation allocation;
   gint width = 0;
-
+  gint extra, extra_per_column;
+  gint full_requested_width = 0;
+  gint number_of_expand_columns = 0;
+  gboolean rtl;
+  
   tree_view = GTK_TREE_VIEW (widget);
 
   for (last_column = g_list_last (tree_view->priv->columns);
@@ -1537,13 +1785,46 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
   if (last_column == NULL)
     return;
 
+  for (first_column = g_list_first (tree_view->priv->columns);
+       first_column && !(GTK_TREE_VIEW_COLUMN (first_column->data)->visible);
+       first_column = first_column->next)
+    ;
+
   allocation.y = 0;
   allocation.height = tree_view->priv->header_height;
 
+  rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
+
+  /* find out how many extra space and expandable columns we have */
   for (list = tree_view->priv->columns; list != last_column->next; list = list->next)
+    {
+      column = (GtkTreeViewColumn *)list->data;
+
+      if (!column->visible)
+       continue;
+
+      full_requested_width += gtk_tree_view_get_real_requested_width_from_column (tree_view, column);
+
+      if (column->expand)
+       number_of_expand_columns++;
+    }
+
+  extra = MAX (widget->allocation.width - full_requested_width, 0);
+  if (number_of_expand_columns > 0)
+    extra_per_column = extra/number_of_expand_columns;
+  else
+    extra_per_column = 0;
+
+  for (list = (rtl ? last_column : first_column); 
+       list != (rtl ? first_column->prev : last_column->next);
+       list = (rtl ? list->prev : list->next)) 
     {
       gint real_requested_width = 0;
+      gint old_width;
+
       column = list->data;
+      old_width = column->width;
+
       if (!column->visible)
        continue;
 
@@ -1552,90 +1833,61 @@ 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;
        }
 
-      if (column->use_resized_width)
-       {
-         real_requested_width = column->resized_width;
-       }
-      else if (column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
-       {
-         real_requested_width = column->fixed_width;
-       }
-      else if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE))
-       {
-         real_requested_width = MAX (column->requested_width, column->button_request);
-       }
-      else
-       {
-         real_requested_width = column->requested_width;
-         if (real_requested_width < 0)
-           real_requested_width = 0;
-       }
-
-      if (column->min_width != -1)
-       real_requested_width = MAX (real_requested_width, column->min_width);
-      if (column->max_width != -1)
-       real_requested_width = MIN (real_requested_width, column->max_width);
+      real_requested_width = gtk_tree_view_get_real_requested_width_from_column (tree_view, column);
 
       allocation.x = width;
       column->width = real_requested_width;
-      if (list == last_column &&
-         width + real_requested_width < widget->allocation.width)
+
+      if (column->expand)
+       {
+         if (number_of_expand_columns == 1)
+           {
+             /* We add the remander to the last column as
+              * */
+             column->width += extra;
+           }
+         else
+           {
+             column->width += extra_per_column;
+             extra -= extra_per_column;
+             number_of_expand_columns --;
+           }
+       }
+      else if (number_of_expand_columns == 0 &&
+              list == last_column)
        {
-         column->width += (widget->allocation.width - column->width - width);
+         column->width += extra;
        }
+
       g_object_notify (G_OBJECT (column), "width");
+
       allocation.width = column->width;
       width += column->width;
+
+      if (column->width > old_width)
+       invalidate_column (tree_view, column);
+
       gtk_widget_size_allocate (column->button, &allocation);
+
       if (column->window)
        gdk_window_move_resize (column->window,
-                                allocation.x + allocation.width - TREE_VIEW_DRAG_WIDTH/2,
+                                allocation.x + (rtl ? 0 : allocation.width) - TREE_VIEW_DRAG_WIDTH/2,
                                allocation.y,
                                 TREE_VIEW_DRAG_WIDTH, allocation.height);
     }
 }
 
-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,
@@ -1644,6 +1896,8 @@ gtk_tree_view_size_allocate (GtkWidget     *widget,
   GList *tmp_list;
   GtkTreeView *tree_view;
   gboolean width_changed = FALSE;
+  gboolean dy_changed = FALSE;
+  gint old_width = widget->allocation.width;           
 
   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
 
@@ -1678,8 +1932,30 @@ gtk_tree_view_size_allocate (GtkWidget     *widget,
   tree_view->priv->hadjustment->lower = 0;
   tree_view->priv->hadjustment->upper = MAX (tree_view->priv->hadjustment->page_size, tree_view->priv->width);
 
-  if (tree_view->priv->hadjustment->value + allocation->width > tree_view->priv->width)
-    tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
+  if (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL)   
+     {
+      if (allocation->width < tree_view->priv->width)
+         {
+         if (tree_view->priv->init_hadjust_value)
+           {
+           tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
+           tree_view->priv->init_hadjust_value = FALSE;
+           }
+         else if(allocation->width != old_width)
+           tree_view->priv->hadjustment->value = CLAMP(tree_view->priv->hadjustment->value - allocation->width + old_width, 0, tree_view->priv->width - allocation->width);
+         else
+           tree_view->priv->hadjustment->value = CLAMP(tree_view->priv->width - (tree_view->priv->prev_width - tree_view->priv->hadjustment->value), 0, tree_view->priv->width - allocation->width);
+         }
+      else
+         {
+         tree_view->priv->hadjustment->value = 0;
+         tree_view->priv->init_hadjust_value = TRUE;
+         }
+     }
+  else
+     if (tree_view->priv->hadjustment->value + allocation->width > tree_view->priv->width)
+        tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
+
   gtk_adjustment_changed (tree_view->priv->hadjustment);
 
   tree_view->priv->vadjustment->page_size = allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view);
@@ -1689,8 +1965,14 @@ gtk_tree_view_size_allocate (GtkWidget     *widget,
   tree_view->priv->vadjustment->upper = MAX (tree_view->priv->vadjustment->page_size, tree_view->priv->height);
 
   if (tree_view->priv->vadjustment->value + allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view) > tree_view->priv->height)
-    gtk_adjustment_set_value (tree_view->priv->vadjustment,
-                             MAX (tree_view->priv->height - tree_view->priv->vadjustment->page_size, 0));
+    {
+      double before = tree_view->priv->vadjustment->value;
+      gtk_adjustment_set_value (tree_view->priv->vadjustment,
+                               MAX (tree_view->priv->height - tree_view->priv->vadjustment->page_size, 0));
+      if (before != tree_view->priv->vadjustment->value)
+        dy_changed = TRUE;
+    }
+
   gtk_adjustment_changed (tree_view->priv->vadjustment);
   
   if (GTK_WIDGET_REALIZED (widget))
@@ -1712,8 +1994,31 @@ 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);
+  if (GTK_WIDGET_REALIZED (widget))
+    {
+      gboolean has_expand_column = FALSE;
+      for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
+       {
+         if (gtk_tree_view_column_get_expand (GTK_TREE_VIEW_COLUMN (tmp_list->data)))
+           {
+             has_expand_column = TRUE;
+             break;
+           }
+       }
+
+      /* This little hack only works if we have an LTR locale, and no column has the  */
+      if (width_changed)
+       {
+         if (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_LTR &&
+             ! has_expand_column)
+           invalidate_last_column (tree_view);
+         else
+           gtk_widget_queue_draw (widget);
+       }
+      
+      if (dy_changed)
+       gtk_widget_queue_draw (widget);
+    }
 }
 
 static gboolean
@@ -1728,17 +2033,28 @@ gtk_tree_view_button_press (GtkWidget      *widget,
   GdkRectangle cell_area;
   gint vertical_separator;
   gint horizontal_separator;
+  gboolean rtl;
 
   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
   g_return_val_if_fail (event != NULL, FALSE);
 
   tree_view = GTK_TREE_VIEW (widget);
+  rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
   gtk_tree_view_stop_editing (tree_view, FALSE);
   gtk_widget_style_get (widget,
                        "vertical_separator", &vertical_separator,
                        "horizontal_separator", &horizontal_separator,
                        NULL);
 
+
+  /* Because grab_focus can cause reentrancy, we delay grab_focus until after
+   * we're done handling the button press.
+   */
+  if (event->window == tree_view->priv->bin_window &&
+      tree_view->priv->tree != NULL)
+    {
+    }
+
   if (event->window == tree_view->priv->bin_window &&
       tree_view->priv->tree != NULL)
     {
@@ -1754,11 +2070,9 @@ gtk_tree_view_button_press (GtkWidget      *widget,
       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);
-      GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
+      gboolean row_double_click = FALSE;
+      gboolean rtl;
+      GtkWidget *grab_widget;
 
       /* are we in an arrow? */
       if (tree_view->priv->prelight_node &&
@@ -1770,11 +2084,14 @@ gtk_tree_view_button_press (GtkWidget      *widget,
              tree_view->priv->button_pressed_node = tree_view->priv->prelight_node;
              tree_view->priv->button_pressed_tree = tree_view->priv->prelight_tree;
              gtk_tree_view_draw_arrow (GTK_TREE_VIEW (widget),
-                                        tree_view->priv->prelight_tree,
+                                       tree_view->priv->prelight_tree,
                                        tree_view->priv->prelight_node,
                                        event->x,
                                        event->y);
            }
+         if (!GTK_WIDGET_HAS_FOCUS (widget))
+           gtk_widget_grab_focus (widget);
+         GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
          return TRUE;
        }
 
@@ -1785,8 +2102,13 @@ gtk_tree_view_button_press (GtkWidget      *widget,
       y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
 
       if (node == NULL)
-       /* We clicked in dead space */
-       return TRUE;
+       {
+         /* We clicked in dead space */
+         if (!GTK_WIDGET_HAS_FOCUS (widget))
+           gtk_widget_grab_focus (widget);
+         GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
+         return TRUE;
+       }
 
       /* Get the path and the node */
       path = _gtk_tree_view_find_path (tree_view, tree, node);
@@ -1796,8 +2118,11 @@ gtk_tree_view_button_press (GtkWidget      *widget,
                                    tree_view->priv->expander_size);
       background_area.x = 0;
 
+
       /* Let the column have a chance at selecting it. */
-      for (list = tree_view->priv->columns; list; list = list->next)
+      rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
+      for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
+          list; list = (rtl ? list->prev : list->next))
        {
          column = list->data;
 
@@ -1828,10 +2153,18 @@ gtk_tree_view_button_press (GtkWidget      *widget,
        }
 
       if (column == NULL)
-       return FALSE;
+       {
+         gtk_tree_path_free (path);
+         if (!GTK_WIDGET_HAS_FOCUS (widget))
+           gtk_widget_grab_focus (widget);
+         GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
+         return FALSE;
+       }
+
+      tree_view->priv->focus_column = column;
 
       /* decide if we edit */
-      if (event->type == GDK_BUTTON_PRESS &&
+      if (event->type == GDK_BUTTON_PRESS && event->button == 1 &&
          !(event->state & gtk_accelerator_get_default_mod_mask ()))
        {
          GtkTreePath *anchor;
@@ -1885,6 +2218,7 @@ gtk_tree_view_button_press (GtkWidget      *widget,
                                                        &area,
                                                        (GdkEvent *)event,
                                                        flags);
+                     g_free (path_string);
                      gtk_tree_path_free (path);
                      gtk_tree_path_free (anchor);
                      return TRUE;
@@ -1900,25 +2234,37 @@ gtk_tree_view_button_press (GtkWidget      *widget,
       /* 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);
+      /* we only handle selection modifications on the first button press
+       */
+      if (event->type == GDK_BUTTON_PRESS)
+        {
+          if ((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
+            tree_view->priv->ctrl_pressed = TRUE;
+          if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
+            tree_view->priv->shift_pressed = TRUE;
 
-      if (event->state & GDK_CONTROL_MASK)
-       {
-         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, TRUE);
-         gtk_tree_view_real_select_cursor_row (tree_view, FALSE);
-       }
-      else
-       {
-         gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
-       }
+          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, 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, TRUE);
+              gtk_tree_view_real_select_cursor_row (tree_view, FALSE);
+            }
+          else
+            {
+              gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
+            }
+
+          tree_view->priv->ctrl_pressed = FALSE;
+          tree_view->priv->shift_pressed = FALSE;
+        }
 
       /* the treeview may have been scrolled because of _set_cursor,
        * correct here
@@ -1932,7 +2278,9 @@ gtk_tree_view_button_press (GtkWidget      *widget,
 
       /* Save press to possibly begin a drag
        */
-      if (!column_handled_click &&
+      grab_widget = gtk_grab_get_current ();
+      if ((grab_widget == NULL || grab_widget == widget) &&
+          !column_handled_click &&
          tree_view->priv->pressed_button < 0)
         {
           tree_view->priv->pressed_button = event->button;
@@ -1940,45 +2288,60 @@ gtk_tree_view_button_press (GtkWidget      *widget,
           tree_view->priv->press_start_y = event->y;
         }
 
-      if (event->button == 1 && event->type == GDK_2BUTTON_PRESS &&
-         tree_view->priv->last_button_press)
-       {
-         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))
-               emit_row_activated = TRUE;
-             gtk_tree_path_free (lsc);
-           }
-       }
-      else if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
+      /* Test if a double click happened on the same row. */
+      if (event->button == 1)
         {
-         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);
-       }
+          /* We also handle triple clicks here, because a user could have done
+           * a first click and a second double click on different rows.
+           */
+          if ((event->type == GDK_2BUTTON_PRESS
+               || event->type == GDK_3BUTTON_PRESS)
+              && tree_view->priv->last_button_press)
+            {
+              GtkTreePath *lsc;
 
-      GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
+              lsc = gtk_tree_row_reference_get_path (tree_view->priv->last_button_press);
+
+              if (lsc)
+                {
+                  row_double_click = !gtk_tree_path_compare (lsc, path);
+                  gtk_tree_path_free (lsc);
+                }
+            }
+
+          if (row_double_click)
+            {
+              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;
+            }
+          else
+            {
+              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);
+            }
+        }
 
-      if (emit_row_activated)
+      if (row_double_click)
        {
          gtk_grab_remove (widget);
          gtk_tree_view_row_activated (tree_view, path, column);
+
+          if (tree_view->priv->pressed_button == event->button)
+            tree_view->priv->pressed_button = -1;
        }
 
       gtk_tree_path_free (path);
 
+      if (!GTK_WIDGET_HAS_FOCUS (widget))
+       gtk_widget_grab_focus (widget);
+      GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
+
       return TRUE;
     }
 
@@ -1997,7 +2360,7 @@ gtk_tree_view_button_press (GtkWidget      *widget,
              gtk_tree_view_column_get_sizing (column) != GTK_TREE_VIEW_COLUMN_AUTOSIZE)
            {
              _gtk_tree_view_column_autosize (tree_view, column);
-             break;
+             return TRUE;
            }
 
          if (gdk_pointer_grab (column->window, FALSE,
@@ -2013,19 +2376,22 @@ 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);
 
          tree_view->priv->drag_pos = i;
-         tree_view->priv->x_drag = (column->button->allocation.x + column->button->allocation.width);
-         break;
+         tree_view->priv->x_drag = column->button->allocation.x + (rtl ? 0 : column->button->allocation.width);
+         return TRUE;
        }
     }
-  return TRUE;
+  return FALSE;
 }
 
 /* GtkWidget::button_release_event helper */
@@ -2034,9 +2400,11 @@ gtk_tree_view_button_release_drag_column (GtkWidget      *widget,
                                          GdkEventButton *event)
 {
   GtkTreeView *tree_view;
+  gboolean rtl;
 
   tree_view = GTK_TREE_VIEW (widget);
 
+  rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
   gdk_display_pointer_ungrab (gtk_widget_get_display (widget), GDK_CURRENT_TIME);
   gdk_display_keyboard_ungrab (gtk_widget_get_display (widget), GDK_CURRENT_TIME);
 
@@ -2057,10 +2425,20 @@ gtk_tree_view_button_release_drag_column (GtkWidget      *widget,
 
   gtk_widget_grab_focus (tree_view->priv->drag_column->button);
 
-  if (tree_view->priv->cur_reorder &&
-      tree_view->priv->cur_reorder->left_column != tree_view->priv->drag_column)
-    gtk_tree_view_move_column_after (tree_view, tree_view->priv->drag_column,
-                                    tree_view->priv->cur_reorder->left_column);
+  if (rtl)
+    {
+      if (tree_view->priv->cur_reorder &&
+         tree_view->priv->cur_reorder->right_column != tree_view->priv->drag_column)
+       gtk_tree_view_move_column_after (tree_view, tree_view->priv->drag_column,
+                                        tree_view->priv->cur_reorder->right_column);
+    }
+  else
+    {
+      if (tree_view->priv->cur_reorder &&
+         tree_view->priv->cur_reorder->left_column != tree_view->priv->drag_column)
+       gtk_tree_view_move_column_after (tree_view, tree_view->priv->drag_column,
+                                        tree_view->priv->cur_reorder->left_column);
+    }
   tree_view->priv->drag_column = NULL;
   gdk_window_hide (tree_view->priv->drag_window);
 
@@ -2093,9 +2471,12 @@ 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);
@@ -2159,6 +2540,19 @@ gtk_tree_view_button_release (GtkWidget      *widget,
   return TRUE;
 }
 
+#if 0
+static gboolean
+gtk_tree_view_configure (GtkWidget *widget,
+                        GdkEventConfigure *event)
+{
+  GtkTreeView *tree_view;
+
+  tree_view = GTK_TREE_VIEW (widget);
+  tree_view->priv->search_dialog_position_func (tree_view, tree_view->priv->search_window);
+
+  return FALSE;
+}
+#endif
 
 /* GtkWidget::motion_event function set.
  */
@@ -2195,61 +2589,98 @@ coords_are_over_arrow (GtkTreeView *tree_view,
 }
 
 static void
-do_unprelight (GtkTreeView *tree_view,
-               /* these are in tree window coords */
-               gint x,
-               gint y)
+do_prelight (GtkTreeView *tree_view,
+             GtkRBTree   *tree,
+             GtkRBNode   *node,
+            /* these are in tree_window coords */
+             gint         x,
+             gint         y)
 {
-  if (tree_view->priv->prelight_node == NULL)
-    return;
+  if (tree_view->priv->prelight_tree == tree &&
+      tree_view->priv->prelight_node == node)
+    {
+      /*  We are still on the same node,
+         but we might need to take care of the arrow  */
+
+      if (tree && node)
+       {
+         gboolean over_arrow;
+         gboolean flag_set;
+
+         over_arrow = coords_are_over_arrow (tree_view, tree, node, x, y);
+         flag_set = GTK_TREE_VIEW_FLAG_SET (tree_view,
+                                            GTK_TREE_VIEW_ARROW_PRELIT);
+
+         if (over_arrow != flag_set)
+           {
+             if (over_arrow)
+               GTK_TREE_VIEW_SET_FLAG (tree_view,
+                                       GTK_TREE_VIEW_ARROW_PRELIT);
+             else
+               GTK_TREE_VIEW_UNSET_FLAG (tree_view,
+                                         GTK_TREE_VIEW_ARROW_PRELIT);
+
+             gtk_tree_view_draw_arrow (tree_view, tree, node, x, y);
+           }
+       }
 
-  GTK_RBNODE_UNSET_FLAG (tree_view->priv->prelight_node, GTK_RBNODE_IS_PRELIT);
+      return;
+    }
 
-  if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT) &&
-      !coords_are_over_arrow (tree_view,
-                              tree_view->priv->prelight_tree,
-                              tree_view->priv->prelight_node,
-                              x,
-                              y))
-    /* We need to unprelight the old arrow. */
+  if (tree_view->priv->prelight_tree && tree_view->priv->prelight_node)
     {
-      GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
+      /*  Unprelight the old node and arrow  */
+
+      GTK_RBNODE_UNSET_FLAG (tree_view->priv->prelight_node,
+                            GTK_RBNODE_IS_PRELIT);
 
-      gtk_tree_view_draw_arrow (tree_view,
-                                tree_view->priv->prelight_tree,
-                                tree_view->priv->prelight_node,
-                                x,
-                                y);
+      if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
+       {
+         GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
+         
+         gtk_tree_view_draw_arrow (tree_view,
+                                   tree_view->priv->prelight_tree,
+                                   tree_view->priv->prelight_node,
+                                   x,
+                                   y);
+       }
 
+      _gtk_tree_view_queue_draw_node (tree_view,
+                                     tree_view->priv->prelight_tree,
+                                     tree_view->priv->prelight_node,
+                                     NULL);
     }
 
-  tree_view->priv->prelight_node = NULL;
-  tree_view->priv->prelight_tree = NULL;
-}
 
-static void
-do_prelight (GtkTreeView *tree_view,
-             GtkRBTree   *tree,
-             GtkRBNode   *node,
-            /* these are in tree_window coords */
-             gint         x,
-             gint         y)
-{
+  /*  Set the new prelight values  */
+
+  tree_view->priv->prelight_node = node;
+  tree_view->priv->prelight_tree = tree;
+
+  if (!node || !tree)
+    return;
+
+  /*  Prelight the new node and arrow  */
+
   if (coords_are_over_arrow (tree_view, tree, node, x, y))
     {
       GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
-    }
 
-  tree_view->priv->prelight_node = node;
-  tree_view->priv->prelight_tree = tree;
+      gtk_tree_view_draw_arrow (tree_view, tree, node, x, y);
+    }
 
   GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_PRELIT);
+
+  _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
 }
 
 static void
 ensure_unprelighted (GtkTreeView *tree_view)
 {
-  do_unprelight (tree_view, -1000, -1000); /* coords not possibly over an arrow */
+  do_prelight (tree_view,
+              NULL, NULL,
+              -1000, -1000); /* coords not possibly over an arrow */
+
   g_assert (tree_view->priv->prelight_node == NULL);
 }
 
@@ -2351,11 +2782,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;
        }
     }
@@ -2423,10 +2854,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;
@@ -2499,10 +2930,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;
@@ -2559,7 +2990,6 @@ gtk_tree_view_update_current_reorder (GtkTreeView *tree_view)
   gint mouse_x;
 
   gdk_window_get_pointer (tree_view->priv->header_window, &mouse_x, NULL, NULL);
-
   for (list = tree_view->priv->column_drag_info; list; list = list->next)
     {
       reorder = (GtkTreeViewColumnReorder *) list->data;
@@ -2650,7 +3080,7 @@ gtk_tree_view_motion_drag_column (GtkWidget      *widget,
   x = CLAMP (x + (gint)event->x - column->drag_x, 0,
             MAX (tree_view->priv->width, GTK_WIDGET (tree_view)->allocation.width) - column->button->allocation.width);
   gdk_window_move (tree_view->priv->drag_window, x, y);
-
+  
   /* autoscroll, if needed */
   gtk_tree_view_horizontal_autoscroll (tree_view);
   /* Update the current reorder position and arrow; */
@@ -2667,65 +3097,29 @@ gtk_tree_view_motion_bin_window (GtkWidget      *widget,
   GtkRBTree *tree;
   GtkRBNode *node;
   gint new_y;
-  GtkRBTree *old_prelight_tree;
-  GtkRBNode *old_prelight_node;
-  gboolean old_arrow_prelit;
 
   tree_view = (GtkTreeView *) widget;
 
   if (tree_view->priv->tree == NULL)
     return FALSE;
 
-  gtk_tree_view_maybe_begin_dragging_row (tree_view, event);
-
-  old_prelight_tree = tree_view->priv->prelight_tree;
-  old_prelight_node = tree_view->priv->prelight_node;
-  old_arrow_prelit = GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
+  /* only check for an initiated drag when a button is pressed */
+  if (tree_view->priv->pressed_button >= 0)
+    gtk_tree_view_maybe_begin_dragging_row (tree_view, event);
 
   new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
   if (new_y < 0)
     new_y = 0;
-  do_unprelight (tree_view, event->x, event->y);
-  _gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
 
-  if (tree == NULL)
-    return TRUE;
+  _gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
 
   /* If we are currently pressing down a button, we don't want to prelight anything else. */
   if ((tree_view->priv->button_pressed_node != NULL) &&
       (tree_view->priv->button_pressed_node != node))
-    return TRUE;
-
+    node = NULL;
 
   do_prelight (tree_view, tree, node, event->x, event->y);
 
-  if (old_prelight_node != tree_view->priv->prelight_node)
-    {
-      if (old_prelight_node)
-       {
-         _gtk_tree_view_queue_draw_node (tree_view,
-                                         old_prelight_tree,
-                                         old_prelight_node,
-                                         NULL);
-       }
-      if (tree_view->priv->prelight_node)
-       {
-         _gtk_tree_view_queue_draw_node (tree_view,
-                                         tree_view->priv->prelight_tree,
-                                         tree_view->priv->prelight_node,
-                                         NULL);
-       }
-    }
-  else if (old_arrow_prelit != GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
-    {
-      if (tree_view->priv->prelight_node)
-       {
-         _gtk_tree_view_queue_draw_node (tree_view,
-                                        tree_view->priv->prelight_tree,
-                                        tree_view->priv->prelight_node,
-                                        NULL);
-       }
-    }
   return TRUE;
 }
 
@@ -2789,9 +3183,13 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
   gint focus_line_width;
   gboolean allow_rules;
   gboolean has_special_cell;
+  gboolean rtl;
+  gint n_visible_columns;
 
   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
 
+  rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
+
   tree_view = GTK_TREE_VIEW (widget);
 
   gtk_widget_style_get (widget,
@@ -2849,11 +3247,21 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
   gdk_drawable_get_size (tree_view->priv->bin_window,
                          &bin_window_width, NULL);
 
-  for (last_column = g_list_last (tree_view->priv->columns);
+
+  n_visible_columns = 0;
+  for (list = tree_view->priv->columns; list; list = list->next)
+    {
+      if (! GTK_TREE_VIEW_COLUMN (list->data)->visible)
+       continue;
+      n_visible_columns ++;
+    }
+
+  /* Find the last column */
+  for (last_column = rtl ? g_list_first (tree_view->priv->columns) : g_list_last (tree_view->priv->columns);
        last_column &&
         !(GTK_TREE_VIEW_COLUMN (last_column->data)->visible) &&
         GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (last_column->data)->button);
-       last_column = last_column->prev)
+       last_column = rtl ? last_column->next : last_column->prev)
     ;
 
   /* Actually process the expose event.  To do this, we want to
@@ -2886,7 +3294,9 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
 
       has_special_cell = gtk_tree_view_has_special_cell (tree_view);
 
-      for (list = tree_view->priv->columns; list; list = list->next)
+      for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
+          list;
+          list = (rtl ? list->prev : list->next))
        {
          GtkTreeViewColumn *column = list->data;
          const gchar *detail = NULL;
@@ -2903,10 +3313,15 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
            }
 
           if (column->show_sort_indicator)
-            flags |= GTK_CELL_RENDERER_SORTED;
+           flags |= GTK_CELL_RENDERER_SORTED;
           else
             flags &= ~GTK_CELL_RENDERER_SORTED;
 
+         if (cursor == node)
+            flags |= GTK_CELL_RENDERER_FOCUSED;
+          else
+            flags &= ~GTK_CELL_RENDERER_FOCUSED;
+
          background_area.x = cell_offset;
          background_area.width = column->width;
 
@@ -2934,7 +3349,8 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
            */
           if (allow_rules && tree_view->priv->has_rules)
             {
-              if (flags & GTK_CELL_RENDERER_SORTED)
+              if ((flags & GTK_CELL_RENDERER_SORTED) &&
+                 n_visible_columns >= 3)
                 {
                   if (parity)
                     detail = "cell_odd_ruled_sorted";
@@ -2951,7 +3367,8 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
             }
           else
             {
-              if (flags & GTK_CELL_RENDERER_SORTED)
+              if ((flags & GTK_CELL_RENDERER_SORTED) &&
+                 n_visible_columns >= 3)
                 {
                   if (parity)
                     detail = "cell_odd_sorted";
@@ -2990,7 +3407,8 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
          if (gtk_tree_view_is_expander_column (tree_view, column) &&
               TREE_VIEW_DRAW_EXPANDERS(tree_view))
            {
-             cell_area.x += depth * tree_view->priv->expander_size;
+             if (!rtl)
+               cell_area.x += depth * tree_view->priv->expander_size;
              cell_area.width -= depth * tree_view->priv->expander_size;
 
               /* If we have an expander column, the highlight underline
@@ -3447,6 +3865,9 @@ gtk_tree_view_key_press (GtkWidget   *widget,
 {
   GtkTreeView *tree_view = (GtkTreeView *) widget;
   GList *list;
+  gboolean rtl;
+
+  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
 
   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG))
     {
@@ -3458,9 +3879,9 @@ gtk_tree_view_key_press (GtkWidget   *widget,
       return TRUE;
     }
 
-  /* FIXME: this is prolly broken when we go bidi */
   if (tree_view->priv->columns && (event->state & GDK_SHIFT_MASK)
-      && (event->keyval == GDK_Left || event->keyval == GDK_Right))
+      && (event->keyval == GDK_Left || event->keyval == GDK_KP_Left
+          || event->keyval == GDK_Right || event->keyval == GDK_KP_Right))
     {
       list = tree_view->priv->columns;
       while (list)
@@ -3471,7 +3892,7 @@ gtk_tree_view_key_press (GtkWidget   *widget,
              if (!column->resizable)
                return TRUE;
 
-             if (event->keyval == GDK_Left)
+             if (event->keyval == GDK_Left || event->keyval == GDK_KP_Left)
                {
                  column->resized_width = MAX (column->resized_width,
                                               column->width);
@@ -3491,7 +3912,8 @@ gtk_tree_view_key_press (GtkWidget   *widget,
                  gtk_widget_queue_resize (widget);
                  return TRUE;
                }
-             else if (event->keyval == GDK_Right)
+             else if (event->keyval == GDK_Right
+                       || event->keyval == GDK_KP_Right)
                {
                  column->resized_width = MAX (column->resized_width,
                                               column->width);
@@ -3509,10 +3931,11 @@ gtk_tree_view_key_press (GtkWidget   *widget,
        }
     }
 
-  /* FIXME: broken when we go bidi? */
   if (tree_view->priv->columns && (event->state & GDK_CONTROL_MASK) &&
-      (event->keyval == GDK_Left || event->keyval == GDK_Right
-       || event->keyval == GDK_Home || event->keyval == GDK_End))
+      (event->keyval == GDK_Left || event->keyval == GDK_KP_Left
+       || event->keyval == GDK_Right || event->keyval == GDK_KP_Right
+       || event->keyval == GDK_Home || event->keyval == GDK_KP_Home
+       || event->keyval == GDK_End || event->keyval == GDK_KP_End))
     {
       list = tree_view->priv->columns;
       while (list)
@@ -3520,7 +3943,8 @@ gtk_tree_view_key_press (GtkWidget   *widget,
          GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (list->data);
          if (GTK_WIDGET_HAS_FOCUS (column->button))
            {
-             if (event->keyval == GDK_Left)
+             if (event->keyval == (rtl ? GDK_Right : GDK_Left)
+                  || event->keyval == (rtl ? GDK_KP_Right : GDK_KP_Left))
                {
                  GtkTreeViewColumn *col;
                  col = gtk_tree_view_get_drop_column (tree_view, column, DROP_LEFT);
@@ -3528,7 +3952,8 @@ gtk_tree_view_key_press (GtkWidget   *widget,
                    gtk_tree_view_move_column_after (tree_view, column, col);
                  return TRUE;
                }
-             else if (event->keyval == GDK_Right)
+             else if (event->keyval == (rtl ? GDK_Left : GDK_Right)
+                       || event->keyval == (rtl ? GDK_KP_Left : GDK_KP_Right))
                {
                  GtkTreeViewColumn *col;
                  col = gtk_tree_view_get_drop_column (tree_view, column, DROP_RIGHT);
@@ -3536,7 +3961,8 @@ gtk_tree_view_key_press (GtkWidget   *widget,
                    gtk_tree_view_move_column_after (tree_view, column, col);
                  return TRUE;
                }
-             else if (event->keyval == GDK_Home)
+             else if (event->keyval == GDK_Home
+                       || event->keyval == GDK_KP_Home)
                {
                  GtkTreeViewColumn *col;
                  col = gtk_tree_view_get_drop_column (tree_view, column, DROP_HOME);
@@ -3544,7 +3970,7 @@ gtk_tree_view_key_press (GtkWidget   *widget,
                    gtk_tree_view_move_column_after (tree_view, column, col);
                  return TRUE;
                }
-             else if (event->keyval == GDK_End)
+             else if (event->keyval == GDK_End || event->keyval == GDK_KP_End)
                {
                  GtkTreeViewColumn *col;
                  col = gtk_tree_view_get_drop_column (tree_view, column, DROP_END);
@@ -3557,9 +3983,10 @@ gtk_tree_view_key_press (GtkWidget   *widget,
        }
     }
 
-  /* FIXME: this is prolly broken when we go bidi */
   if (tree_view->priv->columns &&
-      (event->keyval == GDK_Left || event->keyval == GDK_Right))
+      GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE) &&
+      (event->keyval == GDK_Left || event->keyval == GDK_KP_Left
+       || event->keyval == GDK_Right || event->keyval == GDK_KP_Right))
     {
       gint width = 0;
       list = tree_view->priv->columns;
@@ -3568,7 +3995,9 @@ gtk_tree_view_key_press (GtkWidget   *widget,
          GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (list->data);
          if (GTK_WIDGET_HAS_FOCUS (column->button))
            {
-             if (event->keyval == GDK_Left && list->prev)
+             if ((event->keyval == (rtl ? GDK_Right : GDK_Left)
+                   || event->keyval == (rtl ? GDK_KP_Right : GDK_KP_Left))
+                  && list->prev)
                {
                  GList *tmp;
 
@@ -3585,7 +4014,9 @@ gtk_tree_view_key_press (GtkWidget   *widget,
                  gtk_adjustment_set_value (tree_view->priv->hadjustment, CLAMP (width, tree_view->priv->hadjustment->lower, tree_view->priv->hadjustment->upper - tree_view->priv->hadjustment->page_size));
                  return TRUE;
                }
-             else if (event->keyval == GDK_Right && list->next)
+             else if ((event->keyval == (rtl ? GDK_Left : GDK_Right)
+                        || event->keyval == (rtl ? GDK_KP_Left : GDK_KP_Right))
+                       && list->next)
                {
                  GList *tmp;
 
@@ -3609,7 +4040,10 @@ gtk_tree_view_key_press (GtkWidget   *widget,
        }
     }
 
-  return (* GTK_WIDGET_CLASS (parent_class)->key_press_event) (widget, event);
+  if ((* GTK_WIDGET_CLASS (parent_class)->key_press_event) (widget, event))
+    return TRUE;
+
+  return FALSE;
 }
 
 /* FIXME Is this function necessary? Can I get an enter_notify event
@@ -3645,17 +4079,8 @@ gtk_tree_view_enter_notify (GtkWidget        *widget,
     new_y = 0;
   _gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
 
-  if (node == NULL)
-    return FALSE;
-
   do_prelight (tree_view, tree, node, event->x, event->y);
 
-  if (tree_view->priv->prelight_node)
-    _gtk_tree_view_queue_draw_node (tree_view,
-                                   tree_view->priv->prelight_tree,
-                                   tree_view->priv->prelight_node,
-                                   NULL);
-
   return TRUE;
 }
 
@@ -3679,7 +4104,7 @@ gtk_tree_view_leave_notify (GtkWidget        *widget,
 
   ensure_unprelighted (tree_view);
 
-return TRUE;
+  return TRUE;
 }
 
 
@@ -3687,15 +4112,15 @@ static gint
 gtk_tree_view_focus_out (GtkWidget     *widget,
                         GdkEventFocus *event)
 {
-  GtkWidget   *search_dialog;
+  GtkTreeView *tree_view;
+
+  tree_view = GTK_TREE_VIEW (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);
-  if (search_dialog)
-    gtk_tree_view_search_dialog_destroy (search_dialog, GTK_TREE_VIEW (widget));
+  if (tree_view->priv->search_window)
+    gtk_tree_view_search_dialog_hide (tree_view->priv->search_window, tree_view);
 
   return FALSE;
 }
@@ -3748,6 +4173,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);
 
@@ -3786,7 +4212,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;
@@ -3796,10 +4222,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)
@@ -3815,6 +4244,7 @@ validate_visible_area (GtkTreeView *tree_view)
              if (validate_row (tree_view, tree, node, &iter, path))
                size_changed = TRUE;
            }
+
          if (tree_view->priv->scroll_to_use_align)
            {
              gint height = MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
@@ -3826,10 +4256,62 @@ validate_visible_area (GtkTreeView *tree_view)
            }
          else
            {
-             /* FIXME: */
-             g_warning ("non use_align not implemented yet");
-             gtk_tree_path_free (path);
-             path = NULL;
+             /* two cases:
+              * 1) row not visible
+              * 2) row visible
+              */
+             gint dy;
+             gint height = MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
+
+             dy = _gtk_rbtree_node_find_offset (tree, node);
+
+             if (dy >= tree_view->priv->vadjustment->value &&
+                 dy < (tree_view->priv->vadjustment->value
+                       + tree_view->priv->vadjustment->page_size))
+               {
+                 /* row visible: keep the row at the same position */
+                 area_above = dy - tree_view->priv->vadjustment->value;
+                 area_below = (tree_view->priv->vadjustment->value +
+                               tree_view->priv->vadjustment->page_size)
+                              - dy - height;
+               }
+             else
+               {
+                 /* row not visible */
+                  update_dy = TRUE;
+
+                 if (dy >= 0 && dy <= tree_view->priv->vadjustment->page_size)
+                   {
+                     /* row at the beginning -- fixed */
+                     area_above = dy;
+                     area_below = tree_view->priv->vadjustment->page_size
+                                  - area_above - height;
+                   }
+                 else if (dy >= (tree_view->priv->vadjustment->upper -
+                                 tree_view->priv->vadjustment->page_size)
+                          && dy <= tree_view->priv->vadjustment->upper)
+                   {
+                     /* row at the end -- fixed */
+                     area_above = dy - (tree_view->priv->vadjustment->upper -
+                                  tree_view->priv->vadjustment->page_size);
+                      area_below = tree_view->priv->vadjustment->page_size -
+                                   area_above - height;
+
+                      if (area_below < 0)
+                        {
+                          area_above += area_below;
+                          area_below = 0;
+                        }
+                   }
+                 else
+                   {
+                     /* row somewhere in the middle, bring it to the top
+                      * of the view
+                      */
+                     area_above = 0;
+                     area_below = total_height - height;
+                   }
+               }
            }
        }
       else
@@ -3890,6 +4372,8 @@ validate_visible_area (GtkTreeView *tree_view)
    */
   while (node && area_below > 0)
     {
+      gint new_height;
+
       if (node->children)
        {
          GtkTreeIter parent = iter;
@@ -3943,20 +4427,33 @@ validate_visible_area (GtkTreeView *tree_view)
            }
          while (!done);
        }
+
+      if (!node)
+        break;
+
+      new_height = GTK_RBNODE_GET_HEIGHT (node);
+
       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
          GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
        {
+          gint old_height = new_height;
+
          need_redraw = TRUE;
          if (validate_row (tree_view, tree, node, &iter, path))
-           size_changed = TRUE;
+            {
+              new_height = GTK_RBNODE_GET_HEIGHT (node);
+             size_changed = TRUE;
+
+              area_below -= new_height - old_height;
+            }
        }
-      if (node)
-       area_below -= MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
+
+      area_below -= MAX (new_height, tree_view->priv->expander_size);
     }
   gtk_tree_path_free (path);
 
-  /* If we ran out of tree, and have extra area_below left, we need to remove it
-   * from the area_above */
+  /* If we ran out of tree, and have extra area_below left, we need to add it
+   * to area_above */
   if (area_below > 0)
     area_above += area_below;
 
@@ -3965,6 +4462,8 @@ validate_visible_area (GtkTreeView *tree_view)
   /* We walk backwards */
   while (area_above > 0)
     {
+      gint new_height;
+
       _gtk_rbtree_prev_full (tree, node, &tree, &node);
       if (! gtk_tree_path_prev (above_path) && node != NULL)
        {
@@ -3976,19 +4475,55 @@ validate_visible_area (GtkTreeView *tree_view)
       if (node == NULL)
        break;
 
+      new_height = GTK_RBNODE_GET_HEIGHT (node);
+
       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
          GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
        {
+          gint old_height = new_height;
+
          need_redraw = TRUE;
          if (validate_row (tree_view, tree, node, &iter, above_path))
-           size_changed = TRUE;
+            {
+              new_height = GTK_RBNODE_GET_HEIGHT (node);
+             size_changed = TRUE;
+
+              area_above -= new_height - old_height;
+            }
+       }
+      area_above -= MAX (new_height, tree_view->priv->expander_size);
+      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. */
+      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 we scroll at all, always update dy and kill the top_row */
+  if (tree_view->priv->scroll_to_path &&
+      ! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID))
+    {
+      update_dy = TRUE;
+      if (tree_view->priv->top_row)
+        {
+         gtk_tree_row_reference_free (tree_view->priv->top_row);
+         tree_view->priv->top_row = NULL;
        }
-      area_above -= MAX (GTK_RBNODE_GET_HEIGHT (node), tree_view->priv->expander_size);
-      modify_dy = TRUE;
     }
 
   /* if we walk backwards at all, then we need to reset our dy. */
-  if (modify_dy)
+  if (update_dy)
     {
       gint dy;
       if (node != NULL)
@@ -3999,6 +4534,7 @@ validate_visible_area (GtkTreeView *tree_view)
        {
          dy = 0;
        }
+
       gtk_adjustment_set_value (tree_view->priv->vadjustment, dy);
       need_redraw = TRUE;
     }
@@ -4016,12 +4552,41 @@ 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));
 }
 
+static void
+initialize_fixed_height_mode (GtkTreeView *tree_view)
+{
+  if (!tree_view->priv->tree)
+    return;
+
+  if (tree_view->priv->fixed_height < 0)
+    {
+      GtkTreeIter iter;
+      GtkTreePath *path;
+
+      GtkRBTree *tree = NULL;
+      GtkRBNode *node = NULL;
+
+      tree = tree_view->priv->tree;
+      node = tree->root;
+
+      path = _gtk_tree_view_find_path (tree_view, tree, node);
+      gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
+
+      validate_row (tree_view, tree, node, &iter, path);
+
+      gtk_tree_path_free (path);
+
+      tree_view->priv->fixed_height = MAX (GTK_RBNODE_GET_HEIGHT (node),
+                                           tree_view->priv->expander_size);
+    }
+
+   _gtk_rbtree_set_fixed_height (tree_view->priv->tree,
+                                 tree_view->priv->fixed_height);
+}
 
 /* Our strategy for finding nodes to validate is a little convoluted.  We find
  * the left-most uninvalidated node.  We then try walking right, validating
@@ -4046,10 +4611,16 @@ do_validate_rows (GtkTreeView *tree_view)
   g_assert (tree_view);
 
   if (tree_view->priv->tree == NULL)
+      return FALSE;
+
+  if (tree_view->priv->fixed_height_mode)
     {
-      tree_view->priv->validate_rows_timer = 0;
+      if (tree_view->priv->fixed_height < 0)
+        initialize_fixed_height_mode (tree_view);
+
       return FALSE;
     }
+
   do
     {
       if (! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID))
@@ -4110,7 +4681,9 @@ do_validate_rows (GtkTreeView *tree_view)
          path = _gtk_tree_view_find_path (tree_view, tree, node);
          gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
        }
-      validated_area = validate_row (tree_view, tree, node, &iter, path) | validated_area;
+
+      validated_area = validate_row (tree_view, tree, node, &iter, path) ||
+                       validated_area;
 
       if (!tree_view->priv->fixed_height_check)
         {
@@ -4136,16 +4709,42 @@ do_validate_rows (GtkTreeView *tree_view)
    }
   
  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;
 }
@@ -4158,7 +4757,12 @@ validate_rows_handler (GtkTreeView *tree_view)
   GDK_THREADS_ENTER ();
 
   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;
+    }
+
   GDK_THREADS_LEAVE ();
 
   return retval;
@@ -4311,9 +4915,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)
 {
@@ -4323,7 +4928,7 @@ _gtk_tree_view_install_mark_rows_col_dirty (GtkTreeView *tree_view)
 }
 
 /*
- * This function works synchronously (due to the while (do_validate_rows...)
+ * This function works synchronously (due to the while (validate_rows...)
  * loop).
  *
  * There was a check for column_type != GTK_TREE_VIEW_COLUMN_AUTOSIZE
@@ -4339,7 +4944,7 @@ _gtk_tree_view_column_autosize (GtkTreeView *tree_view,
   _gtk_tree_view_column_cell_set_dirty (column, FALSE);
 
   do_presize_handler (tree_view);
-  while (do_validate_rows (tree_view));
+  while (validate_rows (tree_view));
 
   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
 }
@@ -4369,26 +4974,79 @@ get_source_row (GdkDragContext *context)
     return NULL;
 }
 
+typedef struct
+{
+  GtkTreeRowReference *dest_row;
+  gboolean             path_down_mode;
+  gboolean             empty_view_drop;
+  gboolean             drop_append_mode;
+}
+DestRow;
+
+static void
+dest_row_free (gpointer data)
+{
+  DestRow *dr = (DestRow *)data;
+
+  gtk_tree_row_reference_free (dr->dest_row);
+  g_free (dr);
+}
+
 
 static void
 set_dest_row (GdkDragContext *context,
               GtkTreeModel   *model,
-              GtkTreePath    *dest_row)
+              GtkTreePath    *dest_row,
+              gboolean        path_down_mode,
+              gboolean        empty_view_drop,
+              gboolean        drop_append_mode)
 {
-  g_object_set_data_full (G_OBJECT (context),
-                          "gtk-tree-view-dest-row",
-                          dest_row ? gtk_tree_row_reference_new (model, dest_row) : NULL,
-                          (GDestroyNotify) (dest_row ? gtk_tree_row_reference_free : NULL));
+  DestRow *dr;
+
+  if (!dest_row)
+    {
+      g_object_set_data_full (G_OBJECT (context), "gtk-tree-view-dest-row",
+                              NULL, NULL);
+      return;
+    }
+
+  dr = g_new0 (DestRow, 1);
+
+  dr->dest_row = gtk_tree_row_reference_new (model, dest_row);
+  dr->path_down_mode = path_down_mode;
+  dr->empty_view_drop = empty_view_drop;
+  dr->drop_append_mode = drop_append_mode;
+
+  g_object_set_data_full (G_OBJECT (context), "gtk-tree-view-dest-row",
+                          dr, (GDestroyNotify) dest_row_free);
 }
 
 static GtkTreePath*
-get_dest_row (GdkDragContext *context)
+get_dest_row (GdkDragContext *context,
+              gboolean       *path_down_mode)
 {
-  GtkTreeRowReference *ref =
+  DestRow *dr =
     g_object_get_data (G_OBJECT (context), "gtk-tree-view-dest-row");
 
-  if (ref)
-    return gtk_tree_row_reference_get_path (ref);
+  if (dr)
+    {
+      GtkTreePath *path = NULL;
+
+      if (path_down_mode)
+        *path_down_mode = dr->path_down_mode;
+
+      if (dr->dest_row)
+        path = gtk_tree_row_reference_get_path (dr->dest_row);
+      else if (dr->empty_view_drop)
+        path = gtk_tree_path_new_from_indices (0, -1);
+      else
+        path = NULL;
+
+      if (path && dr->drop_append_mode)
+        gtk_tree_path_next (path);
+
+      return path;
+    }
   else
     return NULL;
 }
@@ -4528,7 +5186,7 @@ remove_scroll_timeout (GtkTreeView *tree_view)
 {
   if (tree_view->priv->scroll_timeout != 0)
     {
-      gtk_timeout_remove (tree_view->priv->scroll_timeout);
+      g_source_remove (tree_view->priv->scroll_timeout);
       tree_view->priv->scroll_timeout = 0;
     }
 }
@@ -4543,7 +5201,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 "
@@ -4561,7 +5219,7 @@ remove_open_timeout (GtkTreeView *tree_view)
 {
   if (tree_view->priv->open_dest_timeout != 0)
     {
-      gtk_timeout_remove (tree_view->priv->open_dest_timeout);
+      g_source_remove (tree_view->priv->open_dest_timeout);
       tree_view->priv->open_dest_timeout = 0;
     }
 }
@@ -4632,6 +5290,7 @@ set_destination_row (GtkTreeView    *tree_view,
   TreeViewDragInfo *di;
   GtkWidget *widget;
   GtkTreePath *old_dest_path = NULL;
+  gboolean can_drop = FALSE;
 
   *suggested_action = 0;
   *target = GDK_NONE;
@@ -4640,7 +5299,7 @@ set_destination_row (GtkTreeView    *tree_view,
 
   di = get_info (tree_view);
 
-  if (di == NULL)
+  if (di == NULL || y - TREE_VIEW_HEADER_HEIGHT (tree_view) < 0)
     {
       /* someone unset us as a drag dest, note that if
        * we return FALSE drag_leave isn't called
@@ -4667,18 +5326,34 @@ set_destination_row (GtkTreeView    *tree_view,
                                           &path,
                                           &pos))
     {
-      /* can't drop here */
+      gint n_children;
+      GtkTreeModel *model;
+
       remove_open_timeout (tree_view);
 
-      gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
-                                       NULL,
-                                       GTK_TREE_VIEW_DROP_BEFORE);
+      /* the row got dropped on empty space, let's setup a special case
+       */
 
       if (path)
        gtk_tree_path_free (path);
 
-      /* don't propagate to parent though */
-      return TRUE;
+      model = gtk_tree_view_get_model (tree_view);
+
+      n_children = gtk_tree_model_iter_n_children (model, NULL);
+      if (n_children)
+        {
+          pos = GTK_TREE_VIEW_DROP_AFTER;
+          path = gtk_tree_path_new_from_indices (n_children - 1, -1);
+        }
+      else
+        {
+          pos = GTK_TREE_VIEW_DROP_BEFORE;
+          path = gtk_tree_path_new_from_indices (0, -1);
+        }
+
+      can_drop = TRUE;
+
+      goto out;
     }
 
   g_assert (path);
@@ -4700,17 +5375,22 @@ set_destination_row (GtkTreeView    *tree_view,
     gtk_tree_path_free (old_dest_path);
 
   if (TRUE /* FIXME if the location droppable predicate */)
+    {
+      can_drop = TRUE;
+    }
+
+out:
+  if (can_drop)
     {
       GtkWidget *source_widget;
 
       *suggested_action = context->suggested_action;
-
       source_widget = gtk_drag_get_source_widget (context);
 
       if (source_widget == widget)
         {
           /* Default to MOVE, unless the user has
-           * pressed ctrl or alt to affect available actions
+           * pressed ctrl or shift to affect available actions
            */
           if ((context->actions & GDK_ACTION_MOVE) != 0)
             *suggested_action = GDK_ACTION_MOVE;
@@ -4734,14 +5414,22 @@ set_destination_row (GtkTreeView    *tree_view,
 
   return TRUE;
 }
-static GtkTreePath*
-get_logical_dest_row (GtkTreeView *tree_view)
 
+static GtkTreePath*
+get_logical_dest_row (GtkTreeView *tree_view,
+                      gboolean    *path_down_mode,
+                      gboolean    *drop_append_mode)
 {
   /* adjust path to point to the row the drop goes in front of */
   GtkTreePath *path = NULL;
   GtkTreeViewDropPosition pos;
 
+  g_return_val_if_fail (path_down_mode != NULL, NULL);
+  g_return_val_if_fail (drop_append_mode != NULL, NULL);
+
+  *path_down_mode = FALSE;
+  *drop_append_mode = 0;
+
   gtk_tree_view_get_drag_dest_row (tree_view, &path, &pos);
 
   if (path == NULL)
@@ -4751,10 +5439,7 @@ get_logical_dest_row (GtkTreeView *tree_view)
     ; /* do nothing */
   else if (pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE ||
            pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
-    {
-      /* get first child, drop before it */
-      gtk_tree_path_down (path);
-    }
+    *path_down_mode = TRUE;
   else
     {
       GtkTreeIter iter;
@@ -4762,17 +5447,14 @@ get_logical_dest_row (GtkTreeView *tree_view)
 
       g_assert (pos == GTK_TREE_VIEW_DROP_AFTER);
 
-      gtk_tree_model_get_iter (model, &iter, path);
-
-      if (!gtk_tree_model_iter_next (model, &iter))
-       g_object_set_data (G_OBJECT (model), "gtk-tree-model-drop-append",
-                          GINT_TO_POINTER (1));
+      if (!gtk_tree_model_get_iter (model, &iter, path) ||
+          !gtk_tree_model_iter_next (model, &iter))
+        *drop_append_mode = 1;
       else
         {
-         g_object_set_data (G_OBJECT (model), "gtk-tree-model-drop-append",
-                            NULL);
-         gtk_tree_path_next (path);
-       }
+          *drop_append_mode = 0;
+          gtk_tree_path_next (path);
+        }
     }
 
   return path;
@@ -4842,25 +5524,6 @@ gtk_tree_view_maybe_begin_dragging_row (GtkTreeView      *tree_view,
                             button,
                             (GdkEvent*)event);
 
-  gtk_drag_set_icon_default (context);
-
-  {
-    GdkPixmap *row_pix;
-
-    row_pix = gtk_tree_view_create_row_drag_icon (tree_view,
-                                                  path);
-
-    gtk_drag_set_icon_pixmap (context,
-                              gdk_drawable_get_colormap (row_pix),
-                              row_pix,
-                              NULL,
-                              /* the + 1 is for the black border in the icon */
-                              tree_view->priv->press_start_x + 1,
-                              cell_y + 1);
-
-    gdk_pixmap_unref (row_pix);
-  }
-
   set_source_row (context, model, path);
 
  out:
@@ -4875,7 +5538,40 @@ static void
 gtk_tree_view_drag_begin (GtkWidget      *widget,
                           GdkDragContext *context)
 {
-  /* do nothing */
+  GtkTreeView *tree_view;
+  GtkTreePath *path = NULL;
+  gint cell_x, cell_y;
+  GdkPixmap *row_pix;
+
+  tree_view = GTK_TREE_VIEW (widget);
+
+  /* if the user uses a custom DnD impl, we don't set the icon here */
+  if (!get_info (tree_view))
+    return;
+
+  gtk_tree_view_get_path_at_pos (tree_view,
+                                 tree_view->priv->press_start_x,
+                                 tree_view->priv->press_start_y,
+                                 &path,
+                                 NULL,
+                                 &cell_x,
+                                 &cell_y);
+
+  g_return_if_fail (path != NULL);
+
+  row_pix = gtk_tree_view_create_row_drag_icon (tree_view,
+                                                path);
+
+  gtk_drag_set_icon_pixmap (context,
+                            gdk_drawable_get_colormap (row_pix),
+                            row_pix,
+                            NULL,
+                            /* the + 1 is for the black border in the icon */
+                            tree_view->priv->press_start_x + 1,
+                            cell_y + 1);
+
+  g_object_unref (row_pix);
+  gtk_tree_path_free (path);
 }
 
 static void
@@ -4998,7 +5694,9 @@ gtk_tree_view_drag_motion (GtkWidget        *widget,
                            gint              y,
                            guint             time)
 {
+  gboolean empty;
   GtkTreePath *path = NULL;
+  GtkTreeModel *model;
   GtkTreeViewDropPosition pos;
   GtkTreeView *tree_view;
   GdkDragAction suggested_action = 0;
@@ -5011,7 +5709,11 @@ gtk_tree_view_drag_motion (GtkWidget        *widget,
 
   gtk_tree_view_get_drag_dest_row (tree_view, &path, &pos);
 
-  if (path == NULL)
+  /* we only know this *after* set_desination_row */
+  model = gtk_tree_view_get_model (tree_view);
+  empty = tree_view->priv->empty_view_drop;
+
+  if (path == NULL && !empty)
     {
       /* Can't drop here. */
       gdk_drag_status (context, 0, time);
@@ -5023,12 +5725,12 @@ gtk_tree_view_drag_motion (GtkWidget        *widget,
            pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE))
         {
           tree_view->priv->open_dest_timeout =
-            gtk_timeout_add (500, open_row_timeout, tree_view);
+            g_timeout_add (500, open_row_timeout, tree_view);
         }
       else if (tree_view->priv->scroll_timeout == 0)
         {
          tree_view->priv->scroll_timeout =
-           gtk_timeout_add (150, scroll_row_timeout, tree_view);
+           g_timeout_add (150, scroll_row_timeout, tree_view);
        }
 
       if (target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
@@ -5066,6 +5768,8 @@ gtk_tree_view_drag_drop (GtkWidget        *widget,
   GdkAtom target = GDK_NONE;
   TreeViewDragInfo *di;
   GtkTreeModel *model;
+  gboolean path_down_mode;
+  gboolean drop_append_mode;
 
   tree_view = GTK_TREE_VIEW (widget);
 
@@ -5085,7 +5789,7 @@ gtk_tree_view_drag_drop (GtkWidget        *widget,
   if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target))
     return FALSE;
 
-  path = get_logical_dest_row (tree_view);
+  path = get_logical_dest_row (tree_view, &path_down_mode, &drop_append_mode);
 
   if (target != GDK_NONE && path != NULL)
     {
@@ -5093,8 +5797,9 @@ gtk_tree_view_drag_drop (GtkWidget        *widget,
        * treat drag data receives as a drop.
        */
       set_status_pending (context, 0);
-
-      set_dest_row (context, model, path);
+      set_dest_row (context, model, path,
+                    path_down_mode, tree_view->priv->empty_view_drop,
+                    drop_append_mode);
     }
 
   if (path)
@@ -5130,6 +5835,8 @@ gtk_tree_view_drag_data_received (GtkWidget        *widget,
   GtkTreeView *tree_view;
   GtkTreePath *dest_row;
   GdkDragAction suggested_action;
+  gboolean path_down_mode;
+  gboolean drop_append_mode;
 
   tree_view = GTK_TREE_VIEW (widget);
 
@@ -5152,17 +5859,33 @@ gtk_tree_view_drag_data_received (GtkWidget        *widget,
        * supposed to call drag_status, not actually paste in the
        * data.
        */
-      path = get_logical_dest_row (tree_view);
+      path = get_logical_dest_row (tree_view, &path_down_mode,
+                                   &drop_append_mode);
 
       if (path == NULL)
         suggested_action = 0;
+      else if (path_down_mode)
+        gtk_tree_path_down (path);
 
       if (suggested_action)
         {
          if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model),
                                                     path,
                                                     selection_data))
-           suggested_action = 0;
+            {
+              if (path_down_mode)
+                {
+                  path_down_mode = FALSE;
+                  gtk_tree_path_up (path);
+
+                  if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model),
+                                                             path,
+                                                             selection_data))
+                    suggested_action = 0;
+                }
+              else
+               suggested_action = 0;
+            }
         }
 
       gdk_drag_status (context, suggested_action, time);
@@ -5179,11 +5902,22 @@ gtk_tree_view_drag_data_received (GtkWidget        *widget,
       return;
     }
 
-  dest_row = get_dest_row (context);
+  dest_row = get_dest_row (context, &path_down_mode);
 
   if (dest_row == NULL)
     return;
 
+  if (selection_data->length >= 0)
+    {
+      if (path_down_mode)
+        {
+          gtk_tree_path_down (dest_row);
+          if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model),
+                                                     dest_row, selection_data))
+            gtk_tree_path_up (dest_row);
+        }
+    }
+
   if (selection_data->length >= 0)
     {
       if (gtk_tree_drag_dest_drag_data_received (GTK_TREE_DRAG_DEST (model),
@@ -5197,10 +5931,18 @@ gtk_tree_view_drag_data_received (GtkWidget        *widget,
                    (context->action == GDK_ACTION_MOVE),
                    time);
 
+  if (gtk_tree_path_get_depth (dest_row) == 1
+      && gtk_tree_path_get_indices (dest_row)[0] == 0)
+    {
+      /* special special case drag to "0", scroll to first item */
+      if (!tree_view->priv->scroll_to_path)
+        gtk_tree_view_scroll_to_cell (tree_view, dest_row, NULL, FALSE, 0.0, 0.0);
+    }
+
   gtk_tree_path_free (dest_row);
 
   /* drop dest_row */
-  set_dest_row (context, NULL, NULL);
+  set_dest_row (context, NULL, NULL, FALSE, FALSE, FALSE);
 }
 
 
@@ -5308,6 +6050,59 @@ gtk_tree_view_has_special_cell (GtkTreeView *tree_view)
   return FALSE;
 }
 
+static void
+column_sizing_notify (GObject    *object,
+                      GParamSpec *pspec,
+                      gpointer    data)
+{
+  GtkTreeViewColumn *c = GTK_TREE_VIEW_COLUMN (object);
+
+  if (gtk_tree_view_column_get_sizing (c) != GTK_TREE_VIEW_COLUMN_FIXED)
+    /* disable fixed height mode */
+    g_object_set (data, "fixed_height_mode", FALSE, NULL);
+}
+
+static void
+gtk_tree_view_set_fixed_height_mode (GtkTreeView *tree_view,
+                                     gboolean     enable)
+{
+  GList *l;
+
+  if (tree_view->priv->fixed_height_mode && enable)
+    return;
+
+  if (!enable)
+    {
+      tree_view->priv->fixed_height_mode = 0;
+      tree_view->priv->fixed_height = -1;
+
+      /* force a revalidation */
+      install_presize_handler (tree_view);
+      return;
+    }
+
+  /* make sure all columns are of type FIXED */
+  for (l = tree_view->priv->columns; l; l = l->next)
+    {
+      GtkTreeViewColumn *c = l->data;
+
+      g_return_if_fail (gtk_tree_view_column_get_sizing (c) == GTK_TREE_VIEW_COLUMN_FIXED);
+    }
+
+  /* yes, we really have to do this is in a separate loop */
+  for (l = tree_view->priv->columns; l; l = l->next)
+    g_signal_connect (l->data, "notify::sizing",
+                      G_CALLBACK (column_sizing_notify), tree_view);
+
+  tree_view->priv->fixed_height_mode = 1;
+  tree_view->priv->fixed_height = -1;
+
+  if (!tree_view->priv->tree)
+    return;
+
+  initialize_fixed_height_mode (tree_view);
+}
+
 /* Returns TRUE if the focus is within the headers, after the focus operation is
  * done
  */
@@ -5320,6 +6115,7 @@ gtk_tree_view_header_focus (GtkTreeView      *tree_view,
 
   GList *last_column, *first_column;
   GList *tmp_list;
+  gboolean rtl;
 
   if (! GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE))
     return FALSE;
@@ -5355,6 +6151,13 @@ gtk_tree_view_header_focus (GtkTreeView      *tree_view,
     }
 
 
+   rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
+   if (rtl) {
+     GList *temp = first_column;
+     first_column = last_column;
+     last_column = temp;
+   }
+
   switch (dir)
     {
     case GTK_DIR_TAB_BACKWARD:
@@ -5566,6 +6369,12 @@ gtk_tree_view_style_set (GtkWidget *widget,
 
   tree_view = GTK_TREE_VIEW (widget);
 
+  if (GTK_WIDGET_REALIZED (widget))
+    {
+      gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
+      gdk_window_set_background (tree_view->priv->bin_window, &widget->style->base[widget->state]);
+    }
+
   gtk_widget_style_get (widget,
                        "expander_size", &tree_view->priv->expander_size,
                        NULL);
@@ -5577,6 +6386,7 @@ gtk_tree_view_style_set (GtkWidget *widget,
       _gtk_tree_view_column_cell_set_dirty (column, TRUE);
     }
 
+  tree_view->priv->fixed_height = -1;
   _gtk_rbtree_mark_invalid (tree_view->priv->tree);
 
   gtk_widget_queue_resize (widget);
@@ -5622,37 +6432,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;
     }
 
@@ -5666,6 +6480,8 @@ gtk_tree_view_real_move_cursor (GtkTreeView       *tree_view,
                                GtkMovementStep    step,
                                gint               count)
 {
+  GdkModifierType state;
+
   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
   g_return_val_if_fail (step == GTK_MOVEMENT_LOGICAL_POSITIONS ||
                        step == GTK_MOVEMENT_VISUAL_POSITIONS ||
@@ -5682,6 +6498,15 @@ gtk_tree_view_real_move_cursor (GtkTreeView       *tree_view,
   GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
 
+  if (gtk_get_current_event_state (&state))
+    {
+      if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
+        tree_view->priv->ctrl_pressed = TRUE;
+      if ((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
+        tree_view->priv->shift_pressed = TRUE;
+    }
+  /* else we assume not pressed */
+
   switch (step)
     {
       /* currently we make no distinction.  When we go bi-di, we need to */
@@ -5702,6 +6527,9 @@ gtk_tree_view_real_move_cursor (GtkTreeView       *tree_view,
       g_assert_not_reached ();
     }
 
+  tree_view->priv->ctrl_pressed = FALSE;
+  tree_view->priv->shift_pressed = FALSE;
+
   return TRUE;
 }
 
@@ -5816,23 +6644,32 @@ gtk_tree_view_row_changed (GtkTreeModel *model,
   if (tree == NULL)
     goto done;
 
-  _gtk_rbtree_node_mark_invalid (tree, node);
-  for (list = tree_view->priv->columns; list; list = list->next)
+  if (tree_view->priv->fixed_height_mode
+      && tree_view->priv->fixed_height >= 0)
     {
-      GtkTreeViewColumn *column;
+      _gtk_rbtree_node_set_height (tree, node, tree_view->priv->fixed_height);
+    }
+  else
+    {
+      _gtk_rbtree_node_mark_invalid (tree, node);
+      for (list = tree_view->priv->columns; list; list = list->next)
+        {
+          GtkTreeViewColumn *column;
 
-      column = list->data;
-      if (! column->visible)
-       continue;
+          column = list->data;
+          if (! column->visible)
+            continue;
 
-      if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
-       {
-         _gtk_tree_view_column_cell_set_dirty (column, TRUE);
-       }
+          if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
+            {
+              _gtk_tree_view_column_cell_set_dirty (column, TRUE);
+            }
+        }
     }
 
  done:
-  install_presize_handler (tree_view);
+  if (!tree_view->priv->fixed_height_mode)
+    install_presize_handler (tree_view);
   if (free_path)
     gtk_tree_path_free (path);
 }
@@ -5849,6 +6686,7 @@ gtk_tree_view_row_inserted (GtkTreeModel *model,
   GtkRBNode *tmpnode = NULL;
   gint depth;
   gint i = 0;
+  gint height;
   gboolean free_path = FALSE;
 
   g_return_if_fail (path != NULL || iter != NULL);
@@ -5910,18 +6748,24 @@ gtk_tree_view_row_inserted (GtkTreeModel *model,
   if (tree == NULL)
     goto done;
 
+  if (tree_view->priv->fixed_height_mode
+      && tree_view->priv->fixed_height >= 0)
+    height = tree_view->priv->fixed_height;
+  else
+    height = 0;
+
   /* ref the node */
   gtk_tree_model_ref_node (tree_view->priv->model, iter);
   if (indices[depth - 1] == 0)
     {
       tmpnode = _gtk_rbtree_find_count (tree, 1);
-      _gtk_rbtree_insert_before (tree, tmpnode, 0, FALSE);
+      _gtk_rbtree_insert_before (tree, tmpnode, height, FALSE);
     }
   else
     {
       tmpnode = _gtk_rbtree_find_count (tree, indices[depth - 1]);
-      _gtk_rbtree_insert_after (tree, tmpnode, 0, FALSE);
-    }
+      _gtk_rbtree_insert_after (tree, tmpnode, height, FALSE);
+    } 
 
  done:
   install_presize_handler (tree_view);
@@ -6013,6 +6857,19 @@ count_children_helper (GtkRBTree *tree,
   (*((gint *)data))++;
 }
 
+static void
+check_selection_helper (GtkRBTree *tree,
+                        GtkRBNode *node,
+                        gpointer   data)
+{
+  gint *value = (gint *)data;
+
+  *value = GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED);
+
+  if (node->children && !*value)
+    _gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, check_selection_helper, data);
+}
+
 static void
 gtk_tree_view_row_deleted (GtkTreeModel *model,
                           GtkTreePath  *path,
@@ -6022,7 +6879,7 @@ gtk_tree_view_row_deleted (GtkTreeModel *model,
   GtkRBTree *tree;
   GtkRBNode *node;
   GList *list;
-  gint selection_changed;
+  gint selection_changed = FALSE;
 
   g_return_if_fail (path != NULL);
 
@@ -6034,8 +6891,9 @@ gtk_tree_view_row_deleted (GtkTreeModel *model,
   if (tree == NULL)
     return;
 
-  /* Change the selection */
-  selection_changed = GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED);
+  /* check if the selection has been changed */
+  _gtk_rbtree_traverse (tree, node, G_POST_ORDER,
+                        check_selection_helper, &selection_changed);
 
   for (list = tree_view->priv->columns; list; list = list->next)
     if (((GtkTreeViewColumn *)list->data)->visible &&
@@ -6051,7 +6909,7 @@ gtk_tree_view_row_deleted (GtkTreeModel *model,
   /* If we have a node expanded/collapsed timeout, remove it */
   if (tree_view->priv->expand_collapse_timeout != 0)
     {
-      gtk_timeout_remove (tree_view->priv->expand_collapse_timeout);
+      g_source_remove (tree_view->priv->expand_collapse_timeout);
       tree_view->priv->expand_collapse_timeout = 0;
 
       /* Reset node */
@@ -6080,14 +6938,31 @@ 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_row_reference_free (tree_view->priv->top_row);
+      tree_view->priv->top_row = NULL;
+    }
+
   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");
 }
 
+static void
+cancel_arrow_animation (GtkTreeView *tree_view)
+{
+  if (tree_view->priv->expand_collapse_timeout)
+    {
+      while (do_expand_collapse (tree_view));
+
+      g_source_remove (tree_view->priv->expand_collapse_timeout);
+      tree_view->priv->expand_collapse_timeout = 0;
+    }
+}
 
 static void
 gtk_tree_view_rows_reordered (GtkTreeModel *model,
@@ -6126,8 +7001,14 @@ gtk_tree_view_rows_reordered (GtkTreeModel *model,
   if (tree == NULL)
     return;
 
+  if (tree_view->priv->edited_column)
+    gtk_tree_view_stop_editing (tree_view, TRUE);
+
   /* we need to be unprelighted */
   ensure_unprelighted (tree_view);
+
+  /* clear the timeout */
+  cancel_arrow_animation (tree_view);
   
   _gtk_rbtree_reorder (tree, new_order, len);
 
@@ -6151,6 +7032,7 @@ gtk_tree_view_get_background_xrange (GtkTreeView       *tree_view,
   GtkTreeViewColumn *tmp_column = NULL;
   gint total_width;
   GList *list;
+  gboolean rtl;
 
   if (x1)
     *x1 = 0;
@@ -6158,8 +7040,12 @@ gtk_tree_view_get_background_xrange (GtkTreeView       *tree_view,
   if (x2)
     *x2 = 0;
 
+  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
+
   total_width = 0;
-  for (list = tree_view->priv->columns; list; list = list->next)
+  for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
+       list;
+       list = (rtl ? list->prev : list->next))
     {
       tmp_column = list->data;
 
@@ -6198,15 +7084,23 @@ gtk_tree_view_get_arrow_xrange (GtkTreeView *tree_view,
   GtkTreeViewColumn *tmp_column = NULL;
   gint total_width;
   gboolean indent_expanders;
+  gboolean rtl;
+
+  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
 
   total_width = 0;
-  for (list = tree_view->priv->columns; list; list = list->next)
+  for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
+       list;
+       list = (rtl ? list->prev : list->next))
     {
       tmp_column = list->data;
 
       if (gtk_tree_view_is_expander_column (tree_view, tmp_column))
         {
-          x_offset = total_width;
+         if (rtl)
+           x_offset = total_width + tmp_column->width - tree_view->priv->expander_size;
+         else
+           x_offset = total_width;
           break;
         }
 
@@ -6219,22 +7113,28 @@ gtk_tree_view_get_arrow_xrange (GtkTreeView *tree_view,
                        NULL);
 
   if (indent_expanders)
-    x_offset += tree_view->priv->expander_size * _gtk_rbtree_get_depth (tree);
-
+    {
+      if (rtl)
+       x_offset -= tree_view->priv->expander_size * _gtk_rbtree_get_depth (tree);
+      else
+       x_offset += tree_view->priv->expander_size * _gtk_rbtree_get_depth (tree);
+    }
   if (x1)
-    *x1 = x_offset;
+    {
+      *x1 = x_offset;
+    }
 
   if (tmp_column && tmp_column->visible)
     {
       /* +1 because x2 isn't included in the range. */
       if (x2)
-        *x2 = x_offset + tree_view->priv->expander_size + 1;
+        *x2 = *x1 + tree_view->priv->expander_size + 1;
     }
   else
     {
       /* return an empty range, the expander column is hidden */
       if (x2)
-        *x2 = x_offset;
+        *x2 = *x1;
     }
 }
 
@@ -6246,11 +7146,16 @@ gtk_tree_view_build_tree (GtkTreeView *tree_view,
                          gboolean     recurse)
 {
   GtkRBNode *temp = NULL;
+  gboolean is_list = GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IS_LIST);
 
   do
     {
       gtk_tree_model_ref_node (tree_view->priv->model, iter);
       temp = _gtk_rbtree_insert_after (tree, temp, 0, FALSE);
+
+      if (is_list)
+        continue;
+
       if (recurse)
        {
          GtkTreeIter child;
@@ -6267,7 +7172,6 @@ gtk_tree_view_build_tree (GtkTreeView *tree_view,
        {
          if ((temp->flags&GTK_RBNODE_IS_PARENT) != GTK_RBNODE_IS_PARENT)
            temp->flags ^= GTK_RBNODE_IS_PARENT;
-         GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_IS_LIST);
        }
     }
   while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
@@ -6401,28 +7305,21 @@ 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)
+    {
+      /* 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. */
+      gdk_window_process_updates (tree_view->priv->bin_window, TRUE);
+      gtk_tree_view_scroll_to_cell (tree_view, path, NULL, FALSE, 0.0, 0.0);
+      gtk_tree_path_free (path);
+    }
 }
 
 static void
@@ -6547,7 +7444,9 @@ gtk_tree_view_is_expander_column (GtkTreeView       *tree_view,
     }
   else
     {
-      for (list = tree_view->priv->columns; list; list = list->next)
+      for (list = tree_view->priv->columns;
+          list;
+          list = list->next)
        if (((GtkTreeViewColumn *)list->data)->visible)
          break;
       if (list && list->data == column)
@@ -6566,26 +7465,26 @@ gtk_tree_view_add_move_binding (GtkBindingSet  *binding_set,
   
   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
@@ -6611,7 +7510,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);
        }
 
@@ -6658,7 +7559,7 @@ gtk_tree_view_set_column_drag_info (GtkTreeView       *tree_view,
   GtkTreeViewColumn *left_column;
   GtkTreeViewColumn *cur_column = NULL;
   GtkTreeViewColumnReorder *reorder;
-
+  gboolean rtl;
   GList *tmp_list;
   gint left;
 
@@ -6666,16 +7567,18 @@ gtk_tree_view_set_column_drag_info (GtkTreeView       *tree_view,
    * are available.
    */
   left_column = NULL;
+  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
 
   /* First, identify all possible drop spots */
-  tmp_list = tree_view->priv->columns;
+  if (rtl)
+    tmp_list = g_list_last (tree_view->priv->columns);
+  else
+    tmp_list = g_list_first (tree_view->priv->columns);
 
   while (tmp_list)
     {
-      g_assert (tmp_list);
-
       cur_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
-      tmp_list = tmp_list->next;
+      tmp_list = rtl?g_list_previous (tmp_list):g_list_next (tmp_list);
 
       if (cur_column->visible == FALSE)
        continue;
@@ -6743,7 +7646,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);
        }
     }
@@ -6753,10 +7656,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);
 
@@ -6783,34 +7687,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_display_pointer_ungrab (gdk_screen_get_display (screen), GDK_CURRENT_TIME);
-  gdk_display_keyboard_ungrab (gdk_screen_get_display (screen), 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_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_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,
@@ -6835,7 +7741,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 ())
@@ -7152,6 +8058,9 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
   GtkTreeIter iter;
   GList *list;
   gboolean found_column = FALSE;
+  gboolean rtl;
+
+  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
 
   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
     return;
@@ -7202,9 +8111,9 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
        }
     loop_end:
       if (count == 1)
-       list = list->next;
+       list = rtl ? list->prev : list->next;
       else
-       list = list->prev;
+       list = rtl ? list->next : list->prev;
     }
 
   if (found_column)
@@ -7214,7 +8123,7 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
                                        cursor_tree,
                                        cursor_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);
     }
   gtk_tree_view_clamp_column_visible (tree_view, tree_view->priv->focus_column);
 }
@@ -7261,46 +8170,51 @@ gtk_tree_view_move_cursor_start_end (GtkTreeView *tree_view,
   gtk_tree_path_free (path);
 }
 
-static void
+static gboolean
 gtk_tree_view_real_select_all (GtkTreeView *tree_view)
 {
   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
-    return;
+    return FALSE;
 
   if (tree_view->priv->selection->type != GTK_SELECTION_MULTIPLE)
-    return;
+    return FALSE;
+
   gtk_tree_selection_select_all (tree_view->priv->selection);
+
+  return TRUE;
 }
 
-static void
+static gboolean
 gtk_tree_view_real_unselect_all (GtkTreeView *tree_view)
 {
   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
-    return;
+    return FALSE;
 
   if (tree_view->priv->selection->type != GTK_SELECTION_MULTIPLE)
-    return;
+    return FALSE;
+
   gtk_tree_selection_unselect_all (tree_view->priv->selection);
+
+  return TRUE;
 }
 
-static void
+static gboolean
 gtk_tree_view_real_select_cursor_row (GtkTreeView *tree_view,
                                      gboolean     start_editing)
 {
   GtkRBTree *cursor_tree = NULL;
   GtkRBNode *cursor_node = NULL;
   GtkTreePath *cursor_path = NULL;
-  GdkModifierType state = 0;
-  cursor_path = NULL;
+  GtkTreeSelectMode mode = 0;
 
   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
-    return;
+    return FALSE;
 
   if (tree_view->priv->cursor)
     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
 
   if (cursor_path == NULL)
-    return;
+    return FALSE;
 
   _gtk_tree_view_find_node (tree_view, cursor_path,
                            &cursor_tree, &cursor_node);
@@ -7308,26 +8222,29 @@ gtk_tree_view_real_select_cursor_row (GtkTreeView *tree_view,
   if (cursor_tree == NULL)
     {
       gtk_tree_path_free (cursor_path);
-      return;
+      return FALSE;
     }
 
-  gtk_get_current_event_state (&state);
-
-  if (! (state & GDK_SHIFT_MASK) &&
-      start_editing &&
+  if (!tree_view->priv->shift_pressed && start_editing &&
       tree_view->priv->focus_column)
     {
       if (gtk_tree_view_start_editing (tree_view, cursor_path))
        {
          gtk_tree_path_free (cursor_path);
-         return;
+         return TRUE;
        }
     }
+
+  if (tree_view->priv->ctrl_pressed)
+    mode |= GTK_TREE_SELECT_MODE_TOGGLE;
+  if (tree_view->priv->shift_pressed)
+    mode |= GTK_TREE_SELECT_MODE_EXTEND;
+
   _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
                                            cursor_node,
                                            cursor_tree,
                                            cursor_path,
-                                           state,
+                                            mode,
                                            FALSE);
 
   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
@@ -7335,13 +8252,16 @@ gtk_tree_view_real_select_cursor_row (GtkTreeView *tree_view,
   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
   _gtk_tree_view_queue_draw_node (tree_view, cursor_tree, cursor_node, NULL);
 
-  if (! (state & GDK_SHIFT_MASK))
-    gtk_tree_view_row_activated (tree_view, cursor_path, tree_view->priv->focus_column);
+  if (!tree_view->priv->shift_pressed)
+    gtk_tree_view_row_activated (tree_view, cursor_path,
+                                 tree_view->priv->focus_column);
     
   gtk_tree_path_free (cursor_path);
+
+  return TRUE;
 }
 
-static void
+static gboolean
 gtk_tree_view_real_toggle_cursor_row (GtkTreeView *tree_view)
 {
   GtkRBTree *cursor_tree = NULL;
@@ -7349,28 +8269,28 @@ gtk_tree_view_real_toggle_cursor_row (GtkTreeView *tree_view)
   GtkTreePath *cursor_path = NULL;
 
   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
-    return;
+    return FALSE;
 
   cursor_path = NULL;
   if (tree_view->priv->cursor)
     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
 
   if (cursor_path == NULL)
-    return;
+    return FALSE;
 
   _gtk_tree_view_find_node (tree_view, cursor_path,
                            &cursor_tree, &cursor_node);
   if (cursor_tree == NULL)
     {
       gtk_tree_path_free (cursor_path);
-      return;
+      return FALSE;
     }
 
   _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
                                            cursor_node,
                                            cursor_tree,
                                            cursor_path,
-                                           GDK_CONTROL_MASK,
+                                            GTK_TREE_SELECT_MODE_TOGGLE,
                                            FALSE);
 
   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
@@ -7378,11 +8298,11 @@ gtk_tree_view_real_toggle_cursor_row (GtkTreeView *tree_view)
   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
   gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
   gtk_tree_path_free (cursor_path);
-}
-
 
+  return TRUE;
+}
 
-static void
+static gboolean
 gtk_tree_view_real_expand_collapse_cursor_row (GtkTreeView *tree_view,
                                               gboolean     logical,
                                               gboolean     expand,
@@ -7393,30 +8313,36 @@ gtk_tree_view_real_expand_collapse_cursor_row (GtkTreeView *tree_view,
   GtkRBNode *node;
 
   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
-    return;
+    return FALSE;
 
   cursor_path = NULL;
   if (tree_view->priv->cursor)
     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
 
   if (cursor_path == NULL)
-    return;
+    return FALSE;
 
   if (_gtk_tree_view_find_node (tree_view, cursor_path, &tree, &node))
-    return;
+    return FALSE;
   
   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
   gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
 
+  if (!logical
+      && gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL)
+    expand = !expand;
+
   if (expand)
     gtk_tree_view_real_expand_row (tree_view, cursor_path, tree, node, open_all, TRUE);
   else
     gtk_tree_view_real_collapse_row (tree_view, cursor_path, tree, node, TRUE);
 
   gtk_tree_path_free (cursor_path);
+
+  return TRUE;
 }
 
-static void
+static gboolean
 gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
 {
   GtkRBTree *cursor_tree = NULL;
@@ -7424,21 +8350,21 @@ gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
   GtkTreePath *cursor_path = NULL;
 
   if (! GTK_WIDGET_HAS_FOCUS (tree_view))
-    return;
+    return FALSE;
 
   cursor_path = NULL;
   if (tree_view->priv->cursor)
     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
 
   if (cursor_path == NULL)
-    return;
+    return FALSE;
 
   _gtk_tree_view_find_node (tree_view, cursor_path,
                            &cursor_tree, &cursor_node);
   if (cursor_tree == NULL)
     {
       gtk_tree_path_free (cursor_path);
-      return;
+      return FALSE;
     }
 
   if (cursor_tree->parent_node)
@@ -7454,7 +8380,7 @@ gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
                                                cursor_node,
                                                cursor_tree,
                                                cursor_path,
-                                               0,
+                                                0,
                                                FALSE);
     }
 
@@ -7463,73 +8389,93 @@ gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
   gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
   gtk_tree_path_free (cursor_path);
+
+  return TRUE;
 }
 
+/* Cut and paste from gtkwindow.c */
 static void
-gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view)
+send_focus_change (GtkWidget *widget,
+                  gboolean   in)
 {
-  GtkWidget *window;
-  GtkWidget *entry;
-  GtkWidget *search_dialog;
-  GdkEventFocus focus_event;
+  GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
 
-  if (! GTK_WIDGET_HAS_FOCUS (tree_view))
-    return;
+  g_object_ref (widget);
+   
+ if (in)
+    GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
+  else
+    GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
 
-  if (tree_view->priv->enable_search == FALSE ||
-      tree_view->priv->search_column < 0)
-    return;
+  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");
 
-  search_dialog = g_object_get_data (G_OBJECT (tree_view),
-                                    GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
-  if (search_dialog)
+  g_object_unref (widget);
+  gdk_event_free (fevent);
+}
+
+static void
+gtk_tree_view_ensure_interactive_directory (GtkTreeView *tree_view)
+{
+  if (tree_view->priv->search_window != NULL)
     return;
 
-  /* set up window */
-  window = gtk_window_new (GTK_WINDOW_POPUP);
-  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",
+  tree_view->priv->search_window = gtk_window_new (GTK_WINDOW_POPUP);
+  gtk_container_set_border_width (GTK_CONTAINER (tree_view->priv->search_window), 3);
+  gtk_window_set_modal (GTK_WINDOW (tree_view->priv->search_window), TRUE);
+  g_signal_connect (tree_view->priv->search_window, "delete_event",
                    G_CALLBACK (gtk_tree_view_search_delete_event),
                    tree_view);
-  g_signal_connect (G_OBJECT (window), "key_press_event",
+  g_signal_connect (tree_view->priv->search_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 (tree_view->priv->search_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",
+  tree_view->priv->search_entry = gtk_entry_new ();
+  gtk_widget_show (tree_view->priv->search_entry);
+  g_signal_connect (tree_view->priv->search_entry, "changed",
+                   G_CALLBACK (gtk_tree_view_search_init),
+                   tree_view);
+  g_signal_connect (tree_view->priv->search_entry, "populate_popup",
                    G_CALLBACK (gtk_tree_view_search_disable_popdown),
                    tree_view);
-  gtk_container_add (GTK_CONTAINER (window), entry);
+  gtk_container_add (GTK_CONTAINER (tree_view->priv->search_window),
+                    tree_view->priv->search_entry);
+}
 
-  /* done, show it */
-  tree_view->priv->search_dialog_position_func (tree_view, window);
-  gtk_widget_show_all (window);
-  gtk_widget_grab_focus (entry);
+static gboolean
+gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view)
+{
+  if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+    return FALSE;
 
-  /* send focus-in event */
-  focus_event.type = GDK_FOCUS_CHANGE;
-  focus_event.in = TRUE;
-  gtk_widget_event (entry, (GdkEvent *) &focus_event);
+  if (tree_view->priv->enable_search == FALSE ||
+      tree_view->priv->search_column < 0)
+    return FALSE;
 
-  /* position window */
+  gtk_tree_view_ensure_interactive_directory (tree_view);
+  gtk_entry_set_text (GTK_ENTRY (tree_view->priv->search_entry), "");
 
-  /* yes, we point to the entry's private text thing here, a bit evil */
-  g_object_set_data (G_OBJECT (window), "gtk-tree-view-text",
-                    (gchar *) gtk_entry_get_text (GTK_ENTRY (entry)));
-  g_object_set_data (G_OBJECT (tree_view),
-                    GTK_TREE_VIEW_SEARCH_DIALOG_KEY, window);
+  /* done, show it */
+  tree_view->priv->search_dialog_position_func (tree_view, tree_view->priv->search_window);
+  gtk_widget_show (tree_view->priv->search_window);
+  gtk_widget_grab_focus (tree_view->priv->search_entry);
+
+  /* send focus-in event */
+  send_focus_change (tree_view->priv->search_entry, TRUE);
 
   /* search first matching iter */
-  gtk_tree_view_search_init (entry, tree_view);
+  gtk_tree_view_search_init (tree_view->priv->search_entry, tree_view);
+
+  return TRUE;
 }
 
 /* this function returns the new width of the column being resized given
@@ -7543,14 +8489,15 @@ gtk_tree_view_new_column_width (GtkTreeView *tree_view,
 {
   GtkTreeViewColumn *column;
   gint width;
+  gboolean rtl;
 
   /* first translate the x position from widget->window
    * to clist->clist_window
    */
-
+  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
   column = g_list_nth (tree_view->priv->columns, i)->data;
-  width = *x - column->button->allocation.x;
-
+  width = rtl ? (column->button->allocation.x + column->button->allocation.width - *x) : (*x - column->button->allocation.x);
   /* Clamp down the value */
   if (column->min_width == -1)
     width = MAX (column->button->requisition.width,
@@ -7560,8 +8507,9 @@ gtk_tree_view_new_column_width (GtkTreeView *tree_view,
                 width);
   if (column->max_width != -1)
     width = MIN (width, column->max_width != -1);
-  *x = column->button->allocation.x + width;
 
+  *x = rtl ? (column->button->allocation.x + column->button->allocation.width - width) : (column->button->allocation.x + width);
   return width;
 }
 
@@ -7582,13 +8530,16 @@ gtk_tree_view_adjustment_changed (GtkAdjustment *adjustment,
                       - tree_view->priv->hadjustment->value,
                       0);
       dy = tree_view->priv->dy - (int) tree_view->priv->vadjustment->value;
+      if (dy && tree_view->priv->edited_column)
+       {
+         if (GTK_IS_WIDGET (tree_view->priv->edited_column->editable_widget))
+           GTK_WIDGET (tree_view->priv->edited_column->editable_widget)->allocation.y += dy;
+       }
       gdk_window_scroll (tree_view->priv->bin_window, 0, dy);
 
       /* update our dy and top_row */
       tree_view->priv->dy = (int) tree_view->priv->vadjustment->value;
       gtk_tree_view_dy_to_top_row (tree_view);
-      gdk_window_process_updates (tree_view->priv->bin_window, TRUE);
-      gdk_window_process_updates (tree_view->priv->header_window, TRUE);
     }
 }
 
@@ -7607,11 +8558,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);
 }
 
 /**
@@ -7625,12 +8572,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
@@ -7673,18 +8615,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),
-                                           (gpointer) gtk_tree_view_row_changed, tree_view);
-      g_signal_handlers_disconnect_by_func (G_OBJECT (tree_view->priv->model),
-                                           (gpointer) gtk_tree_view_row_inserted, tree_view);
-      g_signal_handlers_disconnect_by_func (G_OBJECT (tree_view->priv->model),
-                                           (gpointer) gtk_tree_view_row_has_child_toggled, tree_view);
-      g_signal_handlers_disconnect_by_func (G_OBJECT (tree_view->priv->model),
-                                           (gpointer) gtk_tree_view_row_deleted, tree_view);
-      g_signal_handlers_disconnect_by_func (G_OBJECT (tree_view->priv->model),
-                                           (gpointer) 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);
@@ -7702,11 +8656,23 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
       tree_view->priv->cursor = NULL;
       gtk_tree_row_reference_free (tree_view->priv->anchor);
       tree_view->priv->anchor = NULL;
+      gtk_tree_row_reference_free (tree_view->priv->top_row);
+      tree_view->priv->top_row = NULL;
+      gtk_tree_row_reference_free (tree_view->priv->last_button_press);
+      tree_view->priv->last_button_press = NULL;
+      gtk_tree_row_reference_free (tree_view->priv->last_button_press_2);
+      tree_view->priv->last_button_press_2 = NULL;
+      gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
+      tree_view->priv->scroll_to_path = NULL;
+
+      tree_view->priv->scroll_to_column = NULL;
 
       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->fixed_height = -1;
+      tree_view->priv->dy = tree_view->priv->top_row_dy = 0;
     }
 
   tree_view->priv->model = model;
@@ -7717,19 +8683,22 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
       gint i;
       GtkTreePath *path;
       GtkTreeIter iter;
-
+      GtkTreeModelFlags flags;
 
       if (tree_view->priv->search_column == -1)
        {
          for (i = 0; i < gtk_tree_model_get_n_columns (model); i++)
            {
-             if (gtk_tree_model_get_column_type (model, i) == G_TYPE_STRING)
+             GType type = gtk_tree_model_get_column_type (model, i);
+
+             if (g_value_type_transformable (type, G_TYPE_STRING))
                {
                  tree_view->priv->search_column = i;
                  break;
                }
            }
        }
+
       g_object_ref (tree_view->priv->model);
       g_signal_connect (tree_view->priv->model,
                        "row_changed",
@@ -7752,6 +8721,12 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
                        G_CALLBACK (gtk_tree_view_rows_reordered),
                        tree_view);
 
+      flags = gtk_tree_model_get_flags (tree_view->priv->model);
+      if ((flags & GTK_TREE_MODEL_LIST_ONLY) == GTK_TREE_MODEL_LIST_ONLY)
+        GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_IS_LIST);
+      else
+        GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_IS_LIST);
+
       path = gtk_tree_path_new_first ();
       if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, path))
        {
@@ -7938,7 +8913,7 @@ 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));
 
@@ -8057,7 +9032,9 @@ gtk_tree_view_get_rules_hint (GtkTreeView  *tree_view)
  * @tree_view: A #GtkTreeView.
  * @column: The #GtkTreeViewColumn to add.
  *
- * Appends @column to the list of columns.
+ * Appends @column to the list of columns. If @tree_view has "fixed_height"
+ * mode enbabled, then @column must have its "sizing" property set to be
+ * GTK_TREE_VIEW_COLUMN_FIXED.
  *
  * Return value: The number of columns in @tree_view after appending.
  **/
@@ -8090,11 +9067,23 @@ gtk_tree_view_remove_column (GtkTreeView       *tree_view,
   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
   g_return_val_if_fail (column->tree_view == GTK_WIDGET (tree_view), -1);
 
-  _gtk_tree_view_column_unset_tree_view (column);
-
   if (tree_view->priv->focus_column == column)
     tree_view->priv->focus_column = NULL;
 
+  if (tree_view->priv->edited_column == column)
+    {
+      gtk_tree_view_stop_editing (tree_view, TRUE);
+
+      /* no need to, but just to be sure ... */
+      tree_view->priv->edited_column = NULL;
+    }
+
+  g_signal_handlers_disconnect_by_func (column,
+                                        G_CALLBACK (column_sizing_notify),
+                                        tree_view);
+
+  _gtk_tree_view_column_unset_tree_view (column);
+
   tree_view->priv->columns = g_list_remove (tree_view->priv->columns, column);
   tree_view->priv->n_columns--;
 
@@ -8119,8 +9108,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;
 }
@@ -8132,7 +9121,9 @@ gtk_tree_view_remove_column (GtkTreeView       *tree_view,
  * @position: The position to insert @column in.
  *
  * This inserts the @column into the @tree_view at @position.  If @position is
- * -1, then the column is inserted at the end.
+ * -1, then the column is inserted at the end. If @tree_view has
+ * "fixed_height" mode enabled, then @column must have its "sizing" property
+ * set to be GTK_TREE_VIEW_COLUMN_FIXED.
  *
  * Return value: The number of columns in @tree_view after insertion.
  **/
@@ -8145,7 +9136,11 @@ 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));
+  if (tree_view->priv->fixed_height_mode)
+    g_return_val_if_fail (gtk_tree_view_column_get_sizing (column)
+                          == GTK_TREE_VIEW_COLUMN_FIXED, -1);
+
+  g_object_ref (column);
   gtk_object_sink (GTK_OBJECT (column));
 
   if (tree_view->priv->n_columns == 0 &&
@@ -8155,6 +9150,9 @@ gtk_tree_view_insert_column (GtkTreeView       *tree_view,
       gdk_window_show (tree_view->priv->header_window);
     }
 
+  g_signal_connect (column, "notify::sizing",
+                    G_CALLBACK (column_sizing_notify), tree_view);
+
   tree_view->priv->columns = g_list_insert (tree_view->priv->columns,
                                            column, position);
   tree_view->priv->n_columns++;
@@ -8176,7 +9174,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;
 }
@@ -8191,7 +9189,9 @@ gtk_tree_view_insert_column (GtkTreeView       *tree_view,
  *
  * Creates a new #GtkTreeViewColumn and inserts it into the @tree_view at
  * @position.  If @position is -1, then the newly created column is inserted at
- * the end.  The column is initialized with the attributes given.
+ * the end.  The column is initialized with the attributes given. If @tree_view
+ * has "fixed_height" mode enabled, then @column must have its sizing
+ * property set to be GTK_TREE_VIEW_COLUMN_FIXED.
  *
  * Return value: The number of columns in @tree_view after insertion.
  **/
@@ -8246,6 +9246,8 @@ gtk_tree_view_insert_column_with_attributes (GtkTreeView     *tree_view,
  * with the given cell renderer and a #GtkCellDataFunc to set cell renderer
  * attributes (normally using data from the model). See also
  * gtk_tree_view_column_set_cell_data_func(), gtk_tree_view_column_pack_start().
+ * If @tree_view has "fixed_height" mode enabled, then @column must have its
+ * "sizing" property set to be GTK_TREE_VIEW_COLUMN_FIXED.
  *
  * Return value: number of columns in the tree view post-insert
  **/
@@ -8369,7 +9371,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);
 }
 
 /**
@@ -8516,7 +9518,7 @@ gtk_tree_view_scroll_to_point (GtkTreeView *tree_view,
  *
  * If @use_align is %FALSE, then the alignment arguments are ignored, and the
  * tree does the minimum amount of work to scroll the cell onto the screen.
- * This means that the cell will be scrolled to the edge closest to it's current
+ * This means that the cell will be scrolled to the edge closest to its current
  * position.  If the cell is currently visible on the screen, nothing is done.
  *
  * This function only works if the model is set, and @path is a valid row on the
@@ -8632,10 +9634,39 @@ 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);
 }
 
 
+static void
+gtk_tree_view_expand_all_emission_helper (GtkRBTree *tree,
+                                          GtkRBNode *node,
+                                          gpointer   data)
+{
+  GtkTreeView *tree_view = data;
+
+  if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT &&
+      node->children)
+    {
+      GtkTreePath *path;
+      GtkTreeIter iter;
+
+      path = _gtk_tree_view_find_path (tree_view, tree, node);
+      gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
+
+      g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
+
+      gtk_tree_path_free (path);
+    }
+
+  if (node->children)
+    _gtk_rbtree_traverse (node->children,
+                          node->children->root,
+                          G_PRE_ORDER,
+                          gtk_tree_view_expand_all_emission_helper,
+                          tree_view);
+}
+
 static void
 gtk_tree_view_expand_all_helper (GtkRBTree  *tree,
                                 GtkRBNode  *node,
@@ -8666,6 +9697,13 @@ gtk_tree_view_expand_all_helper (GtkRBTree  *tree,
                                &child,
                                gtk_tree_path_get_depth (path) + 1,
                                TRUE);
+
+      g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
+      _gtk_rbtree_traverse (node->children,
+                            node->children->root,
+                            G_PRE_ORDER,
+                            gtk_tree_view_expand_all_emission_helper,
+                            tree_view);
       gtk_tree_path_free (path);
     }
 }
@@ -8695,14 +9733,25 @@ gtk_tree_view_expand_all (GtkTreeView *tree_view)
 static gboolean
 expand_collapse_timeout (gpointer data)
 {
-  GtkTreeView *tree_view = data;
+  gboolean retval;
+
+  GDK_THREADS_ENTER ();
+
+  retval = do_expand_collapse (data);
+
+  GDK_THREADS_LEAVE ();
+
+  return retval;
+}
+
+static gboolean
+do_expand_collapse (GtkTreeView *tree_view)
+{
   GtkRBNode *node;
   GtkRBTree *tree;
   gboolean expanding;
   gboolean redraw;
 
-  GDK_THREADS_ENTER ();
-
   redraw = FALSE;
   expanding = TRUE;
 
@@ -8751,13 +9800,9 @@ expand_collapse_timeout (gpointer data)
     {
       gtk_tree_view_queue_draw_arrow (tree_view, tree, node, NULL);
 
-      GDK_THREADS_LEAVE ();
-
       return TRUE;
     }
 
-  GDK_THREADS_LEAVE ();
-
   return FALSE;
 }
 
@@ -8773,7 +9818,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));
 
@@ -8807,6 +9852,8 @@ gtk_tree_view_collapse_all (GtkTreeView *tree_view)
  *
  * Expands the row at @path. This will also expand all parent rows of
  * @path as necessary.
+ *
+ * Since: 2.2
  **/
 void
 gtk_tree_view_expand_to_path (GtkTreeView *tree_view,
@@ -8827,11 +9874,11 @@ gtk_tree_view_expand_to_path (GtkTreeView *tree_view,
 
   for (i = 0; i < depth; i++)
     {
-      gtk_tree_path_append_index (path, indices[i]);
-      gtk_tree_view_expand_row (tree_view, path, FALSE);
+      gtk_tree_path_append_index (tmp, indices[i]);
+      gtk_tree_view_expand_row (tree_view, tmp, FALSE);
     }
 
-  gtk_tree_path_free (path);
+  gtk_tree_path_free (tmp);
 }
 
 /* FIXME the bool return values for expand_row and collapse_row are
@@ -8852,9 +9899,9 @@ gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
   GtkTreeIter temp;
   gboolean expand;
 
-
   if (node->children && !open_all)
-    return TRUE;
+    return FALSE;
+
   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT))
     return FALSE;
 
@@ -8862,7 +9909,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;
@@ -8881,7 +9958,7 @@ gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
 
   if (tree_view->priv->expand_collapse_timeout)
     {
-      gtk_timeout_remove (tree_view->priv->expand_collapse_timeout);
+      g_source_remove (tree_view->priv->expand_collapse_timeout);
       tree_view->priv->expand_collapse_timeout = 0;
     }
 
@@ -8895,7 +9972,7 @@ gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
 
   if (animate)
     {
-      tree_view->priv->expand_collapse_timeout = gtk_timeout_add (50, expand_collapse_timeout, tree_view);
+      tree_view->priv->expand_collapse_timeout = g_timeout_add (50, expand_collapse_timeout, tree_view);
       tree_view->priv->expanded_collapsed_node = node;
       tree_view->priv->expanded_collapsed_tree = tree;
 
@@ -8904,7 +9981,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;
 }
 
@@ -8955,14 +10032,15 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
   gboolean collapse;
   gint x, y;
   GList *list;
-  GdkScreen *screen;
+  GdkDisplay *display;
+  GdkWindow *child, *parent;
 
   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;
@@ -9063,14 +10141,14 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
   if (gtk_tree_view_unref_and_check_selection_tree (tree_view, node->children))
     {
       _gtk_rbtree_remove (node->children);
-      g_signal_emit_by_name (G_OBJECT (tree_view->priv->selection), "changed", 0);
+      g_signal_emit_by_name (tree_view->priv->selection, "changed");
     }
   else
     _gtk_rbtree_remove (node->children);
 
   if (tree_view->priv->expand_collapse_timeout)
     {
-      gtk_timeout_remove (tree_view->priv->expand_collapse_timeout);
+      g_source_remove (tree_view->priv->expand_collapse_timeout);
       tree_view->priv->expand_collapse_timeout = 0;
     }
   
@@ -9084,7 +10162,7 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
 
   if (animate)
     {
-      tree_view->priv->expand_collapse_timeout = gtk_timeout_add (50, expand_collapse_timeout, tree_view);
+      tree_view->priv->expand_collapse_timeout = g_timeout_add (50, expand_collapse_timeout, tree_view);
       tree_view->priv->expanded_collapsed_node = node;
       tree_view->priv->expanded_collapsed_tree = tree;
 
@@ -9096,24 +10174,35 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
     }
 
-  g_signal_emit (G_OBJECT (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. */
+  g_signal_emit (tree_view, tree_view_signals[ROW_COLLAPSED], 0, &iter, path);
 
-  screen = gdk_drawable_get_screen (tree_view->priv->bin_window);
-  if (gdk_screen_get_window_at_pointer (screen, &x, &y) == tree_view->priv->bin_window)
+  if (GTK_WIDGET_MAPPED (tree_view))
     {
-      GdkEventMotion event;
-      event.window = tree_view->priv->bin_window;
-      event.x = x;
-      event.y = y;
+      /* now that we've collapsed all rows, we want to try to set the prelight
+       * again. To do this, we fake a motion event and send it to ourselves. */
+
+      display = gdk_drawable_get_display (tree_view->priv->bin_window);
+      child = tree_view->priv->bin_window;
+      parent = gdk_window_get_parent (child);
+
+      if (gdk_window_get_pointer (parent, &x, &y, NULL) == child)
+       {
+         GdkEventMotion event;
+         gint child_x, child_y;
+
+         gdk_window_get_position (child, &child_x, &child_y);
+
+         event.window = tree_view->priv->bin_window;
+         event.x = x - child_x;
+         event.y = y - child_y;
 
-      /* despite the fact this isn't a real event, I'm almost positive it will
-       * never trigger a drag event.  maybe_drag is the only function that uses
-       * more than just event.x and event.y. */
-      gtk_tree_view_motion_bin_window (GTK_WIDGET (tree_view), &event);
+         /* despite the fact this isn't a real event, I'm almost positive it will
+          * never trigger a drag event.  maybe_drag is the only function that uses
+          * more than just event.x and event.y. */
+         gtk_tree_view_motion_bin_window (GTK_WIDGET (tree_view), &event);
+       }
     }
+
   return TRUE;
 }
 
@@ -9234,7 +10323,7 @@ gtk_tree_view_row_expanded (GtkTreeView *tree_view,
   return (node->children != NULL);
 }
 
-static GtkTargetEntry row_targets[] = {
+static const GtkTargetEntry row_targets[] = {
   { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, 0 }
 };
 
@@ -9266,10 +10355,10 @@ gtk_tree_view_get_reorderable (GtkTreeView *tree_view)
  * #GtkTreeStore and #GtkListStore support these.  If @reorderable is %TRUE, then
  * the user can reorder the model by dragging and dropping rows.  The
  * developer can listen to these changes by connecting to the model's
- * signals.
+ * row_inserted and row_deleted signals.
  *
  * This function does not give you any degree of control over the order -- any
- * reorderering is allowed.  If more control is needed, you should probably
+ * reordering is allowed.  If more control is needed, you should probably
  * handle drag and drop manually.
  **/
 void
@@ -9314,7 +10403,6 @@ gtk_tree_view_real_set_cursor (GtkTreeView     *tree_view,
 {
   GtkRBTree *tree = NULL;
   GtkRBNode *node = NULL;
-  GdkModifierType state = 0;
 
   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
     {
@@ -9325,7 +10413,6 @@ gtk_tree_view_real_set_cursor (GtkTreeView     *tree_view,
     }
 
   gtk_tree_row_reference_free (tree_view->priv->cursor);
-  gtk_get_current_event_state (&state);
 
   tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
                                                              tree_view->priv->model,
@@ -9333,10 +10420,32 @@ gtk_tree_view_real_set_cursor (GtkTreeView     *tree_view,
   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
   if (tree != NULL)
     {
-      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, FALSE);
+      GtkRBTree *new_tree = NULL;
+      GtkRBNode *new_node = NULL;
+
+      if (clear_and_select && !tree_view->priv->ctrl_pressed)
+        {
+          GtkTreeSelectMode mode = 0;
+
+          if (tree_view->priv->ctrl_pressed)
+            mode |= GTK_TREE_SELECT_MODE_TOGGLE;
+          if (tree_view->priv->shift_pressed)
+            mode |= GTK_TREE_SELECT_MODE_EXTEND;
+
+          _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
+                                                    node, tree, path, mode,
+                                                    FALSE);
+        }
+
+      /* We have to re-find tree and node here again, somebody might have
+       * cleared the node or the whole tree in the GtkTreeSelection::changed
+       * callback. If the nodes differ we bail out here.
+       */
+      _gtk_tree_view_find_node (tree_view, path, &new_tree, &new_node);
+
+      if (tree != new_tree || node != new_node)
+        return;
+
       if (clamp_node)
         {
          gtk_tree_view_clamp_node_visible (tree_view, tree, node);
@@ -9344,7 +10453,7 @@ gtk_tree_view_real_set_cursor (GtkTreeView     *tree_view,
        }
     }
 
-  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[CURSOR_CHANGED], 0);
+  g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
 }
 
 /**
@@ -9356,6 +10465,9 @@ gtk_tree_view_real_set_cursor (GtkTreeView     *tree_view,
  * Fills in @path and @focus_column with the current path and focus column.  If
  * the cursor isn't currently set, then *@path will be %NULL.  If no column
  * currently has focus, then *@focus_column will be %NULL.
+ *
+ * The returned #GtkTreePath must be freed with gtk_tree_path_free() when
+ * you are done with it.
  **/
 void
 gtk_tree_view_get_cursor (GtkTreeView        *tree_view,
@@ -9387,12 +10499,12 @@ gtk_tree_view_get_cursor (GtkTreeView        *tree_view,
  *
  * 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
- * @column is not %NULL, then focus is given to the column specified by it.
- * Additionally, if @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.
+ * @focus_column is not %NULL, then focus is given to the column specified by 
+ * it. 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 (GtkTreeView       *tree_view,
@@ -9423,6 +10535,8 @@ gtk_tree_view_set_cursor (GtkTreeView       *tree_view,
  * @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.
+ *
+ * Since: 2.2
  **/
 void
 gtk_tree_view_set_cursor_on_cell (GtkTreeView       *tree_view,
@@ -9441,6 +10555,11 @@ gtk_tree_view_set_cursor_on_cell (GtkTreeView       *tree_view,
       g_return_if_fail (GTK_IS_CELL_RENDERER (focus_cell));
     }
 
+  /* cancel the current editing, if it exists */
+  if (tree_view->priv->edited_column &&
+      tree_view->priv->edited_column->editable_widget)
+    gtk_tree_view_stop_editing (tree_view, TRUE);
+
   gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
 
   if (focus_column && focus_column->visible)
@@ -9528,7 +10647,7 @@ gtk_tree_view_get_path_at_pos (GtkTreeView        *tree_view,
   if (tree_view->priv->tree == NULL)
     return FALSE;
 
-  if (x > tree_view->priv->hadjustment->page_size)
+  if (x > tree_view->priv->hadjustment->upper)
     return FALSE;
 
   if (x < 0 || y < 0)
@@ -9565,14 +10684,24 @@ gtk_tree_view_get_path_at_pos (GtkTreeView        *tree_view,
          remaining_x -= tmp_column->width;
        }
 
+      /* If found is FALSE and there is a last_column, then it the remainder
+       * space is in that area
+       */
       if (!found)
         {
-          if (column)
-            *column = last_column;
-
-          if (cell_x)
-            *cell_x = last_column->width + remaining_x;
-        }
+         if (last_column)
+           {
+             if (column)
+               *column = last_column;
+             
+             if (cell_x)
+               *cell_x = last_column->width + remaining_x;
+           }
+         else
+           {
+             return FALSE;
+           }
+       }
     }
 
   y_offset = _gtk_rbtree_find_offset (tree_view->priv->tree,
@@ -9644,9 +10773,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);
@@ -9817,6 +10947,17 @@ unset_reorderable (GtkTreeView *tree_view)
     }
 }
 
+/**
+ * gtk_tree_view_enable_model_drag_source:
+ * @tree_view: a #GtkTreeView
+ * @start_button_mask: Mask of allowed buttons to start drag
+ * @targets: the table of targets that the drag will support
+ * @n_targets: the number of items in @targets
+ * @actions: the bitmask of possible actions for a drag from this
+ *    widget
+ * 
+ * Turns @tree_view into a drag source for automatic DND.
+ **/
 void
 gtk_tree_view_enable_model_drag_source (GtkTreeView              *tree_view,
                                        GdkModifierType           start_button_mask,
@@ -9828,6 +10969,12 @@ gtk_tree_view_enable_model_drag_source (GtkTreeView              *tree_view,
 
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
 
+  gtk_drag_source_set (GTK_WIDGET (tree_view),
+                      0,
+                      NULL,
+                      0,
+                      actions);
+
   di = ensure_info (tree_view);
   clear_source_info (di);
 
@@ -9840,6 +10987,16 @@ gtk_tree_view_enable_model_drag_source (GtkTreeView              *tree_view,
   unset_reorderable (tree_view);
 }
 
+/**
+ * gtk_tree_view_enable_model_drag_dest:
+ * @tree_view: a #GtkTreeView
+ * @targets: the table of targets that the drag will support
+ * @n_targets: the number of items in @targets
+ * @actions: the bitmask of possible actions for a drag from this
+ *    widget
+ * 
+ * Turns @tree_view into a drop destination for automatic DND.
+ **/
 void
 gtk_tree_view_enable_model_drag_dest (GtkTreeView              *tree_view,
                                      const GtkTargetEntry     *targets,
@@ -9867,6 +11024,12 @@ gtk_tree_view_enable_model_drag_dest (GtkTreeView              *tree_view,
   unset_reorderable (tree_view);
 }
 
+/**
+ * gtk_tree_view_unset_rows_drag_source:
+ * @tree_view: a #GtkTreeView
+ * 
+ * Undoes the effect of gtk_tree_view_enable_model_drag_source().
+ **/
 void
 gtk_tree_view_unset_rows_drag_source (GtkTreeView *tree_view)
 {
@@ -9880,6 +11043,7 @@ gtk_tree_view_unset_rows_drag_source (GtkTreeView *tree_view)
     {
       if (di->source_set)
         {
+          gtk_drag_source_unset (GTK_WIDGET (tree_view));
           clear_source_info (di);
           di->source_set = FALSE;
         }
@@ -9891,6 +11055,12 @@ gtk_tree_view_unset_rows_drag_source (GtkTreeView *tree_view)
   unset_reorderable (tree_view);
 }
 
+/**
+ * gtk_tree_view_unset_rows_drag_dest:
+ * @tree_view: a #GtkTreeView
+ * 
+ * Undoes the effect of gtk_tree_view_enable_model_drag_dest().
+ **/
 void
 gtk_tree_view_unset_rows_drag_dest (GtkTreeView *tree_view)
 {
@@ -9916,12 +11086,21 @@ gtk_tree_view_unset_rows_drag_dest (GtkTreeView *tree_view)
   unset_reorderable (tree_view);
 }
 
+/**
+ * gtk_tree_view_set_drag_dest_row:
+ * @tree_view: a #GtkTreeView
+ * @path: The path of the row to highlight, or %NULL.
+ * @pos: Specifies whether to drop before, after or into the row
+ * 
+ * Sets the row that is highlighted for feedback.
+ **/
 void
 gtk_tree_view_set_drag_dest_row (GtkTreeView            *tree_view,
                                  GtkTreePath            *path,
                                  GtkTreeViewDropPosition pos)
 {
   GtkTreePath *current_dest;
+
   /* Note; this function is exported to allow a custom DND
    * implementation, so it can't touch TreeViewDragInfo
    */
@@ -9931,10 +11110,26 @@ gtk_tree_view_set_drag_dest_row (GtkTreeView            *tree_view,
   current_dest = NULL;
 
   if (tree_view->priv->drag_dest_row)
-    current_dest = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
+    {
+      current_dest = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
+      gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
+    }
 
-  if (tree_view->priv->drag_dest_row)
-    gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
+  /* special case a drop on an empty model */
+  tree_view->priv->empty_view_drop = 0;
+
+  if (pos == GTK_TREE_VIEW_DROP_BEFORE && path
+      && gtk_tree_path_get_depth (path) == 1
+      && gtk_tree_path_get_indices (path)[0] == 0)
+    {
+      gint n_children;
+
+      n_children = gtk_tree_model_iter_n_children (tree_view->priv->model,
+                                                   NULL);
+
+      if (!n_children)
+        tree_view->priv->empty_view_drop = 1;
+    }
 
   tree_view->priv->drag_dest_pos = pos;
 
@@ -9969,6 +11164,14 @@ gtk_tree_view_set_drag_dest_row (GtkTreeView            *tree_view,
     }
 }
 
+/**
+ * gtk_tree_view_get_drag_dest_row:
+ * @tree_view: a #GtkTreeView
+ * @path: Return location for the path of the highlighted row, or %NULL.
+ * @pos: Return location for the drop position, or %NULL
+ * 
+ * Gets information about the row that is highlighted for feedback.
+ **/
 void
 gtk_tree_view_get_drag_dest_row (GtkTreeView              *tree_view,
                                  GtkTreePath             **path,
@@ -9981,13 +11184,30 @@ gtk_tree_view_get_drag_dest_row (GtkTreeView              *tree_view,
       if (tree_view->priv->drag_dest_row)
         *path = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
       else
-        *path = NULL;
+        {
+          if (tree_view->priv->empty_view_drop)
+            *path = gtk_tree_path_new_from_indices (0, -1);
+          else
+            *path = NULL;
+        }
     }
 
   if (pos)
     *pos = tree_view->priv->drag_dest_pos;
 }
 
+/**
+ * gtk_tree_view_get_dest_row_at_pos:
+ * @tree_view: a #GtkTreeView
+ * @drag_x: the position to determine the destination row for
+ * @drag_y: the position to determine the destination row for
+ * @path: Return location for the path of the highlighted row, or %NULL.
+ * @pos: Return location for the drop position, or %NULL
+ * 
+ * Determines the destination row for a given position.
+ * 
+ * Return value: whether there is a row at the given postiion,
+ **/
 gboolean
 gtk_tree_view_get_dest_row_at_pos (GtkTreeView             *tree_view,
                                    gint                     drag_x,
@@ -10283,10 +11503,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,
@@ -10326,7 +11547,9 @@ gtk_tree_view_get_search_equal_func (GtkTreeView *tree_view)
  * @search_user_data: user data to pass to @search_equal_func, or %NULL
  * @search_destroy: Destroy notifier for @search_user_data, or %NULL
  *
- * Sets the compare function for the interactive search capabilities.
+ * Sets the compare function for the interactive search capabilities; note
+ * that somewhat like strcmp() returning 0 for equality
+ * #GtkTreeViewSearchEqualFunc returns %FALSE on matches.
  **/
 void
 gtk_tree_view_set_search_equal_func (GtkTreeView                *tree_view,
@@ -10348,36 +11571,15 @@ gtk_tree_view_set_search_equal_func (GtkTreeView                *tree_view,
 }
 
 static void
-gtk_tree_view_search_dialog_destroy (GtkWidget   *search_dialog,
+gtk_tree_view_search_dialog_hide (GtkWidget   *search_dialog,
                                     GtkTreeView *tree_view)
 {
-  GtkEntry *entry = (GtkEntry *)(gtk_container_get_children (GTK_CONTAINER (search_dialog)))->data;
-  gint *selected_iter;
-
   if (tree_view->priv->disable_popdown)
     return;
 
-  if (entry)
-    {
-      GdkEventFocus focus_event;
-
-      focus_event.type = GDK_FOCUS_CHANGE;
-      focus_event.in = FALSE;
-      gtk_widget_event (GTK_WIDGET (entry), (GdkEvent *) &focus_event);
-    }
-
-  /* remove data from tree_view */
-  g_object_set_data (G_OBJECT (tree_view), GTK_TREE_VIEW_SEARCH_DIALOG_KEY,
-                    NULL);
-
-  selected_iter = g_object_get_data (G_OBJECT (search_dialog),
-                                    "gtk-tree-view-selected-iter");
-  if (selected_iter)
-    g_free (selected_iter);
-  g_object_set_data (G_OBJECT (search_dialog), "gtk-tree-view-selected-iter",
-                    NULL);
-
-  gtk_widget_destroy (search_dialog);
+  /* send focus-in event */
+  send_focus_change (GTK_WIDGET (tree_view->priv->search_entry), FALSE);
+  gtk_widget_hide (search_dialog);
 }
 
 static void
@@ -10394,9 +11596,9 @@ gtk_tree_view_search_position_func (GtkTreeView *tree_view,
   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_get_width (screen))
@@ -10424,7 +11626,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);
 }
 
@@ -10456,7 +11658,7 @@ gtk_tree_view_search_delete_event (GtkWidget *widget,
 {
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
-  gtk_tree_view_search_dialog_destroy (widget, tree_view);
+  gtk_tree_view_search_dialog_hide (widget, tree_view);
 
   return TRUE;
 }
@@ -10468,7 +11670,7 @@ gtk_tree_view_search_button_press_event (GtkWidget *widget,
 {
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
 
-  gtk_tree_view_search_dialog_destroy (widget, tree_view);
+  gtk_tree_view_search_dialog_hide (widget, tree_view);
 
   return TRUE;
 }
@@ -10486,19 +11688,19 @@ gtk_tree_view_search_key_press_event (GtkWidget *widget,
       event->keyval == GDK_Return ||
       event->keyval == GDK_Tab)
     {
-      gtk_tree_view_search_dialog_destroy (widget, tree_view);
+      gtk_tree_view_search_dialog_hide (widget, tree_view);
       return TRUE;
     }
 
   /* select previous matching iter */
-  if (event->keyval == GDK_Up)
+  if (event->keyval == GDK_Up || event->keyval == GDK_KP_Up)
     {
       gtk_tree_view_search_move (widget, tree_view, TRUE);
       return TRUE;
     }
 
   /* select next matching iter */
-  if (event->keyval == GDK_Down)
+  if (event->keyval == GDK_Down || event->keyval == GDK_KP_Down)
     {
       gtk_tree_view_search_move (widget, tree_view, FALSE);
       return TRUE;
@@ -10513,20 +11715,18 @@ gtk_tree_view_search_move (GtkWidget   *window,
                           gboolean     up)
 {
   gboolean ret;
-  gint *selected_iter;
   gint len;
   gint count = 0;
-  gchar *text;
+  const gchar *text;
   GtkTreeIter iter;
   GtkTreeModel *model;
   GtkTreeSelection *selection;
 
-  text = g_object_get_data (G_OBJECT (window), "gtk-tree-view-text");
-  selected_iter = g_object_get_data (G_OBJECT (window), "gtk-tree-view-selected-iter");
+  text = gtk_entry_get_text (GTK_ENTRY (tree_view->priv->search_entry));
 
   g_return_if_fail (text != NULL);
 
-  if (!selected_iter || (up && *selected_iter == 1))
+  if (up && tree_view->priv->selected_iter == 1)
     return;
 
   len = strlen (text);
@@ -10542,12 +11742,12 @@ gtk_tree_view_search_move (GtkWidget   *window,
   gtk_tree_model_get_iter_first (model, &iter);
 
   ret = gtk_tree_view_search_iter (model, selection, &iter, text,
-                                  &count, up?((*selected_iter) - 1):((*selected_iter + 1)));
+                                  &count, up?((tree_view->priv->selected_iter) - 1):((tree_view->priv->selected_iter + 1)));
 
   if (ret)
     {
       /* found */
-      *selected_iter += up?(-1):(1);
+      tree_view->priv->selected_iter += up?(-1):(1);
     }
   else
     {
@@ -10556,7 +11756,7 @@ gtk_tree_view_search_move (GtkWidget   *window,
       gtk_tree_model_get_iter_first (model, &iter);
       gtk_tree_view_search_iter (model, selection,
                                 &iter, text,
-                                &count, *selected_iter);
+                                &count, tree_view->priv->selected_iter);
     }
 }
 
@@ -10568,25 +11768,46 @@ gtk_tree_view_search_equal_func (GtkTreeModel *model,
                                 gpointer      search_data)
 {
   gboolean retval = TRUE;
+  const gchar *str;
   gchar *normalized_string;
   gchar *normalized_key;
-  gchar *case_normalized_string;
-  gchar *case_normalized_key;
+  gchar *case_normalized_string = NULL;
+  gchar *case_normalized_key = NULL;
   GValue value = {0,};
-  gint key_len;
+  GValue transformed = {0,};
 
   gtk_tree_model_get_value (model, iter, column, &value);
-  normalized_string = g_utf8_normalize (g_value_get_string (&value), -1, G_NORMALIZE_ALL);
-  normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
-  case_normalized_string = g_utf8_casefold (normalized_string, -1);
-  case_normalized_key = g_utf8_casefold (normalized_key, -1);
 
-  key_len = strlen (case_normalized_key);
+  g_value_init (&transformed, G_TYPE_STRING);
 
-  if (!strncmp (case_normalized_key, case_normalized_string, key_len))
-    retval = FALSE;
+  if (!g_value_transform (&value, &transformed))
+    {
+      g_value_unset (&value);
+      return TRUE;
+    }
 
   g_value_unset (&value);
+
+  str = g_value_get_string (&transformed);
+  if (!str)
+    {
+      g_value_unset (&transformed);
+      return TRUE;
+    }
+
+  normalized_string = g_utf8_normalize (str, -1, G_NORMALIZE_ALL);
+  normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
+
+  if (normalized_string && normalized_key)
+    {
+      case_normalized_string = g_utf8_casefold (normalized_string, -1);
+      case_normalized_key = g_utf8_casefold (normalized_key, -1);
+
+      if (strstr (case_normalized_string, case_normalized_key))
+        retval = FALSE;
+    }
+
+  g_value_unset (&transformed);
   g_free (normalized_key);
   g_free (normalized_string);
   g_free (case_normalized_key);
@@ -10700,9 +11921,6 @@ gtk_tree_view_search_iter (GtkTreeModel     *model,
     }
   while (1);
 
-  if (path)
-    gtk_tree_path_free (path);
-
   return FALSE;
 }
 
@@ -10711,7 +11929,6 @@ gtk_tree_view_search_init (GtkWidget   *entry,
                           GtkTreeView *tree_view)
 {
   gint ret;
-  gint *selected_iter;
   gint len;
   gint count = 0;
   const gchar *text;
@@ -10731,10 +11948,6 @@ gtk_tree_view_search_init (GtkWidget   *entry,
 
   /* search */
   gtk_tree_selection_unselect_all (selection);
-  selected_iter = g_object_get_data (G_OBJECT (window), "gtk-tree-view-selected-iter");
-  if (selected_iter)
-    g_free (selected_iter);
-  g_object_set_data (G_OBJECT (window), "gtk-tree-view-selected-iter", NULL);
 
   if (len < 1)
     return;
@@ -10746,12 +11959,7 @@ gtk_tree_view_search_init (GtkWidget   *entry,
                                   &count, 1);
 
   if (ret)
-    {
-      selected_iter = g_malloc (sizeof (int));
-      *selected_iter = 1;
-      g_object_set_data (G_OBJECT (window), "gtk-tree-view-selected-iter",
-                        selected_iter);
-    }
+    tree_view->priv->selected_iter = 1;
 }
 
 static void
@@ -10764,7 +11972,8 @@ gtk_tree_view_remove_widget (GtkCellEditable *cell_editable,
   _gtk_tree_view_column_stop_editing (tree_view->priv->edited_column);
   tree_view->priv->edited_column = NULL;
 
-  gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+  if (GTK_WIDGET_HAS_FOCUS (cell_editable))
+    gtk_widget_grab_focus (GTK_WIDGET (tree_view));
 
   gtk_container_remove (GTK_CONTAINER (tree_view),
                        GTK_WIDGET (cell_editable));
@@ -10811,6 +12020,13 @@ gtk_tree_view_start_editing (GtkTreeView *tree_view,
                               cursor_path,
                               tree_view->priv->focus_column,
                               &cell_area);
+
+  if (gtk_tree_view_is_expander_column (tree_view, tree_view->priv->focus_column) && TREE_VIEW_DRAW_EXPANDERS (tree_view))
+    {
+      cell_area.x += tree_view->priv->expander_size;
+      cell_area.width -= tree_view->priv->expander_size;
+    }
+
   if (_gtk_tree_view_column_cell_event (tree_view->priv->focus_column,
                                        &editable_widget,
                                        NULL,
@@ -10872,7 +12088,8 @@ 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