drag/drop actions: add touch event support

https://bugzilla.gnome.org/show_bug.cgi?id=678049
This commit is contained in:
Lionel Landwerlin 2012-06-13 16:02:05 +01:00
parent 1af7de8ac8
commit 132e4b98d1
4 changed files with 190 additions and 49 deletions

View File

@ -93,7 +93,9 @@ struct _ClutterDragActionPrivate
ClutterDragAxis drag_axis; ClutterDragAxis drag_axis;
ClutterInputDevice *device; ClutterInputDevice *device;
ClutterEventSequence *sequence;
gulong button_press_id; gulong button_press_id;
gulong touch_begin_id;
gulong capture_id; gulong capture_id;
gfloat press_x; gfloat press_x;
@ -183,11 +185,18 @@ emit_drag_begin (ClutterDragAction *action,
if (priv->stage != NULL) if (priv->stage != NULL)
{ {
clutter_stage_set_motion_events_enabled (priv->stage, FALSE); clutter_stage_set_motion_events_enabled (priv->stage, FALSE);
_clutter_stage_add_drag_actor (priv->stage, if (clutter_event_type (event) == CLUTTER_TOUCH_BEGIN)
clutter_event_get_device (event), _clutter_stage_add_touch_drag_actor (priv->stage,
priv->drag_handle != NULL clutter_event_get_event_sequence (event),
? priv->drag_handle priv->drag_handle != NULL
: actor); ? priv->drag_handle
: actor);
else
_clutter_stage_add_pointer_drag_actor (priv->stage,
clutter_event_get_device (event),
priv->drag_handle != NULL
? priv->drag_handle
: actor);
} }
g_signal_emit (action, drag_signals[DRAG_BEGIN], 0, g_signal_emit (action, drag_signals[DRAG_BEGIN], 0,
@ -301,7 +310,16 @@ emit_drag_end (ClutterDragAction *action,
priv->motion_events_enabled); priv->motion_events_enabled);
if (priv->last_motion_device != NULL) if (priv->last_motion_device != NULL)
_clutter_stage_remove_drag_actor (priv->stage, priv->last_motion_device); {
if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE)
_clutter_stage_remove_pointer_drag_actor (priv->stage,
priv->last_motion_device);
else
_clutter_stage_remove_touch_drag_actor (priv->stage,
priv->sequence);
}
priv->sequence = NULL;
priv->in_drag = FALSE; priv->in_drag = FALSE;
} }
@ -324,6 +342,11 @@ on_captured_event (ClutterActor *stage,
switch (clutter_event_type (event)) switch (clutter_event_type (event))
{ {
case CLUTTER_TOUCH_UPDATE:
if (clutter_event_get_event_sequence (event) == priv->sequence)
emit_drag_motion (action, actor, event);
break;
case CLUTTER_MOTION: case CLUTTER_MOTION:
{ {
ClutterModifierType mods = clutter_event_get_state (event); ClutterModifierType mods = clutter_event_get_state (event);
@ -339,6 +362,12 @@ on_captured_event (ClutterActor *stage,
} }
break; break;
case CLUTTER_TOUCH_END:
case CLUTTER_TOUCH_CANCEL:
if (clutter_event_get_event_sequence (event) == priv->sequence)
emit_drag_end (action, actor, event);
break;
case CLUTTER_BUTTON_RELEASE: case CLUTTER_BUTTON_RELEASE:
if (priv->in_drag) if (priv->in_drag)
emit_drag_end (action, actor, event); emit_drag_end (action, actor, event);
@ -358,9 +387,9 @@ on_captured_event (ClutterActor *stage,
} }
static gboolean static gboolean
on_button_press (ClutterActor *actor, on_drag_begin (ClutterActor *actor,
ClutterEvent *event, ClutterEvent *event,
ClutterDragAction *action) ClutterDragAction *action)
{ {
ClutterDragActionPrivate *priv = action->priv; ClutterDragActionPrivate *priv = action->priv;
@ -368,8 +397,22 @@ on_button_press (ClutterActor *actor,
return CLUTTER_EVENT_PROPAGATE; return CLUTTER_EVENT_PROPAGATE;
/* dragging is only performed using the primary button */ /* dragging is only performed using the primary button */
if (clutter_event_get_button (event) != CLUTTER_BUTTON_PRIMARY) switch (clutter_event_type (event))
return CLUTTER_EVENT_PROPAGATE; {
case CLUTTER_BUTTON_PRESS:
if (clutter_event_get_button (event) != CLUTTER_BUTTON_PRIMARY)
return CLUTTER_EVENT_PROPAGATE;
break;
case CLUTTER_TOUCH_BEGIN:
if (priv->sequence != NULL)
return CLUTTER_EVENT_PROPAGATE;
priv->sequence = clutter_event_get_event_sequence (event);
break;
default:
return CLUTTER_EVENT_PROPAGATE;
}
if (priv->stage == NULL) if (priv->stage == NULL)
priv->stage = CLUTTER_STAGE (clutter_actor_get_stage (actor)); priv->stage = CLUTTER_STAGE (clutter_actor_get_stage (actor));
@ -416,9 +459,13 @@ clutter_drag_action_set_actor (ClutterActorMeta *meta,
old_actor = clutter_actor_meta_get_actor (meta); old_actor = clutter_actor_meta_get_actor (meta);
if (old_actor != NULL) if (old_actor != NULL)
g_signal_handler_disconnect (old_actor, priv->button_press_id); {
g_signal_handler_disconnect (old_actor, priv->button_press_id);
g_signal_handler_disconnect (old_actor, priv->touch_begin_id);
}
priv->button_press_id = 0; priv->button_press_id = 0;
priv->touch_begin_id = 0;
} }
if (priv->capture_id != 0) if (priv->capture_id != 0)
@ -435,9 +482,14 @@ clutter_drag_action_set_actor (ClutterActorMeta *meta,
priv->in_drag = FALSE; priv->in_drag = FALSE;
if (actor != NULL) if (actor != NULL)
priv->button_press_id = g_signal_connect (actor, "button-press-event", {
G_CALLBACK (on_button_press), priv->button_press_id = g_signal_connect (actor, "button-press-event",
meta); G_CALLBACK (on_drag_begin),
meta);
priv->touch_begin_id = g_signal_connect (actor, "touch-event",
G_CALLBACK (on_drag_begin),
meta);
}
CLUTTER_ACTOR_META_CLASS (clutter_drag_action_parent_class)->set_actor (meta, actor); CLUTTER_ACTOR_META_CLASS (clutter_drag_action_parent_class)->set_actor (meta, actor);
} }
@ -555,9 +607,13 @@ clutter_drag_action_dispose (GObject *gobject)
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (gobject)); actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (gobject));
if (actor != NULL) if (actor != NULL)
g_signal_handler_disconnect (actor, priv->button_press_id); {
g_signal_handler_disconnect (actor, priv->button_press_id);
g_signal_handler_disconnect (actor, priv->touch_begin_id);
}
priv->button_press_id = 0; priv->button_press_id = 0;
priv->touch_begin_id = 0;
} }
clutter_drag_action_set_drag_handle (CLUTTER_DRAG_ACTION (gobject), NULL); clutter_drag_action_set_drag_handle (CLUTTER_DRAG_ACTION (gobject), NULL);

