diff options
author | Lucas Rocha <lucasr@gnome.org> | 2010-11-11 22:23:09 +0000 |
---|---|---|
committer | Emmanuele Bassi <ebassi@linux.intel.com> | 2010-11-30 11:46:01 +0000 |
commit | 548afc4d35c4525be04bc0d1ae4d2b3b7a8a30d1 (patch) | |
tree | e9d53b43ccf850f14e20c438d7d4e6af76c3ef00 | |
parent | 5dc3dbcccb822924fc2938a25ed7320a20851da7 (diff) | |
download | clutter-548afc4d35c4525be04bc0d1ae4d2b3b7a8a30d1.tar.gz |
click-action: don't use pointer grabs
The same behavior can be achieved by capturing events on stage while
button is pressed. This fixes a problem when using click and drag
actions on the same actor as there no grabs involved.
http://bugzilla.clutter-project.org/show_bug.cgi?id=2409
(cherry picked from commit 03a713e18e842d29a73f9cefb38e689ceefb35ed)
Signed-off-by: Emmanuele Bassi <ebassi@linux.intel.com>
-rw-r--r-- | clutter/clutter-click-action.c | 85 |
1 files changed, 67 insertions, 18 deletions
diff --git a/clutter/clutter-click-action.c b/clutter/clutter-click-action.c index 116e75e5f..be1fffecf 100644 --- a/clutter/clutter-click-action.c +++ b/clutter/clutter-click-action.c @@ -61,7 +61,10 @@ struct _ClutterClickActionPrivate { + ClutterActor *stage; + guint event_id; + gulong capture_id; guint press_button; @@ -92,6 +95,11 @@ static guint click_signals[LAST_SIGNAL] = { 0, }; G_DEFINE_TYPE (ClutterClickAction, clutter_click_action, CLUTTER_TYPE_ACTION); +/* forward declaration */ +static gboolean on_captured_event (ClutterActor *stage, + ClutterEvent *event, + ClutterClickAction *action); + static inline void click_action_set_pressed (ClutterClickAction *action, gboolean is_pressed) @@ -111,7 +119,6 @@ on_event (ClutterActor *actor, ClutterClickAction *action) { ClutterClickActionPrivate *priv = action->priv; - gboolean res = FALSE; if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action))) return FALSE; @@ -130,44 +137,73 @@ on_event (ClutterActor *actor, priv->is_held = TRUE; priv->press_button = clutter_event_get_button (event); - clutter_grab_pointer (actor); + + if (priv->stage == NULL) + priv->stage = clutter_actor_get_stage (actor); + + priv->capture_id = g_signal_connect_after (priv->stage, "captured-event", + G_CALLBACK (on_captured_event), + action); click_action_set_pressed (action, TRUE); - res = TRUE; break; + case CLUTTER_ENTER: + click_action_set_pressed (action, priv->is_held); + break; + + case CLUTTER_LEAVE: + click_action_set_pressed (action, priv->is_held); + break; + + default: + break; + } + + return FALSE; +} + +static gboolean +on_captured_event (ClutterActor *stage, + ClutterEvent *event, + ClutterClickAction *action) +{ + ClutterClickActionPrivate *priv = action->priv; + ClutterActor *actor; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)); + + switch (clutter_event_type (event)) + { case CLUTTER_BUTTON_RELEASE: + if (!priv->is_held) + return TRUE; + if (clutter_event_get_button (event) != priv->press_button || clutter_event_get_click_count (event) != 1) return FALSE; - if (!priv->is_held) - return TRUE; - priv->is_held = FALSE; - clutter_ungrab_pointer (); + + /* disconnect the capture */ + if (priv->capture_id != 0) + { + g_signal_handler_disconnect (priv->stage, priv->capture_id); + priv->capture_id = 0; + } if (!clutter_actor_contains (actor, clutter_event_get_source (event))) return FALSE; click_action_set_pressed (action, FALSE); g_signal_emit (action, click_signals[CLICKED], 0, actor); - res = TRUE; - break; - - case CLUTTER_ENTER: - click_action_set_pressed (action, priv->is_held); - break; - - case CLUTTER_LEAVE: - click_action_set_pressed (action, priv->is_held); break; default: break; } - return res; + return FALSE; } static void @@ -184,6 +220,13 @@ clutter_click_action_set_actor (ClutterActorMeta *meta, priv->event_id = 0; } + if (priv->capture_id != 0) + { + g_signal_handler_disconnect (priv->stage, priv->capture_id); + priv->capture_id = 0; + priv->stage = NULL; + } + if (actor != NULL) priv->event_id = g_signal_connect (actor, "event", G_CALLBACK (on_event), @@ -328,7 +371,13 @@ clutter_click_action_release (ClutterClickAction *action) return; priv->is_held = FALSE; - clutter_ungrab_pointer (); + + /* disconnect the capture */ + if (priv->capture_id != 0) + { + g_signal_handler_disconnect (priv->stage, priv->capture_id); + priv->capture_id = 0; + } click_action_set_pressed (action, FALSE); } |