--- a/gtk/gtktreeview.c
+++ b/gtk/gtktreeview.c
@@ -43,6 +43,8 @@
 #include "gtkframe.h"
 #include "gtktreemodelsort.h"
 #include "gtktooltip.h"
+#include "gtkicontheme.h"
+#include "gtkeventbox.h"
 #include "gtkprivate.h"
 #include "gtkalias.h"
 
@@ -54,6 +56,9 @@
 #define GTK_TREE_VIEW_SEARCH_DIALOG_TIMEOUT 5000
 #define AUTO_EXPAND_TIMEOUT 500
 
+#define HILDON_TICK_MARK_SIZE 48
+#define HILDON_ROW_HEADER_HEIGHT 35
+
 /* The "background" areas of all rows/cells add up to cover the entire tree.
  * The background includes all inter-row and inter-cell spacing.
  * The "cell" areas are the cell_area passed in to gtk_cell_renderer_render(),
@@ -120,6 +125,8 @@
   EXPAND_COLLAPSE_CURSOR_ROW,
   SELECT_CURSOR_PARENT,
   START_INTERACTIVE_SEARCH,
+  ROW_INSENSITIVE,
+  HILDON_ROW_TAPPED,
   LAST_SIGNAL
 };
 
@@ -144,7 +151,10 @@
   PROP_RUBBER_BANDING,
   PROP_ENABLE_GRID_LINES,
   PROP_ENABLE_TREE_LINES,
-  PROP_TOOLTIP_COLUMN
+  PROP_TOOLTIP_COLUMN,
+  PROP_HILDON_UI_MODE,
+  PROP_ACTION_AREA_VISIBLE,
+  PROP_ACTION_AREA_ORIENTATION
 };
 
 /* object signals */
@@ -478,9 +488,16 @@
 static void     add_scroll_timeout                   (GtkTreeView *tree_view);
 static void     remove_scroll_timeout                (GtkTreeView *tree_view);
 
-static guint tree_view_signals [LAST_SIGNAL] = { 0 };
+static gboolean gtk_tree_view_tap_and_hold_query (GtkWidget *widget,
+						  GdkEvent  *event);
+static void     free_queued_select_row           (GtkTreeView  *tree_view);
+static void     free_queued_activate_row         (GtkTreeView  *tree_view);
+static void     free_queued_actions              (GtkTreeView  *tree_view);
 
-
+static void     hildon_tree_view_set_action_area_height (GtkTreeView *tree_view);
+static void hildon_tree_view_setup_row_header_layout (GtkTreeView *tree_view);
+
+static guint tree_view_signals [LAST_SIGNAL] = { 0 };
 
 /* GType Methods
  */
@@ -544,6 +561,12 @@
   widget_class->grab_notify = gtk_tree_view_grab_notify;
   widget_class->state_changed = gtk_tree_view_state_changed;
 
+  g_signal_override_class_closure (g_signal_lookup ("tap-and-hold-query",
+						    GTK_TYPE_WIDGET),
+				   GTK_TYPE_TREE_VIEW,
+				   g_cclosure_new (G_CALLBACK (gtk_tree_view_tap_and_hold_query),
+						   NULL, NULL));
+
   /* GtkContainer signals */
   container_class->remove = gtk_tree_view_remove;
   container_class->forall = gtk_tree_view_forall;
@@ -715,7 +738,7 @@
 				     g_param_spec_boolean ("show-expanders",
 							   P_("Show Expanders"),
 							   P_("View has expanders"),
-							   TRUE,
+							   FALSE,
 							   GTK_PARAM_READWRITE));
 
     /**
@@ -732,7 +755,7 @@
 						       P_("Extra indentation for each level"),
 						       0,
 						       G_MAXINT,
-						       0,
+						       10,
 						       GTK_PARAM_READWRITE));
 
     g_object_class_install_property (o_class,
@@ -740,7 +763,7 @@
                                      g_param_spec_boolean ("rubber-banding",
                                                            P_("Rubber Banding"),
                                                            P_("Whether to enable selection of multiple items by dragging the mouse pointer"),
-                                                           FALSE,
+							   TRUE,
                                                            GTK_PARAM_READWRITE));
 
     g_object_class_install_property (o_class,
@@ -770,10 +793,73 @@
 						       -1,
 						       GTK_PARAM_READWRITE));
 
+    /**
+     * GtkTreeView:hildon-ui-mode:
+     *
+     * Specifies which UI mode to use.  A setting of #HILDON_UI_MODE_NORMAL
+     * will cause the tree view to disable selections and emit row-activated
+     * as soon as a row is pressed.  When #HILDON_UI_MODE_EDIT is set,
+     * selections can be made according to the setting of the mode on
+     * GtkTreeSelection.
+     *
+     * Toggling this property will cause the tree view to select an
+     * appropriate selection mode if not already done.
+     *
+     * Since: maemo 5.0
+     * Stability: unstable
+     */
+    g_object_class_install_property (o_class,
+				     PROP_HILDON_UI_MODE,
+				     g_param_spec_enum ("hildon-ui-mode",
+							P_("Hildon UI Mode"),
+							P_("The Hildon UI mode according to which the tree view should behave"),
+							HILDON_TYPE_UI_MODE,
+							HILDON_UI_MODE_NORMAL,
+							GTK_PARAM_READWRITE));
+
+    /**
+     * GtkTreeView:action-area-visible:
+     *
+     * Makes the action area of the GtkTreeView visible or invisible.
+     * Based on the value of the GtkTreeView:action-area-orientation
+     * property a certain height will be allocated above the first row
+     * for the action area.
+     *
+     * Since: maemo 5.0
+     * Stability: unstable
+     */
+    g_object_class_install_property (o_class,
+				     PROP_ACTION_AREA_VISIBLE,
+				     g_param_spec_boolean ("action-area-visible",
+							   P_("Action Area Visible"),
+							   P_("Whether the action area above the first row is visible"),
+							   FALSE,
+							   GTK_PARAM_READWRITE));
+
+    /**
+     * GtkTreeView:action-area-orientation:
+     *
+     * Sets the orientation of the action area.  This is either
+     * horizontal (landscape) or vertical (portrait).  The height of
+     * the action area depends on this setting.
+     *
+     * Since: maemo 5.0
+     * Stability: unstable
+     */
+    g_object_class_install_property (o_class,
+				     PROP_ACTION_AREA_ORIENTATION,
+				     g_param_spec_enum ("action-area-orientation",
+							 P_("Action Area Orientation"),
+							 P_("Determines the orientation of the action area."),
+							 GTK_TYPE_ORIENTATION,
+							 GTK_ORIENTATION_HORIZONTAL,
+							GTK_PARAM_READWRITE));
+
   /* Style properties */
 #define _TREE_VIEW_EXPANDER_SIZE 12
 #define _TREE_VIEW_VERTICAL_SEPARATOR 2
 #define _TREE_VIEW_HORIZONTAL_SEPARATOR 2
+#define _TREE_VIEW_SEPARATOR_HEIGHT 2
 
   gtk_widget_class_install_style_property (widget_class,
 					   g_param_spec_int ("expander-size",
@@ -872,6 +958,43 @@
 								"\1\1",
 								GTK_PARAM_READABLE));
 
+  /**
+   * GtkTreeView:separator-height:
+   *
+   * Height in pixels of a separator.
+   *
+   * Since: maemo 3.0
+   * Stability: Unstable
+   */
+  gtk_widget_class_install_style_property (widget_class,
+					   g_param_spec_int ("separator-height",
+							     P_("Separator height"),
+							     P_("Height of the separator"),
+							     0,
+							     G_MAXINT,
+							     _TREE_VIEW_SEPARATOR_HEIGHT,
+							     GTK_PARAM_READABLE));
+
+  /**
+   * GtkTreeView:row-height:
+   *
+   * Height in pixels of a row.  When set, all rows will use this height,
+   * except for row separators and row headers.  A value of -1 means this
+   * value is unset.  Setting this property does not imply fixed height
+   * mode will be turned on, so columns are still properly autosized.
+   *
+   * Since: maemo 5.0
+   * Stability: Unstable
+   */
+  gtk_widget_class_install_style_property (widget_class,
+					   g_param_spec_int ("row-height",
+							     P_("Row height"),
+							     P_("Height of a row"),
+							     -1,
+							     G_MAXINT,
+							     -1,
+							     GTK_PARAM_READABLE));
+
   /* Signals */
   /**
    * GtkTreeView::set-scroll-adjustments
@@ -1109,6 +1232,36 @@
 		  _gtk_marshal_BOOLEAN__VOID,
 		  G_TYPE_BOOLEAN, 0);
 
+  /**
+   * GtkTreeView::row-insensitive:
+   * @tree_view: the object which received the signal.
+   * @path: the path where the cursor is tried to be moved.
+   *
+   * Emitted when the user tries to move cursor to an insesitive row.
+   *
+   * Since: maemo 1.0
+   * Stability: Unstable
+   */
+  tree_view_signals[ROW_INSENSITIVE] =
+     g_signal_new ("row_insensitive",
+		  G_TYPE_FROM_CLASS (o_class),
+		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+		  G_STRUCT_OFFSET (GtkTreeViewClass, row_insensitive),
+		  NULL, NULL,
+		  _gtk_marshal_VOID__OBJECT,
+		  G_TYPE_NONE, 1,
+		  GTK_TYPE_TREE_PATH);
+
+  tree_view_signals[HILDON_ROW_TAPPED] =
+      g_signal_new ("hildon_row_tapped",
+		    G_TYPE_FROM_CLASS (o_class),
+		    G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+		    0,
+		    NULL, NULL,
+		    _gtk_marshal_VOID__BOXED,
+		    G_TYPE_NONE, 1,
+		    GTK_TYPE_TREE_PATH);
+
   /* Key bindings */
   gtk_tree_view_add_move_binding (binding_set, GDK_Up, 0, TRUE,
 				  GTK_MOVEMENT_DISPLAY_LINES, -1);
@@ -1333,9 +1486,7 @@
   gtk_widget_set_can_focus (GTK_WIDGET (tree_view), TRUE);
   gtk_widget_set_redraw_on_allocate (GTK_WIDGET (tree_view), FALSE);
 
-  tree_view->priv->flags =  GTK_TREE_VIEW_SHOW_EXPANDERS
-                            | GTK_TREE_VIEW_DRAW_KEYFOCUS
-                            | GTK_TREE_VIEW_HEADERS_VISIBLE;
+  tree_view->priv->flags = GTK_TREE_VIEW_DRAW_KEYFOCUS;
 
   /* We need some padding */
   tree_view->priv->dy = 0;
@@ -1368,9 +1519,27 @@
   tree_view->priv->hover_selection = FALSE;
   tree_view->priv->hover_expand = FALSE;
 
-  tree_view->priv->level_indentation = 0;
+  tree_view->priv->level_indentation = 10;
+
+  tree_view->priv->queued_select_row = NULL;
+  tree_view->priv->queued_expand_row = NULL;
+  tree_view->priv->queued_activate_row = NULL;
+  tree_view->priv->queued_tapped_row = NULL;
+
+  tree_view->priv->highlighted_node = NULL;
+  tree_view->priv->highlighted_tree = NULL;
+
+  tree_view->priv->queued_ctrl_pressed = FALSE;
+  tree_view->priv->queued_shift_pressed = FALSE;
+
+  tree_view->priv->hildon_ui_mode = HILDON_UI_MODE_NORMAL;
+  gtk_widget_style_get (GTK_WIDGET (tree_view),
+			"hildon-mode", &tree_view->priv->hildon_mode,
+			NULL);
 
-  tree_view->priv->rubber_banding_enable = FALSE;
+  tree_view->priv->level_indentation = 10;
+
+  tree_view->priv->rubber_banding_enable = TRUE;
 
   tree_view->priv->grid_lines = GTK_TREE_VIEW_GRID_LINES_NONE;
   tree_view->priv->tree_lines_enabled = FALSE;
@@ -1384,9 +1553,13 @@
 
   tree_view->priv->event_last_x = -10000;
   tree_view->priv->event_last_y = -10000;
-}
 
-
+  tree_view->priv->rows_offset = 0;
+  tree_view->priv->action_area_visible = FALSE;
+  tree_view->priv->action_area_orientation = GTK_ORIENTATION_HORIZONTAL;
+  tree_view->priv->action_area_event_box = NULL;
+  tree_view->priv->action_area_box = NULL;
+}
 
 /* GObject Methods
  */
@@ -1460,6 +1633,15 @@
     case PROP_TOOLTIP_COLUMN:
       gtk_tree_view_set_tooltip_column (tree_view, g_value_get_int (value));
       break;
+    case PROP_HILDON_UI_MODE:
+      hildon_tree_view_set_hildon_ui_mode (tree_view, g_value_get_enum (value));
+      break;
+    case PROP_ACTION_AREA_VISIBLE:
+      hildon_tree_view_set_action_area_visible (tree_view, g_value_get_boolean (value));
+      break;
+    case PROP_ACTION_AREA_ORIENTATION:
+      hildon_tree_view_set_action_area_orientation (tree_view, g_value_get_enum (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1535,6 +1717,15 @@
     case PROP_TOOLTIP_COLUMN:
       g_value_set_int (value, tree_view->priv->tooltip_column);
       break;
+    case PROP_HILDON_UI_MODE:
+      g_value_set_enum (value, tree_view->priv->hildon_ui_mode);
+      break;
+    case PROP_ACTION_AREA_VISIBLE:
+      g_value_set_boolean (value, tree_view->priv->action_area_visible);
+      break;
+    case PROP_ACTION_AREA_ORIENTATION:
+      g_value_set_enum (value, tree_view->priv->action_area_orientation);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1595,6 +1786,8 @@
   tree_view->priv->prelight_node = NULL;
   tree_view->priv->expanded_collapsed_node = NULL;
   tree_view->priv->expanded_collapsed_tree = NULL;
+  tree_view->priv->highlighted_node = NULL;
+  tree_view->priv->highlighted_tree = NULL;
 }
 
 static void
@@ -1650,6 +1843,30 @@
       tree_view->priv->top_row = NULL;
     }
 
+  if (tree_view->priv->queued_select_row != NULL)
+    {
+      gtk_tree_row_reference_free (tree_view->priv->queued_select_row);
+      tree_view->priv->queued_select_row = NULL;
+    }
+
+  if (tree_view->priv->queued_expand_row != NULL)
+    {
+      gtk_tree_row_reference_free (tree_view->priv->queued_expand_row);
+      tree_view->priv->queued_expand_row = NULL;
+    }
+
+  if (tree_view->priv->queued_activate_row != NULL)
+    {
+      gtk_tree_row_reference_free (tree_view->priv->queued_activate_row);
+      tree_view->priv->queued_activate_row = NULL;
+    }
+
+  if (tree_view->priv->queued_tapped_row != NULL)
+    {
+      gtk_tree_row_reference_free (tree_view->priv->queued_tapped_row);
+      tree_view->priv->queued_tapped_row = NULL;
+  }
+
   if (tree_view->priv->column_drop_func_data &&
       tree_view->priv->column_drop_func_data_destroy)
     {
@@ -1701,6 +1918,24 @@
       tree_view->priv->row_separator_data = NULL;
     }
   
+  if (tree_view->priv->row_header_destroy && tree_view->priv->row_header_data)
+    {
+      (* tree_view->priv->row_header_destroy) (tree_view->priv->row_header_data);
+      tree_view->priv->row_header_data = NULL;
+    }
+
+  if (tree_view->priv->row_header_layout)
+    {
+      g_object_unref (tree_view->priv->row_header_layout);
+      tree_view->priv->row_header_layout = NULL;
+    }
+
+  if (tree_view->priv->tickmark_icon)
+    {
+      g_object_unref (tree_view->priv->tickmark_icon);
+      tree_view->priv->tickmark_icon = NULL;
+    }
+
   gtk_tree_view_set_model (tree_view, NULL);
 
   if (tree_view->priv->hadjustment)
