text: Port to GtkDropTarget

This commit is contained in:
Matthias Clasen 2020-01-01 20:47:19 -05:00
parent 025eee112c
commit 6e602e052b

View File

@ -68,6 +68,7 @@
#include "gtknative.h"
#include "gtkactionmuxerprivate.h"
#include "gtkdragsource.h"
#include "gtkdragdest.h"
#include "a11y/gtktextaccessible.h"
@ -332,19 +333,16 @@ static void gtk_text_state_flags_changed (GtkWidget *widget,
GtkStateFlags previous_state);
static void gtk_text_root (GtkWidget *widget);
static gboolean gtk_text_drag_drop (GtkWidget *widget,
GdkDrop *drop,
static gboolean gtk_text_drag_drop (GtkDropTarget *dest,
int x,
int y);
static gboolean gtk_text_drag_motion (GtkWidget *widget,
GdkDrop *drop,
int y,
GtkText *text);
static gboolean gtk_text_drag_motion (GtkDropTarget *dest,
int x,
int y);
static void gtk_text_drag_leave (GtkWidget *widget,
GdkDrop *drop);
static void gtk_text_drag_data_received (GtkWidget *widget,
GdkDrop *drop,
GtkSelectionData *selection_data);
int y,
GtkText *text);
static void gtk_text_drag_leave (GtkDropTarget *dest,
GtkText *text);
/* GtkEditable method implementations
@ -726,10 +724,6 @@ gtk_text_class_init (GtkTextClass *class)
widget_class->root = gtk_text_root;
widget_class->mnemonic_activate = gtk_text_mnemonic_activate;
widget_class->popup_menu = gtk_text_popup_menu;
widget_class->drag_drop = gtk_text_drag_drop;
widget_class->drag_motion = gtk_text_drag_motion;
widget_class->drag_leave = gtk_text_drag_leave;
widget_class->drag_data_received = gtk_text_drag_data_received;
class->move_cursor = gtk_text_move_cursor;
class->insert_at_cursor = gtk_text_insert_at_cursor;
@ -1710,6 +1704,8 @@ gtk_text_init (GtkText *self)
GtkGesture *gesture;
GtkEventController *controller;
int i;
GtkDropTarget *dest;
GdkContentFormats *formats;
gtk_widget_set_can_focus (GTK_WIDGET (self), TRUE);
gtk_widget_set_overflow (GTK_WIDGET (self), GTK_OVERFLOW_HIDDEN);
@ -1730,9 +1726,14 @@ gtk_text_init (GtkText *self)
priv->selection_content = g_object_new (GTK_TYPE_TEXT_CONTENT, NULL);
GTK_TEXT_CONTENT (priv->selection_content)->self = self;
gtk_drag_dest_set (GTK_WIDGET (self), 0, NULL,
GDK_ACTION_COPY | GDK_ACTION_MOVE);
gtk_drag_dest_add_text_targets (GTK_WIDGET (self));
formats = gdk_content_formats_new (NULL, 0);
formats = gtk_content_formats_add_text_targets (formats);
dest = gtk_drop_target_new (0, formats, GDK_ACTION_COPY | GDK_ACTION_MOVE);
g_signal_connect (dest, "drag-motion", G_CALLBACK (gtk_text_drag_motion), self);
g_signal_connect (dest, "drag-leave", G_CALLBACK (gtk_text_drag_leave), self);
g_signal_connect (dest, "drag-drop", G_CALLBACK (gtk_text_drag_drop), self);
gdk_content_formats_unref (formats);
gtk_drop_target_attach (dest, GTK_WIDGET (self));
/* This object is completely private. No external entity can gain a reference
* to it; so we create it here and destroy it in finalize().
@ -6106,90 +6107,17 @@ gtk_text_selection_bubble_popup_set (GtkText *self)
}
static void
gtk_text_drag_leave (GtkWidget *widget,
GdkDrop *drop)
gtk_text_drag_leave (GtkDropTarget *dest,
GtkText *self)
{
GtkText *self = GTK_TEXT (widget);
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
GtkWidget *widget = GTK_WIDGET (self);
gtk_drag_unhighlight (widget);
priv->dnd_position = -1;
gtk_widget_queue_draw (widget);
}
static gboolean
gtk_text_drag_drop (GtkWidget *widget,
GdkDrop *drop,
int x,
int y)
{
GtkText *self = GTK_TEXT (widget);
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
GdkAtom target = NULL;
if (priv->editable)
target = gtk_drag_dest_find_target (widget, drop, NULL);
if (target != NULL)
{
priv->drop_position = gtk_text_find_position (self, x + priv->scroll_offset);
gtk_drag_get_data (widget, drop, target);
}
else
gdk_drop_finish (drop, 0);
return TRUE;
}
static gboolean
gtk_text_drag_motion (GtkWidget *widget,
GdkDrop *drop,
int x,
int y)
{
GtkText *self = GTK_TEXT (widget);
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
GdkDragAction suggested_action;
int new_position, old_position;
old_position = priv->dnd_position;
new_position = gtk_text_find_position (self, x + priv->scroll_offset);
if (priv->editable &&
gtk_drag_dest_find_target (widget, drop, NULL) != NULL)
{
suggested_action = GDK_ACTION_COPY | GDK_ACTION_MOVE;
if (priv->selection_bound == priv->current_pos ||
new_position < priv->selection_bound ||
new_position > priv->current_pos)
{
priv->dnd_position = new_position;
}
else
{
priv->dnd_position = -1;
}
}
else
{
/* Entry not editable, or no text */
suggested_action = 0;
priv->dnd_position = -1;
}
gdk_drop_status (drop, suggested_action);
if (suggested_action == 0)
gtk_drag_unhighlight (widget);
else
gtk_drag_highlight (widget);
if (priv->dnd_position != old_position)
gtk_widget_queue_draw (widget);
return TRUE;
}
static GdkDragAction
gtk_text_get_action (GtkText *self,
GdkDrop *drop)
@ -6218,19 +6146,20 @@ gtk_text_get_action (GtkText *self,
}
static void
gtk_text_drag_data_received (GtkWidget *widget,
GdkDrop *drop,
GtkSelectionData *selection_data)
got_text (GObject *source,
GAsyncResult *result,
gpointer data)
{
GtkText *self = GTK_TEXT (widget);
GdkDrop *drop = GDK_DROP (source);
GtkText *self = GTK_TEXT (data);
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
GdkDragAction action;
char *str;
GdkDragAction action;
str = (char *) gtk_selection_data_get_text (selection_data);
str = gdk_drop_read_text_finish (drop, result, NULL);
action = gtk_text_get_action (self, drop);
if (action && str && priv->editable)
if (action && str)
{
int length = -1;
int pos;
@ -6265,6 +6194,76 @@ gtk_text_drag_data_received (GtkWidget *widget,
g_free (str);
}
static gboolean
gtk_text_drag_drop (GtkDropTarget *dest,
int x,
int y,
GtkText *self)
{
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
GdkDrop *drop = gtk_drop_target_get_drop (dest);
if (priv->editable && gdk_drop_has_value (drop, G_TYPE_STRING))
{
priv->drop_position = gtk_text_find_position (self, x + priv->scroll_offset);
gdk_drop_read_text_async (drop, NULL, got_text, self);
}
else
gdk_drop_finish (drop, 0);
return TRUE;
}
static gboolean
gtk_text_drag_motion (GtkDropTarget *dest,
int x,
int y,
GtkText *self)
{
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
GdkDrop *drop = gtk_drop_target_get_drop (dest);
GtkWidget *widget = GTK_WIDGET (self);
GdkDragAction suggested_action;
int new_position, old_position;
old_position = priv->dnd_position;
new_position = gtk_text_find_position (self, x + priv->scroll_offset);
if (priv->editable &&
gtk_drop_target_find_mimetype (dest) != NULL)
{
suggested_action = GDK_ACTION_COPY | GDK_ACTION_MOVE;
if (priv->selection_bound == priv->current_pos ||
new_position < priv->selection_bound ||
new_position > priv->current_pos)
{
priv->dnd_position = new_position;
}
else
{
priv->dnd_position = -1;
}
}
else
{
/* Entry not editable, or no text */
suggested_action = 0;
priv->dnd_position = -1;
}
gdk_drop_status (drop, suggested_action);
if (suggested_action == 0)
gtk_drag_unhighlight (widget);
else
gtk_drag_highlight (widget);
if (priv->dnd_position != old_position)
gtk_widget_queue_draw (widget);
return TRUE;
}
/* We display the cursor when
*
* - the selection is empty, AND