forked from AuroraMiddleware/gtk
Turn GtkDropTarget into an event controller
We are still propagating the drag events manually, but we are now calling gtk_widget_run_controllers to pass them to drop targets.
This commit is contained in:
parent
f960eb6ab4
commit
dfb2cbdfdb
140
gtk/gtkdnd.c
140
gtk/gtkdnd.c
@ -63,26 +63,9 @@
|
||||
*/
|
||||
|
||||
|
||||
typedef struct _GtkDragDestInfo GtkDragDestInfo;
|
||||
|
||||
struct _GtkDragDestInfo
|
||||
{
|
||||
GtkWidget *widget; /* Widget in which drag is in */
|
||||
GdkDrop *drop; /* drop */
|
||||
};
|
||||
|
||||
/* Forward declarations */
|
||||
static GtkWidget *gtk_drop_find_widget (GtkWidget *widget,
|
||||
static gboolean gtk_drop_find_widget (GtkWidget *widget,
|
||||
GdkEvent *event);
|
||||
static void gtk_drag_dest_leave (GtkWidget *widget,
|
||||
GdkDrop *drop);
|
||||
static gboolean gtk_drop_target_handle_event (GtkDropTarget *dest,
|
||||
GdkEvent *event);
|
||||
static void gtk_drag_dest_set_widget (GtkDragDestInfo *info,
|
||||
GtkWidget *widget);
|
||||
|
||||
static GtkDragDestInfo * gtk_drag_get_dest_info (GdkDrop *drop,
|
||||
gboolean create);
|
||||
|
||||
|
||||
/*
|
||||
@ -116,41 +99,17 @@ _gtk_drag_dest_handle_event (GtkWidget *toplevel,
|
||||
break;
|
||||
|
||||
case GDK_DRAG_LEAVE:
|
||||
if (info->widget)
|
||||
if (info->dest)
|
||||
{
|
||||
gtk_drag_dest_leave (info->widget, drop);
|
||||
gtk_drag_dest_set_widget (info, NULL);
|
||||
gtk_drop_target_emit_drag_leave (info->dest, drop);
|
||||
gtk_drag_dest_set_target (info, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case GDK_DRAG_MOTION:
|
||||
case GDK_DROP_START:
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
if (event_type == GDK_DROP_START)
|
||||
{
|
||||
/* We send a leave here so that the widget unhighlights
|
||||
* properly.
|
||||
*/
|
||||
if (info->widget)
|
||||
{
|
||||
gtk_drag_dest_leave (info->widget, drop);
|
||||
gtk_drag_dest_set_widget (info, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
widget = gtk_drop_find_widget (toplevel, event);
|
||||
|
||||
if (info->widget && info->widget != widget)
|
||||
{
|
||||
gtk_drag_dest_leave (info->widget, drop);
|
||||
gtk_drag_dest_set_widget (info, NULL);
|
||||
}
|
||||
|
||||
if (widget)
|
||||
gtk_drag_dest_set_widget (info, widget);
|
||||
else
|
||||
if (!gtk_drop_find_widget (toplevel, event))
|
||||
gdk_drop_status (drop, 0);
|
||||
}
|
||||
break;
|
||||
@ -160,7 +119,7 @@ _gtk_drag_dest_handle_event (GtkWidget *toplevel,
|
||||
}
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
static gboolean
|
||||
gtk_drop_find_widget (GtkWidget *event_widget,
|
||||
GdkEvent *event)
|
||||
{
|
||||
@ -170,26 +129,25 @@ gtk_drop_find_widget (GtkWidget *event_widget,
|
||||
|
||||
if (!gtk_widget_get_mapped (event_widget) ||
|
||||
!gtk_widget_get_sensitive (event_widget))
|
||||
return NULL;
|
||||
return FALSE;
|
||||
|
||||
gdk_event_get_coords (event, &x, &y);
|
||||
|
||||
widget = gtk_widget_pick (event_widget, x, y, GTK_PICK_DEFAULT);
|
||||
|
||||
if (!widget)
|
||||
return NULL;
|
||||
return FALSE;
|
||||
|
||||
gtk_widget_translate_coordinates (event_widget, widget, x, y, &wx, &wy);
|
||||
|
||||
while (widget)
|
||||
{
|
||||
GtkDropTarget *dest;
|
||||
GtkWidget *parent;
|
||||
GList *hierarchy = NULL;
|
||||
gboolean found = FALSE;
|
||||
|
||||
if (!gtk_widget_get_mapped (widget))
|
||||
return NULL;
|
||||
return FALSE;
|
||||
|
||||
if (gtk_widget_get_state_flags (widget) & GTK_STATE_FLAG_INSENSITIVE)
|
||||
{
|
||||
@ -207,17 +165,9 @@ gtk_drop_find_widget (GtkWidget *event_widget,
|
||||
hierarchy = g_list_prepend (hierarchy, g_object_ref (parent));
|
||||
}
|
||||
|
||||
/* If the current widget is registered as a drop site, check to
|
||||
* emit "drag-motion" to check if we are actually in a drop
|
||||
* site.
|
||||
*/
|
||||
dest = gtk_drop_target_get (widget);
|
||||
if (dest)
|
||||
{
|
||||
gdk_event_set_coords (event, wx, wy);
|
||||
found = gtk_drop_target_handle_event (dest, event);
|
||||
gdk_event_set_coords (event, x, y);
|
||||
}
|
||||
gdk_event_set_coords (event, wx, wy);
|
||||
found = gtk_widget_run_controllers (widget, event, GTK_PHASE_BUBBLE);
|
||||
gdk_event_set_coords (event, x, y);
|
||||
|
||||
if (!found)
|
||||
{
|
||||
@ -236,33 +186,33 @@ gtk_drop_find_widget (GtkWidget *event_widget,
|
||||
g_list_free_full (hierarchy, g_object_unref);
|
||||
|
||||
if (found)
|
||||
return widget;
|
||||
return TRUE;
|
||||
|
||||
if (parent)
|
||||
g_object_remove_weak_pointer (G_OBJECT (parent), (gpointer *) &parent);
|
||||
else
|
||||
return NULL;
|
||||
return FALSE;
|
||||
|
||||
if (!gtk_widget_translate_coordinates (widget, parent, wx, wy, &wx, &wy))
|
||||
return NULL;
|
||||
return FALSE;
|
||||
|
||||
widget = parent;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_drag_dest_set_widget (GtkDragDestInfo *info,
|
||||
GtkWidget *widget)
|
||||
void
|
||||
gtk_drag_dest_set_target (GtkDragDestInfo *info,
|
||||
GtkDropTarget *dest)
|
||||
{
|
||||
if (info->widget)
|
||||
g_object_remove_weak_pointer (G_OBJECT (info->widget), (gpointer *) &info->widget);
|
||||
if (info->dest)
|
||||
g_object_remove_weak_pointer (G_OBJECT (info->dest), (gpointer *) &info->dest);
|
||||
|
||||
info->widget = widget;
|
||||
info->dest = dest;
|
||||
|
||||
if (info->widget)
|
||||
g_object_add_weak_pointer (G_OBJECT (info->widget), (gpointer *) &info->widget);
|
||||
if (info->dest)
|
||||
g_object_add_weak_pointer (G_OBJECT (info->dest), (gpointer *) &info->dest);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -270,12 +220,12 @@ gtk_drag_dest_info_destroy (gpointer data)
|
||||
{
|
||||
GtkDragDestInfo *info = (GtkDragDestInfo *)data;
|
||||
|
||||
gtk_drag_dest_set_widget (info, NULL);
|
||||
gtk_drag_dest_set_target (info, NULL);
|
||||
|
||||
g_slice_free (GtkDragDestInfo, data);
|
||||
}
|
||||
|
||||
static GtkDragDestInfo *
|
||||
GtkDragDestInfo *
|
||||
gtk_drag_get_dest_info (GdkDrop *drop,
|
||||
gboolean create)
|
||||
{
|
||||
@ -295,41 +245,3 @@ gtk_drag_get_dest_info (GdkDrop *drop,
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/*
|
||||
* Default drag handlers
|
||||
*/
|
||||
static void
|
||||
gtk_drag_dest_leave (GtkWidget *widget,
|
||||
GdkDrop *drop)
|
||||
{
|
||||
GtkDropTarget *dest;
|
||||
|
||||
dest = gtk_drop_target_get (widget);
|
||||
g_return_if_fail (dest != NULL);
|
||||
|
||||
gtk_drop_target_emit_drag_leave (dest, drop);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_drop_target_handle_event (GtkDropTarget *dest,
|
||||
GdkEvent *event)
|
||||
{
|
||||
GdkDrop *drop;
|
||||
double x, y;
|
||||
|
||||
drop = gdk_event_get_drop (event);
|
||||
gdk_event_get_coords (event, &x, &y);
|
||||
|
||||
switch ((int)gdk_event_get_event_type (event))
|
||||
{
|
||||
case GDK_DRAG_MOTION:
|
||||
return gtk_drop_target_emit_drag_motion (dest, drop, x, y);
|
||||
case GDK_DROP_START:
|
||||
return gtk_drop_target_emit_drag_drop (dest, drop, x, y);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
#define __GTK_DND_PRIVATE_H__
|
||||
|
||||
#include "gtkwidget.h"
|
||||
#include "gtkdragdest.h"
|
||||
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@ -27,6 +28,19 @@ G_BEGIN_DECLS
|
||||
void _gtk_drag_dest_handle_event (GtkWidget *toplevel,
|
||||
GdkEvent *event);
|
||||
|
||||
typedef struct _GtkDragDestInfo GtkDragDestInfo;
|
||||
|
||||
struct _GtkDragDestInfo
|
||||
{
|
||||
GtkDropTarget *dest;
|
||||
GdkDrop *drop; /* drop */
|
||||
};
|
||||
|
||||
GtkDragDestInfo * gtk_drag_get_dest_info (GdkDrop *drop,
|
||||
gboolean create);
|
||||
void gtk_drag_dest_set_target (GtkDragDestInfo *info,
|
||||
GtkDropTarget *dest);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_DND_PRIVATE_H__ */
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include "gtkintl.h"
|
||||
#include "gtknative.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
#include "gtkeventcontroller.h"
|
||||
#include "gtkeventcontrollerprivate.h"
|
||||
#include "gtkmarshalers.h"
|
||||
#include "gtkselectionprivate.h"
|
||||
|
||||
@ -51,7 +51,7 @@
|
||||
|
||||
struct _GtkDropTarget
|
||||
{
|
||||
GObject parent_instance;
|
||||
GtkEventController parent_object;
|
||||
|
||||
GdkContentFormats *formats;
|
||||
GdkDragAction actions;
|
||||
@ -64,7 +64,7 @@ struct _GtkDropTarget
|
||||
|
||||
struct _GtkDropTargetClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
GtkEventControllerClass parent_class;
|
||||
|
||||
gboolean (*drag_motion) (GtkDropTarget *dest,
|
||||
int x,
|
||||
@ -94,7 +94,15 @@ static gboolean gtk_drop_target_drag_motion (GtkDropTarget *dest,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
G_DEFINE_TYPE (GtkDropTarget, gtk_drop_target, G_TYPE_OBJECT);
|
||||
static gboolean gtk_drop_target_handle_event (GtkEventController *controller,
|
||||
const GdkEvent *event);
|
||||
static gboolean gtk_drop_target_filter_event (GtkEventController *controller,
|
||||
const GdkEvent *event);
|
||||
static void gtk_drop_target_set_widget (GtkEventController *controller,
|
||||
GtkWidget *widget);
|
||||
static void gtk_drop_target_unset_widget (GtkEventController *controller);
|
||||
|
||||
G_DEFINE_TYPE (GtkDropTarget, gtk_drop_target, GTK_TYPE_EVENT_CONTROLLER);
|
||||
|
||||
static void
|
||||
gtk_drop_target_init (GtkDropTarget *dest)
|
||||
@ -165,11 +173,17 @@ static void
|
||||
gtk_drop_target_class_init (GtkDropTargetClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GtkEventControllerClass *controller_class = GTK_EVENT_CONTROLLER_CLASS (class);
|
||||
|
||||
object_class->finalize = gtk_drop_target_finalize;
|
||||
object_class->set_property = gtk_drop_target_set_property;
|
||||
object_class->get_property = gtk_drop_target_get_property;
|
||||
|
||||
controller_class->handle_event = gtk_drop_target_handle_event;
|
||||
controller_class->filter_event = gtk_drop_target_filter_event;
|
||||
controller_class->set_widget = gtk_drop_target_set_widget;
|
||||
controller_class->unset_widget = gtk_drop_target_unset_widget;
|
||||
|
||||
class->drag_motion = gtk_drop_target_drag_motion;
|
||||
|
||||
/**
|
||||
@ -445,28 +459,11 @@ void
|
||||
gtk_drop_target_attach (GtkDropTarget *dest,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkDropTarget *old_dest;
|
||||
|
||||
g_return_if_fail (GTK_IS_DROP_TARGET (dest));
|
||||
g_return_if_fail (dest->widget == NULL);
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
|
||||
old_dest = g_object_get_data (G_OBJECT (widget), I_("gtk-drag-dest"));
|
||||
if (old_dest)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (widget, gtk_drag_dest_realized, old_dest);
|
||||
g_signal_handlers_disconnect_by_func (widget, gtk_drag_dest_hierarchy_changed, old_dest);
|
||||
}
|
||||
|
||||
if (gtk_widget_get_realized (widget))
|
||||
gtk_drag_dest_realized (widget);
|
||||
|
||||
dest->widget = widget;
|
||||
|
||||
g_signal_connect (widget, "realize", G_CALLBACK (gtk_drag_dest_realized), dest);
|
||||
g_signal_connect (widget, "notify::root", G_CALLBACK (gtk_drag_dest_hierarchy_changed), dest);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (widget), I_("gtk-drag-dest"), dest, g_object_unref);
|
||||
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (dest), GTK_PHASE_BUBBLE);
|
||||
gtk_widget_add_controller (widget, GTK_EVENT_CONTROLLER (dest));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -478,17 +475,12 @@ gtk_drop_target_attach (GtkDropTarget *dest,
|
||||
void
|
||||
gtk_drop_target_detach (GtkDropTarget *dest)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
g_return_if_fail (GTK_IS_DROP_TARGET (dest));
|
||||
|
||||
if (dest->widget)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (dest->widget, gtk_drag_dest_realized, dest);
|
||||
g_signal_handlers_disconnect_by_func (dest->widget, gtk_drag_dest_hierarchy_changed, dest);
|
||||
|
||||
g_object_set_data (G_OBJECT (dest->widget), I_("gtk-drag-dest"), NULL);
|
||||
|
||||
dest->widget = NULL;
|
||||
}
|
||||
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest));
|
||||
gtk_widget_remove_controller (widget, GTK_EVENT_CONTROLLER (dest));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -504,7 +496,7 @@ gtk_drop_target_get_target (GtkDropTarget *dest)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_DROP_TARGET (dest), NULL);
|
||||
|
||||
return dest->widget;
|
||||
return gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -650,6 +642,10 @@ void
|
||||
gtk_drop_target_set_armed (GtkDropTarget *dest,
|
||||
gboolean armed)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest));
|
||||
|
||||
dest->armed_pending = FALSE;
|
||||
|
||||
if (dest->armed == armed)
|
||||
@ -657,13 +653,10 @@ gtk_drop_target_set_armed (GtkDropTarget *dest,
|
||||
|
||||
dest->armed = armed;
|
||||
|
||||
if (dest->widget)
|
||||
{
|
||||
if (armed)
|
||||
gtk_drag_highlight (dest->widget);
|
||||
else
|
||||
gtk_drag_unhighlight (dest->widget);
|
||||
}
|
||||
if (armed)
|
||||
gtk_drag_highlight (widget);
|
||||
else
|
||||
gtk_drag_unhighlight (widget);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (dest), properties[PROP_ARMED]);
|
||||
}
|
||||
@ -674,6 +667,104 @@ gtk_drop_target_get_armed (GtkDropTarget *dest)
|
||||
return dest->armed;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_drop_target_filter_event (GtkEventController *controller,
|
||||
const GdkEvent *event)
|
||||
{
|
||||
switch ((int)gdk_event_get_event_type (event))
|
||||
{
|
||||
case GDK_DRAG_ENTER:
|
||||
case GDK_DRAG_LEAVE:
|
||||
case GDK_DRAG_MOTION:
|
||||
case GDK_DROP_START:
|
||||
return GTK_EVENT_CONTROLLER_CLASS (gtk_drop_target_parent_class)->filter_event (controller, event);
|
||||
|
||||
default:;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_drop_target_handle_event (GtkEventController *controller,
|
||||
const GdkEvent *event)
|
||||
{
|
||||
GtkDropTarget *dest = GTK_DROP_TARGET (controller);
|
||||
GdkDrop *drop;
|
||||
GtkDragDestInfo *info;
|
||||
double x, y;
|
||||
gboolean found = FALSE;
|
||||
|
||||
gdk_event_get_coords (event, &x, &y);
|
||||
|
||||
drop = gdk_event_get_drop (event);
|
||||
info = gtk_drag_get_dest_info (drop, TRUE);
|
||||
|
||||
switch ((int)gdk_event_get_event_type (event))
|
||||
{
|
||||
case GDK_DRAG_MOTION:
|
||||
found = gtk_drop_target_emit_drag_motion (dest, drop, x, y);
|
||||
break;
|
||||
|
||||
case GDK_DROP_START:
|
||||
/* We send a leave before the drop so that the widget unhighlights
|
||||
* properly.
|
||||
*/
|
||||
if (info->dest)
|
||||
{
|
||||
gtk_drop_target_emit_drag_leave (info->dest, drop);
|
||||
gtk_drag_dest_set_target (info, NULL);
|
||||
}
|
||||
|
||||
found = gtk_drop_target_emit_drag_drop (dest, drop, x, y);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
if (info->dest && info->dest != dest)
|
||||
{
|
||||
gtk_drop_target_emit_drag_leave (info->dest, drop);
|
||||
gtk_drag_dest_set_target (info, NULL);
|
||||
}
|
||||
|
||||
gtk_drag_dest_set_target (info, dest);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_drop_target_set_widget (GtkEventController *controller,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkDropTarget *dest = GTK_DROP_TARGET (controller);
|
||||
|
||||
GTK_EVENT_CONTROLLER_CLASS (gtk_drop_target_parent_class)->set_widget (controller, widget);
|
||||
|
||||
if (gtk_widget_get_realized (widget))
|
||||
gtk_drag_dest_realized (widget);
|
||||
|
||||
g_signal_connect (widget, "realize", G_CALLBACK (gtk_drag_dest_realized), dest);
|
||||
g_signal_connect (widget, "notify::root", G_CALLBACK (gtk_drag_dest_hierarchy_changed), dest);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_drop_target_unset_widget (GtkEventController *controller)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = gtk_event_controller_get_widget (controller);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (widget, gtk_drag_dest_realized, controller);
|
||||
g_signal_handlers_disconnect_by_func (widget, gtk_drag_dest_hierarchy_changed, controller);
|
||||
|
||||
GTK_EVENT_CONTROLLER_CLASS (gtk_drop_target_parent_class)->unset_widget (controller);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_drag_highlight: (method)
|
||||
* @widget: a widget to highlight
|
||||
@ -810,13 +901,16 @@ gtk_drop_target_read_selection (GtkDropTarget *dest,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
GtkWidget *widget;
|
||||
|
||||
g_return_if_fail (GTK_IS_DROP_TARGET (dest));
|
||||
|
||||
task = g_task_new (dest, NULL, callback, user_data);
|
||||
g_object_set_data_full (G_OBJECT (task), "drop", g_object_ref (dest->drop), g_object_unref);
|
||||
if (dest->widget)
|
||||
g_object_set_data (G_OBJECT (task), "display", gtk_widget_get_display (dest->widget));
|
||||
|
||||
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest));
|
||||
if (widget)
|
||||
g_object_set_data (G_OBJECT (task), "display", gtk_widget_get_display (widget));
|
||||
|
||||
gdk_drop_read_async (dest->drop,
|
||||
(const char *[2]) { target, NULL },
|
||||
|
Loading…
Reference in New Issue
Block a user