@@ -2036,7 +2271,7 @@
   if (tree_view->priv->tree == NULL)
     tree_view->priv->height = 0;
   else
-    tree_view->priv->height = tree_view->priv->tree->root->offset;
+    tree_view->priv->height = tree_view->priv->tree->root->offset + tree_view->priv->rows_offset;
 }
 
 static void
@@ -2228,6 +2463,13 @@
 	number_of_expand_columns++;
     }
 
+  if (tree_view->priv->hildon_mode == HILDON_FREMANTLE
+	&& tree_view->priv->hildon_ui_mode == HILDON_UI_MODE_EDIT
+	&& tree_view->priv->selection->type == GTK_SELECTION_MULTIPLE)
+    {
+	full_requested_width += HILDON_TICK_MARK_SIZE;
+    }
+
   /* Only update the expand value if the width of the widget has changed,
    * or the number of expand columns has changed, or if there are no expand
    * columns, or if we didn't have an size-allocation yet after the
@@ -2381,6 +2623,17 @@
       allocation.y = child->y;
       allocation.width = child->width;
       allocation.height = child->height;
+
+      if (tree_view->priv->rows_offset != 0
+	  && tree_view->priv->action_area_event_box == child->widget)
+	{
+	  /* Set the child's location to be the area above the first row */
+	  allocation.x = 0;
+	  allocation.y = -tree_view->priv->dy;
+	  allocation.width = MAX (widget->allocation.width, tree_view->priv->width);
+	  allocation.height = tree_view->priv->rows_offset;
+	}
+
       gtk_widget_size_allocate (child->widget, &allocation);
     }
 
@@ -2521,25 +2774,41 @@
 static inline gboolean
 row_is_separator (GtkTreeView *tree_view,
 		  GtkTreeIter *iter,
+		  gboolean    *is_header,
 		  GtkTreePath *path)
 {
   gboolean is_separator = FALSE;
+  GtkTreeIter tmpiter;
 
-  if (tree_view->priv->row_separator_func)
+  if (tree_view->priv->row_separator_func
+      || tree_view->priv->row_header_func)
     {
-      GtkTreeIter tmpiter;
-
       if (iter)
-        tmpiter = *iter;
+	tmpiter = *iter;
       else
-        {
-          if (!gtk_tree_model_get_iter (tree_view->priv->model, &tmpiter, path))
-            return FALSE;
-        }
+	gtk_tree_model_get_iter (tree_view->priv->model, &tmpiter, path);
+    }
 
-      is_separator = tree_view->priv->row_separator_func (tree_view->priv->model,
-                                                          &tmpiter,
-                                                          tree_view->priv->row_separator_data);
+  if (tree_view->priv->row_separator_func)
+    {
+      is_separator = (* tree_view->priv->row_separator_func) (tree_view->priv->model,
+							      &tmpiter,
+							      tree_view->priv->row_separator_data);
+    }
+
+  if (tree_view->priv->row_header_func)
+    {
+      gboolean tmp;
+
+      tmp = (* tree_view->priv->row_header_func) (tree_view->priv->model,
+						  &tmpiter,
+						  NULL,
+						  tree_view->priv->row_header_data);
+
+      is_separator |= tmp;
+
+      if (is_header)
+	*is_header = tmp;
     }
 
   return is_separator;
@@ -2589,6 +2858,7 @@
       gboolean row_double_click = FALSE;
       gboolean rtl;
       gboolean node_selected;
+      gboolean node_is_selectable;
 
       /* Empty tree? */
       if (tree_view->priv->tree == NULL)
@@ -2633,7 +2903,7 @@
 
       /* Get the path and the node */
       path = _gtk_tree_view_find_path (tree_view, tree, node);
-      path_is_selectable = !row_is_separator (tree_view, NULL, path);
+      path_is_selectable = !row_is_separator (tree_view, NULL, NULL, path);
 
       if (!path_is_selectable)
 	{
@@ -2689,6 +2959,17 @@
 	  break;
 	}
 
+      if (tree_view->priv->hildon_mode == HILDON_FREMANTLE
+	  && tree_view->priv->hildon_ui_mode == HILDON_UI_MODE_EDIT
+	  && tree_view->priv->selection->type == GTK_SELECTION_MULTIPLE
+	  && (gint)event->x < background_area.x + HILDON_TICK_MARK_SIZE)
+	{
+	  GList *list;
+
+	  list = (rtl ? g_list_first (tree_view->priv->columns) : g_list_last (tree_view->priv->columns));
+	  column = list->data;
+	}
+
       if (column == NULL)
 	{
 	  gtk_tree_path_free (path);
@@ -2765,6 +3046,39 @@
 	    gtk_tree_path_free (anchor);
 	}
 
+      node_selected = GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED);
+      node_is_selectable =
+	_gtk_tree_selection_row_is_selectable (tree_view->priv->selection,
+					       node, path);
+
+      /* Save press to possibly begin a drag
+       */
+      if (!column_handled_click &&
+	  !tree_view->priv->in_grab &&
+	  tree_view->priv->pressed_button < 0)
+	{
+	  tree_view->priv->pressed_button = event->button;
+	  tree_view->priv->press_start_x = event->x;
+	  tree_view->priv->press_start_y = event->y;
+
+	  if (tree_view->priv->hildon_mode == HILDON_DIABLO
+	      && tree_view->priv->rubber_banding_enable
+	      && node_is_selectable
+	      && !node_selected
+	      && tree_view->priv->selection->type == GTK_SELECTION_MULTIPLE)
+	    {
+	      tree_view->priv->press_start_y += tree_view->priv->dy;
+	      tree_view->priv->rubber_band_x = event->x;
+	      tree_view->priv->rubber_band_y = event->y + tree_view->priv->dy;
+	      tree_view->priv->rubber_band_status = RUBBER_BAND_MAYBE_START;
+
+	      if ((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
+		tree_view->priv->rubber_band_modify = TRUE;
+	      if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
+		tree_view->priv->rubber_band_extend = TRUE;
+	    }
+	}
+
       /* select */
       node_selected = GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED);
       pre_val = tree_view->priv->vadjustment->value;
@@ -2782,7 +3096,106 @@
           if (focus_cell)
             gtk_tree_view_column_focus_cell (column, focus_cell);
 
-          if (event->state & GTK_MODIFY_SELECTION_MOD_MASK)
+	  /* The most reliable way is to use another row reference,
+	   * instead of trying to get it done with the intricate
+	   * logic below.
+	   */
+	  gtk_tree_row_reference_free (tree_view->priv->queued_tapped_row);
+	  tree_view->priv->queued_tapped_row =
+	      gtk_tree_row_reference_new (tree_view->priv->model, path);
+
+	  if (tree_view->priv->hildon_mode == HILDON_FREMANTLE
+	      && tree_view->priv->hildon_ui_mode == HILDON_UI_MODE_NORMAL)
+	    {
+	      /* This row should be activated on button-release */
+	      gtk_tree_row_reference_free (tree_view->priv->queued_activate_row);
+	      tree_view->priv->queued_activate_row = gtk_tree_row_reference_new (tree_view->priv->model, path);
+
+	      /* Mark the node as selected to create a highlight effect */
+	      tree_view->priv->highlighted_tree = tree;
+	      tree_view->priv->highlighted_node = node;
+	      gtk_tree_view_queue_draw_path (tree_view, path, NULL);
+	    }
+	  else if (tree_view->priv->hildon_mode == HILDON_DIABLO
+		   && node_selected
+		   && !column_handled_click
+		   && gtk_tree_row_reference_valid (tree_view->priv->cursor))
+	    {
+	      GtkTreePath *cursor_path;
+
+	      cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
+	      if (!gtk_tree_path_compare (cursor_path, path))
+		{
+		  gtk_tree_row_reference_free (tree_view->priv->queued_activate_row);
+		  tree_view->priv->queued_activate_row = gtk_tree_row_reference_new (tree_view->priv->model, path);
+		}
+
+	      gtk_tree_path_free (cursor_path);
+	    }
+
+	  if (node_is_selectable
+	      && tree_view->priv->hildon_mode == HILDON_DIABLO
+	      && !column_handled_click
+	      && !tree_view->priv->queued_activate_row
+	      && tree_view->priv->rubber_band_status == RUBBER_BAND_OFF
+	      && gtk_tree_selection_get_mode (tree_view->priv->selection) == GTK_SELECTION_MULTIPLE)
+	    {
+	      GtkTreePath *old_cursor_path = NULL;
+
+	      /* We do not know at this stage if a user is going to do
+	       * a DnD or tap and hold operation, so avoid clearing
+	       * the current selection.
+	       */
+	      if (tree_view->priv->queued_select_row)
+		gtk_tree_row_reference_free (tree_view->priv->queued_select_row);
+	      tree_view->priv->queued_select_row = NULL;
+
+	      /* Do move the focus */
+	      if (tree_view->priv->cursor)
+		{
+		  old_cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
+		  gtk_tree_row_reference_free (tree_view->priv->cursor);
+		}
+
+	      tree_view->priv->cursor = gtk_tree_row_reference_new (tree_view->priv->model, path);
+
+	      if (old_cursor_path)
+		{
+		  gtk_tree_view_queue_draw_path (tree_view,
+						 old_cursor_path, NULL);
+		  gtk_tree_path_free (old_cursor_path);
+		}
+
+	      tree_view->priv->queued_ctrl_pressed = tree_view->priv->modify_selection_pressed;
+	      tree_view->priv->queued_shift_pressed = tree_view->priv->extend_selection_pressed;
+	      tree_view->priv->queued_select_row =
+		  gtk_tree_row_reference_new (tree_view->priv->model, path);
+
+	      gtk_tree_view_queue_draw_path (tree_view, path, NULL);
+	    }
+	  else if (node_is_selectable
+		   && tree_view->priv->hildon_mode == HILDON_FREMANTLE
+		   && tree_view->priv->hildon_ui_mode == HILDON_UI_MODE_EDIT
+		   && !column_handled_click
+		   && !tree_view->priv->queued_activate_row)
+	    {
+	      /* In new-style we do not want to set cursor,
+	       * instead we highlight the node.
+	       */
+	      if (tree_view->priv->queued_select_row)
+		gtk_tree_row_reference_free (tree_view->priv->queued_select_row);
+	      tree_view->priv->queued_select_row = NULL;
+
+	      tree_view->priv->highlighted_node = node;
+	      tree_view->priv->highlighted_tree = tree;
+
+	      tree_view->priv->queued_select_row =
+		  gtk_tree_row_reference_new (tree_view->priv->model, path);
+
+	      gtk_tree_view_queue_draw_path (tree_view, path, NULL);
+	    }
+	  /* Else, set the cursor as usual */
+	  else if (event->state & GTK_MODIFY_SELECTION_MOD_MASK)
             {
               gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
               gtk_tree_view_real_toggle_cursor_row (tree_view);
@@ -2794,7 +3207,10 @@
             }
           else
             {
-              gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
+	      if (tree_view->priv->queued_activate_row)
+		gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
+	      else
+		gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
             }
 
           tree_view->priv->modify_selection_pressed = FALSE;
@@ -2811,74 +3227,24 @@
       cell_area.y += dval;
       background_area.y += dval;
 
-      /* Save press to possibly begin a drag
-       */
-      if (!column_handled_click &&
-	  !tree_view->priv->in_grab &&
-	  tree_view->priv->pressed_button < 0)
-        {
-          tree_view->priv->pressed_button = event->button;
-          tree_view->priv->press_start_x = event->x;
-          tree_view->priv->press_start_y = event->y;
-
-	  if (tree_view->priv->rubber_banding_enable
-	      && !node_selected
-	      && tree_view->priv->selection->type == GTK_SELECTION_MULTIPLE)
+      if (event->button == 1)
+	{
+	  if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT))
 	    {
-	      tree_view->priv->press_start_y += tree_view->priv->dy;
-	      tree_view->priv->rubber_band_x = event->x;
-	      tree_view->priv->rubber_band_y = event->y + tree_view->priv->dy;
-	      tree_view->priv->rubber_band_status = RUBBER_BAND_MAYBE_START;
-
-	      if ((event->state & GTK_MODIFY_SELECTION_MOD_MASK) == GTK_MODIFY_SELECTION_MOD_MASK)
-		tree_view->priv->rubber_band_modify = TRUE;
-	      if ((event->state & GTK_EXTEND_SELECTION_MOD_MASK) == GTK_EXTEND_SELECTION_MOD_MASK)
-		tree_view->priv->rubber_band_extend = TRUE;
+	      /* The behavior is as follows:
+	       * - For a tap on a collapsed node: always expand (and the
+	       *   cursor moves to it.
+	       * - For a tap on an expxanded node: collapse if and only
+	       *   if the node is currently the cursor node.
+	       */
+	      if (!node->children
+		  || (node_selected && node->children))
+		{
+		  gtk_tree_row_reference_free (tree_view->priv->queued_expand_row);
+		  tree_view->priv->queued_expand_row =
+		    gtk_tree_row_reference_new (tree_view->priv->model, path);
+		}
 	    }
-        }
-
-      /* Test if a double click happened on the same row. */
-      if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
-        {
-          int double_click_time, double_click_distance;
-
-          g_object_get (gtk_settings_get_default (),
-                        "gtk-double-click-time", &double_click_time,
-                        "gtk-double-click-distance", &double_click_distance,
-                        NULL);
-
-          /* Same conditions as _gdk_event_button_generate */
-          if (tree_view->priv->last_button_x != -1 &&
-              (event->time < tree_view->priv->last_button_time + double_click_time) &&
-              (ABS (event->x - tree_view->priv->last_button_x) <= double_click_distance) &&
-              (ABS (event->y - tree_view->priv->last_button_y) <= double_click_distance))
-            {
-              /* We do no longer compare paths of this row and the
-               * row clicked previously.  We use the double click
-               * distance to decide whether this is a valid click,
-               * allowing the mouse to slightly move over another row.
-               */
-              row_double_click = TRUE;
-
-              tree_view->priv->last_button_time = 0;
-              tree_view->priv->last_button_x = -1;
-              tree_view->priv->last_button_y = -1;
-            }
-          else
-            {
-              tree_view->priv->last_button_time = event->time;
-              tree_view->priv->last_button_x = event->x;
-              tree_view->priv->last_button_y = event->y;
-            }
-        }
-
-      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);
@@ -3039,6 +3405,9 @@
 			      GdkEventButton *event)
 {
   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
+  gint new_y;
+  GtkRBTree *tree;
+  GtkRBNode *node;
 
   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG))
     return gtk_tree_view_button_release_drag_column (widget, event);
@@ -3052,6 +3421,171 @@
   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE))
     return gtk_tree_view_button_release_column_resize (widget, event);
 
