drag-action: Ensure that we can destroy the drag handle

If the DragAction has a drag handle that gets destroyed inside the
::drag-end signal handler, the destruction sequence will trigger a
callback we have in place to check if the handle is being destroyed
mid-drag, e.g. from a ::drag-motion event.

The callback on the drag handle destruction will check if we are still
in the middle of a drag and emit the ::drag-end signal to allow cleaning
up; the callback erroneously uses the drag handle as the argument for
the emit_drag_end() function — instead of the actor to which the drag
action has been attached. Also, by the time we emit the ::drag-end, we
are not dragging the actor any more, so we shouldn't be emitted the
::drag-end signal twice.

The fix is, thus, made of two parts:

  - reset the in_drag boolean before emitting the ::drag-end signal
    so that destroying the drag handle will not result in a double
    signal emission;

  - use the correct actor when calling emit_drag_end().

https://bugzilla.gnome.org/show_bug.cgi?id=681814
This commit is contained in:
Emmanuele Bassi 2012-08-20 18:56:20 +01:00
parent 449dca8034
commit 06ea2cf7b1

View File

@ -306,6 +306,8 @@ emit_drag_end (ClutterDragAction *action,
priv->last_motion_device = clutter_event_get_device (event); priv->last_motion_device = clutter_event_get_device (event);
} }
priv->in_drag = FALSE;
/* we might not have emitted ::drag-begin yet */ /* we might not have emitted ::drag-begin yet */
if (!priv->emit_delayed_press) if (!priv->emit_delayed_press)
g_signal_emit (action, drag_signals[DRAG_END], 0, g_signal_emit (action, drag_signals[DRAG_END], 0,
@ -334,8 +336,6 @@ emit_drag_end (ClutterDragAction *action,
} }
priv->sequence = NULL; priv->sequence = NULL;
priv->in_drag = FALSE;
} }
static gboolean static gboolean
@ -1062,12 +1062,14 @@ clutter_drag_action_get_drag_threshold (ClutterDragAction *action,
} }
static void static void
on_drag_handle_destroy (ClutterActor *actor, on_drag_handle_destroy (ClutterActor *handle,
ClutterDragAction *action) ClutterDragAction *action)
{ {
ClutterDragActionPrivate *priv = action->priv; ClutterDragActionPrivate *priv = action->priv;
ClutterActor *actor;
/* make sure we reset the state */ /* make sure we reset the state */
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
if (priv->in_drag) if (priv->in_drag)
emit_drag_end (action, actor, NULL); emit_drag_end (action, actor, NULL);