forked from AuroraMiddleware/gtk
Use normal event propagation for DND events
This works just fine, now that drop targets are event controllers. There is only a very vestigial gtk_drag_dest_handle_event() left that deals with corner cases.
This commit is contained in:
parent
6a7f39e6d2
commit
f898bee032
104
gtk/gtkdnd.c
104
gtk/gtkdnd.c
@ -62,23 +62,19 @@
|
||||
* Drop API makes use of signals in the #GtkWidget class.
|
||||
*/
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
static gboolean gtk_drop_find_widget (GtkWidget *widget,
|
||||
GdkEvent *event);
|
||||
|
||||
|
||||
/*
|
||||
* _gtk_drag_dest_handle_event:
|
||||
* gtk_drag_dest_handle_event:
|
||||
* @toplevel: Toplevel widget that received the event
|
||||
* @event: the event to handle
|
||||
*
|
||||
* Called from widget event handling code on Drag events
|
||||
* for destinations.
|
||||
* for destinations. For drag-motion and drop-start events,
|
||||
* this function is only called if no event handler has
|
||||
* handled the event.
|
||||
*/
|
||||
void
|
||||
_gtk_drag_dest_handle_event (GtkWidget *toplevel,
|
||||
GdkEvent *event)
|
||||
gtk_drag_dest_handle_event (GtkWidget *toplevel,
|
||||
GdkEvent *event)
|
||||
{
|
||||
GtkDropTarget *dest;
|
||||
GdkDrop *drop;
|
||||
@ -107,10 +103,7 @@ _gtk_drag_dest_handle_event (GtkWidget *toplevel,
|
||||
|
||||
case GDK_DRAG_MOTION:
|
||||
case GDK_DROP_START:
|
||||
{
|
||||
if (!gtk_drop_find_widget (toplevel, event))
|
||||
gdk_drop_status (drop, 0);
|
||||
}
|
||||
gdk_drop_status (drop, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -118,89 +111,6 @@ _gtk_drag_dest_handle_event (GtkWidget *toplevel,
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_drop_find_widget (GtkWidget *event_widget,
|
||||
GdkEvent *event)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
double x, y;
|
||||
int wx, wy;
|
||||
|
||||
if (!gtk_widget_get_mapped (event_widget) ||
|
||||
!gtk_widget_get_sensitive (event_widget))
|
||||
return FALSE;
|
||||
|
||||
gdk_event_get_coords (event, &x, &y);
|
||||
|
||||
widget = gtk_widget_pick (event_widget, x, y, GTK_PICK_DEFAULT);
|
||||
|
||||
if (!widget)
|
||||
return FALSE;
|
||||
|
||||
gtk_widget_translate_coordinates (event_widget, widget, x, y, &wx, &wy);
|
||||
|
||||
while (widget)
|
||||
{
|
||||
GtkWidget *parent;
|
||||
GList *hierarchy = NULL;
|
||||
gboolean found = FALSE;
|
||||
|
||||
if (!gtk_widget_get_mapped (widget))
|
||||
return FALSE;
|
||||
|
||||
if (gtk_widget_get_state_flags (widget) & GTK_STATE_FLAG_INSENSITIVE)
|
||||
{
|
||||
widget = gtk_widget_get_parent (widget);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* need to reference the entire hierarchy temporarily in case the
|
||||
* ::drag-motion/::drag-drop callbacks change the widget hierarchy.
|
||||
*/
|
||||
for (parent = widget;
|
||||
parent;
|
||||
parent = gtk_widget_get_parent (parent))
|
||||
{
|
||||
hierarchy = g_list_prepend (hierarchy, g_object_ref (parent));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
/* Get the parent before unreffing the hierarchy because
|
||||
* invoking the callback might have destroyed the widget
|
||||
*/
|
||||
parent = gtk_widget_get_parent (widget);
|
||||
|
||||
/* The parent might be going away when unreffing the
|
||||
* hierarchy, so also protect againt that
|
||||
*/
|
||||
if (parent)
|
||||
g_object_add_weak_pointer (G_OBJECT (parent), (gpointer *) &parent);
|
||||
}
|
||||
|
||||
g_list_free_full (hierarchy, g_object_unref);
|
||||
|
||||
if (found)
|
||||
return TRUE;
|
||||
|
||||
if (parent)
|
||||
g_object_remove_weak_pointer (G_OBJECT (parent), (gpointer *) &parent);
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
if (!gtk_widget_translate_coordinates (widget, parent, wx, wy, &wx, &wy))
|
||||
return FALSE;
|
||||
|
||||
widget = parent;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
clear_current_dest (gpointer data, GObject *former_object)
|
||||
{
|
||||
|
@ -25,8 +25,8 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void _gtk_drag_dest_handle_event (GtkWidget *toplevel,
|
||||
GdkEvent *event);
|
||||
void gtk_drag_dest_handle_event (GtkWidget *toplevel,
|
||||
GdkEvent *event);
|
||||
|
||||
void gtk_drop_set_current_dest (GdkDrop *drop,
|
||||
GtkDropTarget *dest);
|
||||
|
@ -1676,6 +1676,20 @@ is_focus_event (GdkEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_dnd_event (GdkEvent *event)
|
||||
{
|
||||
switch ((guint) event->any.type)
|
||||
{
|
||||
case GDK_DRAG_ENTER:
|
||||
case GDK_DRAG_LEAVE:
|
||||
case GDK_DRAG_MOTION:
|
||||
case GDK_DROP_START:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_widget_active_state (GtkWidget *target,
|
||||
@ -1818,6 +1832,25 @@ handle_key_event (GdkEvent *event)
|
||||
return focus_widget ? focus_widget : event_widget;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
handle_dnd_event (GdkEvent *event)
|
||||
{
|
||||
GtkWidget *event_widget;
|
||||
GtkWidget *target;
|
||||
gdouble x, y;
|
||||
GtkWidget *native;
|
||||
|
||||
event_widget = gtk_get_event_widget (event);
|
||||
|
||||
if (!gdk_event_get_coords (event, &x, &y))
|
||||
return event_widget;
|
||||
|
||||
native = GTK_WIDGET (gtk_widget_get_native (event_widget));
|
||||
target = gtk_widget_pick (native, x, y, GTK_PICK_DEFAULT);
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_main_do_event:
|
||||
* @event: An event to process (normally passed by GDK)
|
||||
@ -1914,6 +1947,8 @@ gtk_main_do_event (GdkEvent *event)
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
else if (is_dnd_event (event))
|
||||
target_widget = handle_dnd_event (event);
|
||||
|
||||
if (!target_widget)
|
||||
goto cleanup;
|
||||
@ -2028,12 +2063,17 @@ gtk_main_do_event (GdkEvent *event)
|
||||
/* Crossing event propagation happens during picking */
|
||||
break;
|
||||
|
||||
case GDK_DRAG_ENTER:
|
||||
case GDK_DRAG_LEAVE:
|
||||
case GDK_DRAG_MOTION:
|
||||
case GDK_DROP_START:
|
||||
_gtk_drag_dest_handle_event (target_widget, event);
|
||||
if (gtk_propagate_event (target_widget, event))
|
||||
break;
|
||||
G_GNUC_FALLTHROUGH;
|
||||
|
||||
case GDK_DRAG_ENTER:
|
||||
case GDK_DRAG_LEAVE:
|
||||
gtk_drag_dest_handle_event (target_widget, event);
|
||||
break;
|
||||
|
||||
case GDK_EVENT_LAST:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
@ -2623,14 +2663,19 @@ propagate_event_down (GtkWidget *widget,
|
||||
return handled_event;
|
||||
}
|
||||
|
||||
void
|
||||
gboolean
|
||||
gtk_propagate_event_internal (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
GtkWidget *topmost)
|
||||
{
|
||||
/* Propagate the event down and up */
|
||||
if (!propagate_event_down (widget, event, topmost))
|
||||
propagate_event_up (widget, event, topmost);
|
||||
if (propagate_event_down (widget, event, topmost))
|
||||
return TRUE;
|
||||
|
||||
if (propagate_event_up (widget, event, topmost))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2657,8 +2702,10 @@ gtk_propagate_event_internal (GtkWidget *widget,
|
||||
* certainly better ways to achieve your goals. For example, use
|
||||
* gtk_widget_queue_draw() instead
|
||||
* of making up expose events.
|
||||
*
|
||||
* Returns: %TRUE if the event was handled
|
||||
*/
|
||||
void
|
||||
gboolean
|
||||
gtk_propagate_event (GtkWidget *widget,
|
||||
GdkEvent *event)
|
||||
{
|
||||
@ -2666,8 +2713,8 @@ gtk_propagate_event (GtkWidget *widget,
|
||||
GtkWidget *event_widget, *topmost = NULL;
|
||||
GdkDevice *device;
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
g_return_if_fail (event != NULL);
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
|
||||
event_widget = gtk_get_event_widget (event);
|
||||
window_group = gtk_main_get_window_group (event_widget);
|
||||
@ -2679,5 +2726,5 @@ gtk_propagate_event (GtkWidget *widget,
|
||||
if (!topmost)
|
||||
topmost = gtk_window_group_get_current_grab (window_group);
|
||||
|
||||
gtk_propagate_event_internal (widget, event, topmost);
|
||||
return gtk_propagate_event_internal (widget, event, topmost);
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ GtkWidget *gtk_get_event_target_with_type (GdkEvent *event,
|
||||
GType type);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_propagate_event (GtkWidget *widget,
|
||||
gboolean gtk_propagate_event (GtkWidget *widget,
|
||||
GdkEvent *event);
|
||||
|
||||
|
||||
|
@ -90,7 +90,7 @@ gboolean _gtk_translate_keyboard_accel_state (GdkKeymap *keymap,
|
||||
gint *level,
|
||||
GdkModifierType *consumed_modifiers);
|
||||
|
||||
void gtk_propagate_event_internal (GtkWidget *widget,
|
||||
gboolean gtk_propagate_event_internal (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
GtkWidget *topmost);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user