+  if (tree_view->priv->tree)
+    {
+      /* Get the node where the mouse was released */
+      new_y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, event->y);
+      if (new_y < 0)
+	new_y = 0;
+      _gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
+    }
+  else
+    {
+      /* We just set tree and node to NULL otherwise.  We still want
+       * to run through below's logic to free row references where needed.
+       */
+      tree = NULL;
+      node = NULL;
+    }
+
+  if (gtk_tree_row_reference_valid (tree_view->priv->queued_select_row))
+    {
+      GtkTreePath *path;
+      GtkRBTree *select_tree;
+      GtkRBNode *select_node;
+
+      path = gtk_tree_row_reference_get_path (tree_view->priv->queued_select_row);
+      _gtk_tree_view_find_node (tree_view, path,
+				&select_tree, &select_node);
+
+      if (tree == select_tree && node == select_node)
+	{
+	  if (tree_view->priv->queued_ctrl_pressed)
+	    {
+	      gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
+	      gtk_tree_view_real_toggle_cursor_row (tree_view);
+	      GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
+	    }
+	  else if (tree_view->priv->queued_shift_pressed)
+	    {
+	      gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
+	      gtk_tree_view_real_select_cursor_row (tree_view, FALSE);
+	      GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
+	    }
+	  else
+	    gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
+	}
+
+      free_queued_select_row (tree_view);
+      gtk_tree_path_free (path);
+      tree_view->priv->queued_ctrl_pressed = FALSE;
+      tree_view->priv->queued_shift_pressed = FALSE;
+    }
+
+  if (gtk_tree_row_reference_valid (tree_view->priv->queued_activate_row))
+    {
+      GtkTreePath *path;
+      GtkRBTree *activate_tree;
+      GtkRBNode *activate_node;
+
+      path = gtk_tree_row_reference_get_path (tree_view->priv->queued_activate_row);
+
+      if (tree_view->priv->hildon_mode == HILDON_FREMANTLE
+	  && tree_view->priv->hildon_ui_mode == HILDON_UI_MODE_NORMAL)
+	{
+	  if (tree_view->priv->highlighted_node)
+	    {
+	      _gtk_tree_view_queue_draw_node (tree_view,
+					      tree_view->priv->highlighted_tree,
+					      tree_view->priv->highlighted_node,
+					      NULL);
+
+	      tree_view->priv->highlighted_tree = NULL;
+	      tree_view->priv->highlighted_node = NULL;
+	    }
+	}
+
+      _gtk_tree_view_find_node (tree_view, path,
+				&activate_tree, &activate_node);
+
+      /* Only emit activated if the mouse was released from the
+       * same row where the mouse was pressed.
+       */
+      if (tree == activate_tree && node == activate_node)
+	{
+	  gtk_tree_view_row_activated (tree_view, path,
+				       tree_view->priv->focus_column);
+	}
+
+      gtk_tree_path_free (path);
+
+      gtk_tree_row_reference_free (tree_view->priv->queued_activate_row);
+      tree_view->priv->queued_activate_row = NULL;
+    }
+
+  if (gtk_tree_row_reference_valid (tree_view->priv->queued_expand_row))
+    {
+      GtkTreePath *path;
+      GtkRBTree *expand_tree;
+      GtkRBNode *expand_node = NULL;
+
+      path = gtk_tree_row_reference_get_path (tree_view->priv->queued_expand_row);
+
+      if (tree_view->priv->hildon_mode == HILDON_FREMANTLE)
+	{
+	  /* We should not take the cursor into accont.  We do check
+	   * with the node where the mouse was released.
+	   */
+	  _gtk_tree_view_find_node (tree_view, path,
+				    &expand_tree, &expand_node);
+
+	  if (tree != expand_tree || node != expand_node)
+	    expand_node = NULL;
+	}
+      else
+	{
+	  GtkTreePath *cursor_path;
+
+	  cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
+
+	  if (!gtk_tree_path_compare (cursor_path, path))
+	    _gtk_tree_view_find_node (tree_view, path,
+				      &expand_tree, &expand_node);
+
+	  gtk_tree_path_free (cursor_path);
+	}
+
+      if (expand_node)
+	{
+	  if (!expand_node->children)
+	    gtk_tree_view_real_expand_row (tree_view, path,
+					   expand_tree, expand_node,
+					   FALSE, TRUE);
+	  else
+	    gtk_tree_view_real_collapse_row (tree_view, path,
+					     expand_tree, expand_node, TRUE);
+	}
+
+      gtk_tree_path_free (path);
+
+      gtk_tree_row_reference_free (tree_view->priv->queued_expand_row);
+      tree_view->priv->queued_expand_row = NULL;
+    }
+
+  /* The hildon-row-tapped signal is executed as the last, so that
+   * any action (selection change, activation, expansion/collapse)
+   * has already been processed.
+   */
+  if (gtk_tree_row_reference_valid (tree_view->priv->queued_tapped_row))
+    {
+      GtkTreePath *path;
+      GtkRBTree *tapped_tree;
+      GtkRBNode *tapped_node;
+
+      path = gtk_tree_row_reference_get_path (tree_view->priv->queued_tapped_row);
+      _gtk_tree_view_find_node (tree_view, path,
+				&tapped_tree, &tapped_node);
+
+      if (tree == tapped_tree && node == tapped_node)
+	g_signal_emit (tree_view, tree_view_signals[HILDON_ROW_TAPPED],
+		       0, path);
+
+      gtk_tree_path_free (path);
+
+      gtk_tree_row_reference_free (tree_view->priv->queued_tapped_row);
+      tree_view->priv->queued_tapped_row = NULL;
+    }
+
   if (tree_view->priv->button_pressed_node == NULL)
     return FALSE;
 
@@ -3331,6 +3865,22 @@
 }
 
 static void
+ensure_unhighlighted (GtkTreeView *tree_view)
+{
+  /* Unconditionally unhighlight */
+  if (tree_view->priv->highlighted_node)
+    {
+      _gtk_tree_view_queue_draw_node (tree_view,
+				      tree_view->priv->highlighted_tree,
+				      tree_view->priv->highlighted_node,
+				      NULL);
+
+      tree_view->priv->highlighted_tree = NULL;
+      tree_view->priv->highlighted_node = NULL;
+    }
+}
+
+static void
 update_prelight (GtkTreeView *tree_view,
                  gint         x,
                  gint         y)
@@ -3780,13 +4330,6 @@
 
       gtk_tree_path_free (tmp_path);
 
-      /* ... and the cursor to the end path */
-      tmp_path = _gtk_tree_view_find_path (tree_view,
-					   tree_view->priv->rubber_band_end_tree,
-					   tree_view->priv->rubber_band_end_node);
-      gtk_tree_view_real_set_cursor (GTK_TREE_VIEW (tree_view), tmp_path, FALSE, FALSE);
-      gtk_tree_path_free (tmp_path);
-
       _gtk_tree_selection_emit_changed (tree_view->priv->selection);
     }
 
@@ -3868,6 +4411,8 @@
 	    GTK_RBNODE_UNSET_FLAG (start_node, GTK_RBNODE_IS_SELECTED);
 	}
 
+      add_scroll_timeout (tree_view);
+
       _gtk_tree_view_queue_draw_node (tree_view, start_tree, start_node, NULL);
 
 node_not_selectable:
@@ -3903,6 +4448,7 @@
 {
   GtkRBTree *start_tree, *end_tree;
   GtkRBNode *start_node, *end_node;
+  GtkTreePath *path;
 
   _gtk_rbtree_find_offset (tree_view->priv->tree, MIN (tree_view->priv->press_start_y, tree_view->priv->rubber_band_y), &start_tree, &start_node);
   _gtk_rbtree_find_offset (tree_view->priv->tree, MAX (tree_view->priv->press_start_y, tree_view->priv->rubber_band_y), &end_tree, &end_node);
@@ -4001,6 +4547,17 @@
 
   tree_view->priv->rubber_band_end_tree = end_tree;
   tree_view->priv->rubber_band_end_node = end_node;
+
+  /* In maemo the cursor needs to follow the stylus */
+  if (gtk_tree_view_get_path_at_pos (tree_view,
+				     tree_view->priv->rubber_band_x,
+				     RBTREE_Y_TO_TREE_WINDOW_Y (tree_view, tree_view->priv->rubber_band_y),
+				     &path,
+				     NULL, NULL, NULL))
+    {
+      gtk_tree_view_real_set_cursor (tree_view, path, FALSE, FALSE);
+      gtk_tree_path_free (path);
+    }
 }
 
 static void
@@ -4009,8 +4566,6 @@
   gint x, y;
   GdkRectangle old_area;
   GdkRectangle new_area;
-  GdkRectangle common;
-  GdkRegion *invalid_region;
 
   old_area.x = MIN (tree_view->priv->press_start_x, tree_view->priv->rubber_band_x);
   old_area.y = MIN (tree_view->priv->press_start_y, tree_view->priv->rubber_band_y) - tree_view->priv->dy;
@@ -4027,30 +4582,6 @@
   new_area.width = ABS (x - tree_view->priv->press_start_x) + 1;
   new_area.height = ABS (y - tree_view->priv->press_start_y) + 1;
 
-  invalid_region = gdk_region_rectangle (&old_area);
-  gdk_region_union_with_rect (invalid_region, &new_area);
-
-  gdk_rectangle_intersect (&old_area, &new_area, &common);
-  if (common.width > 2 && common.height > 2)
-    {
-      GdkRegion *common_region;
-
-      /* make sure the border is invalidated */
-      common.x += 1;
-      common.y += 1;
-      common.width -= 2;
-      common.height -= 2;
-
-      common_region = gdk_region_rectangle (&common);
-
-      gdk_region_subtract (invalid_region, common_region);
-      gdk_region_destroy (common_region);
-    }
-
-  gdk_window_invalidate_region (tree_view->priv->bin_window, invalid_region, TRUE);
-
-  gdk_region_destroy (invalid_region);
-
   tree_view->priv->rubber_band_x = x;
   tree_view->priv->rubber_band_y = y;
 
@@ -4115,6 +4646,20 @@
 
   if (tree_view->priv->rubber_band_status == RUBBER_BAND_MAYBE_START)
     {
+      if (tree_view->priv->hildon_mode == HILDON_DIABLO
+	  && gtk_tree_row_reference_valid (tree_view->priv->queued_select_row))
+	{
+	  GtkTreePath *path;
+
+	  /* We now know we won't rubber band -- select the row */
+	  path = gtk_tree_row_reference_get_path (tree_view->priv->queued_select_row);
+	  gtk_tree_view_real_set_cursor (tree_view, path, FALSE, FALSE);
+
+	  gtk_tree_path_free (path);
+	}
+
+      free_queued_actions (tree_view);
+
       gtk_grab_add (GTK_WIDGET (tree_view));
       gtk_tree_view_update_rubber_band (tree_view);
 
@@ -4127,8 +4672,27 @@
       add_scroll_timeout (tree_view);
     }
 
+  /* If the drag-threshold has been passed, the row should
+   * not be activated or selected and the highlight removed.
+   */
+  if (tree_view->priv->hildon_mode == HILDON_FREMANTLE
+      && gtk_drag_check_threshold (widget,
+				   tree_view->priv->press_start_x,
+				   tree_view->priv->press_start_y,
+				   event->x, event->y))
+    {
+      if (tree_view->priv->hildon_ui_mode == HILDON_UI_MODE_NORMAL)
+	free_queued_activate_row (tree_view);
+      else if (tree_view->priv->hildon_ui_mode == HILDON_UI_MODE_EDIT)
+	free_queued_select_row (tree_view);
+
+      gtk_tree_row_reference_free (tree_view->priv->queued_tapped_row);
+      tree_view->priv->queued_tapped_row = NULL;
+  }
+
   /* only check for an initiated drag when a button is pressed */
   if (tree_view->priv->pressed_button >= 0
+      && tree_view->priv->hildon_mode == HILDON_DIABLO
       && !tree_view->priv->rubber_band_status)
     gtk_tree_view_maybe_begin_dragging_row (tree_view, event);
 
@@ -4310,6 +4874,46 @@
     }
 }
 
+static void
+gtk_tree_view_draw_row_header (GtkTreeView     *tree_view,
+			       GtkTreeIter     *iter,
+			       GdkEventExpose  *event,
+			       GdkRectangle    *cell_area)
+{
+  gchar *label = NULL;
+  int width, height;
+  gboolean is_header;
+  GtkWidget *widget = GTK_WIDGET (tree_view);
+
+  g_return_if_fail (tree_view->priv->row_header_func != NULL);
+
+  is_header = (* tree_view->priv->row_header_func) (tree_view->priv->model,
+						    iter,
+						    &label,
+						    tree_view->priv->row_header_data);
+
+  g_return_if_fail (is_header == TRUE);
+  g_return_if_fail (tree_view->priv->row_header_layout != NULL);
+
+  pango_layout_set_text (tree_view->priv->row_header_layout,
+			 label, strlen (label));
+  pango_layout_get_pixel_size (tree_view->priv->row_header_layout,
+			       &width, &height);
+
+  gtk_paint_layout (widget->style,
+		    event->window,
+		    widget->state,
+		    TRUE,
+		    &event->area,
+		    widget,
+		    "treeview-group-header",
+		    cell_area->x + (cell_area->width - width) / 2,
+		    cell_area->y + cell_area->height - height,
+		    tree_view->priv->row_header_layout);
+
+  g_free (label);
+}
+
 /* Warning: Very scary function.
  * Modify at your own risk
  *
@@ -4356,6 +4960,8 @@
   gboolean got_pointer = FALSE;
   gboolean row_ending_details;
   gboolean draw_vgrid_lines, draw_hgrid_lines;
+  gint expose_start;
+  gboolean render_checkboxes = FALSE;
 
   rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
 
@@ -4379,11 +4985,27 @@
 
   validate_visible_area (tree_view);
 
-  new_y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, event->area.y);
+  if (G_UNLIKELY (tree_view->priv->rows_offset != 0)
+      && tree_view->priv->dy <= tree_view->priv->rows_offset
+      && event->area.y <= tree_view->priv->rows_offset - tree_view->priv->dy)
+    {
+      /* As long as a part of the button window is visible ... */
+      expose_start = tree_view->priv->rows_offset - tree_view->priv->dy;
+      y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree,
+					   tree_view->priv->rows_offset,
+					   &tree, &node);
+    }
+  else
+    {
+      new_y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, event->area.y);
+
+      if (new_y < 0)
+	new_y = 0;
+
+      expose_start = event->area.y;
+      y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
+    }
 
-  if (new_y < 0)
-    new_y = 0;
-  y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
   bin_window_width = gdk_window_get_width (tree_view->priv->bin_window);
   bin_window_height = gdk_window_get_height (tree_view->priv->bin_window);
 
@@ -4395,7 +5017,7 @@
                           GTK_SHADOW_NONE,
                           &event->area,
                           widget,
-                          "cell_even",
+			  "cell_blank",
                           0, tree_view->priv->height,
                           bin_window_width,
                           bin_window_height - tree_view->priv->height);
@@ -4449,6 +5071,13 @@
       n_visible_columns ++;
     }
 
+  if (tree_view->priv->hildon_mode == HILDON_FREMANTLE
+      && tree_view->priv->hildon_ui_mode == HILDON_UI_MODE_EDIT
+      && tree_view->priv->selection->type == GTK_SELECTION_MULTIPLE)
+    {
+      render_checkboxes = TRUE;
+    }
+
   /* Find the last column */
   for (last_column = g_list_last (tree_view->priv->columns);
        last_column && !(GTK_TREE_VIEW_COLUMN (last_column->data)->visible);
@@ -4472,8 +5101,9 @@
       gboolean is_separator = FALSE;
       gboolean is_first = FALSE;
       gboolean is_last = FALSE;
+      gboolean is_header = FALSE;
       
-      is_separator = row_is_separator (tree_view, &iter, NULL);
+      is_separator = row_is_separator (tree_view, &iter, &is_header, NULL);
 
       max_height = ROW_HEIGHT (tree_view, BACKGROUND_HEIGHT (node));
 
@@ -4481,7 +5111,7 @@
       highlight_x = 0; /* should match x coord of first cell */
       expander_cell_width = 0;
 
-      background_area.y = y_offset + event->area.y;
+      background_area.y = y_offset + expose_start;
       background_area.height = max_height;
 
       flags = 0;
@@ -4489,7 +5119,8 @@
       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PRELIT))
 	flags |= GTK_CELL_RENDERER_PRELIT;
 
