diff options
author | Matthias Clasen <mclasen@redhat.com> | 2016-05-19 16:59:10 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2016-05-23 07:58:42 -0400 |
commit | a2d723c13391e560cce7e5aed62554114f346c83 (patch) | |
tree | d40314b73bda2fb763d8913250841fd0beb7d574 | |
parent | 3270bdb98102523394a7d4c501f91a0a6ae8936e (diff) | |
download | gtk+-a2d723c13391e560cce7e5aed62554114f346c83.tar.gz |
treeview: Fix a rubberbanding-related crash
When starting a rubberband selection from an empty area, we could run
into crashes if the selection moves over the rows and then back out
to unpopulated area. Handle this case without crashing.
https://bugzilla.gnome.org/show_bug.cgi?id=766336
-rw-r--r-- | gtk/gtktreeview.c | 55 |
1 files changed, 41 insertions, 14 deletions
diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index f6f0c1c8a8..a72750cc7a 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -4381,24 +4381,30 @@ gtk_tree_view_stop_rubber_band (GtkTreeView *tree_view) gtk_widget_queue_draw (GTK_WIDGET (tree_view)); /* The anchor path should be set to the start path */ - tmp_path = _gtk_tree_path_new_from_rbtree (tree_view->priv->rubber_band_start_tree, - tree_view->priv->rubber_band_start_node); + if (tree_view->priv->rubber_band_start_node) + { + tmp_path = _gtk_tree_path_new_from_rbtree (tree_view->priv->rubber_band_start_tree, + tree_view->priv->rubber_band_start_node); - if (tree_view->priv->anchor) - gtk_tree_row_reference_free (tree_view->priv->anchor); + if (tree_view->priv->anchor) + gtk_tree_row_reference_free (tree_view->priv->anchor); - tree_view->priv->anchor = - gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), - tree_view->priv->model, - tmp_path); + tree_view->priv->anchor = + gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), + tree_view->priv->model, + tmp_path); - gtk_tree_path_free (tmp_path); + gtk_tree_path_free (tmp_path); + } /* ... and the cursor to the end path */ - tmp_path = _gtk_tree_path_new_from_rbtree (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, 0); - gtk_tree_path_free (tmp_path); + if (tree_view->priv->rubber_band_end_node) + { + tmp_path = _gtk_tree_path_new_from_rbtree (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, 0); + gtk_tree_path_free (tmp_path); + } _gtk_tree_selection_emit_changed (tree_view->priv->selection); @@ -4535,7 +4541,28 @@ gtk_tree_view_update_rubber_band_selection (GtkTreeView *tree_view) _gtk_rbtree_find_offset (tree_view->priv->tree, MAX (tree_view->priv->press_start_y, bin_y), &end_tree, &end_node); /* Handle the start area first */ - if (!tree_view->priv->rubber_band_start_node) + if (!start_node && !end_node) + { + if (tree_view->priv->rubber_band_start_node) + { + GtkRBNode *node = tree_view->priv->rubber_band_start_node; + GtkRBTree *tree = tree_view->priv->rubber_band_start_tree; + + if (tree_view->priv->rubber_band_modify) + { + /* Toggle the selection state */ + if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED)) + GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_IS_SELECTED); + else + GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SELECTED); + } + else + GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_IS_SELECTED); + + _gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL); + } + } + if (!tree_view->priv->rubber_band_start_node || !start_node) { gtk_tree_view_update_rubber_band_selection_range (tree_view, start_tree, |