summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2020-01-05 23:49:22 -0500
committerMatthias Clasen <mclasen@redhat.com>2020-01-08 18:48:21 -0500
commitf898bee032040c17fe0282aa69cb54ef31f9d0ff (patch)
tree02cc01c6caa500767bed7dc14361d5a3c66020ac
parent6a7f39e6d23fd982034440d9f95d568b0011dc5b (diff)
downloadgtk+-f898bee032040c17fe0282aa69cb54ef31f9d0ff.tar.gz
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.
-rw-r--r--gtk/gtkdnd.c104
-rw-r--r--gtk/gtkdndprivate.h4
-rw-r--r--gtk/gtkmain.c67
-rw-r--r--gtk/gtkmain.h2
-rw-r--r--gtk/gtkprivate.h2
5 files changed, 68 insertions, 111 deletions
diff --git a/gtk/gtkdnd.c b/gtk/gtkdnd.c
index 1ebbf9666a..5bb5b45190 100644
--- a/gtk/gtkdnd.c
+++ b/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)
{
diff --git a/gtk/gtkdndprivate.h b/gtk/gtkdndprivate.h
index a520b1cf08..4de9a173d5 100644
--- a/gtk/gtkdndprivate.h
+++ b/gtk/gtkdndprivate.h
@@ -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);
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index fe5868a95d..504fe53382 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -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);
}
diff --git a/gtk/gtkmain.h b/gtk/gtkmain.h
index 81c1e574ad..0009c4d90e 100644
--- a/gtk/gtkmain.h
+++ b/gtk/gtkmain.h
@@ -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);
diff --git a/gtk/gtkprivate.h b/gtk/gtkprivate.h
index 2732f064c8..38dfe92a31 100644
--- a/gtk/gtkprivate.h
+++ b/gtk/gtkprivate.h
@@ -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);