-      if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
+      if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED)
+      || node == tree_view->priv->highlighted_node)
         flags |= GTK_CELL_RENDERER_SELECTED;
 
       parity = _gtk_rbtree_node_find_parity (tree, node);
@@ -4503,12 +5134,13 @@
 	   list = (rtl ? list->prev : list->next))
         {
 	  GtkTreeViewColumn *column = list->data;
-	  gtk_tree_view_column_cell_set_cell_data (column,
-						   tree_view->priv->model,
-						   &iter,
-						   GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
-						   node->children?TRUE:FALSE);
-        }
+	  gtk_tree_view_column_cell_set_cell_data_with_hint (column,
+							     tree_view->priv->model,
+							     &iter,
+							     GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
+							     node->children?TRUE:FALSE,
+							     GTK_TREE_CELL_DATA_HINT_KEY_FOCUS);
+	}
 
       has_special_cell = gtk_tree_view_has_special_cell (tree_view);
 
@@ -4543,7 +5175,11 @@
 	  background_area.x = cell_offset;
 	  background_area.width = column->width;
 
-          cell_area = background_area;
+	  /* Nasty hack to get background handling for free */
+	  if (render_checkboxes && column == last_column->data)
+	    background_area.width += HILDON_TICK_MARK_SIZE;
+
+	  cell_area = background_area;
           cell_area.y += vertical_separator / 2;
           cell_area.x += horizontal_separator / 2;
           cell_area.height -= vertical_separator;
@@ -4682,6 +5318,93 @@
 				  background_area.height);
 	    }
 
+	  /* Nasty hack to get background handling for free */
+	  if (render_checkboxes && column == last_column->data)
+	    {
+	      background_area.width -= HILDON_TICK_MARK_SIZE;
+	      cell_area.width -= HILDON_TICK_MARK_SIZE;
+
+	      if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
+		gdk_draw_pixbuf (event->window,
+				 NULL,
+				 tree_view->priv->tickmark_icon,
+				 0, 0,
+				 background_area.x + background_area.width,
+				 background_area.y + (background_area.height - HILDON_TICK_MARK_SIZE) / 2,
+				 HILDON_TICK_MARK_SIZE,
+				 HILDON_TICK_MARK_SIZE,
+				 GDK_RGB_DITHER_MAX,
+				 0, 0);
+	    }
+
+	  if (node == drag_highlight)
+	    {
+	      /* Draw indicator for the drop
+	       */
+	      gint highlight_y = -1;
+	      GtkRBTree *tree = NULL;
+	      GtkRBNode *node = NULL;
+	      gint width;
+
+	      switch (tree_view->priv->drag_dest_pos)
+		{
+		case GTK_TREE_VIEW_DROP_BEFORE:
+		  highlight_y = background_area.y - 1;
+		  if (highlight_y < 0)
+			  highlight_y = 0;
+		  break;
+
+		case GTK_TREE_VIEW_DROP_AFTER:
+		  highlight_y = background_area.y + background_area.height - 1;
+		  break;
+
+		case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
+		case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
+		  _gtk_tree_view_find_node (tree_view, drag_dest_path, &tree, &node);
+
+		  if (tree == NULL)
+		    break;
+		  gdk_drawable_get_size (tree_view->priv->bin_window,
+					 &width, NULL);
+
+		  if (row_ending_details)
+		    gtk_paint_focus (widget->style,
+				     tree_view->priv->bin_window,
+				     gtk_widget_get_state (widget),
+				     &event->area,
+				     widget,
+				     (is_first
+				      ? (is_last ? "treeview-drop-indicator" : "treeview-drop-indicator-left" )
+				      : (is_last ? "treeview-drop-indicator-right" : "tree-view-drop-indicator-middle" )),
+				     0, BACKGROUND_FIRST_PIXEL (tree_view, tree, node)
+				     - focus_line_width / 2,
+				     width, ROW_HEIGHT (tree_view, BACKGROUND_HEIGHT (node))
+				   - focus_line_width + 1);
+		  else
+		    gtk_paint_focus (widget->style,
+				     tree_view->priv->bin_window,
+				     gtk_widget_get_state (widget),
+				     &event->area,
+				     widget,
+				     "treeview-drop-indicator",
+				     0, BACKGROUND_FIRST_PIXEL (tree_view, tree, node)
+				     - focus_line_width / 2,
+				     width, ROW_HEIGHT (tree_view, BACKGROUND_HEIGHT (node))
+				     - focus_line_width + 1);
+		  break;
+		}
+
+	      if (highlight_y >= 0)
+		{
+		  gdk_draw_line (event->window,
+				 widget->style->fg_gc[gtk_widget_get_state (widget)],
+				 rtl ? highlight_x + expander_cell_width : highlight_x,
+				 highlight_y,
+				 rtl ? 0 : bin_window_width,
+				 highlight_y);
+		}
+	    }
+
 	  if (gtk_tree_view_is_expander_column (tree_view, column))
 	    {
 	      if (!rtl)
@@ -4702,7 +5425,14 @@
               highlight_x = cell_area.x;
 	      expander_cell_width = cell_area.width;
 
-	      if (is_separator)
+	      if (is_header)
+		{
+		  gtk_tree_view_draw_row_header (tree_view,
+						 &iter,
+						 event,
+						 &cell_area);
+		}
+	      else if (is_separator)
 		gtk_paint_hline (widget->style,
 				 event->window,
 				 state,
@@ -4737,7 +5467,14 @@
 	    }
 	  else
 	    {
-	      if (is_separator)
+	      if (is_header)
+		{
+		  gtk_tree_view_draw_row_header (tree_view,
+						 &iter,
+						 event,
+						 &cell_area);
+		}
+	      else if (is_separator)
 		gtk_paint_hline (widget->style,
 				 event->window,
 				 state,
@@ -4862,73 +5599,6 @@
 	  cell_offset += column->width;
 	}
 
-      if (node == drag_highlight)
-        {
-          /* Draw indicator for the drop
-           */
-          gint highlight_y = -1;
-	  GtkRBTree *tree = NULL;
-	  GtkRBNode *node = NULL;
-	  gint width;
-
-          switch (tree_view->priv->drag_dest_pos)
-            {
-            case GTK_TREE_VIEW_DROP_BEFORE:
-              highlight_y = background_area.y - 1;
-	      if (highlight_y < 0)
-		      highlight_y = 0;
-              break;
-
-            case GTK_TREE_VIEW_DROP_AFTER:
-              highlight_y = background_area.y + background_area.height - 1;
-              break;
-
-            case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
-            case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
-	      _gtk_tree_view_find_node (tree_view, drag_dest_path, &tree, &node);
-
-	      if (tree == NULL)
-		break;
-              width = gdk_window_get_width (tree_view->priv->bin_window);
-
-	      if (row_ending_details)
-		gtk_paint_focus (widget->style,
-			         tree_view->priv->bin_window,
-				 gtk_widget_get_state (widget),
-				 &event->area,
-				 widget,
-				 (is_first
-				  ? (is_last ? "treeview-drop-indicator" : "treeview-drop-indicator-left" )
-				  : (is_last ? "treeview-drop-indicator-right" : "tree-view-drop-indicator-middle" )),
-				 0, BACKGROUND_FIRST_PIXEL (tree_view, tree, node)
-				 - focus_line_width / 2,
-				 width, ROW_HEIGHT (tree_view, BACKGROUND_HEIGHT (node))
-			       - focus_line_width + 1);
-	      else
-		gtk_paint_focus (widget->style,
-			         tree_view->priv->bin_window,
-				 gtk_widget_get_state (widget),
-				 &event->area,
-				 widget,
-				 "treeview-drop-indicator",
-				 0, BACKGROUND_FIRST_PIXEL (tree_view, tree, node)
-				 - focus_line_width / 2,
-				 width, ROW_HEIGHT (tree_view, BACKGROUND_HEIGHT (node))
-				 - focus_line_width + 1);
-              break;
-            }
-
-          if (highlight_y >= 0)
-            {
-              gtk_tree_view_draw_line (tree_view, event->window,
-                                       GTK_TREE_VIEW_FOREGROUND_LINE,
-                                       rtl ? highlight_x + expander_cell_width : highlight_x,
-                                       highlight_y,
-                                       rtl ? 0 : bin_window_width,
-                                       highlight_y);
-            }
-        }
-
       /* draw the big row-spanning focus rectangle, if needed */
       if (!has_special_cell && node == cursor &&
 	  GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS) &&
@@ -5042,21 +5712,6 @@
 done:
   gtk_tree_view_draw_grid_lines (tree_view, event, n_visible_columns);
 
- if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
-   {
-     GdkRectangle *rectangles;
-     gint n_rectangles;
-
-     gdk_region_get_rectangles (event->region,
-				&rectangles,
-				&n_rectangles);
-
-     while (n_rectangles--)
-       gtk_tree_view_paint_rubber_band (tree_view, &rectangles[n_rectangles]);
-
-     g_free (rectangles);
-   }
-
   if (cursor_path)
     gtk_tree_path_free (cursor_path);
 
@@ -5504,6 +6159,15 @@
    * the typeahead find capabilities. */
   if (gtk_widget_has_focus (GTK_WIDGET (tree_view))
       && tree_view->priv->enable_search
+      /* These are usually handled via keybindings, but these do not
+	    * function in Fremantle mode.  Therefore we need to explicitly
+	    * check for these there.
+	    */
+      && event->keyval != GDK_ISO_Enter
+      && event->keyval != GDK_KP_Enter
+      && event->keyval != GDK_Return
+      && event->keyval != GDK_space
+      && event->keyval != GDK_KP_Space
       && !tree_view->priv->search_custom_entry_set)
     {
       GdkEvent *new_event;
@@ -5730,13 +6394,15 @@
   gint grid_line_width;
   gboolean wide_separators;
   gint separator_height;
+  gint row_height;
+  gboolean is_header = FALSE;
 
   /* double check the row needs validating */
   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) &&
       ! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
     return FALSE;
 
-  is_separator = row_is_separator (tree_view, iter, NULL);
+  is_separator = row_is_separator (tree_view, iter, &is_header, NULL);
 
   gtk_widget_style_get (GTK_WIDGET (tree_view),
 			"focus-padding", &focus_pad,
@@ -5746,6 +6412,7 @@
 			"grid-line-width", &grid_line_width,
                         "wide-separators",  &wide_separators,
                         "separator-height", &separator_height,
+			"row-height", &row_height,
 			NULL);
   
   draw_vgrid_lines =
@@ -5793,10 +6460,12 @@
 	}
       else
         {
-          if (wide_separators)
-            height = separator_height + 2 * focus_pad;
-          else
-            height = 2 + 2 * focus_pad;
+	  if (is_header)
+	     {
+	       height = HILDON_ROW_HEADER_HEIGHT;
+	     }
+	   else
+	    height = separator_height + 2 * focus_pad;
         }
 
       if (gtk_tree_view_is_expander_column (tree_view, column))
@@ -5817,6 +6486,14 @@
 	    tmp_width += grid_line_width;
 	}
 
+      if (tree_view->priv->hildon_mode == HILDON_FREMANTLE
+	  && tree_view->priv->hildon_ui_mode == HILDON_UI_MODE_EDIT
+	  && tree_view->priv->selection->type == GTK_SELECTION_MULTIPLE)
+	{
+	  tmp_width += HILDON_TICK_MARK_SIZE;
+	  height = MAX (height, HILDON_TICK_MARK_SIZE);
+	}
+
       if (tmp_width > column->requested_width)
 	{
 	  retval = TRUE;
@@ -5827,6 +6504,9 @@
   if (draw_hgrid_lines)
     height += grid_line_width;
 
+  if (row_height != -1 && !is_separator && !is_header)
+    height = row_height;
+
   if (height != GTK_RBNODE_GET_HEIGHT (node))
     {
       retval = TRUE;
@@ -6180,33 +6860,166 @@
     {
       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. */
+      /* 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 (tree_view->priv->scroll_to_path)
+    {
+      gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
+      tree_view->priv->scroll_to_path = NULL;
+    }
+
+  if (above_path)
+    gtk_tree_path_free (above_path);
+
+  if (tree_view->priv->scroll_to_column)
+    {
+      tree_view->priv->scroll_to_column = NULL;
+    }
+  if (need_redraw)
+    gtk_widget_queue_draw (GTK_WIDGET (tree_view));
+}
+
+/* You can pass in focus_pad, separator_height to save
+ * calls to gtk_widget_style_get() (especially for
+ * gtk_tree_view_nodes_set_fixed_height).
+ */
+static inline int
+determine_row_height (GtkTreeView *tree_view,
+		      GtkTreeIter *iter,
+		      int          focus_pad,
+		      int          separator_height)
+{
+  int height;
+  gboolean is_separator, is_header = FALSE;
+
+  /* Determine the correct height for this node.  This is
+   * analogous to what is found in validate_row().
+   */
+  is_separator = row_is_separator (tree_view, iter, &is_header, NULL);
+
+  if (!is_separator)
+    height = tree_view->priv->fixed_height;
+  else if (is_header)
+    height = HILDON_ROW_HEADER_HEIGHT;
+  else
+    {
+      if (focus_pad == -1 || separator_height == -1)
+	gtk_widget_style_get (GTK_WIDGET (tree_view),
+			      "focus-padding", &focus_pad,
+			      "separator-height", &separator_height,
+			      NULL);
+
+      height = separator_height + 2 * focus_pad;
+    }
+
+  return height;
+}
+
+/* This function is basically an extended and non-recursive version of
+ * _gtk_rbtree_set_fixed_height() which also keeps track of the current
+ * iter.  We can then pass this iter in to the row separator and
+ * row header funcs.
+ */
+static void
+gtk_tree_view_nodes_set_fixed_height (GtkTreeView *tree_view)
+{
+  int focus_pad;
+  int separator_height;
+  GtkRBTree *tree;
+  GtkRBNode *node;
+  GtkTreeIter iter;
+
+  tree = tree_view->priv->tree;
+
+  if (tree == NULL)
+    return;
+
+  node = tree->root;
+  g_assert (node);
+
+  /* Rewind tree, we start at the first node */
+  while (node->left != tree->nil)
+    node = node->left;
+
+  gtk_tree_model_get_iter_first (tree_view->priv->model, &iter);
+
+  gtk_widget_style_get (GTK_WIDGET (tree_view),
+			"focus-padding", &focus_pad,
+			"separator-height", &separator_height,
+			NULL);
+
+  /* This loop is equivalent to the one in bin_expose, but with
+   * the extra assertions removed.
+   */
+  do
+    {
+      if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID))
+	{
+	  int height;
+
+	  height = determine_row_height (tree_view, &iter,
+					 focus_pad, separator_height);
+
+	  _gtk_rbtree_node_set_height (tree, node, height);
+	  _gtk_rbtree_node_mark_valid (tree, node);
+	}
+
+      if (node->children)
+	{
+	  GtkTreeIter parent = iter;
+
+	  tree = node->children;
+	  node = tree->root;
+
+	  g_assert (node != tree->nil);
 
-      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));
-    }
+	  while (node->left != tree->nil)
+	    node = node->left;
 
-  if (tree_view->priv->scroll_to_path)
-    {
-      gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
-      tree_view->priv->scroll_to_path = NULL;
-    }
+	  gtk_tree_model_iter_children (tree_view->priv->model,
+					&iter, &parent);
+	}
+      else
+	{
+	  gboolean done = FALSE;
 
-  if (above_path)
-    gtk_tree_path_free (above_path);
+	  do
+	    {
+	      node = _gtk_rbtree_next (tree, node);
+	      if (node != NULL)
+		{
+		  gtk_tree_model_iter_next (tree_view->priv->model, &iter);
+		  done = TRUE;
+		}
+	      else
+		{
+		  GtkTreeIter parent_iter = iter;
 
-  if (tree_view->priv->scroll_to_column)
-    {
-      tree_view->priv->scroll_to_column = NULL;
+		  node = tree->parent_node;
+		  tree = tree->parent_tree;
+
+		  if (!tree)
+		    /* We are done */
+		    return;
+
+		  gtk_tree_model_iter_parent (tree_view->priv->model,
+					      &iter, &parent_iter);
+		}
+	    }
+	  while (!done);
+	}
     }
