summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLucas Rocha <lucasr@gnome.org>2010-11-11 22:23:09 +0000
committerEmmanuele Bassi <ebassi@linux.intel.com>2010-11-30 11:46:01 +0000
commit548afc4d35c4525be04bc0d1ae4d2b3b7a8a30d1 (patch)
treee9d53b43ccf850f14e20c438d7d4e6af76c3ef00
parent5dc3dbcccb822924fc2938a25ed7320a20851da7 (diff)
downloadclutter-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.c85
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);
}