From fc43ec0bbc414558e31df98475ee6ba57433cab0 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Wed, 19 Feb 2020 04:44:41 +0100 Subject: [PATCH] gtk: Bubble drag events like motion events Emit crossing events - with a new GTK_CROSSING_DROP type - like we do for motion events. There is no more special casing for them. Note that the gesture has not been updated yet, so some obscure behavior may occur. --- gtk/gtkeventcontrollerprivate.h | 7 ++- gtk/gtkmain.c | 86 ++++++++++++++------------------- gtk/gtkwidgetprivate.h | 6 --- 3 files changed, 42 insertions(+), 57 deletions(-) diff --git a/gtk/gtkeventcontrollerprivate.h b/gtk/gtkeventcontrollerprivate.h index e9e17f14e4..571d78f960 100644 --- a/gtk/gtkeventcontrollerprivate.h +++ b/gtk/gtkeventcontrollerprivate.h @@ -24,7 +24,8 @@ typedef enum { GTK_CROSSING_FOCUS, - GTK_CROSSING_POINTER + GTK_CROSSING_POINTER, + GTK_CROSSING_DROP } GtkCrossingType; typedef enum { @@ -47,11 +48,12 @@ typedef struct _GtkCrossingData GtkCrossingData; * @new_descendent: the direct child of the receiving widget that * is an ancestor of @new_target, or %NULL if @new_target is not * a descendent of the receiving widget + * @drop: the #GdkDrop if this is info for a drop operation * * The struct that is passed to gtk_event_controller_handle_crossing(). * * The @old_target and @new_target fields are set to the old or new - * focus or hover location. + * focus, drop or hover location. */ struct _GtkCrossingData { GtkCrossingType type; @@ -61,6 +63,7 @@ struct _GtkCrossingData { GtkWidget *old_descendent; GtkWidget *new_target; GtkWidget *new_descendent; + GdkDrop *drop; }; struct _GtkEventController diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index 20b232c5f6..98bb83dd22 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1304,12 +1304,14 @@ translate_event_coordinates (GdkEvent *event, return TRUE; } -void +static void gtk_synthesize_crossing_events (GtkRoot *toplevel, + GtkCrossingType crossing_type, GtkWidget *old_target, GtkWidget *new_target, GdkEvent *event, - GdkCrossingMode mode) + GdkCrossingMode mode, + GdkDrop *drop) { GtkCrossingData crossing; GtkWidget *ancestor; @@ -1324,12 +1326,13 @@ gtk_synthesize_crossing_events (GtkRoot *toplevel, else ancestor = NULL; - crossing.type = GTK_CROSSING_POINTER; + crossing.type = crossing_type; crossing.mode = mode; crossing.old_target = old_target; crossing.old_descendent = NULL; crossing.new_target = new_target; crossing.new_descendent = NULL; + crossing.drop = drop; crossing.direction = GTK_CROSSING_OUT; @@ -1360,7 +1363,8 @@ gtk_synthesize_crossing_events (GtkRoot *toplevel, check_crossing_invariants (widget, &crossing); translate_event_coordinates (event, &x, &y, widget); gtk_widget_handle_crossing (widget, &crossing, x, y); - gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_PRELIGHT); + if (crossing_type == GTK_CROSSING_POINTER) + gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_PRELIGHT); widget = gtk_widget_get_parent (widget); } @@ -1399,7 +1403,8 @@ gtk_synthesize_crossing_events (GtkRoot *toplevel, translate_event_coordinates (event, &x, &y, widget); gtk_widget_handle_crossing (widget, &crossing, x, y); - gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_PRELIGHT, FALSE); + if (crossing_type == GTK_CROSSING_POINTER) + gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_PRELIGHT, FALSE); } g_list_free (list); @@ -1445,8 +1450,12 @@ is_pointing_event (GdkEvent *event) case GDK_TOUCH_CANCEL: case GDK_TOUCHPAD_PINCH: case GDK_TOUCHPAD_SWIPE: + case GDK_DRAG_ENTER: + case GDK_DRAG_LEAVE: + case GDK_DRAG_MOTION: + case GDK_DROP_START: return TRUE; - break; + default: return FALSE; } @@ -1479,21 +1488,6 @@ is_focus_event (GdkEvent *event) } } -static gboolean -is_dnd_event (GdkEvent *event) -{ - switch ((guint) gdk_event_get_event_type (event)) - { - 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, const gboolean release) @@ -1549,14 +1543,22 @@ handle_pointing_event (GdkEvent *event) case GDK_TOUCH_CANCEL: old_target = update_pointer_focus_state (toplevel, event, NULL); if (type == GDK_LEAVE_NOTIFY) - gtk_synthesize_crossing_events (GTK_ROOT (toplevel), old_target, NULL, - event, gdk_crossing_event_get_mode (event)); + gtk_synthesize_crossing_events (GTK_ROOT (toplevel), GTK_CROSSING_POINTER, old_target, NULL, + event, gdk_crossing_event_get_mode (event), NULL); + break; + case GDK_DRAG_LEAVE: + old_target = update_pointer_focus_state (toplevel, event, NULL); + gtk_synthesize_crossing_events (GTK_ROOT (toplevel), GTK_CROSSING_DROP, old_target, NULL, + event, GDK_CROSSING_NORMAL, gdk_drag_event_get_drop (event)); break; case GDK_ENTER_NOTIFY: if (gdk_crossing_event_get_mode (event) == GDK_CROSSING_GRAB || gdk_crossing_event_get_mode (event) == GDK_CROSSING_UNGRAB) break; G_GNUC_FALLTHROUGH; + case GDK_DRAG_ENTER: + case GDK_DRAG_MOTION: + case GDK_DROP_START: case GDK_TOUCH_BEGIN: case GDK_TOUCH_UPDATE: case GDK_MOTION_NOTIFY: @@ -1575,14 +1577,18 @@ handle_pointing_event (GdkEvent *event) if (!gtk_window_lookup_pointer_focus_implicit_grab (toplevel, device, sequence)) { - gtk_synthesize_crossing_events (GTK_ROOT (toplevel), old_target, target, - event, GDK_CROSSING_NORMAL); + gtk_synthesize_crossing_events (GTK_ROOT (toplevel), GTK_CROSSING_POINTER, old_target, target, + event, GDK_CROSSING_NORMAL, NULL); } gtk_window_maybe_update_cursor (toplevel, NULL, device); } - - if (type == GDK_TOUCH_BEGIN) + else if (type == GDK_DRAG_ENTER || type == GDK_DRAG_MOTION || type == GDK_DROP_START) + { + gtk_synthesize_crossing_events (GTK_ROOT (toplevel), GTK_CROSSING_DROP, old_target, target, + event, GDK_CROSSING_NORMAL, gdk_drag_event_get_drop (event)); + } + else if (type == GDK_TOUCH_BEGIN) gtk_window_set_pointer_focus_grab (toplevel, device, sequence, target); /* Let it take the effective pointer focus anyway, as it may change due @@ -1605,8 +1611,8 @@ handle_pointing_event (GdkEvent *event) new_target = gtk_widget_pick (GTK_WIDGET (native), x, y, GTK_PICK_DEFAULT); if (new_target == NULL) new_target = GTK_WIDGET (toplevel); - gtk_synthesize_crossing_events (GTK_ROOT (toplevel), target, new_target, - event, GDK_CROSSING_UNGRAB); + gtk_synthesize_crossing_events (GTK_ROOT (toplevel), GTK_CROSSING_POINTER, target, new_target, + event, GDK_CROSSING_UNGRAB, NULL); gtk_window_maybe_update_cursor (toplevel, NULL, device); } @@ -1640,23 +1646,6 @@ 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); - - gdk_event_get_position (event, &x, &y); - native = GTK_WIDGET (gtk_widget_get_native (event_widget)); - target = gtk_widget_pick (native, x, y, GTK_PICK_DEFAULT); - - return target; -} - void gtk_main_do_event (GdkEvent *event) { @@ -1715,8 +1704,6 @@ 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; @@ -1812,14 +1799,15 @@ gtk_main_do_event (GdkEvent *event) /* Crossing event propagation happens during picking */ break; - case GDK_DRAG_ENTER: case GDK_DRAG_MOTION: case GDK_DROP_START: if (gtk_propagate_event (target_widget, event)) break; G_GNUC_FALLTHROUGH; + case GDK_DRAG_ENTER: case GDK_DRAG_LEAVE: + /* Crossing event propagation happens during picking */ gtk_drag_dest_handle_event (target_widget, event); break; diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h index 93ded92b50..b1efa36f39 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -259,12 +259,6 @@ GdkSurface * _gtk_widget_get_device_surface (GtkWidget *widget, GdkDevice *device); GList * _gtk_widget_list_devices (GtkWidget *widget); -void gtk_synthesize_crossing_events (GtkRoot *toplevel, - GtkWidget *from, - GtkWidget *to, - GdkEvent *source, - GdkCrossingMode mode); - void _gtk_widget_synthesize_crossing (GtkWidget *from, GtkWidget *to, GdkDevice *device,