-  if (need_redraw)
-    gtk_widget_queue_draw (GTK_WIDGET (tree_view));
+  while (TRUE);
 }
 
 static void
@@ -6227,6 +7040,29 @@
       node = tree->root;
 
       path = _gtk_tree_view_find_path (tree_view, tree, node);
+
+      /* Search for the first regular row */
+      while (node)
+	{
+	  gboolean is_header = FALSE, is_separator;
+
+	  is_separator = row_is_separator (tree_view, NULL, &is_header, path);
+	  if (!is_separator && !is_header)
+	    break;
+
+	  _gtk_rbtree_next_full (tree, node, &tree, &node);
+
+	  gtk_tree_path_free (path);
+
+	  if (node)
+	    path = _gtk_tree_view_find_path (tree_view, tree, node);
+	  else
+	    path = NULL;
+	}
+
+      if  (!path)
+	return;
+
       gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
 
       validate_row (tree_view, tree, node, &iter, path);
@@ -6236,8 +7072,16 @@
       tree_view->priv->fixed_height = ROW_HEIGHT (tree_view, GTK_RBNODE_GET_HEIGHT (node));
     }
 
-   _gtk_rbtree_set_fixed_height (tree_view->priv->tree,
-                                 tree_view->priv->fixed_height, TRUE);
+  /* If a separator or row header func has been set, we cannot
+   * uniformly set the same height on all rows.  We fall back to
+   * a slower alternative.
+   */
+  if (tree_view->priv->row_separator_func
+      || tree_view->priv->row_header_func)
+    gtk_tree_view_nodes_set_fixed_height (tree_view);
+  else
+    _gtk_rbtree_set_fixed_height (tree_view->priv->tree,
+				  tree_view->priv->fixed_height, TRUE);
 }
 
 /* Our strategy for finding nodes to validate is a little convoluted.  We find
@@ -7206,6 +8050,9 @@
 
   set_source_row (context, model, path);
 
+  /* Clear pending actions on row */
+  free_queued_actions (tree_view);
+
  out:
   if (path)
     gtk_tree_path_free (path);
@@ -7708,12 +8555,20 @@
 gtk_tree_view_has_special_cell (GtkTreeView *tree_view)
 {
   GList *list;
+  guint n_specials = 0;
 
   for (list = tree_view->priv->columns; list; list = list->next)
     {
       if (!((GtkTreeViewColumn *)list->data)->visible)
 	continue;
-      if (_gtk_tree_view_column_count_special_cells (list->data))
+      /* We return true if there is more than one special cell.  Since
+       * we do not want to have the per-cell focus rectangles when there
+       * is only a single activatable cell, we return FALSE for
+       * n_specials == 1
+       */
+      n_specials += _gtk_tree_view_column_count_special_cells (list->data);
+
+      if (n_specials > 1)
 	return TRUE;
     }
 
@@ -7813,148 +8668,11 @@
 			    GtkDirectionType  dir,
 			    gboolean          clamp_column_visible)
 {
-  GtkWidget *focus_child;
-
-  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;
-
-  focus_child = GTK_CONTAINER (tree_view)->focus_child;
-
-  first_column = tree_view->priv->columns;
-  while (first_column)
-    {
-      if (gtk_widget_get_can_focus (GTK_TREE_VIEW_COLUMN (first_column->data)->button) &&
-	  GTK_TREE_VIEW_COLUMN (first_column->data)->visible &&
-	  (GTK_TREE_VIEW_COLUMN (first_column->data)->clickable ||
-	   GTK_TREE_VIEW_COLUMN (first_column->data)->reorderable))
-	break;
-      first_column = first_column->next;
-    }
-
-  /* No headers are visible, or are focusable.  We can't focus in or out.
-   */
-  if (first_column == NULL)
-    return FALSE;
-
-  last_column = g_list_last (tree_view->priv->columns);
-  while (last_column)
-    {
-      if (gtk_widget_get_can_focus (GTK_TREE_VIEW_COLUMN (last_column->data)->button) &&
-	  GTK_TREE_VIEW_COLUMN (last_column->data)->visible &&
-	  (GTK_TREE_VIEW_COLUMN (last_column->data)->clickable ||
-	   GTK_TREE_VIEW_COLUMN (last_column->data)->reorderable))
-	break;
-      last_column = last_column->prev;
-    }
-
-
-  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
-
-  switch (dir)
-    {
-    case GTK_DIR_TAB_BACKWARD:
-    case GTK_DIR_TAB_FORWARD:
-    case GTK_DIR_UP:
-    case GTK_DIR_DOWN:
-      if (focus_child == NULL)
-	{
-	  if (tree_view->priv->focus_column != NULL &&
-              gtk_widget_get_can_focus (tree_view->priv->focus_column->button))
-	    focus_child = tree_view->priv->focus_column->button;
-	  else
-	    focus_child = GTK_TREE_VIEW_COLUMN (first_column->data)->button;
-	  gtk_widget_grab_focus (focus_child);
-	  break;
-	}
-      return FALSE;
-
-    case GTK_DIR_LEFT:
-    case GTK_DIR_RIGHT:
-      if (focus_child == NULL)
-	{
-	  if (tree_view->priv->focus_column != NULL)
-	    focus_child = tree_view->priv->focus_column->button;
-	  else if (dir == GTK_DIR_LEFT)
-	    focus_child = GTK_TREE_VIEW_COLUMN (last_column->data)->button;
-	  else
-	    focus_child = GTK_TREE_VIEW_COLUMN (first_column->data)->button;
-	  gtk_widget_grab_focus (focus_child);
-	  break;
-	}
-
-      if (gtk_widget_child_focus (focus_child, dir))
-	{
-	  /* The focus moves inside the button. */
-	  /* This is probably a great example of bad UI */
-	  break;
-	}
-
-      /* We need to move the focus among the row of buttons. */
-      for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
-	if (GTK_TREE_VIEW_COLUMN (tmp_list->data)->button == focus_child)
-	  break;
-
-      if ((tmp_list == first_column && dir == (rtl ? GTK_DIR_RIGHT : GTK_DIR_LEFT))
-	  || (tmp_list == last_column && dir == (rtl ? GTK_DIR_LEFT : GTK_DIR_RIGHT)))
-        {
-	  gtk_widget_error_bell (GTK_WIDGET (tree_view));
-	  break;
-	}
-
-      while (tmp_list)
-	{
-	  GtkTreeViewColumn *column;
-
-	  if (dir == (rtl ? GTK_DIR_LEFT : GTK_DIR_RIGHT))
-	    tmp_list = tmp_list->next;
-	  else
-	    tmp_list = tmp_list->prev;
-
-	  if (tmp_list == NULL)
-	    {
-	      g_warning ("Internal button not found");
-	      break;
-	    }
-	  column = tmp_list->data;
-	  if (column->button &&
-	      column->visible &&
-	      gtk_widget_get_can_focus (column->button))
-	    {
-	      focus_child = column->button;
-	      gtk_widget_grab_focus (column->button);
-	      break;
-	    }
-	}
-      break;
-    default:
-      g_assert_not_reached ();
-      break;
-    }
-
-  /* if focus child is non-null, we assume it's been set to the current focus child
+  /* Skip headers when acquiring focus; behave the same as the headers
+   * are invisible.
    */
-  if (focus_child)
-    {
-      for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
-	if (GTK_TREE_VIEW_COLUMN (tmp_list->data)->button == focus_child)
-	  {
-	    tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
-	    break;
-	  }
-
-      if (clamp_column_visible)
-        {
-	  gtk_tree_view_clamp_column_visible (tree_view,
-					      tree_view->priv->focus_column,
-					      FALSE);
-	}
-    }
 
-  return (focus_child != NULL);
+  return FALSE;
 }
 
 /* This function returns in 'path' the first focusable path, if the given path
@@ -7978,7 +8696,9 @@
   if (!tree || !node)
     return FALSE;
 
-  while (node && row_is_separator (tree_view, NULL, *path))
+  while (node &&
+	 !_gtk_tree_selection_row_is_selectable (tree_view->priv->selection,
+						 node, *path))
     {
       if (search_forward)
 	_gtk_rbtree_next_full (tree, node, &tree, &node);
@@ -8097,6 +8817,31 @@
   tree_view->priv->fixed_height = -1;
   _gtk_rbtree_mark_invalid (tree_view->priv->tree);
 
+  /* Cache the hildon-mode because it is slow to call gtk_widget_style_get
+   * too much. */
+  gtk_widget_style_get (GTK_WIDGET (tree_view),
+			"hildon-mode", &tree_view->priv->hildon_mode,
+			NULL);
+
+  /* Reset the UI mode */
+  hildon_tree_view_set_hildon_ui_mode (tree_view,
+				       tree_view->priv->hildon_ui_mode);
+
+  if (tree_view->priv->row_header_layout)
+    hildon_tree_view_setup_row_header_layout (tree_view);
+
+  if (tree_view->priv->tickmark_icon)
+    g_object_unref (tree_view->priv->tickmark_icon);
+
+  tree_view->priv->tickmark_icon =
+      gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+				"widgets_tickmark_list",
+				HILDON_TICK_MARK_SIZE,
+				0, NULL);
+
+  if (tree_view->priv->action_area_visible)
+    hildon_tree_view_set_action_area_height (tree_view);
+
   gtk_widget_queue_resize (widget);
 }
 
@@ -8354,10 +9099,39 @@
   if (tree == NULL)
     goto done;
 
+  /* Unselect the row if it just became insensitive */
+  if (!_gtk_tree_selection_row_is_selectable (tree_view->priv->selection,
+					      node, path)
+      && gtk_tree_row_reference_valid (tree_view->priv->cursor))
+    {
+      GtkTreePath *cursor_path;
+
+      cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
+      if (! gtk_tree_path_compare (path, cursor_path))
+	{
+	  gtk_tree_row_reference_free (tree_view->priv->cursor);
+	  tree_view->priv->cursor = NULL;
+	}
+
+      gtk_tree_selection_unselect_path (tree_view->priv->selection, path);
+
+      gtk_tree_path_free (cursor_path);
+    }
+
   if (tree_view->priv->fixed_height_mode
       && tree_view->priv->fixed_height >= 0)
     {
-      _gtk_rbtree_node_set_height (tree, node, tree_view->priv->fixed_height);
+      if (tree_view->priv->row_separator_func
+	  || tree_view->priv->row_header_func)
+	{
+	  int height;
+
+	  height = determine_row_height (tree_view, iter, -1, -1);
+	  _gtk_rbtree_node_set_height (tree, node, height);
+	}
+      else
+	_gtk_rbtree_node_set_height (tree, node, tree_view->priv->fixed_height);
+
       if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
 	gtk_tree_view_node_queue_redraw (tree_view, tree, node);
     }
@@ -8407,7 +9181,13 @@
 
   if (tree_view->priv->fixed_height_mode
       && tree_view->priv->fixed_height >= 0)
-    height = tree_view->priv->fixed_height;
+    {
+      if (tree_view->priv->row_separator_func
+	  || tree_view->priv->row_header_func)
+	height = determine_row_height (tree_view, iter, -1, -1);
+      else
+	height = tree_view->priv->fixed_height;
+    }
   else
     height = 0;
 
@@ -8420,7 +9200,13 @@
     gtk_tree_model_get_iter (model, iter, path);
 
   if (tree_view->priv->tree == NULL)
-    tree_view->priv->tree = _gtk_rbtree_new ();
+    {
+      tree_view->priv->tree = _gtk_rbtree_new ();
+
+      if (G_UNLIKELY (tree_view->priv->rows_offset != 0))
+	_gtk_rbtree_set_base_offset (tree_view->priv->tree,
+				     tree_view->priv->rows_offset);
+    }
 
   tmptree = tree = tree_view->priv->tree;
 
@@ -8485,6 +9271,23 @@
       tmpnode = _gtk_rbtree_insert_after (tree, tmpnode, height, FALSE);
     }
 