View File

@ -127,24 +127,40 @@ on_stage_capture (ClutterStage *stage,
{ {
DropTarget *data = user_data; DropTarget *data = user_data;
gfloat event_x, event_y; gfloat event_x, event_y;
ClutterInputDevice *device;
ClutterActor *actor, *drag_actor; ClutterActor *actor, *drag_actor;
ClutterDropAction *drop_action; ClutterDropAction *drop_action;
gboolean was_reactive; gboolean was_reactive;
if (!(clutter_event_type (event) == CLUTTER_MOTION || switch (clutter_event_type (event))
clutter_event_type (event) == CLUTTER_BUTTON_RELEASE)) {
return CLUTTER_EVENT_PROPAGATE; case CLUTTER_MOTION:
case CLUTTER_BUTTON_RELEASE:
{
ClutterInputDevice *device;
if (!(clutter_event_get_state (event) & CLUTTER_BUTTON1_MASK)) if (!(clutter_event_get_state (event) & CLUTTER_BUTTON1_MASK))
return CLUTTER_EVENT_PROPAGATE; return CLUTTER_EVENT_PROPAGATE;
device = clutter_event_get_device (event);
drag_actor = _clutter_stage_get_pointer_drag_actor (stage, device);
if (drag_actor == NULL)
return CLUTTER_EVENT_PROPAGATE;
}
break;
case CLUTTER_TOUCH_UPDATE:
case CLUTTER_TOUCH_END:
drag_actor = _clutter_stage_get_touch_drag_actor (stage,
clutter_event_get_event_sequence (event));
if (drag_actor == NULL)
return CLUTTER_EVENT_PROPAGATE;
break;
default:
return CLUTTER_EVENT_PROPAGATE;
}
clutter_event_get_coords (event, &event_x, &event_y); clutter_event_get_coords (event, &event_x, &event_y);
device = clutter_event_get_device (event);
drag_actor = _clutter_stage_get_drag_actor (stage, device);
if (drag_actor == NULL)
return CLUTTER_EVENT_PROPAGATE;
/* get the actor under the cursor, excluding the dragged actor; we /* get the actor under the cursor, excluding the dragged actor; we
* use reactivity because it won't cause any scene invalidation * use reactivity because it won't cause any scene invalidation
@ -210,7 +226,8 @@ on_stage_capture (ClutterStage *stage,
} }
out: out:
if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE) if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE ||
clutter_event_type (event) == CLUTTER_TOUCH_END)
{ {
if (data->last_action != NULL) if (data->last_action != NULL)
{ {

View File

@ -101,13 +101,21 @@ void _clutter_stage_release_pick_id (ClutterStage *stage,
ClutterActor * _clutter_stage_get_actor_by_pick_id (ClutterStage *stage, ClutterActor * _clutter_stage_get_actor_by_pick_id (ClutterStage *stage,
gint32 pick_id); gint32 pick_id);
void _clutter_stage_add_drag_actor (ClutterStage *stage, void _clutter_stage_add_pointer_drag_actor (ClutterStage *stage,
ClutterInputDevice *device, ClutterInputDevice *device,
ClutterActor *actor); ClutterActor *actor);
ClutterActor * _clutter_stage_get_drag_actor (ClutterStage *stage, ClutterActor * _clutter_stage_get_pointer_drag_actor (ClutterStage *stage,
ClutterInputDevice *device); ClutterInputDevice *device);
void _clutter_stage_remove_drag_actor (ClutterStage *stage, void _clutter_stage_remove_pointer_drag_actor (ClutterStage *stage,
ClutterInputDevice *device); ClutterInputDevice *device);
void _clutter_stage_add_touch_drag_actor (ClutterStage *stage,
ClutterEventSequence *sequence,
ClutterActor *actor);
ClutterActor * _clutter_stage_get_touch_drag_actor (ClutterStage *stage,
ClutterEventSequence *sequence);
void _clutter_stage_remove_touch_drag_actor (ClutterStage *stage,
ClutterEventSequence *sequence);
ClutterStageState _clutter_stage_get_state (ClutterStage *stage); ClutterStageState _clutter_stage_get_state (ClutterStage *stage);
gboolean _clutter_stage_is_activated (ClutterStage *stage); gboolean _clutter_stage_is_activated (ClutterStage *stage);

View File

@ -4299,17 +4299,19 @@ _clutter_stage_get_actor_by_pick_id (ClutterStage *stage,
} }
void void
_clutter_stage_add_drag_actor (ClutterStage *stage, _clutter_stage_add_pointer_drag_actor (ClutterStage *stage,
ClutterInputDevice *device, ClutterInputDevice *device,
ClutterActor *actor) ClutterActor *actor)
{ {
GHashTable *drag_actors; GHashTable *drag_actors;
drag_actors = g_object_get_data (G_OBJECT (stage), "__clutter_stage_drag_actors"); drag_actors = g_object_get_data (G_OBJECT (stage),
"__clutter_stage_pointer_drag_actors");
if (drag_actors == NULL) if (drag_actors == NULL)
{ {
drag_actors = g_hash_table_new (NULL, NULL); drag_actors = g_hash_table_new (NULL, NULL);
g_object_set_data_full (G_OBJECT (stage), "__clutter_stage_drag_actors", g_object_set_data_full (G_OBJECT (stage),
"__clutter_stage_pointer_drag_actors",
drag_actors, drag_actors,
(GDestroyNotify) g_hash_table_destroy); (GDestroyNotify) g_hash_table_destroy);
} }
@ -4318,12 +4320,13 @@ _clutter_stage_add_drag_actor (ClutterStage *stage,
} }
ClutterActor * ClutterActor *
_clutter_stage_get_drag_actor (ClutterStage *stage, _clutter_stage_get_pointer_drag_actor (ClutterStage *stage,
ClutterInputDevice *device) ClutterInputDevice *device)
{ {
GHashTable *drag_actors; GHashTable *drag_actors;
drag_actors = g_object_get_data (G_OBJECT (stage), "__clutter_stage_drag_actors"); drag_actors = g_object_get_data (G_OBJECT (stage),
"__clutter_stage_pointer_drag_actors");
if (drag_actors == NULL) if (drag_actors == NULL)
return NULL; return NULL;
@ -4331,19 +4334,76 @@ _clutter_stage_get_drag_actor (ClutterStage *stage,
} }
void void
_clutter_stage_remove_drag_actor (ClutterStage *stage, _clutter_stage_remove_pointer_drag_actor (ClutterStage *stage,
ClutterInputDevice *device) ClutterInputDevice *device)
{ {
GHashTable *drag_actors; GHashTable *drag_actors;
drag_actors = g_object_get_data (G_OBJECT (stage), "__clutter_stage_drag_actors"); drag_actors = g_object_get_data (G_OBJECT (stage),
"__clutter_stage_pointer_drag_actors");
if (drag_actors == NULL) if (drag_actors == NULL)
return; return;
g_hash_table_remove (drag_actors, device); g_hash_table_remove (drag_actors, device);
if (g_hash_table_size (drag_actors) == 0) if (g_hash_table_size (drag_actors) == 0)
g_object_set_data (G_OBJECT (stage), "__clutter_stage_drag_actors", NULL); g_object_set_data (G_OBJECT (stage),
"__clutter_stage_pointer_drag_actors",
NULL);
}
void
_clutter_stage_add_touch_drag_actor (ClutterStage *stage,
ClutterEventSequence *sequence,
ClutterActor *actor)
{
GHashTable *drag_actors;
drag_actors = g_object_get_data (G_OBJECT (stage),
"__clutter_stage_touch_drag_actors");
if (drag_actors == NULL)
{
drag_actors = g_hash_table_new (NULL, NULL);
g_object_set_data_full (G_OBJECT (stage),
"__clutter_stage_touch_drag_actors",
drag_actors,
(GDestroyNotify) g_hash_table_destroy);
}
g_hash_table_replace (drag_actors, sequence, actor);
}
ClutterActor *
_clutter_stage_get_touch_drag_actor (ClutterStage *stage,
ClutterEventSequence *sequence)
{
GHashTable *drag_actors;
drag_actors = g_object_get_data (G_OBJECT (stage),
"__clutter_stage_touch_drag_actors");
if (drag_actors == NULL)
return NULL;
return g_hash_table_lookup (drag_actors, sequence);
}
void
_clutter_stage_remove_touch_drag_actor (ClutterStage *stage,
ClutterEventSequence *sequence)
{
GHashTable *drag_actors;
drag_actors = g_object_get_data (G_OBJECT (stage),
"__clutter_stage_touch_drag_actors");
if (drag_actors == NULL)
return;
g_hash_table_remove (drag_actors, sequence);
if (g_hash_table_size (drag_actors) == 0)
g_object_set_data (G_OBJECT (stage),
"__clutter_stage_touch_drag_actors",
NULL);
} }
/*< private > /*< private >