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
This commit is contained in:
Emmanuele Bassi 2011-08-30 10:47:12 +01:00
parent f1a7cd7c0f
commit d847d43f70

View File

@ -88,6 +88,8 @@ struct _ClutterDragActionPrivate
gfloat last_motion_x; gfloat last_motion_x;
gfloat last_motion_y; gfloat last_motion_y;
ClutterModifierType last_motion_state;
ClutterInputDevice *last_motion_device;
gfloat transformed_press_x; gfloat transformed_press_x;
gfloat transformed_press_y; gfloat transformed_press_y;
@ -191,6 +193,8 @@ emit_drag_motion (ClutterDragAction *action,
gfloat motion_x, motion_y; gfloat motion_x, motion_y;
clutter_event_get_coords (event, &priv->last_motion_x, &priv->last_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) if (priv->drag_handle != NULL && !priv->emit_delayed_press)
drag_handle = priv->drag_handle; drag_handle = priv->drag_handle;
@ -254,14 +258,23 @@ emit_drag_end (ClutterDragAction *action,
{ {
ClutterDragActionPrivate *priv = action->priv; 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 */ /* 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,
actor, actor,
priv->last_motion_x, priv->last_motion_y, priv->last_motion_x, priv->last_motion_y,
clutter_event_get_state (event)); priv->last_motion_state);
/* disconnect the capture */ /* disconnect the capture */
if (priv->capture_id != 0) if (priv->capture_id != 0)
@ -272,8 +285,9 @@ emit_drag_end (ClutterDragAction *action,
clutter_stage_set_motion_events_enabled (priv->stage, clutter_stage_set_motion_events_enabled (priv->stage,
priv->motion_events_enabled); 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; priv->in_drag = FALSE;
} }
@ -388,16 +402,20 @@ clutter_drag_action_set_actor (ClutterActorMeta *meta,
old_actor = clutter_actor_meta_get_actor (meta); old_actor = clutter_actor_meta_get_actor (meta);
g_signal_handler_disconnect (old_actor, priv->button_press_id); 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->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; priv->stage = NULL;
} }
clutter_drag_action_set_drag_handle (CLUTTER_DRAG_ACTION (meta), NULL);
priv->in_drag = FALSE;
if (actor != NULL) if (actor != NULL)
priv->button_press_id = g_signal_connect (actor, "button-press-event", priv->button_press_id = g_signal_connect (actor, "button-press-event",
G_CALLBACK (on_button_press), G_CALLBACK (on_button_press),
@ -849,7 +867,13 @@ static void
on_drag_handle_destroy (ClutterActor *actor, on_drag_handle_destroy (ClutterActor *actor,
ClutterDragAction *action) 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;
} }
/** /**