[gtk/wip/otte/dnd: 1/9] drop: Add a state machine for tracking events



commit 5a726bc6656d543f9a0d02e38b2ae76d60f52390
Author: Benjamin Otte <otte redhat com>
Date:   Sun Feb 16 06:08:27 2020 +0100

    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);
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]