treeview: Replace cursor handling by keeping the node

Previously the code used a GtkTreeRowReference, which was (a) less
performant and more importantly (b) hiding errors.
The errors being hidden were the referenced row becoming invalid or
collapsed, because such rows would not be valid cursor rows and it would
be necesary to select a new row and emit a "cursor-changed" signal.

So if a crash bisects down to this commit, it is very likely that the
cursor has not correctly been updated and the cursor row is invalid.
This commit is contained in:
Benjamin Otte
2011-12-10 02:06:33 +01:00
parent 2a59265df1
commit e01af5c5c9

View File

@ -317,7 +317,8 @@ struct _GtkTreeViewPrivate
gint cursor_offset; gint cursor_offset;
GtkTreeRowReference *anchor; GtkTreeRowReference *anchor;
GtkTreeRowReference *cursor; GtkRBNode *cursor_node;
GtkRBTree *cursor_tree;
GtkTreeViewColumn *focus_column; GtkTreeViewColumn *focus_column;
@ -2055,9 +2056,6 @@ gtk_tree_view_destroy (GtkWidget *widget)
tree_view->priv->destroy_count_data = NULL; tree_view->priv->destroy_count_data = NULL;
} }
gtk_tree_row_reference_free (tree_view->priv->cursor);
tree_view->priv->cursor = NULL;
gtk_tree_row_reference_free (tree_view->priv->anchor); gtk_tree_row_reference_free (tree_view->priv->anchor);
tree_view->priv->anchor = NULL; tree_view->priv->anchor = NULL;
@ -4678,8 +4676,6 @@ gtk_tree_view_bin_draw (GtkWidget *widget,
GtkRBTree *tree; GtkRBTree *tree;
GList *list; GList *list;
GtkRBNode *node; GtkRBNode *node;
GtkRBNode *cursor = NULL;
GtkRBTree *cursor_tree = NULL;
GtkRBNode *drag_highlight = NULL; GtkRBNode *drag_highlight = NULL;
GtkRBTree *drag_highlight_tree = NULL; GtkRBTree *drag_highlight_tree = NULL;
GtkTreeIter iter; GtkTreeIter iter;
@ -4695,7 +4691,6 @@ gtk_tree_view_bin_draw (GtkWidget *widget,
gint expander_cell_width; gint expander_cell_width;
gint bin_window_width; gint bin_window_width;
gint bin_window_height; gint bin_window_height;
GtkTreePath *cursor_path;
GtkTreePath *drag_dest_path; GtkTreePath *drag_dest_path;
GList *first_column, *last_column; GList *first_column, *last_column;
gint vertical_separator; gint vertical_separator;
@ -4766,16 +4761,8 @@ gtk_tree_view_bin_draw (GtkWidget *widget,
depth = gtk_tree_path_get_depth (path); depth = gtk_tree_path_get_depth (path);
gtk_tree_path_free (path); gtk_tree_path_free (path);
cursor_path = NULL;
drag_dest_path = NULL; drag_dest_path = NULL;
if (tree_view->priv->cursor)
cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
if (cursor_path)
_gtk_tree_view_find_node (tree_view, cursor_path,
&cursor_tree, &cursor);
if (tree_view->priv->drag_dest_row) if (tree_view->priv->drag_dest_row)
drag_dest_path = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row); drag_dest_path = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
@ -4895,7 +4882,7 @@ gtk_tree_view_bin_draw (GtkWidget *widget,
else else
flags &= ~GTK_CELL_RENDERER_SORTED; flags &= ~GTK_CELL_RENDERER_SORTED;
if (cursor == node) if (tree_view->priv->cursor_node == node)
flags |= GTK_CELL_RENDERER_FOCUSED; flags |= GTK_CELL_RENDERER_FOCUSED;
else else
flags &= ~GTK_CELL_RENDERER_FOCUSED; flags &= ~GTK_CELL_RENDERER_FOCUSED;
@ -4984,7 +4971,7 @@ gtk_tree_view_bin_draw (GtkWidget *widget,
gtk_style_context_add_region (context, GTK_STYLE_REGION_ROW, row_flags); gtk_style_context_add_region (context, GTK_STYLE_REGION_ROW, row_flags);
gtk_style_context_add_region (context, GTK_STYLE_REGION_COLUMN, column_flags); gtk_style_context_add_region (context, GTK_STYLE_REGION_COLUMN, column_flags);
if (node == cursor && has_can_focus_cell if (node == tree_view->priv->cursor_node && has_can_focus_cell
&& ((column == tree_view->priv->focus_column && ((column == tree_view->priv->focus_column
&& tree_view->priv->draw_keyfocus && && tree_view->priv->draw_keyfocus &&
gtk_widget_has_visible_focus (widget)) gtk_widget_has_visible_focus (widget))
@ -5224,7 +5211,7 @@ gtk_tree_view_bin_draw (GtkWidget *widget,
} }
/* draw the big row-spanning focus rectangle, if needed */ /* draw the big row-spanning focus rectangle, if needed */
if (!has_can_focus_cell && node == cursor && if (!has_can_focus_cell && node == tree_view->priv->cursor_node &&
tree_view->priv->draw_keyfocus && tree_view->priv->draw_keyfocus &&
gtk_widget_has_visible_focus (widget)) gtk_widget_has_visible_focus (widget))
{ {
@ -5317,9 +5304,6 @@ done:
if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE) if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
gtk_tree_view_paint_rubber_band (tree_view, cr); gtk_tree_view_paint_rubber_band (tree_view, cr);
if (cursor_path)
gtk_tree_path_free (cursor_path);
if (drag_dest_path) if (drag_dest_path)
gtk_tree_path_free (drag_dest_path); gtk_tree_path_free (drag_dest_path);
@ -8712,8 +8696,9 @@ gtk_tree_view_row_changed (GtkTreeModel *model,
g_return_if_fail (path != NULL || iter != NULL); g_return_if_fail (path != NULL || iter != NULL);
if (tree_view->priv->cursor != NULL) if (tree_view->priv->cursor_node != NULL)
cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); cursor_path = _gtk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
tree_view->priv->cursor_node);
else else
cursor_path = NULL; cursor_path = NULL;
@ -10057,8 +10042,9 @@ gtk_tree_view_focus_to_cursor (GtkTreeView *tree_view)
return; return;
cursor_path = NULL; cursor_path = NULL;
if (tree_view->priv->cursor) if (tree_view->priv->cursor_node)
cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); cursor_path = _gtk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
tree_view->priv->cursor_node);
if (cursor_path == NULL) if (cursor_path == NULL)
{ {
@ -10085,9 +10071,6 @@ gtk_tree_view_focus_to_cursor (GtkTreeView *tree_view)
TRUE, NULL, NULL); TRUE, NULL, NULL);
} }
gtk_tree_row_reference_free (tree_view->priv->cursor);
tree_view->priv->cursor = NULL;
if (cursor_path) if (cursor_path)
{ {
if (gtk_tree_selection_get_mode (tree_view->priv->selection) == GTK_SELECTION_MULTIPLE) if (gtk_tree_selection_get_mode (tree_view->priv->selection) == GTK_SELECTION_MULTIPLE)
@ -10139,8 +10122,6 @@ gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view,
gint count) gint count)
{ {
gint selection_count; gint selection_count;
GtkRBTree *cursor_tree = NULL;
GtkRBNode *cursor_node = NULL;
GtkRBTree *new_cursor_tree = NULL; GtkRBTree *new_cursor_tree = NULL;
GtkRBNode *new_cursor_node = NULL; GtkRBNode *new_cursor_node = NULL;
GtkTreePath *cursor_path = NULL; GtkTreePath *cursor_path = NULL;
@ -10154,18 +10135,11 @@ gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view,
if (! gtk_widget_has_focus (GTK_WIDGET (tree_view))) if (! gtk_widget_has_focus (GTK_WIDGET (tree_view)))
return; return;
cursor_path = NULL; if (tree_view->priv->cursor_node == NULL)
if (!gtk_tree_row_reference_valid (tree_view->priv->cursor))
/* FIXME: we lost the cursor; should we get the first? */
return; return;
cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); cursor_path = _gtk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
_gtk_tree_view_find_node (tree_view, cursor_path, tree_view->priv->cursor_node);
&cursor_tree, &cursor_node);
if (cursor_tree == NULL)
/* FIXME: we lost the cursor; should we get the first? */
return;
direction = count < 0 ? GTK_DIR_UP : GTK_DIR_DOWN; direction = count < 0 ? GTK_DIR_UP : GTK_DIR_DOWN;
@ -10178,9 +10152,9 @@ gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view,
{ {
gtk_tree_view_column_cell_set_cell_data (tree_view->priv->focus_column, gtk_tree_view_column_cell_set_cell_data (tree_view->priv->focus_column,
tree_view->priv->model, tree_view->priv->model,
&iter, &iter,
GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT), GTK_RBNODE_FLAG_SET (tree_view->priv->cursor_node, GTK_RBNODE_IS_PARENT),
cursor_node->children?TRUE:FALSE); tree_view->priv->cursor_node->children ? TRUE : FALSE);
/* Save the last cell that had focus, if we hit the end of the view we'll give /* Save the last cell that had focus, if we hit the end of the view we'll give
* focus back to it. */ * focus back to it. */
@ -10193,7 +10167,7 @@ gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view,
selection_count = gtk_tree_selection_count_selected_rows (tree_view->priv->selection); selection_count = gtk_tree_selection_count_selected_rows (tree_view->priv->selection);
selectable = _gtk_tree_selection_row_is_selectable (tree_view->priv->selection, selectable = _gtk_tree_selection_row_is_selectable (tree_view->priv->selection,
cursor_node, tree_view->priv->cursor_node,
cursor_path); cursor_path);
if (selection_count == 0 if (selection_count == 0
@ -10202,16 +10176,16 @@ gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view,
&& selectable) && selectable)
{ {
/* Don't move the cursor, but just select the current node */ /* Don't move the cursor, but just select the current node */
new_cursor_tree = cursor_tree; new_cursor_tree = tree_view->priv->cursor_tree;
new_cursor_node = cursor_node; new_cursor_node = tree_view->priv->cursor_node;
} }
else else
{ {
if (count == -1) if (count == -1)
_gtk_rbtree_prev_full (cursor_tree, cursor_node, _gtk_rbtree_prev_full (tree_view->priv->cursor_tree, tree_view->priv->cursor_node,
&new_cursor_tree, &new_cursor_node); &new_cursor_tree, &new_cursor_node);
else else
_gtk_rbtree_next_full (cursor_tree, cursor_node, _gtk_rbtree_next_full (tree_view->priv->cursor_tree, tree_view->priv->cursor_node,
&new_cursor_tree, &new_cursor_node); &new_cursor_tree, &new_cursor_node);
} }
@ -10238,20 +10212,21 @@ gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view,
new_cursor_node == NULL) new_cursor_node == NULL)
{ {
if (count == -1) if (count == -1)
_gtk_rbtree_next_full (cursor_tree, cursor_node, _gtk_rbtree_next_full (tree_view->priv->cursor_tree, tree_view->priv->cursor_node,
&new_cursor_tree, &new_cursor_node); &new_cursor_tree, &new_cursor_node);
else else
_gtk_rbtree_prev_full (cursor_tree, cursor_node, _gtk_rbtree_prev_full (tree_view->priv->cursor_tree, tree_view->priv->cursor_node,
&new_cursor_tree, &new_cursor_node); &new_cursor_tree, &new_cursor_node);
if (new_cursor_node == NULL if (new_cursor_node == NULL
&& !GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_SELECTED)) && !GTK_RBNODE_FLAG_SET (tree_view->priv->cursor_node, GTK_RBNODE_IS_SELECTED))
{ {
new_cursor_node = cursor_node; new_cursor_node = tree_view->priv->cursor_node;
new_cursor_tree = cursor_tree; new_cursor_tree = tree_view->priv->cursor_tree;
} }
else else
{ {
new_cursor_tree = NULL;
new_cursor_node = NULL; new_cursor_node = NULL;
} }
} }
@ -10268,7 +10243,9 @@ gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view,
} }
else else
{ {
gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node); gtk_tree_view_clamp_node_visible (tree_view,
tree_view->priv->cursor_tree,
tree_view->priv->cursor_node);
if (!tree_view->priv->extend_selection_pressed) if (!tree_view->priv->extend_selection_pressed)
{ {
@ -10304,12 +10281,12 @@ static void
gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view, gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
gint count) gint count)
{ {
GtkRBTree *cursor_tree = NULL;
GtkRBNode *cursor_node = NULL;
GtkTreePath *old_cursor_path = NULL; GtkTreePath *old_cursor_path = NULL;
GtkTreePath *cursor_path = NULL; GtkTreePath *cursor_path = NULL;
GtkRBTree *start_cursor_tree = NULL; GtkRBTree *start_cursor_tree = NULL;
GtkRBNode *start_cursor_node = NULL; GtkRBNode *start_cursor_node = NULL;
GtkRBTree *cursor_tree;
GtkRBNode *cursor_node;
gint y; gint y;
gint window_y; gint window_y;
gint vertical_separator; gint vertical_separator;
@ -10317,25 +10294,15 @@ gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
if (!gtk_widget_has_focus (GTK_WIDGET (tree_view))) if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
return; return;
if (gtk_tree_row_reference_valid (tree_view->priv->cursor)) if (tree_view->priv->cursor_node == NULL)
old_cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
else
/* This is sorta weird. Focus in should give us a cursor */
return; return;
old_cursor_path = _gtk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
tree_view->priv->cursor_node);
gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical-separator", &vertical_separator, NULL); gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical-separator", &vertical_separator, NULL);
_gtk_tree_view_find_node (tree_view, old_cursor_path,
&cursor_tree, &cursor_node);
if (cursor_tree == NULL) y = _gtk_rbtree_node_find_offset (tree_view->priv->cursor_tree, tree_view->priv->cursor_node);
{
/* FIXME: we lost the cursor. Should we try to get one? */
gtk_tree_path_free (old_cursor_path);
return;
}
g_return_if_fail (cursor_node != NULL);
y = _gtk_rbtree_node_find_offset (cursor_tree, cursor_node);
window_y = RBTREE_Y_TO_TREE_WINDOW_Y (tree_view, y); window_y = RBTREE_Y_TO_TREE_WINDOW_Y (tree_view, y);
y += tree_view->priv->cursor_offset; y += tree_view->priv->cursor_offset;
y += count * (int)gtk_adjustment_get_page_increment (tree_view->priv->vadjustment); y += count * (int)gtk_adjustment_get_page_increment (tree_view->priv->vadjustment);
@ -10413,8 +10380,6 @@ static void
gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view, gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
gint count) gint count)
{ {
GtkRBTree *cursor_tree = NULL;
GtkRBNode *cursor_node = NULL;
GtkTreePath *cursor_path = NULL; GtkTreePath *cursor_path = NULL;
GtkTreeViewColumn *column; GtkTreeViewColumn *column;
GtkTreeIter iter; GtkTreeIter iter;
@ -10431,14 +10396,12 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
if (!gtk_widget_has_focus (GTK_WIDGET (tree_view))) if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
return; return;
if (gtk_tree_row_reference_valid (tree_view->priv->cursor)) if (tree_view->priv->cursor_node == NULL)
cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
else
return; return;
_gtk_tree_view_find_node (tree_view, cursor_path, &cursor_tree, &cursor_node); cursor_path = _gtk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
if (cursor_tree == NULL) tree_view->priv->cursor_node);
return;
if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path) == FALSE) if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path) == FALSE)
{ {
gtk_tree_path_free (cursor_path); gtk_tree_path_free (cursor_path);
@ -10472,8 +10435,8 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
gtk_tree_view_column_cell_set_cell_data (column, gtk_tree_view_column_cell_set_cell_data (column,
tree_view->priv->model, tree_view->priv->model,
&iter, &iter,
GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT), GTK_RBNODE_FLAG_SET (tree_view->priv->cursor_node, GTK_RBNODE_IS_PARENT),
cursor_node->children?TRUE:FALSE); tree_view->priv->cursor_node->children ? TRUE : FALSE);
cell_area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (column)); cell_area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (column));
if (gtk_cell_area_focus (cell_area, direction)) if (gtk_cell_area_focus (cell_area, direction))
@ -10494,8 +10457,8 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
{ {
if (!gtk_tree_view_has_can_focus_cell (tree_view)) if (!gtk_tree_view_has_can_focus_cell (tree_view))
_gtk_tree_view_queue_draw_node (tree_view, _gtk_tree_view_queue_draw_node (tree_view,
cursor_tree, tree_view->priv->cursor_tree,
cursor_node, tree_view->priv->cursor_node,
NULL); NULL);
g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0); g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
gtk_widget_grab_focus (GTK_WIDGET (tree_view)); gtk_widget_grab_focus (GTK_WIDGET (tree_view));
@ -10621,12 +10584,12 @@ gtk_tree_view_real_select_cursor_row (GtkTreeView *tree_view,
if (!gtk_widget_has_focus (GTK_WIDGET (tree_view))) if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
return FALSE; return FALSE;
if (tree_view->priv->cursor) if (tree_view->priv->cursor_node == NULL)
cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
if (cursor_path == NULL)
return FALSE; return FALSE;
cursor_path = _gtk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
tree_view->priv->cursor_node);
_gtk_tree_view_find_node (tree_view, cursor_path, _gtk_tree_view_find_node (tree_view, cursor_path,
&cursor_tree, &cursor_node); &cursor_tree, &cursor_node);
@ -10693,20 +10656,11 @@ gtk_tree_view_real_toggle_cursor_row (GtkTreeView *tree_view)
if (!gtk_widget_has_focus (GTK_WIDGET (tree_view))) if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
return FALSE; return FALSE;
cursor_path = NULL; if (tree_view->priv->cursor_node == NULL)
if (tree_view->priv->cursor)
cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
if (cursor_path == NULL)
return FALSE; return FALSE;
_gtk_tree_view_find_node (tree_view, cursor_path, cursor_path = _gtk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
&cursor_tree, &cursor_node); tree_view->priv->cursor_node);
if (cursor_tree == NULL)
{
gtk_tree_path_free (cursor_path);
return FALSE;
}
_gtk_tree_selection_internal_select_node (tree_view->priv->selection, _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
cursor_node, cursor_node,
@ -10721,10 +10675,12 @@ gtk_tree_view_real_toggle_cursor_row (GtkTreeView *tree_view)
*/ */
_gtk_tree_view_find_node (tree_view, cursor_path, &new_tree, &new_node); _gtk_tree_view_find_node (tree_view, cursor_path, &new_tree, &new_node);
if (cursor_tree != new_tree || cursor_node != new_node) if (tree_view->priv->cursor_node != new_node)
return FALSE; return FALSE;
gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node); gtk_tree_view_clamp_node_visible (tree_view,
tree_view->priv->cursor_tree,
tree_view->priv->cursor_node);
gtk_widget_grab_focus (GTK_WIDGET (tree_view)); gtk_widget_grab_focus (GTK_WIDGET (tree_view));
gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL); gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
@ -10740,24 +10696,18 @@ gtk_tree_view_real_expand_collapse_cursor_row (GtkTreeView *tree_view,
gboolean open_all) gboolean open_all)
{ {
GtkTreePath *cursor_path = NULL; GtkTreePath *cursor_path = NULL;
GtkRBTree *tree;
GtkRBNode *node;
if (!gtk_widget_has_focus (GTK_WIDGET (tree_view))) if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
return FALSE; return FALSE;
cursor_path = NULL; if (tree_view->priv->cursor_node == NULL)
if (tree_view->priv->cursor)
cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
if (cursor_path == NULL)
return FALSE; return FALSE;
if (_gtk_tree_view_find_node (tree_view, cursor_path, &tree, &node)) cursor_path = _gtk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
return FALSE; tree_view->priv->cursor_node);
/* Don't handle the event if we aren't an expander */ /* Don't handle the event if we aren't an expander */
if (!((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT)) if (!GTK_RBNODE_FLAG_SET (tree_view->priv->cursor_node, GTK_RBNODE_IS_PARENT))
return FALSE; return FALSE;
if (!logical if (!logical
@ -10765,9 +10715,18 @@ gtk_tree_view_real_expand_collapse_cursor_row (GtkTreeView *tree_view,
expand = !expand; expand = !expand;
if (expand) if (expand)
gtk_tree_view_real_expand_row (tree_view, cursor_path, tree, node, open_all, TRUE); gtk_tree_view_real_expand_row (tree_view,
cursor_path,
tree_view->priv->cursor_tree,
tree_view->priv->cursor_node,
open_all,
TRUE);
else else
gtk_tree_view_real_collapse_row (tree_view, cursor_path, tree, node, TRUE); gtk_tree_view_real_collapse_row (tree_view,
cursor_path,
tree_view->priv->cursor_tree,
tree_view->priv->cursor_node,
TRUE);
gtk_tree_path_free (cursor_path); gtk_tree_path_free (cursor_path);
@ -10777,34 +10736,21 @@ gtk_tree_view_real_expand_collapse_cursor_row (GtkTreeView *tree_view,
static gboolean static gboolean
gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view) gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
{ {
GtkRBTree *cursor_tree = NULL;
GtkRBNode *cursor_node = NULL;
GtkTreePath *cursor_path = NULL; GtkTreePath *cursor_path = NULL;
GdkModifierType state; GdkModifierType state;
if (!gtk_widget_has_focus (GTK_WIDGET (tree_view))) if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
goto out; goto out;
cursor_path = NULL; if (tree_view->priv->cursor_node == NULL)
if (tree_view->priv->cursor)
cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
if (cursor_path == NULL)
goto out; goto out;
_gtk_tree_view_find_node (tree_view, cursor_path, cursor_path = _gtk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
&cursor_tree, &cursor_node); tree_view->priv->cursor_node);
if (cursor_tree == NULL)
{
gtk_tree_path_free (cursor_path);
goto out;
}
if (cursor_tree->parent_node) if (tree_view->priv->cursor_tree->parent_node)
{ {
gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL); gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
cursor_node = cursor_tree->parent_node;
cursor_tree = cursor_tree->parent_tree;
gtk_tree_path_up (cursor_path); gtk_tree_path_up (cursor_path);
@ -11369,8 +11315,8 @@ gtk_tree_view_set_model (GtkTreeView *tree_view,
gtk_tree_row_reference_free (tree_view->priv->drag_dest_row); gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
tree_view->priv->drag_dest_row = NULL; tree_view->priv->drag_dest_row = NULL;
gtk_tree_row_reference_free (tree_view->priv->cursor); tree_view->priv->cursor_tree = NULL;
tree_view->priv->cursor = NULL; tree_view->priv->cursor_node = NULL;
gtk_tree_row_reference_free (tree_view->priv->anchor); gtk_tree_row_reference_free (tree_view->priv->anchor);
tree_view->priv->anchor = NULL; tree_view->priv->anchor = NULL;
gtk_tree_row_reference_free (tree_view->priv->top_row); gtk_tree_row_reference_free (tree_view->priv->top_row);
@ -12871,13 +12817,10 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
gtk_tree_path_free (child_path); gtk_tree_path_free (child_path);
} }
if (gtk_tree_row_reference_valid (tree_view->priv->cursor)) if (tree_view->priv->cursor_node)
{ {
GtkTreePath *cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); cursor_changed = (node->children == tree_view->priv->cursor_tree)
|| _gtk_rbtree_contains (node->children, tree_view->priv->cursor_tree);
cursor_changed = gtk_tree_path_is_ancestor (path, cursor_path);
gtk_tree_path_free (cursor_path);
} }
if (gtk_tree_row_reference_valid (tree_view->priv->anchor)) if (gtk_tree_row_reference_valid (tree_view->priv->anchor))
@ -13156,41 +13099,31 @@ gtk_tree_view_real_set_cursor (GtkTreeView *tree_view,
gboolean clear_and_select, gboolean clear_and_select,
gboolean clamp_node) gboolean clamp_node)
{ {
GtkRBTree *tree = NULL; if (tree_view->priv->cursor_node)
GtkRBNode *node = NULL;
if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
{ {
GtkTreePath *cursor_path; _gtk_tree_view_queue_draw_node (tree_view,
cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); tree_view->priv->cursor_tree,
gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL); tree_view->priv->cursor_node,
gtk_tree_path_free (cursor_path); NULL);
} }
gtk_tree_row_reference_free (tree_view->priv->cursor);
tree_view->priv->cursor = NULL;
/* One cannot set the cursor on a separator. Also, if /* One cannot set the cursor on a separator. Also, if
* _gtk_tree_view_find_node returns TRUE, it ran out of tree * _gtk_tree_view_find_node returns TRUE, it ran out of tree
* before finding the tree and node belonging to path. The * before finding the tree and node belonging to path. The
* path maps to a non-existing path and we will silently bail out. * path maps to a non-existing path and we will silently bail out.
* We unset tree and node to avoid further processing. * We unset tree and node to avoid further processing.
*/ */
if (!row_is_separator (tree_view, NULL, path) if (row_is_separator (tree_view, NULL, path)
&& _gtk_tree_view_find_node (tree_view, path, &tree, &node) == FALSE) || _gtk_tree_view_find_node (tree_view,
path,
&tree_view->priv->cursor_tree,
&tree_view->priv->cursor_node))
{ {
tree_view->priv->cursor = tree_view->priv->cursor_tree = NULL;
gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->cursor_node = NULL;
tree_view->priv->model,
path);
}
else
{
tree = NULL;
node = NULL;
} }
if (tree != NULL) if (tree_view->priv->cursor_node != NULL)
{ {
GtkRBTree *new_tree = NULL; GtkRBTree *new_tree = NULL;
GtkRBNode *new_node = NULL; GtkRBNode *new_node = NULL;
@ -13203,7 +13136,10 @@ gtk_tree_view_real_set_cursor (GtkTreeView *tree_view,
mode |= GTK_TREE_SELECT_MODE_EXTEND; mode |= GTK_TREE_SELECT_MODE_EXTEND;
_gtk_tree_selection_internal_select_node (tree_view->priv->selection, _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
node, tree, path, mode, tree_view->priv->cursor_node,
tree_view->priv->cursor_tree,
path,
mode,
FALSE); FALSE);
} }
@ -13213,13 +13149,18 @@ gtk_tree_view_real_set_cursor (GtkTreeView *tree_view,
*/ */
_gtk_tree_view_find_node (tree_view, path, &new_tree, &new_node); _gtk_tree_view_find_node (tree_view, path, &new_tree, &new_node);
if (tree != new_tree || node != new_node) if (tree_view->priv->cursor_node != new_node)
return; return;
if (clamp_node) if (clamp_node)
{ {
gtk_tree_view_clamp_node_visible (tree_view, tree, node); gtk_tree_view_clamp_node_visible (tree_view,
_gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL); tree_view->priv->cursor_tree,
tree_view->priv->cursor_node);
_gtk_tree_view_queue_draw_node (tree_view,
tree_view->priv->cursor_tree,
tree_view->priv->cursor_node,
NULL);
} }
} }
@ -13248,8 +13189,9 @@ gtk_tree_view_get_cursor (GtkTreeView *tree_view,
if (path) if (path)
{ {
if (gtk_tree_row_reference_valid (tree_view->priv->cursor)) if (tree_view->priv->cursor_node)
*path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); *path = _gtk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
tree_view->priv->cursor_node);
else else
*path = NULL; *path = NULL;
} }
@ -15081,8 +15023,6 @@ gtk_tree_view_search_activate (GtkEntry *entry,
GtkTreeView *tree_view) GtkTreeView *tree_view)
{ {
GtkTreePath *path; GtkTreePath *path;
GtkRBNode *node;
GtkRBTree *tree;
gtk_tree_view_search_dialog_hide (tree_view->priv->search_window, gtk_tree_view_search_dialog_hide (tree_view->priv->search_window,
tree_view, tree_view,
@ -15090,14 +15030,13 @@ gtk_tree_view_search_activate (GtkEntry *entry,
/* If we have a row selected and it's the cursor row, we activate /* If we have a row selected and it's the cursor row, we activate
* the row XXX */ * the row XXX */
if (gtk_tree_row_reference_valid (tree_view->priv->cursor)) if (tree_view->priv->cursor_node &&
GTK_RBNODE_FLAG_SET (tree_view->priv->cursor_node, GTK_RBNODE_IS_SELECTED))
{ {
path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); path = _gtk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
tree_view->priv->cursor_node);
_gtk_tree_view_find_node (tree_view, path, &tree, &node); gtk_tree_view_row_activated (tree_view, path, tree_view->priv->focus_column);
if (node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
gtk_tree_view_row_activated (tree_view, path, tree_view->priv->focus_column);
gtk_tree_path_free (path); gtk_tree_path_free (path);
} }