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.
This commit is contained in:
Benjamin Otte
2020-02-19 04:44:41 +01:00
parent be4b34aa8f
commit fc43ec0bbc
3 changed files with 42 additions and 57 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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,