From e14d6fe9d5398b0e0edc82ffece1f1726445758a Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Thu, 6 Jan 2022 16:30:34 -0800 Subject: [PATCH] textview: remove drag selection after dnd move action If we have a GDK_ACTION_MOVE, we need to delete the selection. However, previously this only worked when the drop target and drag source were different applications, as the selection would get messed up along the way. Instead, we stash marks for the duration of the operation so that we can delete the appropriate selection when completing the move. --- gtk/gtktextview.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c index db23e9ad86..44fd7c7576 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -231,8 +231,13 @@ struct _GtkTextViewPrivate guint first_validate_idle; /* Idle to revalidate onscreen portion, runs before resize */ guint incremental_validate_idle; /* Idle to revalidate offscreen portions, runs after redraw */ + /* Mark for drop target */ GtkTextMark *dnd_mark; + /* Mark for selection of drag source */ + GtkTextMark *dnd_drag_begin_mark; + GtkTextMark *dnd_drag_end_mark; + GtkIMContext *im_context; GtkWidget *popup_menu; GMenuModel *extra_menu; @@ -8056,8 +8061,26 @@ static void dnd_finished_cb (GdkDrag *drag, GtkTextView *self) { - if (gdk_drag_get_selected_action (drag) == GDK_ACTION_MOVE) - gtk_text_buffer_delete_selection (self->priv->buffer, TRUE, self->priv->editable); + GtkTextBuffer *buffer = self->priv->buffer; + + if (self->priv->dnd_drag_begin_mark) + { + if (gdk_drag_get_selected_action (drag) == GDK_ACTION_MOVE) + { + { + GtkTextIter begin, end; + + gtk_text_buffer_get_iter_at_mark (buffer, &begin, self->priv->dnd_drag_begin_mark); + gtk_text_buffer_get_iter_at_mark (buffer, &end, self->priv->dnd_drag_end_mark); + gtk_text_buffer_delete (buffer, &begin, &end); + } + } + + gtk_text_buffer_delete_mark (buffer, self->priv->dnd_drag_begin_mark); + gtk_text_buffer_delete_mark (buffer, self->priv->dnd_drag_end_mark); + self->priv->dnd_drag_begin_mark = NULL; + self->priv->dnd_drag_end_mark = NULL; + } self->priv->drag = NULL; } @@ -8067,6 +8090,16 @@ dnd_cancel_cb (GdkDrag *drag, GdkDragCancelReason reason, GtkTextView *self) { + GtkTextBuffer *buffer = self->priv->buffer; + + if (self->priv->dnd_drag_begin_mark) + { + gtk_text_buffer_delete_mark (buffer, self->priv->dnd_drag_begin_mark); + gtk_text_buffer_delete_mark (buffer, self->priv->dnd_drag_end_mark); + self->priv->dnd_drag_begin_mark = NULL; + self->priv->dnd_drag_end_mark = NULL; + } + self->priv->drag = NULL; } @@ -8108,6 +8141,9 @@ gtk_text_view_start_selection_dnd (GtkTextView *text_view, paintable = gtk_text_util_create_rich_drag_icon (widget, buffer, &start, &end); gtk_drag_icon_set_from_paintable (drag, paintable, 0, 0); g_object_unref (paintable); + + text_view->priv->dnd_drag_begin_mark = gtk_text_buffer_create_mark (buffer, NULL, &start, TRUE); + text_view->priv->dnd_drag_end_mark = gtk_text_buffer_create_mark (buffer, NULL, &end, TRUE); } text_view->priv->drag = drag;