+  /* If this was the first node inserted in the tree, we want to
+   * select it.
+   */
+  if (tree_view->priv->hildon_mode == HILDON_FREMANTLE
+      && tree_view->priv->hildon_ui_mode == HILDON_UI_MODE_EDIT
+      && tree_view->priv->selection->type != GTK_SELECTION_MULTIPLE
+      && gtk_tree_selection_count_selected_rows (tree_view->priv->selection) < 1)
+    {
+      GtkTreePath *tmppath;
+
+      tmppath = gtk_tree_path_new_first ();
+      search_first_focusable_path (tree_view, &tmppath,
+				   TRUE, NULL, NULL);
+      gtk_tree_selection_select_path (tree_view->priv->selection, tmppath);
+      gtk_tree_path_free (tmppath);
+    }
+
  done:
   if (height > 0)
     {
@@ -8631,6 +9434,8 @@
 
   /* Ensure we don't have a dangling pointer to a dead node */
   ensure_unprelighted (tree_view);
+  free_queued_actions (tree_view);
+  ensure_unhighlighted (tree_view);
 
   /* Cancel editting if we've started */
   gtk_tree_view_stop_editing (tree_view, TRUE);
@@ -8638,6 +9443,12 @@
   /* If we have a node expanded/collapsed timeout, remove it */
   remove_expand_collapse_timeout (tree_view);
 
+  /* Stop rubber banding as row deletion invalidates the start/end
+   * rbtree/nodes. Should consider updating the pointers instead.
+   */
+  if (tree_view->priv->rubber_band_status)
+    gtk_tree_view_stop_rubber_band (tree_view);
+
   if (tree_view->priv->destroy_count_func)
     {
       gint child_count = 0;
@@ -8666,6 +9477,24 @@
 
   install_scroll_sync_handler (tree_view);
 
+  if (selection_changed
+      && tree_view->priv->hildon_mode == HILDON_FREMANTLE
+      && tree_view->priv->hildon_ui_mode == HILDON_UI_MODE_EDIT
+      && tree_view->priv->selection->type != GTK_SELECTION_MULTIPLE
+      && gtk_tree_selection_count_selected_rows (tree_view->priv->selection) < 1)
+    {
+      GtkTreePath *tmppath;
+
+      /* One item must be selected, now there is none.  If iter_first
+       * does not exist, the view is empty.
+       */
+      tmppath = gtk_tree_path_new_first ();
+      search_first_focusable_path (tree_view, &tmppath,
+				   TRUE, NULL, NULL);
+      gtk_tree_selection_select_path (tree_view->priv->selection, tmppath);
+      gtk_tree_path_free (tmppath);
+    }
+
   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
 
   if (selection_changed)
@@ -8714,6 +9543,8 @@
 
   /* we need to be unprelighted */
   ensure_unprelighted (tree_view);
+  free_queued_actions (tree_view);
+  ensure_unhighlighted (tree_view);
 
   /* clear the timeout */
   cancel_arrow_animation (tree_view);
@@ -9590,6 +10421,9 @@
 {
   GtkTreePath *cursor_path;
 
+  if (tree_view->priv->hildon_mode == HILDON_FREMANTLE)
+    return;
+
   if ((tree_view->priv->tree == NULL) ||
       (! gtk_widget_get_realized (GTK_WIDGET (tree_view))))
     return;
@@ -9628,8 +10462,11 @@
 
       if (cursor_path)
 	{
-	  if (tree_view->priv->selection->type == GTK_SELECTION_MULTIPLE)
-	    gtk_tree_view_real_set_cursor (tree_view, cursor_path, FALSE, FALSE);
+	  if ((tree_view->priv->selection->type == GTK_SELECTION_MULTIPLE)
+	      && tree_view->priv->hildon_mode == HILDON_DIABLO)
+	    {
+	      gtk_tree_view_real_set_cursor (tree_view, cursor_path, FALSE, FALSE);
+	    }
 	  else
 	    gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, FALSE);
 	}
@@ -9833,6 +10670,8 @@
 
   if (y >= tree_view->priv->height)
     y = tree_view->priv->height - 1;
+  else if (tree_view->priv->rows_offset != 0 && y < tree_view->priv->rows_offset)
+    y = tree_view->priv->rows_offset;
 
   tree_view->priv->cursor_offset =
     _gtk_rbtree_find_offset (tree_view->priv->tree, y,
@@ -9942,11 +10781,12 @@
       if (column->visible == FALSE)
 	goto loop_end;
 
-      gtk_tree_view_column_cell_set_cell_data (column,
-					       tree_view->priv->model,
-					       &iter,
-					       GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT),
-					       cursor_node->children?TRUE:FALSE);
+      gtk_tree_view_column_cell_set_cell_data_with_hint (column,
+							 tree_view->priv->model,
+							 &iter,
+							 GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT),
+							 cursor_node->children?TRUE:FALSE,
+							 GTK_TREE_CELL_DATA_HINT_KEY_FOCUS);
 
       if (rtl)
         {
@@ -10007,6 +10847,12 @@
 
   gtk_tree_view_get_cursor (tree_view, &old_path, NULL);
 
+  /* Immediately return when there is no cursor.  (Like all other
+   * cursor movement handlers -- should prolly go upstream).
+   */
+  if (!old_path)
+    return;
+
   cursor_tree = tree_view->priv->tree;
   cursor_node = cursor_tree->root;
 
@@ -10115,6 +10961,54 @@
       return FALSE;
     }
 
+  if (start_editing)
+    {
+      GList *list;
+      gboolean rtl;
+      GtkTreeIter iter;
+
+      /* In case we have only one activatable cell in the tree view, we have
+       * a special case.  We will have to set the cell data on the cursor
+       * row in order to figure out.
+       */
+      gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path);
+      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 *column = list->data;
+	  gtk_tree_view_column_cell_set_cell_data_with_hint (column,
+							     tree_view->priv->model,
+							     &iter,
+							     GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT),
+							     cursor_node->children?TRUE:FALSE,
+							     GTK_TREE_CELL_DATA_HINT_KEY_FOCUS);
+	}
+
+      if (!gtk_tree_view_has_special_cell (tree_view))
+	{
+	  /* We now set focus_column to the first column with an activatable
+	   * cell that we can find.  This is either none, or the one with
+	   * the only activatable cell that is around.
+	   */
+	  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;
+
+	      if (column->visible
+		  && _gtk_tree_view_column_count_special_cells (column))
+		{
+		  tree_view->priv->focus_column = column;
+		  break;
+		}
+	    }
+	}
+    }
+
   if (!tree_view->priv->extend_selection_pressed && start_editing &&
       tree_view->priv->focus_column)
     {
@@ -10235,18 +11129,40 @@
   if (_gtk_tree_view_find_node (tree_view, cursor_path, &tree, &node))
     return FALSE;
 
-  /* Don't handle the event if we aren't an expander */
-  if (!((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT))
-    return FALSE;
-
   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);
+    {
+      gboolean expanded;
+
+      expanded = gtk_tree_view_real_expand_row (tree_view, cursor_path,
+						tree, node, open_all, TRUE);
+      if (!expanded
+	  && !gtk_widget_keynav_failed (GTK_WIDGET (tree_view), GTK_DIR_RIGHT))
+	{
+	  GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tree_view));
+	  if (toplevel)
+	    gtk_widget_child_focus (toplevel, GTK_DIR_TAB_FORWARD);
+	}
+    }
   else
-    gtk_tree_view_real_collapse_row (tree_view, cursor_path, tree, node, TRUE);
+    {
+      gboolean collapsed;
+
+      collapsed = gtk_tree_view_real_collapse_row (tree_view, cursor_path,
+						   tree, node, TRUE);
+      if (!collapsed
+	  && !gtk_widget_keynav_failed (GTK_WIDGET (tree_view), GTK_DIR_LEFT))
+	{
+	  GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tree_view));
+	  if (toplevel)
+	    gtk_widget_child_focus (toplevel, GTK_DIR_TAB_BACKWARD);
+
+	  gtk_tree_view_real_select_cursor_parent (tree_view);
+	}
+    }
 
   gtk_tree_path_free (cursor_path);
 
@@ -10361,6 +11277,7 @@
      }
    
   tree_view->priv->search_window = gtk_window_new (GTK_WINDOW_POPUP);
+  gtk_window_set_is_temporary (GTK_WINDOW (tree_view->priv->search_window), TRUE);
   gtk_window_set_screen (GTK_WINDOW (tree_view->priv->search_window), screen);
 
   if (GTK_WINDOW (toplevel)->group)
@@ -10792,6 +11709,11 @@
       gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
       tree_view->priv->scroll_to_path = NULL;
 
+      tree_view->priv->highlighted_tree = NULL;
+      tree_view->priv->highlighted_node = NULL;
+
+      free_queued_actions (tree_view);
+
       tree_view->priv->scroll_to_column = NULL;
 
       g_object_unref (tree_view->priv->model);
@@ -10859,8 +11781,24 @@
       if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, path))
 	{
 	  tree_view->priv->tree = _gtk_rbtree_new ();
+
+	  if (G_UNLIKELY (tree_view->priv->rows_offset != 0))
+	    _gtk_rbtree_set_base_offset (tree_view->priv->tree,
+					 tree_view->priv->rows_offset);
+
 	  gtk_tree_view_build_tree (tree_view, tree_view->priv->tree, &iter, 1, FALSE);
 	}
+
+      if (tree_view->priv->hildon_mode == HILDON_FREMANTLE
+	  && tree_view->priv->hildon_ui_mode == HILDON_UI_MODE_EDIT
+	  && tree_view->priv->selection->type != GTK_SELECTION_MULTIPLE)
+	{
+	  /* Select the first item */
+	  search_first_focusable_path (tree_view, &path,
+				       TRUE, NULL, NULL);
+	  gtk_tree_selection_select_path (tree_view->priv->selection, path);
+	}
+
       gtk_tree_path_free (path);
 
       /*  FIXME: do I need to do this? gtk_tree_view_create_buttons (tree_view); */
@@ -12079,6 +13017,12 @@
   GtkTreeIter iter;
   GtkTreeIter temp;
   gboolean expand;
+  gint dy;
+  GtkTreeIter tmpiter;
+  GtkTreePath *tmppath;
+  GtkRBTree *tmptree;
+  GtkRBNode *tmpnode;
+  gint branch_height;
 
   if (animate)
     g_object_get (gtk_widget_get_settings (GTK_WIDGET (tree_view)),
@@ -12147,12 +13091,54 @@
 			    gtk_tree_path_get_depth (path) + 1,
 			    open_all);
 
-  remove_expand_collapse_timeout (tree_view);
+  remove_expand_collapse_timeout (tree_view);
+
+  if (animate)
+    add_expand_collapse_timeout (tree_view, tree, node, TRUE);
+
+  /* We do validate new nodes ourselves below, but we still need
+   * somebody to take care of the actual resizing.
+   */
+  if (gtk_widget_get_mapped (GTK_WIDGET (tree_view)))
+    gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+
+  install_presize_handler (tree_view);
+
+  gtk_tree_model_get_iter (tree_view->priv->model, &tmpiter, path);
+  _gtk_tree_view_find_node (tree_view, path, &tmptree, &tmpnode);
+
+  validate_row (tree_view, tmptree, tmpnode, &tmpiter, path);
+  branch_height = ROW_HEIGHT (tree_view, GTK_RBNODE_GET_HEIGHT (tmpnode));
+  dy = _gtk_rbtree_node_find_offset (tmptree, tmpnode);
+
+  tmppath = gtk_tree_path_copy (path);
+  gtk_tree_path_down (tmppath);
+  gtk_tree_model_get_iter (tree_view->priv->model, &tmpiter, tmppath);
+
+  do
+    {
+      _gtk_tree_view_find_node (tree_view, tmppath, &tmptree, &tmpnode);
+
+      validate_row (tree_view, tmptree, tmpnode, &tmpiter, tmppath);
+      branch_height += ROW_HEIGHT (tree_view, GTK_RBNODE_GET_HEIGHT (tmpnode));
+
+      gtk_tree_path_next (tmppath);
+    }
+  while (gtk_tree_model_iter_next (tree_view->priv->model, &tmpiter));
+
+  gtk_tree_path_prev (tmppath);
 
-  if (animate)
-    add_expand_collapse_timeout (tree_view, tree, node, TRUE);
+  /* We scroll to the just expanded row if the expanding row and its children
+   * do not fit in the view.
+   * Otherwise, if the last child is not visible, we scroll to it to make
+   * sure all children are visible.
+   */
+  if (branch_height > GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view))
+    gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.0, 0.0);
+  else if (dy + branch_height > tree_view->priv->vadjustment->value + tree_view->priv->vadjustment->page_size)
+    gtk_tree_view_scroll_to_cell (tree_view, tmppath, NULL, TRUE, 1.0, 0.0);
 
-  install_presize_handler (tree_view);
+  gtk_tree_path_free (tmppath);
 
   g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
   if (open_all && node->children)
@@ -12556,6 +13542,20 @@
   GtkRBTree *tree = NULL;
   GtkRBNode *node = NULL;
 
+  _gtk_tree_view_find_node (tree_view, path, &tree, &node);
+
+  /* If we are in legacy or in (new-style) edit mode, row-insensitive
+   * can be emitted.
+   */
+  if ((tree_view->priv->hildon_mode == HILDON_DIABLO
+       || tree_view->priv->hildon_ui_mode == HILDON_UI_MODE_EDIT)
+      && !_gtk_tree_selection_row_is_selectable (tree_view->priv->selection,
+						 node, path))
+    {
+      g_signal_emit (tree_view, tree_view_signals[ROW_INSENSITIVE], 0, path);
+      return;
+    }
+
   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
     {
       GtkTreePath *cursor_path;
@@ -12573,18 +13573,21 @@
    * path maps to a non-existing path and we will silently bail out.
    * We unset tree and node to avoid further processing.
    */
-  if (!row_is_separator (tree_view, NULL, path)
-      && _gtk_tree_view_find_node (tree_view, path, &tree, &node) == FALSE)
+  if (tree_view->priv->hildon_mode == HILDON_DIABLO)
     {
-      tree_view->priv->cursor =
-          gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
-                                            tree_view->priv->model,
-                                            path);
-    }
-  else
-    {
-      tree = NULL;
-      node = NULL;
+      if (!row_is_separator (tree_view, NULL, NULL, path)
+	  && _gtk_tree_view_find_node (tree_view, path, &tree, &node) == FALSE)
+	{
+	  tree_view->priv->cursor =
+	      gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
+						tree_view->priv->model,
+						path);
+	}
+      else
+	{
+	  tree = NULL;
+	  node = NULL;
+	}
     }
 
   if (tree != NULL)
@@ -12596,8 +13599,13 @@
         {
           GtkTreeSelectMode mode = 0;
 
-          if (tree_view->priv->modify_selection_pressed)
-            mode |= GTK_TREE_SELECT_MODE_TOGGLE;
+	  if (tree_view->priv->modify_selection_pressed ||
+	      (tree_view->priv->hildon_mode == HILDON_FREMANTLE
+	       && tree_view->priv->hildon_ui_mode == HILDON_UI_MODE_EDIT
+	       && tree_view->priv->selection->type == GTK_SELECTION_MULTIPLE))
+	    {
+	      mode |= GTK_TREE_SELECT_MODE_TOGGLE;
+	    }
           if (tree_view->priv->extend_selection_pressed)
             mode |= GTK_TREE_SELECT_MODE_EXTEND;
 
@@ -12622,7 +13630,9 @@
 	}
     }
 
-  g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
+  /* Only in the original mode we want to handle the cursor */
+  if (tree_view->priv->hildon_mode == HILDON_DIABLO)
+    g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
 }
 
 /**
@@ -13780,6 +14790,7 @@
   gboolean is_separator = FALSE;
   gboolean rtl;
   cairo_t *cr;
+  gboolean is_header = FALSE;
 
   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
   g_return_val_if_fail (path != NULL, NULL);
@@ -13804,7 +14815,7 @@
                                 path))
     return NULL;
   
-  is_separator = row_is_separator (tree_view, &iter, NULL);
+  is_separator = row_is_separator (tree_view, &iter, &is_header, NULL);
 
   cell_offset = x;
 
@@ -13872,7 +14883,14 @@
 
       if (gtk_tree_view_column_cell_is_visible (column))
 	{
-	  if (is_separator)
+	  if (is_header)
+	    {
+	      gtk_tree_view_draw_row_header (tree_view,
+					     &iter,
+					     NULL,
+					     &cell_area);
+	    }
+	  else if (is_separator)
 	    gtk_paint_hline (widget->style,
 			     drawable,
 			     GTK_STATE_NORMAL,
@@ -15141,6 +16159,83 @@
   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
 }
 
+HildonTreeViewRowHeaderFunc
+hildon_tree_view_get_row_header_func (GtkTreeView *tree_view)
+{
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
+
+  return tree_view->priv->row_header_func;
+}
+
+static void
+hildon_tree_view_setup_row_header_layout (GtkTreeView *tree_view)
+{
+  GdkColor font_color;
+  GtkStyle *font_style;
+  GtkWidget *widget = GTK_WIDGET (tree_view);
+
+  font_style = gtk_rc_get_style_by_paths (gtk_settings_get_default (),
+					  "EmpSmallSystemFont",
+					  NULL, G_TYPE_NONE);
+  if (font_style)
+    {
+      pango_layout_set_font_description (tree_view->priv->row_header_layout,
+					 font_style->font_desc);
+    }
+
+  if (gtk_style_lookup_color (widget->style, "SecondaryTextColor", &font_color))
+    {
+      PangoAttrList *list;
+      PangoAttribute *attr;
+
+      list = pango_attr_list_new ();
+      attr = pango_attr_foreground_new (font_color.red,
+					font_color.green,
+					font_color.blue);
+      attr->start_index = 0;
+      attr->end_index = G_MAXINT;
+      pango_attr_list_insert (list, attr);
+
+      pango_layout_set_attributes (tree_view->priv->row_header_layout,
+				   list);
+
+      pango_attr_list_unref (list);
+    }
+}
+
+void
+hildon_tree_view_set_row_header_func (GtkTreeView                 *tree_view,
+				      HildonTreeViewRowHeaderFunc  func,
+				      gpointer                     data,
+				      GDestroyNotify               destroy)
+{
+  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+
+  if (tree_view->priv->row_header_destroy)
+    (* tree_view->priv->row_header_destroy) (tree_view->priv->row_header_data);
+
+  tree_view->priv->row_header_func = func;
+  tree_view->priv->row_header_data = data;
+  tree_view->priv->row_header_destroy = destroy;
+
+  if (func && !tree_view->priv->row_header_layout)
+    {
+      tree_view->priv->row_header_layout =
+	  gtk_widget_create_pango_layout (GTK_WIDGET (tree_view), "");
+
+      hildon_tree_view_setup_row_header_layout (tree_view);
+    }
+  else if (!func && tree_view->priv->row_header_layout)
+    {
+      g_object_unref (tree_view->priv->row_header_layout);
+      tree_view->priv->row_header_layout = NULL;
+    }
+
+  /* Have the tree recalculate heights */
+  _gtk_rbtree_mark_invalid (tree_view->priv->tree);
+  gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+}
+
   
 static void
 gtk_tree_view_grab_notify (GtkWidget *widget,
@@ -15156,6 +16251,21 @@
 
       if (tree_view->priv->rubber_band_status)
 	gtk_tree_view_stop_rubber_band (tree_view);
+
+      if (tree_view->priv->queued_expand_row)
+	{
+	  gtk_tree_row_reference_free (tree_view->priv->queued_expand_row);
+	  tree_view->priv->queued_expand_row = NULL;
+	}
+
+      if (tree_view->priv->queued_tapped_row)
+	{
+	  gtk_tree_row_reference_free (tree_view->priv->queued_tapped_row);
+	  tree_view->priv->queued_tapped_row = NULL;
+	}
+
+      free_queued_select_row (tree_view);
+      free_queued_activate_row (tree_view);
     }
 }
 
