From 3083308d1cd6825604669b41639e94540a93b26d Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Sat, 20 Apr 2013 11:42:04 -0400 Subject: [PATCH 1/3] Actually use the drop_state, instead of encoding things in new_bookmark_index This lets us keep the new_bookmark_index untouched even when the drop state goes from armed to unarmed. That will in turn let us drop in the right place... Signed-off-by: Federico Mena Quintero --- gtk/gtkplacessidebar.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/gtk/gtkplacessidebar.c b/gtk/gtkplacessidebar.c index 7982e0f9c3..33acbfee7c 100644 --- a/gtk/gtkplacessidebar.c +++ b/gtk/gtkplacessidebar.c @@ -1420,14 +1420,15 @@ free_drag_data (GtkPlacesSidebar *sidebar) static void remove_drop_bookmark_feedback_row (GtkPlacesSidebar *sidebar) { - if (sidebar->new_bookmark_index != -1) { + if (sidebar->drop_state != DROP_STATE_NORMAL) { gboolean success; GtkTreeIter iter; success = gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (sidebar->store), &iter, NULL, sidebar->new_bookmark_index); g_assert (success); gtk_list_store_remove (sidebar->store, &iter); - sidebar->new_bookmark_index = -1; + + sidebar->drop_state = DROP_STATE_NORMAL; } } @@ -1460,22 +1461,31 @@ start_drop_feedback (GtkPlacesSidebar *sidebar, GtkTreePath *path, GtkTreeViewDr if (drop_as_bookmarks) { int new_bookmark_index; GtkTreePath *new_path; + gboolean need_feedback_row; new_bookmark_index = gtk_tree_path_get_indices (path)[0]; - if (pos == GTK_TREE_VIEW_DROP_AFTER) new_bookmark_index++; - if (sidebar->new_bookmark_index != new_bookmark_index) { + if (sidebar->drop_state == DROP_STATE_NORMAL) + need_feedback_row = TRUE; + else { + /* Feedback row already exists; remove it if its position needs to change */ + + if (sidebar->new_bookmark_index == new_bookmark_index) + need_feedback_row = FALSE; + else { + if (sidebar->new_bookmark_index < new_bookmark_index) + new_bookmark_index--; /* since the removal of the old feedback row pushed items one position up */ + + remove_drop_bookmark_feedback_row (sidebar); + need_feedback_row = TRUE; + } + } + + if (need_feedback_row) { GtkTreeIter iter; - if (sidebar->new_bookmark_index != -1 - && sidebar->new_bookmark_index < new_bookmark_index) - new_bookmark_index--; /* since the removal of the old feedback row pushed items one position up */ - - remove_drop_bookmark_feedback_row (sidebar); - - /* Insert the new feedback row */ sidebar->new_bookmark_index = new_bookmark_index; gtk_list_store_insert_with_values (sidebar->store, &iter, sidebar->new_bookmark_index, PLACES_SIDEBAR_COLUMN_ROW_TYPE, PLACES_DROP_FEEDBACK, @@ -1485,9 +1495,11 @@ start_drop_feedback (GtkPlacesSidebar *sidebar, GtkTreePath *path, GtkTreeViewDr -1); } - new_path = gtk_tree_path_new_from_indices (new_bookmark_index, -1); + new_path = gtk_tree_path_new_from_indices (sidebar->new_bookmark_index, -1); gtk_tree_view_set_drag_dest_row (sidebar->tree_view, new_path, GTK_TREE_VIEW_DROP_INTO_OR_BEFORE); gtk_tree_path_free (new_path); + + sidebar->drop_state = DROP_STATE_NEW_BOOKMARK_ARMED; } else gtk_tree_view_set_drag_dest_row (sidebar->tree_view, path, pos); } @@ -1827,6 +1839,7 @@ drag_drop_callback (GtkTreeView *tree_view, GtkPlacesSidebar *sidebar) { gboolean retval = FALSE; + sidebar->drop_occured = TRUE; retval = get_drag_data (tree_view, context, time); g_signal_stop_emission_by_name (tree_view, "drag-drop"); From 9c38ff7dfbcd255a29ca3ce78c571bac6a5ea074 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Sat, 20 Apr 2013 12:30:48 -0400 Subject: [PATCH 2/3] Drop in the right place when the feedback row is active Signed-off-by: Federico Mena Quintero --- gtk/gtkplacessidebar.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/gtk/gtkplacessidebar.c b/gtk/gtkplacessidebar.c index 33acbfee7c..35e218372f 100644 --- a/gtk/gtkplacessidebar.c +++ b/gtk/gtkplacessidebar.c @@ -1312,7 +1312,7 @@ compute_drop_position (GtkTreeView *tree_view, goto out; } - /* Never drop on headings, but special case the bookmarks heading, +o /* Never drop on headings, but special case the bookmarks heading, * so we can drop bookmarks in between it and the first bookmark. */ if (place_type == PLACES_HEADING @@ -1795,7 +1795,9 @@ drag_data_received_callback (GtkWidget *widget, position++; if (tree_pos == GTK_TREE_VIEW_DROP_BEFORE - || tree_pos == GTK_TREE_VIEW_DROP_AFTER) { + || tree_pos == GTK_TREE_VIEW_DROP_AFTER + || place_type == PLACES_DROP_FEEDBACK) { + remove_drop_bookmark_feedback_row (sidebar); drop_files_as_bookmarks (sidebar, source_file_list, position); success = TRUE; drop_as_bookmarks = TRUE; @@ -1825,6 +1827,7 @@ drag_data_received_callback (GtkWidget *widget, out: sidebar->drop_occured = FALSE; free_drag_data (sidebar); + remove_drop_bookmark_feedback_row (sidebar); gtk_drag_finish (context, success, FALSE, time); gtk_tree_path_free (tree_path); From 3b34e70f132ddc6794063fb84a73812b6632f05a Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Sat, 20 Apr 2013 14:20:07 -0400 Subject: [PATCH 3/3] Remove the drop feedback row a little time after drag_leave Since ::drag-leave gets emitted before ::drag-drop, we can't just remove the drop feedback row in drag-leave, as we *need* it during drag-drop. So, we use the same trick as in testdnd.c - we install a timeout handler in our drag-leave callback, and remove the feedback in the timeout callback. Signed-off-by: Federico Mena Quintero --- gtk/gtkplacessidebar.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/gtk/gtkplacessidebar.c b/gtk/gtkplacessidebar.c index 35e218372f..acbd59e1ea 100644 --- a/gtk/gtkplacessidebar.c +++ b/gtk/gtkplacessidebar.c @@ -165,6 +165,7 @@ struct _GtkPlacesSidebar { DropState drop_state; int new_bookmark_index; + guint drag_leave_timeout_id; guint show_desktop : 1; }; @@ -1312,7 +1313,7 @@ compute_drop_position (GtkTreeView *tree_view, goto out; } -o /* Never drop on headings, but special case the bookmarks heading, + /* Never drop on headings, but special case the bookmarks heading, * so we can drop bookmarks in between it and the first bookmark. */ if (place_type == PLACES_HEADING @@ -1606,15 +1607,30 @@ drag_motion_callback (GtkTreeView *tree_view, return TRUE; } +static gboolean +drag_leave_timeout_cb (gpointer data) +{ + GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (data); + + free_drag_data (sidebar); + stop_drop_feedback (sidebar); + remove_drop_bookmark_feedback_row (sidebar); + + sidebar->drag_leave_timeout_id = 0; + return FALSE; +} + static void drag_leave_callback (GtkTreeView *tree_view, GdkDragContext *context, unsigned int time, GtkPlacesSidebar *sidebar) { - free_drag_data (sidebar); - stop_drop_feedback (sidebar); - remove_drop_bookmark_feedback_row (sidebar); + if (sidebar->drag_leave_timeout_id) + g_source_remove (sidebar->drag_leave_timeout_id); + + sidebar->drag_leave_timeout_id = gdk_threads_add_timeout (500, drag_leave_timeout_cb, sidebar); + g_signal_stop_emission_by_name (tree_view, "drag-leave"); } @@ -3779,6 +3795,11 @@ gtk_places_sidebar_dispose (GObject *object) sidebar->tree_view = NULL; + if (sidebar->drag_leave_timeout_id) { + g_source_remove (sidebar->drag_leave_timeout_id); + sidebar->drag_leave_timeout_id = 0; + } + free_drag_data (sidebar); if (sidebar->bookmarks_manager != NULL) {