From d847d43f70d29be78b529b19046b453a05135fa3 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 30 Aug 2011 10:47:12 +0100 Subject: [PATCH] actions/drag: Be more reliable when destroying the drag handle Whenever the drag handle gets destroyed mid-drag we need to cancel any current drag operation and reset the state of the DragAction. https://bugzilla.gnome.org/show_bug.cgi?id=657681 --- clutter/clutter-drag-action.c | 44 +++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/clutter/clutter-drag-action.c b/clutter/clutter-drag-action.c index c8302be1b..cf3760097 100644 --- a/clutter/clutter-drag-action.c +++ b/clutter/clutter-drag-action.c @@ -88,6 +88,8 @@ struct _ClutterDragActionPrivate gfloat last_motion_x; gfloat last_motion_y; + ClutterModifierType last_motion_state; + ClutterInputDevice *last_motion_device; gfloat transformed_press_x; gfloat transformed_press_y; @@ -191,6 +193,8 @@ emit_drag_motion (ClutterDragAction *action, gfloat motion_x, motion_y; clutter_event_get_coords (event, &priv->last_motion_x, &priv->last_motion_y); + priv->last_motion_state = clutter_event_get_state (event); + priv->last_motion_device = clutter_event_get_device (event); if (priv->drag_handle != NULL && !priv->emit_delayed_press) drag_handle = priv->drag_handle; @@ -254,14 +258,23 @@ emit_drag_end (ClutterDragAction *action, { ClutterDragActionPrivate *priv = action->priv; - clutter_event_get_coords (event, &priv->last_motion_x, &priv->last_motion_y); + /* if we have an event, update our own state, otherwise we'll + * just use the currently stored state when emitting the ::drag-end + * signal + */ + if (event != NULL) + { + clutter_event_get_coords (event, &priv->last_motion_x, &priv->last_motion_y); + priv->last_motion_state = clutter_event_get_state (event); + priv->last_motion_device = clutter_event_get_device (event); + } /* we might not have emitted ::drag-begin yet */ if (!priv->emit_delayed_press) g_signal_emit (action, drag_signals[DRAG_END], 0, actor, priv->last_motion_x, priv->last_motion_y, - clutter_event_get_state (event)); + priv->last_motion_state); /* disconnect the capture */ if (priv->capture_id != 0) @@ -272,8 +285,9 @@ emit_drag_end (ClutterDragAction *action, clutter_stage_set_motion_events_enabled (priv->stage, priv->motion_events_enabled); - _clutter_stage_remove_drag_actor (priv->stage, - clutter_event_get_device (event)); + + if (priv->last_motion_device != NULL) + _clutter_stage_remove_drag_actor (priv->stage, priv->last_motion_device); priv->in_drag = FALSE; } @@ -388,16 +402,20 @@ clutter_drag_action_set_actor (ClutterActorMeta *meta, old_actor = clutter_actor_meta_get_actor (meta); g_signal_handler_disconnect (old_actor, priv->button_press_id); - - if (priv->capture_id != 0) - g_signal_handler_disconnect (old_actor, priv->capture_id); - priv->button_press_id = 0; - priv->capture_id = 0; + } + if (priv->capture_id != 0 && priv->stage != NULL) + { + g_signal_handler_disconnect (priv->stage, priv->capture_id); + priv->capture_id = 0; priv->stage = NULL; } + clutter_drag_action_set_drag_handle (CLUTTER_DRAG_ACTION (meta), NULL); + + priv->in_drag = FALSE; + if (actor != NULL) priv->button_press_id = g_signal_connect (actor, "button-press-event", G_CALLBACK (on_button_press), @@ -849,7 +867,13 @@ static void on_drag_handle_destroy (ClutterActor *actor, ClutterDragAction *action) { - action->priv->drag_handle = NULL; + ClutterDragActionPrivate *priv = action->priv; + + /* make sure we reset the state */ + if (priv->in_drag) + emit_drag_end (action, actor, NULL); + + priv->drag_handle = NULL; } /**