@@ -15755,5 +16865,373 @@
   return tree_view->priv->tooltip_column;
 }
 
+static gboolean
+gtk_tree_view_tap_and_hold_query (GtkWidget *widget,
+				  GdkEvent  *event)
+{
+  GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
+  GtkTreePath *path;
+  GtkRBTree *tree = NULL;
+  GtkRBNode *node = NULL;
+  gdouble x, y;
+  gint new_y;
+  gboolean sensitive;
+
+  if (!tree_view->priv->tree)
+    return FALSE;
+
+  if (!gdk_event_get_coords (event, &x, &y))
+    return FALSE;
+
+  new_y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y);
+  if (new_y < 0)
+    new_y = 0;
+  _gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
+  if (node == NULL)
+    return TRUE;
+
+  path = _gtk_tree_view_find_path (tree_view, tree, node);
+
+  if (tree_view->priv->hildon_mode == HILDON_FREMANTLE
+      && tree_view->priv->hildon_ui_mode == HILDON_UI_MODE_NORMAL)
+    {
+      /* The normal mode has no notion of selection, so we special-case
+       * it here.
+       */
+      sensitive = !row_is_separator (tree_view, NULL, NULL, path);
+    }
+  else
+    {
+      sensitive = _gtk_tree_selection_row_is_selectable (tree_view->priv->selection,
+							 node, path);
+    }
+
+  gtk_tree_path_free (path);
+
+  return !sensitive;
+}
+
+static void
+free_queued_select_row (GtkTreeView *tree_view)
+{
+  /* We only clear the selected flag (used for highlight) if the node
+   * was previously *not* selected.
+   */
+  if (tree_view->priv->hildon_mode == HILDON_FREMANTLE
+      && gtk_tree_row_reference_valid (tree_view->priv->queued_select_row))
+    {
+      if (tree_view->priv->highlighted_node)
+	{
+	  _gtk_tree_view_queue_draw_node (tree_view,
+					  tree_view->priv->highlighted_tree,
+					  tree_view->priv->highlighted_node,
+					  NULL);
+
+	  tree_view->priv->highlighted_tree = NULL;
+	  tree_view->priv->highlighted_node = NULL;
+	}
+    }
+
+  gtk_tree_row_reference_free (tree_view->priv->queued_select_row);
+  tree_view->priv->queued_select_row = NULL;
+}
+
+static void
+free_queued_activate_row (GtkTreeView *tree_view)
+{
+  if (tree_view->priv->hildon_mode == HILDON_FREMANTLE
+      && tree_view->priv->hildon_ui_mode == HILDON_UI_MODE_NORMAL
+      && gtk_tree_row_reference_valid (tree_view->priv->queued_activate_row))
+    {
+      if (tree_view->priv->highlighted_node)
+	{
+	  _gtk_tree_view_queue_draw_node (tree_view,
+					  tree_view->priv->highlighted_tree,
+					  tree_view->priv->highlighted_node,
+					  NULL);
+
+	  tree_view->priv->highlighted_tree = NULL;
+	  tree_view->priv->highlighted_node = NULL;
+	}
+    }
+
+  gtk_tree_row_reference_free (tree_view->priv->queued_activate_row);
+  tree_view->priv->queued_activate_row = NULL;
+}
+
+static void
+free_queued_actions (GtkTreeView *tree_view)
+{
+  free_queued_activate_row (tree_view);
+  free_queued_select_row (tree_view);
+
+  gtk_tree_row_reference_free (tree_view->priv->queued_expand_row);
+  tree_view->priv->queued_expand_row = NULL;
+
+  gtk_tree_row_reference_free (tree_view->priv->queued_tapped_row);
+  tree_view->priv->queued_tapped_row = NULL;
+}
+
+HildonUIMode
+hildon_tree_view_get_hildon_ui_mode (GtkTreeView *tree_view)
+{
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), 0);
+
+  return tree_view->priv->hildon_ui_mode;
+}
+
+void
+hildon_tree_view_set_hildon_ui_mode (GtkTreeView   *tree_view,
+				     HildonUIMode   hildon_ui_mode)
+{
+  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+
+  /* Don't check if the new mode matches the old mode; always continue
+   * so that the selection corrections below always happen.
+   */
+  tree_view->priv->hildon_ui_mode = hildon_ui_mode;
+
+  if (tree_view->priv->hildon_mode == HILDON_DIABLO)
+    return;
+
+  /* For both normal and edit mode a couple of things are disabled. */
+
+  /* Mode-specific settings */
+  if (hildon_ui_mode == HILDON_UI_MODE_NORMAL)
+    {
+      gtk_tree_selection_set_mode (tree_view->priv->selection,
+				   GTK_SELECTION_NONE);
+    }
+  else if (hildon_ui_mode == HILDON_UI_MODE_EDIT)
+    {
+      if (gtk_tree_selection_get_mode (tree_view->priv->selection) == GTK_SELECTION_NONE)
+	{
+	  gtk_tree_selection_set_mode (tree_view->priv->selection,
+				       GTK_SELECTION_SINGLE);
+	}
+
+      if (tree_view->priv->selection->type != GTK_SELECTION_MULTIPLE
+	  && gtk_tree_selection_count_selected_rows (tree_view->priv->selection) < 1)
+	{
+	  GtkTreePath *path;
+
+	  /* Select the first item */
+	  path = gtk_tree_path_new_first ();
+	  search_first_focusable_path (tree_view, &path,
+				       TRUE, NULL, NULL);
+	  gtk_tree_selection_select_path (tree_view->priv->selection, path);
+	  gtk_tree_path_free (path);
+	}
+    }
+  else
+    g_assert_not_reached ();
+}
+
+static void
+hildon_tree_view_set_rows_offset (GtkTreeView *tree_view,
+				  int          rows_offset)
+{
+  if (tree_view->priv->rows_offset == rows_offset)
+    return;
+
+  tree_view->priv->rows_offset = rows_offset;
+  if (tree_view->priv->tree)
+    _gtk_rbtree_set_base_offset (tree_view->priv->tree, rows_offset);
+
+  gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+}
+
+static void
+hildon_tree_view_create_action_area (GtkTreeView *tree_view)
+{
+  /* gtk_tree_view_put() takes over ownership and so we do not
+   * have to unref these values in gtk_tree_view_destroy().
+   */
+  tree_view->priv->action_area_event_box = gtk_event_box_new ();
+  gtk_tree_view_put (tree_view, tree_view->priv->action_area_event_box,
+		     0, 0, 0, 0);
+
+  if (tree_view->priv->action_area_orientation == GTK_ORIENTATION_HORIZONTAL)
+    tree_view->priv->action_area_box = gtk_hbox_new (TRUE, 0);
+  else if (tree_view->priv->action_area_orientation == GTK_ORIENTATION_VERTICAL)
+    tree_view->priv->action_area_box = gtk_vbox_new (TRUE, 0);
+
+  gtk_container_add (GTK_CONTAINER (tree_view->priv->action_area_event_box),
+		     tree_view->priv->action_area_box);
+}
+
+static void
+hildon_tree_view_set_action_area_height (GtkTreeView *tree_view)
+{
+  if (tree_view->priv->action_area_orientation == GTK_ORIENTATION_HORIZONTAL)
+    {
+      int row_height;
+
+      gtk_widget_style_get (GTK_WIDGET (tree_view),
+			    "row-height", &row_height,
+			    NULL);
+      hildon_tree_view_set_rows_offset (tree_view, row_height);
+    }
+  else if (tree_view->priv->action_area_orientation == GTK_ORIENTATION_VERTICAL)
+    {
+      GList *children;
+
+      /* The height in portrait mode is currently hardcoded to 90px per
+       * button.
+       */
+      children = gtk_container_get_children (GTK_CONTAINER (tree_view->priv->action_area_box));
+      hildon_tree_view_set_rows_offset (tree_view,
+					g_list_length (children) * 90);
+      g_list_free (children);
+    }
+}
+
+void
+hildon_tree_view_set_action_area_visible (GtkTreeView *tree_view,
+					  gboolean     visible)
+{
+  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+
+  if (tree_view->priv->action_area_visible == !!visible)
+    return;
+
+  tree_view->priv->action_area_visible = visible;
+
+  if (visible)
+    {
+      hildon_tree_view_set_action_area_height (tree_view);
+
+      if (!tree_view->priv->action_area_event_box)
+	hildon_tree_view_create_action_area (tree_view);
+
+      gtk_widget_show (tree_view->priv->action_area_box);
+      gtk_widget_show (tree_view->priv->action_area_event_box);
+    }
+  else
+    {
+      gtk_widget_hide (tree_view->priv->action_area_event_box);
+
+      hildon_tree_view_set_rows_offset (tree_view, 0);
+    }
+}
+
+gboolean
+hildon_tree_view_get_action_area_visible (GtkTreeView *tree_view)
+{
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
+
+  return tree_view->priv->action_area_visible;
+}
+
+static void
+hildon_tree_view_rotate_action_area_box (GtkBox *old_box,
+					 GtkBox *new_box)
+{
+  int spacing, border_width;
+  GList *children, *child;
+  gboolean homogeneous;
+
+  g_object_get (old_box,
+		"homogeneous", &homogeneous,
+		"spacing", &spacing,
+		"border-width", &border_width,
+		NULL);
+
+  g_object_set (new_box,
+		"homogeneous", homogeneous,
+		"spacing", spacing,
+		"border-width", border_width,
+		NULL);
+
+  children = gtk_container_get_children (GTK_CONTAINER (old_box));
+  for (child = children; child; child = child->next)
+    {
+      guint padding;
+      gboolean expand, fill;
+      GtkPackType type;
+      GtkWidget *widget = child->data;
+
+      g_object_ref (widget);
+      gtk_box_query_child_packing (old_box, widget,
+				   &expand, &fill, &padding, &type);
+      gtk_container_remove (GTK_CONTAINER (old_box), widget);
+      gtk_container_add (GTK_CONTAINER (new_box), widget);
+      gtk_box_set_child_packing (new_box, widget,
+				 expand, fill, padding, type);
+      g_object_unref (widget);
+    }
+
+  g_list_free (children);
+
+  if (gtk_widget_get_visible (GTK_WIDGET (old_box)))
+    gtk_widget_show (GTK_WIDGET (new_box));
+}
+
+void
+hildon_tree_view_set_action_area_orientation (GtkTreeView    *tree_view,
+					      GtkOrientation  orientation)
+{
+  GtkWidget *old_box;
+  GtkWidget *new_box;
+
+  g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+
+  if (tree_view->priv->action_area_orientation == orientation)
+    return;
+
+  tree_view->priv->action_area_orientation = orientation;
+
+  old_box = tree_view->priv->action_area_box;
+  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+    new_box = gtk_hbox_new (TRUE, 0);
+  else if (orientation == GTK_ORIENTATION_VERTICAL)
+    new_box = gtk_vbox_new (TRUE, 0);
+
+  if (tree_view->priv->action_area_visible)
+    hildon_tree_view_set_action_area_height (tree_view);
+
+  hildon_tree_view_rotate_action_area_box (GTK_BOX (old_box),
+					   GTK_BOX (new_box));
+
+  gtk_widget_destroy (old_box);
+
+  tree_view->priv->action_area_box = new_box;
+  gtk_container_add (GTK_CONTAINER (tree_view->priv->action_area_event_box),
+		     tree_view->priv->action_area_box);
+}
+
+GtkOrientation
+hildon_tree_view_get_action_area_orientation (GtkTreeView *tree_view)
+{
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), 0);
+
+  return tree_view->priv->action_area_orientation;
+}
+
+/**
+ * hildon_tree_view_get_action_area_box:
+ * @tree_view: a #GtkTreeView
+ *
+ * Returns the GtkBox is embedded in GtkTreeView's action area.  Depending
+ * on the setting of the GtkTreeView:action-area-orientation property
+ * this is either a GtkHBox or GtkVBox.  You do not own a reference to
+ * the returned widget and thus this value should not be unreferenced.
+ *
+ * Returns: a pointer to a GtkBox.  This pointer should not be unreferenced.
+ *
+ * Since: maemo 5.0
+ * Stability: unstable
+ */
+GtkWidget *
+hildon_tree_view_get_action_area_box (GtkTreeView *tree_view)
+{
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
+
+  if (!tree_view->priv->action_area_event_box)
+    hildon_tree_view_create_action_area (tree_view);
+
+  return tree_view->priv->action_area_box;
+}
+
 #define __GTK_TREE_VIEW_C__
 #include "gtkaliasdef.c"
--- a/gtk/gtktreeview.h
+++ b/gtk/gtktreeview.h
@@ -111,7 +111,8 @@
   void (*_gtk_reserved1) (void);
   void (*_gtk_reserved2) (void);
   void (*_gtk_reserved3) (void);
-  void (*_gtk_reserved4) (void);
+  void (* row_insensitive)                (GtkTreeView       *tree_view,
+					   GtkTreePath *path);
 };
 
 
@@ -134,7 +135,10 @@
 typedef void     (*GtkTreeViewSearchPositionFunc) (GtkTreeView  *tree_view,
 						   GtkWidget    *search_dialog,
 						   gpointer      user_data);
-
+typedef gboolean (*HildonTreeViewRowHeaderFunc) (GtkTreeModel      *model,
+						 GtkTreeIter       *iter,
+						 gchar            **header_text,
+						 gpointer data);
 
 /* Creators */
 GType                  gtk_tree_view_get_type                      (void) G_GNUC_CONST;
@@ -392,6 +396,27 @@
 								  gpointer                    data,
 								  GDestroyNotify              destroy);
 
+HildonTreeViewRowHeaderFunc hildon_tree_view_get_row_header_func (GtkTreeView                 *tree_view);
+void                        hildon_tree_view_set_row_header_func (GtkTreeView                 *tree_view,
+								  HildonTreeViewRowHeaderFunc  func,
+								  gpointer                     data,
+								  GDestroyNotify               destroy);
+
+HildonUIMode                hildon_tree_view_get_hildon_ui_mode  (GtkTreeView                 *tree_view);
+void                        hildon_tree_view_set_hildon_ui_mode  (GtkTreeView                 *tree_view,
+								  HildonUIMode                 mode);
+
+
+void                        hildon_tree_view_set_action_area_visible       (GtkTreeView    *tree_view,
+									    gboolean        visible);
+gboolean                    hildon_tree_view_get_action_area_visible       (GtkTreeView    *tree_view);
+
+void                        hildon_tree_view_set_action_area_orientation   (GtkTreeView    *tree_view,
+									    GtkOrientation  orientation);
+GtkOrientation              hildon_tree_view_get_action_area_orientation   (GtkTreeView    *tree_view);
+
+GtkWidget *hildon_tree_view_get_action_area_box (GtkTreeView *tree_view);
+
 GtkTreeViewGridLines        gtk_tree_view_get_grid_lines         (GtkTreeView                *tree_view);
 void                        gtk_tree_view_set_grid_lines         (GtkTreeView                *tree_view,
 								  GtkTreeViewGridLines        grid_lines);
