From 5a726bc6656d543f9a0d02e38b2ae76d60f52390 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 16 Feb 2020 06:08:27 +0100 Subject: [PATCH] drop: Add a state machine for tracking events --- gdk/gdkdrop.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/gdk/gdkdrop.c b/gdk/gdkdrop.c index 9871d1c776..d4605aa8da 100644 --- a/gdk/gdkdrop.c +++ b/gdk/gdkdrop.c @@ -42,6 +42,13 @@ struct _GdkDropPrivate { GdkContentFormats *formats; GdkSurface *surface; GdkDragAction actions; + + guint entered : 1; /* TRUE if we got an enter event but not a leave event yet */ + enum { + GDK_DROP_STATE_NONE, /* pointer is dragging along */ + GDK_DROP_STATE_DROPPING, /* DROP_START has been sent */ + GDK_DROP_STATE_FINISHED /* gdk_drop_finish() has been called */ + } state : 2; }; enum { @@ -203,7 +210,8 @@ gdk_drop_set_property (GObject *gobject, case PROP_DRAG: priv->drag = g_value_dup_object (value); - gdk_drop_add_formats (self, gdk_drag_get_formats (priv->drag)); + if (priv->drag) + gdk_drop_add_formats (self, gdk_drag_get_formats (priv->drag)); break; case PROP_FORMATS: @@ -271,6 +279,11 @@ gdk_drop_finalize (GObject *object) GdkDrop *self = GDK_DROP (object); GdkDropPrivate *priv = gdk_drop_get_instance_private (self); + /* someone forgot to send a LEAVE signal */ + g_warn_if_fail (!priv->entered); + /* Should we emit finish() here if necessary? + * For now that's the backends' job */ + g_clear_object (&priv->device); g_clear_object (&priv->drag); @@ -495,6 +508,7 @@ gdk_drop_set_actions (GdkDrop *self, GdkDropPrivate *priv = gdk_drop_get_instance_private (self); g_return_if_fail (GDK_IS_DROP (self)); + g_return_if_fail (priv->state == GDK_DROP_STATE_NONE); g_return_if_fail ((actions & GDK_ACTION_ASK) == 0); if (priv->actions == actions) @@ -547,7 +561,10 @@ void gdk_drop_status (GdkDrop *self, GdkDragAction actions) { + GdkDropPrivate *priv = gdk_drop_get_instance_private (self); + g_return_if_fail (GDK_IS_DROP (self)); + g_return_if_fail (priv->state != GDK_DROP_STATE_FINISHED); GDK_DROP_GET_CLASS (self)->status (self, actions); } @@ -567,10 +584,15 @@ void gdk_drop_finish (GdkDrop *self, GdkDragAction action) { + GdkDropPrivate *priv = gdk_drop_get_instance_private (self); + g_return_if_fail (GDK_IS_DROP (self)); + g_return_if_fail (priv->state == GDK_DROP_STATE_DROPPING); g_return_if_fail (gdk_drag_action_is_unique (action)); GDK_DROP_GET_CLASS (self)->finish (self, action); + + priv->state = GDK_DROP_STATE_FINISHED; } static void @@ -583,6 +605,8 @@ gdk_drop_read_internal (GdkDrop *self, { GdkDropPrivate *priv = gdk_drop_get_instance_private (self); + g_return_if_fail (priv->state != GDK_DROP_STATE_FINISHED); + if (priv->drag) { gdk_drop_read_local_async (self, @@ -738,6 +762,8 @@ gdk_drop_read_value_internal (GdkDrop *self, GValue *value; GTask *task; + g_return_if_fail (priv->state != GDK_DROP_STATE_FINISHED); + task = g_task_new (self, cancellable, callback, user_data); g_task_set_priority (task, io_priority); g_task_set_source_tag (task, source_tag); @@ -941,12 +967,16 @@ gdk_drop_emit_enter_event (GdkDrop *self, GdkDropPrivate *priv = gdk_drop_get_instance_private (self); GdkEvent *event; + g_warn_if_fail (!priv->entered); + event = gdk_event_new (GDK_DRAG_ENTER); event->any.surface = g_object_ref (priv->surface); event->dnd.drop = g_object_ref (self); event->dnd.time = time; gdk_event_set_device (event, priv->device); + priv->entered = TRUE; + gdk_drop_do_emit_event (event, dont_queue); } @@ -961,6 +991,8 @@ gdk_drop_emit_motion_event (GdkDrop *self, GdkEvent *event; int x, y; + g_warn_if_fail (priv->entered); + gdk_surface_get_origin (priv->surface, &x, &y); event = gdk_event_new (GDK_DRAG_MOTION); @@ -984,12 +1016,16 @@ gdk_drop_emit_leave_event (GdkDrop *self, GdkDropPrivate *priv = gdk_drop_get_instance_private (self); GdkEvent *event; + g_warn_if_fail (priv->entered); + event = gdk_event_new (GDK_DRAG_LEAVE); event->any.surface = g_object_ref (priv->surface); event->dnd.drop = g_object_ref (self); event->dnd.time = time; gdk_event_set_device (event, priv->device); + priv->entered = FALSE; + gdk_drop_do_emit_event (event, dont_queue); } @@ -1004,6 +1040,9 @@ gdk_drop_emit_drop_event (GdkDrop *self, GdkEvent *event; int x, y; + g_warn_if_fail (priv->entered); + g_warn_if_fail (priv->state == GDK_DROP_STATE_NONE); + gdk_surface_get_origin (priv->surface, &x, &y); event = gdk_event_new (GDK_DROP_START); @@ -1016,6 +1055,8 @@ gdk_drop_emit_drop_event (GdkDrop *self, event->dnd.y = y_root - y; gdk_event_set_device (event, priv->device); + priv->state = GDK_DROP_STATE_DROPPING; + gdk_drop_do_emit_event (event, dont_queue); }