--- a/gtk/gtktreeprivate.h
+++ b/gtk/gtktreeprivate.h
@@ -28,7 +28,7 @@
 #include <gtk/gtktreeselection.h>
 #include <gtk/gtkrbtree.h>
 
-#define TREE_VIEW_DRAG_WIDTH 6
+#define TREE_VIEW_DRAG_WIDTH 28
 
 typedef enum
 {
@@ -300,6 +300,37 @@
 
   /* Whether our key press handler is to avoid sending an unhandled binding to the search entry */
   guint search_entry_avoid_unhandled_binding : 1;
+
+  /* Fields for Maemo specific functionality */
+  GtkTreeRowReference *queued_select_row;
+  GtkTreeRowReference *queued_expand_row;
+  GtkTreeRowReference *queued_activate_row;
+  GtkTreeRowReference *queued_tapped_row;
+
+  GtkRBNode *highlighted_node;
+  GtkRBTree *highlighted_tree;
+
+  GtkTreeCellDataHint cell_data_hint;
+
+  HildonUIMode hildon_ui_mode;
+  HildonMode hildon_mode;
+
+  GdkPixbuf *tickmark_icon;
+
+  HildonTreeViewRowHeaderFunc row_header_func;
+  gpointer row_header_data;
+  GDestroyNotify row_header_destroy;
+  PangoLayout *row_header_layout;
+
+  gint rows_offset;
+  GtkOrientation action_area_orientation;
+  GtkWidget *action_area_event_box;
+  GtkWidget *action_area_box;
+
+  guint queued_shift_pressed : 1;
+  guint queued_ctrl_pressed : 1;
+
+  guint action_area_visible : 1;
 };
 
 #ifdef __GNUC__
--- a/gtk/gtktreeviewcolumn.c
+++ b/gtk/gtktreeviewcolumn.c
@@ -851,7 +851,7 @@
 		    G_CALLBACK (gtk_tree_view_column_button_clicked),
 		    tree_column);
 
-  tree_column->alignment = gtk_alignment_new (tree_column->xalign, 0.5, 0.0, 0.0);
+  tree_column->alignment = gtk_alignment_new (tree_column->xalign, 0.5, 1.0, 1.0);
 
   hbox = gtk_hbox_new (FALSE, 2);
   tree_column->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
@@ -916,7 +916,7 @@
 
   /* Set up the actual button */
   gtk_alignment_set (GTK_ALIGNMENT (alignment), tree_column->xalign,
-		     0.5, 0.0, 0.0);
+		     0.5, 1.0, 1.0);
       
   if (tree_column->child)
     {
@@ -926,6 +926,7 @@
 				current_child);
 	  gtk_container_add (GTK_CONTAINER (alignment),
 			     tree_column->child);
+	  current_child = tree_column->child;
 	}
     }
   else 
@@ -948,6 +949,14 @@
 					  "");
     }
 
+  if (GTK_IS_MISC (current_child))
+    {
+      gfloat yalign;
+
+      gtk_misc_get_alignment (GTK_MISC (current_child), NULL, &yalign);
+      gtk_misc_set_alignment (GTK_MISC (current_child), tree_column->xalign, yalign);
+    }
+
   if (GTK_IS_TREE_SORTABLE (model))
     gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model),
 					  &sort_column_id,
@@ -2536,6 +2545,100 @@
 }
 
 /**
+ * gtk_tree_view_column_cell_set_cell_data_with_hint:
+ * @tree_column: A #GtkTreeViewColumn.
+ * @tree_model: The #GtkTreeModel to to get the cell renderers attributes from.
+ * @iter: The #GtkTreeIter to to get the cell renderer's attributes from.
+ * @is_expander: %TRUE, if the row has children
+ * @is_expanded: %TRUE, if the row has visible children
+ * @hint: A #GtkTreeCellDataHint for the #GtkTreeCellDataFunc.
+ *
+ * Sets the cell renderer based on the @tree_model and @iter.  That is, for
+ * every attribute mapping in @tree_column, it will get a value from the set
+ * column on the @iter, and use that value to set the attribute on the cell
+ * renderer.  The @hint is a hint for the #GtkTreeCellDataFunc so that it does not
+ * have to set all cell renderer properties, possible leading to some
+ * optimizations.  This is used primarily by the #GtkTreeView.
+ *
+ * Since: maemo 4.0
+ * Stability: Unstable
+ **/
+void
+gtk_tree_view_column_cell_set_cell_data_with_hint (GtkTreeViewColumn   *tree_column,
+						   GtkTreeModel        *tree_model,
+						   GtkTreeIter         *iter,
+						   gboolean             is_expander,
+						   gboolean             is_expanded,
+						   GtkTreeCellDataHint  hint)
+{
+  GSList *list;
+  GValue value = { 0, };
+  GList *cell_list;
+
+  g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
+
+  if (tree_model == NULL)
+    return;
+
+  GTK_TREE_VIEW (tree_column->tree_view)->priv->cell_data_hint = hint;
+
+  for (cell_list = tree_column->cell_list; cell_list; cell_list = cell_list->next)
+    {
+      GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) cell_list->data;
+      GObject *cell = (GObject *) info->cell;
+
+      list = info->attributes;
+
+      g_object_freeze_notify (cell);
+
+      if (info->cell->is_expander != is_expander)
+	g_object_set (cell, "is-expander", is_expander, NULL);
+
+      if (info->cell->is_expanded != is_expanded)
+	g_object_set (cell, "is-expanded", is_expanded, NULL);
+
+      while (list && list->next)
+	{
+	  gtk_tree_model_get_value (tree_model, iter,
+				    GPOINTER_TO_INT (list->next->data),
+				    &value);
+	  g_object_set_property (cell, (gchar *) list->data, &value);
+	  g_value_unset (&value);
+	  list = list->next->next;
+	}
+
+      if (info->func)
+	(* info->func) (tree_column, info->cell, tree_model, iter, info->func_data);
+      g_object_thaw_notify (G_OBJECT (info->cell));
+    }
+}
+
+/**
+ * gtk_tree_view_column_get_cell_data_hint:
+ * @tree_column: A #GtkTreeViewColumn.
+ *
+ * Returns the current value of the cell data hint as a
+ * #GtkTreeCellDataHint.  Note that the value returned is only
+ * valid when called from a #GtkTreeCellDataFunc.  The value of the hint
+ * tells you why the #GtkTreeView is calling the #GtkTreeCellDataFunc.
+ * Based on this hint, you can omit to generate the data and set certain
+ * cell renderer properties to improve performance.
+ *
+ * Return value: A #GtkTreeCellDataHint with the hint.
+ *
+ * Since: maemo 4.0
+ * Stability: Unstable
+ */
+GtkTreeCellDataHint
+gtk_tree_view_column_get_cell_data_hint (GtkTreeViewColumn *tree_column)
+{
+  g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
+  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_column->tree_view), 0);
+
+  return GTK_TREE_VIEW (tree_column->tree_view)->priv->cell_data_hint;
+}
+
+/**
  * gtk_tree_view_column_cell_set_cell_data:
  * @tree_column: A #GtkTreeViewColumn.
  * @tree_model: The #GtkTreeModel to to get the cell renderers attributes from.
@@ -2564,6 +2667,8 @@
   if (tree_model == NULL)
     return;
 
+  GTK_TREE_VIEW (tree_column->tree_view)->priv->cell_data_hint = GTK_TREE_CELL_DATA_HINT_ALL;
+
   for (cell_list = tree_column->cell_list; cell_list; cell_list = cell_list->next)
     {
       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) cell_list->data;
--- a/gtk/gtktreeviewcolumn.h
+++ b/gtk/gtktreeviewcolumn.h
@@ -238,6 +238,25 @@
 void                    gtk_tree_view_column_queue_resize        (GtkTreeViewColumn       *tree_column);
 GtkWidget              *gtk_tree_view_column_get_tree_view       (GtkTreeViewColumn       *tree_column);
 
+/**
+ * GtkTreeCellDataHint:
+ *
+ * See gtk_tree_view_column_get_cell_data_hint().
+ **/
+typedef enum
+{
+  GTK_TREE_CELL_DATA_HINT_ALL,
+  GTK_TREE_CELL_DATA_HINT_KEY_FOCUS,
+  GTK_TREE_CELL_DATA_HINT_SENSITIVITY
+} GtkTreeCellDataHint;
+
+void                       gtk_tree_view_column_cell_set_cell_data_with_hint (GtkTreeViewColumn          *tree_column,
+									      GtkTreeModel               *tree_model,
+									      GtkTreeIter                *iter,
+									      gboolean                    is_expander,
+									      gboolean                    is_expanded,
+									      GtkTreeCellDataHint  hint);
+GtkTreeCellDataHint gtk_tree_view_column_get_cell_data_hint (GtkTreeViewColumn *tree_column);
 
 G_END_DECLS
 
--- a/gtk/gtktreeselection.c
+++ b/gtk/gtktreeselection.c
@@ -25,6 +25,7 @@
 #include "gtkmarshalers.h"
 #include "gtkintl.h"
 #include "gtkalias.h"
+#include "gtkcelllayout.h"
 
 static void gtk_tree_selection_finalize          (GObject               *object);
 static gint gtk_tree_selection_real_select_all   (GtkTreeSelection      *selection);
@@ -160,12 +161,24 @@
 			     GtkSelectionMode  type)
 {
   GtkTreeSelectionFunc tmp_func;
+  HildonMode mode;
   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
 
   if (selection->type == type)
     return;
 
-  
+  gtk_widget_style_get (GTK_WIDGET (selection->tree_view),
+			"hildon-mode", &mode,
+			NULL);
+
+  if (mode == HILDON_FREMANTLE
+      && selection->tree_view->priv->hildon_ui_mode == HILDON_UI_MODE_NORMAL
+      && type != GTK_SELECTION_NONE)
+    {
+      g_warning ("Cannot change the selection mode to anything other than GTK_SELECTION_NONE if hildon-ui-mode is GTK_HILDON_UI_MODE_NORMAL.\n");
+      return;
+    }
+
   if (type == GTK_SELECTION_NONE)
     {
       /* We do this so that we unconditionally unset all rows
@@ -202,6 +215,47 @@
             }
 	}
 
+      if (!selected
+	   && mode == HILDON_FREMANTLE
+	   && selection->tree_view->priv->hildon_ui_mode == HILDON_UI_MODE_EDIT)
+	 {
+	   GList *rows;
+
+	   /* One item must stay selected; we look for the first selected
+	    * item we can find, that one becomes the anchor.  We silently
+	    * assume here that there is at least *one* selected row,
+	    * as mandated by any new-style edit mode.  When switching
+	    * from SELECTION_NONE there is no selected row, and the
+	    * tree view will be responsible for selecting a node.
+	    */
+
+	   if (anchor_path)
+	     gtk_tree_path_free (anchor_path);
+
+	   /* FIXME: this can be obviously optimized by walking
+	    * the selection tree ourselves; or probably having a _real
+	    * variant of _get_selected_rows() that we can tell to stop
+	    * as soon as a selected node is found.
+	    */
+	   rows = gtk_tree_selection_get_selected_rows (selection, NULL);
+	   if (rows)
+	     {
+	       anchor_path = gtk_tree_path_copy (rows->data);
+	       g_list_foreach (rows, (GFunc)gtk_tree_path_free, NULL);
+	       g_list_free (rows);
+
+	       _gtk_tree_view_find_node (selection->tree_view,
+					 anchor_path,
+					 &tree,
+					 &node);
+
+	       if (node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
+		 selected = TRUE;
+
+	       g_return_if_fail (selected == TRUE);
+	     }
+	}
+
       /* We do this so that we unconditionally unset all rows
        */
       tmp_func = selection->user_func;
@@ -221,6 +275,23 @@
     }
 
   selection->type = type;
+
+  if (type == GTK_SELECTION_SINGLE
+      || type == GTK_SELECTION_BROWSE)
+    {
+      GtkTreeIter iter;
+
+      /* Make sure the cursor is on a selected node */
+      if (gtk_tree_selection_get_selected (selection, NULL, &iter))
+	{
+	  GtkTreePath *path;
+
+	  path = gtk_tree_model_get_path (selection->tree_view->priv->model,
+					  &iter);
+	  gtk_tree_view_set_cursor (selection->tree_view, path, NULL, FALSE);
+	  gtk_tree_path_free (path);
+	}
+    }
 }
 
 /**
@@ -1249,6 +1320,39 @@
     g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
 }
 
+static gboolean
+tree_column_is_sensitive (GtkTreeViewColumn *column,
+			  GtkTreeModel      *model,
+			  GtkTreeIter       *iter)
+{
+  GList *cells, *list;
+  gboolean sensitive = TRUE;
+  gboolean visible;
+
+  gtk_tree_view_column_cell_set_cell_data_with_hint (column, model,
+						     iter, FALSE, FALSE,
+						     GTK_TREE_CELL_DATA_HINT_SENSITIVITY);
+
+  cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+
+  list = cells;
+  while (list)
+    {
+      g_object_get (list->data,
+		    "sensitive", &sensitive,
+		    "visible", &visible,
+		    NULL);
+
+      if (visible && sensitive)
+	break;
+
+      list = list->next;
+    }
+  g_list_free (cells);
+
+  return sensitive;
+}
+
 gboolean
 _gtk_tree_selection_row_is_selectable (GtkTreeSelection *selection,
 				       GtkRBNode        *node,
@@ -1256,6 +1360,17 @@
 {
   GtkTreeIter iter;
   gboolean sensitive = FALSE;
+  GList *list;
+  HildonMode mode;
+
+  gtk_widget_style_get (GTK_WIDGET (selection->tree_view),
+			"hildon-mode", &mode,
+			NULL);
+
+  /* normal-mode does not support selections */
+  if (mode == HILDON_FREMANTLE
+      && selection->tree_view->priv->hildon_ui_mode == HILDON_UI_MODE_NORMAL)
+    return FALSE;
 
   if (!gtk_tree_model_get_iter (selection->tree_view->priv->model, &iter, path))
     sensitive = TRUE;
@@ -1269,6 +1384,29 @@
 	return FALSE;
     }
 
+  if (!sensitive && selection->tree_view->priv->row_header_func)
+    {
+      /* never allow separators to be selected */
+      if ((* selection->tree_view->priv->row_header_func) (selection->tree_view->priv->model,
+							   &iter,
+							   NULL,
+							   selection->tree_view->priv->row_header_data))
+	return FALSE;
+    }
+
+  for (list = selection->tree_view->priv->columns; list && !sensitive; list = list->next)
+    {
+      GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (list->data);
+
+      if (!column->visible)
+	continue;
+
+      sensitive = tree_column_is_sensitive (column, selection->tree_view->priv->model, &iter);
+    }
+
+  if (!sensitive)
+    return FALSE;
+
   if (selection->user_func)
     return (*selection->user_func) (selection, selection->tree_view->priv->model, path,
 				    GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED),
@@ -1453,6 +1591,11 @@
       path = _gtk_tree_view_find_path (selection->tree_view, tree, node);
       toggle = _gtk_tree_selection_row_is_selectable (selection, node, path);
       gtk_tree_path_free (path);
+
+      /* Allow unselecting an insensitive row */
+      if (!toggle && !select
+	  && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
+	toggle = TRUE;
     }
 
   if (toggle)
