[clutter/android-enter-leave: 23/29] gesture-action: add multiple point support and touch events support
- From: Lionel Landwerlin <llandwerlin src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [clutter/android-enter-leave: 23/29] gesture-action: add multiple point support and touch events support
- Date: Wed, 11 Jul 2012 17:08:59 +0000 (UTC)
commit 86603abd6f4c090a74250f214b3fa009fcefc073
Author: Lionel Landwerlin <llandwerlin gmail com>
Date: Thu Jun 21 02:55:56 2012 +0100
gesture-action: add multiple point support and touch events support
https://bugzilla.gnome.org/show_bug.cgi?id=678586
clutter/clutter-gesture-action.c | 340 ++++++++++++++++++++++------
clutter/clutter-gesture-action.h | 3 +
clutter/clutter.symbols | 2 +
doc/reference/clutter/clutter-sections.txt | 2 +
4 files changed, 273 insertions(+), 74 deletions(-)
---
diff --git a/clutter/clutter-gesture-action.c b/clutter/clutter-gesture-action.c
index 15da745..35e6fbd 100644
--- a/clutter/clutter-gesture-action.c
+++ b/clutter/clutter-gesture-action.c
@@ -5,6 +5,7 @@
*
* Copyright (C) 2010 Intel Corporation.
* Copyright (C) 2011 Robert Bosch Car Multimedia GmbH.
+ * Copyright (C) 2012 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -61,18 +62,29 @@
#include "clutter-marshal.h"
#include "clutter-private.h"
+#define MAX_GESTURE_POINTS (10)
+
+typedef struct
+{
+ ClutterInputDevice *device;
+ ClutterEventSequence *sequence;
+
+ gfloat press_x, press_y;
+ gfloat last_motion_x, last_motion_y;
+ gfloat release_x, release_y;
+} GesturePoint;
+
struct _ClutterGestureActionPrivate
{
ClutterActor *stage;
+ gint requested_nb_points;
+ GArray *points;
+
guint actor_capture_id;
gulong stage_capture_id;
- gfloat press_x, press_y;
- gfloat last_motion_x, last_motion_y;
- gfloat release_x, release_y;
-
- guint in_drag : 1;
+ guint in_gesture : 1;
};
enum
@@ -89,6 +101,72 @@ static guint gesture_signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (ClutterGestureAction, clutter_gesture_action, CLUTTER_TYPE_ACTION);
+static GesturePoint *
+gesture_register_point (ClutterGestureAction *action, ClutterEvent *event)
+{
+ ClutterGestureActionPrivate *priv = action->priv;
+ GesturePoint *point = NULL;
+
+ if (priv->points->len >= MAX_GESTURE_POINTS)
+ return NULL;
+
+ g_array_set_size (priv->points, priv->points->len + 1);
+ point = &g_array_index (priv->points, GesturePoint, priv->points->len - 1);
+
+ point->device = clutter_event_get_device (event);
+
+ clutter_event_get_coords (event, &point->press_x, &point->press_y);
+ point->last_motion_x = point->press_x;
+ point->last_motion_y = point->press_y;
+
+ if (clutter_event_type (event) != CLUTTER_BUTTON_PRESS)
+ point->sequence = clutter_event_get_event_sequence (event);
+ else
+ point->sequence = NULL;
+
+ return point;
+}
+
+static GesturePoint *
+gesture_find_point (ClutterGestureAction *action,
+ ClutterEvent *event,
+ gint *position)
+{
+ ClutterGestureActionPrivate *priv = action->priv;
+ GesturePoint *point = NULL;
+ ClutterEventType type = clutter_event_type (event);
+ ClutterInputDevice *device = clutter_event_get_device (event);
+ ClutterEventSequence *sequence = NULL;
+ gint i;
+
+ if ((type != CLUTTER_BUTTON_PRESS) &&
+ (type != CLUTTER_BUTTON_RELEASE) &&
+ (type != CLUTTER_MOTION))
+ sequence = clutter_event_get_event_sequence (event);
+
+ for (i = 0; i < priv->points->len; i++)
+ {
+ if ((g_array_index (priv->points, GesturePoint, i).device == device) &&
+ (g_array_index (priv->points, GesturePoint, i).sequence == sequence))
+ {
+ if (position != NULL)
+ *position = i;
+ point = &g_array_index (priv->points, GesturePoint, i);
+ break;
+ }
+ }
+
+ return point;
+}
+
+static void
+gesture_unregister_point (ClutterGestureAction *action, gint position)
+{
+ ClutterGestureActionPrivate *priv = action->priv;
+
+ g_array_remove_index (priv->points, position);
+}
+
static gboolean
signal_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu,
@@ -109,7 +187,7 @@ cancel_gesture (ClutterGestureAction *action)
ClutterGestureActionPrivate *priv = action->priv;
ClutterActor *actor;
- priv->in_drag = FALSE;
+ priv->in_gesture = FALSE;
g_signal_handler_disconnect (priv->stage, priv->stage_capture_id);
priv->stage_capture_id = 0;
@@ -125,7 +203,12 @@ stage_captured_event_cb (ClutterActor *stage,
{
ClutterGestureActionPrivate *priv = action->priv;
ClutterActor *actor;
+ gint position;
gboolean return_value;
+ GesturePoint *point;
+
+ if ((point = gesture_find_point (action, event, &position)) == NULL)
+ return CLUTTER_EVENT_PROPAGATE;
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
@@ -144,64 +227,77 @@ stage_captured_event_cb (ClutterActor *stage,
cancel_gesture (action);
return CLUTTER_EVENT_PROPAGATE;
}
+ }
+ /* Follow same code path as a touch event update */
- clutter_event_get_coords (event, &priv->last_motion_x,
- &priv->last_motion_y);
+ case CLUTTER_TOUCH_UPDATE:
+ clutter_event_get_coords (event,
+ &point->last_motion_x,
+ &point->last_motion_y);
- if (!clutter_actor_transform_stage_point (actor,
- priv->last_motion_x,
- priv->last_motion_y,
- NULL, NULL))
- return CLUTTER_EVENT_PROPAGATE;
+ if (priv->points->len < priv->requested_nb_points)
+ return CLUTTER_EVENT_PROPAGATE;
- if (!priv->in_drag)
- {
- gint drag_threshold;
- ClutterSettings *settings = clutter_settings_get_default ();
-
- g_object_get (settings,
- "dnd-drag-threshold", &drag_threshold,
- NULL);
-
- if ((ABS (priv->press_y - priv->last_motion_y) >= drag_threshold) ||
- (ABS (priv->press_x - priv->last_motion_x) >= drag_threshold))
- {
- priv->in_drag = TRUE;
-
- g_signal_emit (action, gesture_signals[GESTURE_BEGIN], 0, actor,
- &return_value);
- if (!return_value)
- {
- cancel_gesture (action);
- return CLUTTER_EVENT_PROPAGATE;
- }
- }
- else
- return CLUTTER_EVENT_PROPAGATE;
- }
+ if (!priv->in_gesture)
+ {
+ gint drag_threshold;
+ ClutterSettings *settings = clutter_settings_get_default ();
- g_signal_emit (action, gesture_signals[GESTURE_PROGRESS], 0, actor,
- &return_value);
- if (!return_value)
+ g_object_get (settings,
+ "dnd-drag-threshold", &drag_threshold,
+ NULL);
+
+ if ((ABS (point->press_y - point->last_motion_y) >= drag_threshold) ||
+ (ABS (point->press_x - point->last_motion_x) >= drag_threshold))
{
- cancel_gesture (action);
- return CLUTTER_EVENT_PROPAGATE;
+ priv->in_gesture = TRUE;
+
+ g_signal_emit (action, gesture_signals[GESTURE_BEGIN], 0, actor,
+ &return_value);
+ if (!return_value)
+ {
+ cancel_gesture (action);
+ return CLUTTER_EVENT_PROPAGATE;
+ }
}
- }
+ else
+ return CLUTTER_EVENT_PROPAGATE;
+ }
+
+ g_signal_emit (action, gesture_signals[GESTURE_PROGRESS], 0, actor,
+ &return_value);
+ if (!return_value)
+ {
+ cancel_gesture (action);
+ return CLUTTER_EVENT_PROPAGATE;
+ }
break;
case CLUTTER_BUTTON_RELEASE:
+ case CLUTTER_TOUCH_END:
{
- clutter_event_get_coords (event, &priv->release_x, &priv->release_y);
-
- g_signal_handler_disconnect (priv->stage, priv->stage_capture_id);
- priv->stage_capture_id = 0;
+ clutter_event_get_coords (event, &point->release_x, &point->release_y);
- if (priv->in_drag)
+ if (priv->in_gesture &&
+ ((priv->points->len - 1) < priv->requested_nb_points))
{
- priv->in_drag = FALSE;
+ priv->in_gesture = FALSE;
g_signal_emit (action, gesture_signals[GESTURE_END], 0, actor);
}
+
+ gesture_unregister_point (action, position);
+ }
+ break;
+
+ case CLUTTER_TOUCH_CANCEL:
+ {
+ if (priv->in_gesture)
+ {
+ priv->in_gesture = FALSE;
+ cancel_gesture (action);
+ }
+
+ gesture_unregister_point (action, position);
}
break;
@@ -209,6 +305,12 @@ stage_captured_event_cb (ClutterActor *stage,
break;
}
+ if (priv->points->len == 0)
+ {
+ g_signal_handler_disconnect (priv->stage, priv->stage_capture_id);
+ priv->stage_capture_id = 0;
+ }
+
return CLUTTER_EVENT_PROPAGATE;
}
@@ -218,22 +320,25 @@ actor_captured_event_cb (ClutterActor *actor,
ClutterGestureAction *action)
{
ClutterGestureActionPrivate *priv = action->priv;
+ GesturePoint *point;
- if (clutter_event_type (event) != CLUTTER_BUTTON_PRESS)
+ if ((clutter_event_type (event) != CLUTTER_BUTTON_PRESS) &&
+ (clutter_event_type (event) != CLUTTER_TOUCH_BEGIN))
return CLUTTER_EVENT_PROPAGATE;
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action)))
return CLUTTER_EVENT_PROPAGATE;
- clutter_event_get_coords (event, &priv->press_x, &priv->press_y);
+ point = gesture_register_point (action, event);
if (priv->stage == NULL)
priv->stage = clutter_actor_get_stage (actor);
- priv->stage_capture_id =
- g_signal_connect_after (priv->stage, "captured-event",
- G_CALLBACK (stage_captured_event_cb),
- action);
+ if (priv->stage_capture_id == 0)
+ priv->stage_capture_id =
+ g_signal_connect_after (priv->stage, "captured-event",
+ G_CALLBACK (stage_captured_event_cb),
+ action);
return CLUTTER_EVENT_PROPAGATE;
}
@@ -394,9 +499,8 @@ clutter_gesture_action_init (ClutterGestureAction *self)
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, CLUTTER_TYPE_GESTURE_ACTION,
ClutterGestureActionPrivate);
- self->priv->press_x = self->priv->press_y = 0.f;
- self->priv->last_motion_x = self->priv->last_motion_y = 0.f;
- self->priv->release_x = self->priv->release_y = 0.f;
+ self->priv->points = g_array_sized_new (FALSE, TRUE, sizeof (GesturePoint), 3);
+ self->priv->requested_nb_points = 1;
}
/**
@@ -433,15 +537,17 @@ clutter_gesture_action_get_press_coords (ClutterGestureAction *action,
gfloat *press_y)
{
g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
-
- if (device != 0)
- g_warning ("Multi-device support not yet implemented");
+ g_return_if_fail (action->priv->points->len > device);
if (press_x)
- *press_x = action->priv->press_x;
+ *press_x = g_array_index (action->priv->points,
+ GesturePoint,
+ device).press_x;
if (press_y)
- *press_y = action->priv->press_y;
+ *press_y = g_array_index (action->priv->points,
+ GesturePoint,
+ device).press_y;
}
/**
@@ -465,15 +571,17 @@ clutter_gesture_action_get_motion_coords (ClutterGestureAction *action,
gfloat *motion_y)
{
g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
-
- if (device != 0)
- g_warning ("Multi-device support not yet implemented");
+ g_return_if_fail (action->priv->points->len > device);
if (motion_x)
- *motion_x = action->priv->last_motion_x;
+ *motion_x = g_array_index (action->priv->points,
+ GesturePoint,
+ device).last_motion_x;
if (motion_y)
- *motion_y = action->priv->last_motion_y;
+ *motion_y = g_array_index (action->priv->points,
+ GesturePoint,
+ device).last_motion_y;
}
/**
@@ -495,13 +603,97 @@ clutter_gesture_action_get_release_coords (ClutterGestureAction *action,
gfloat *release_y)
{
g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
-
- if (device != 0)
- g_warning ("Multi-device support not yet implemented");
+ g_return_if_fail (action->priv->points->len > device);
if (release_x)
- *release_x = action->priv->release_x;
+ *release_x = g_array_index (action->priv->points,
+ GesturePoint,
+ device).release_x;
if (release_y)
- *release_y = action->priv->release_y;
+ *release_y = g_array_index (action->priv->points,
+ GesturePoint,
+ device).release_y;
+}
+
+/**
+ * clutter_gesture_action_get_n_touch_points:
+ * @action: a #ClutterGestureAction
+ *
+ * Retrieves the number of requested points to trigger the gesture.
+ *
+ * Return value: the number of points to trigger the gesture.
+ *
+ * Since: 1.12
+ */
+gint
+clutter_gesture_action_get_n_touch_points (ClutterGestureAction *action)
+{
+ g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0);
+
+ return action->priv->requested_nb_points;
+}
+
+/**
+ * clutter_gesture_action_set_n_touch_points:
+ * @action: a #ClutterGestureAction
+ * @nb_points: a number of points
+ *
+ * Sets the number of points needed to trigger the gesture.
+ *
+ * Since: 1.12
+ */
+void
+clutter_gesture_action_set_n_touch_points (ClutterGestureAction *action,
+ gint nb_points)
+{
+ ClutterGestureActionPrivate *priv;
+
+ g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
+ g_return_if_fail (nb_points >= 1);
+
+ priv = action->priv;
+
+ priv->requested_nb_points = nb_points;
+
+ if (priv->in_gesture)
+ {
+ if (priv->points->len < priv->requested_nb_points)
+ cancel_gesture (action);
+ }
+ else
+ {
+ if (priv->points->len >= priv->requested_nb_points)
+ {
+ ClutterActor *actor =
+ clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
+ ClutterSettings *settings = clutter_settings_get_default ();
+ gint i, drag_threshold;
+
+ g_object_get (settings,
+ "dnd-drag-threshold", &drag_threshold,
+ NULL);
+
+ for (i = 0; i < priv->points->len; i++)
+ {
+ GesturePoint *point = &g_array_index (priv->points, GesturePoint, i);
+
+ if ((ABS (point->press_y - point->last_motion_y) >= drag_threshold) ||
+ (ABS (point->press_x - point->last_motion_x) >= drag_threshold))
+ {
+ gboolean return_value;
+
+ priv->in_gesture = TRUE;
+
+ g_signal_emit (action, gesture_signals[GESTURE_BEGIN], 0, actor,
+ &return_value);
+
+ if (!return_value)
+ cancel_gesture (action);
+
+ break;
+ }
+ }
+ }
+ }
}
diff --git a/clutter/clutter-gesture-action.h b/clutter/clutter-gesture-action.h
index 02af94b..5a1b168 100644
--- a/clutter/clutter-gesture-action.h
+++ b/clutter/clutter-gesture-action.h
@@ -102,6 +102,9 @@ GType clutter_gesture_action_get_type (void) G_GNUC_CONST;
ClutterAction * clutter_gesture_action_new (void);
+gint clutter_gesture_action_get_n_touch_points (ClutterGestureAction *action);
+void clutter_gesture_action_set_n_touch_points (ClutterGestureAction *action,
+ gint nb_points);
void clutter_gesture_action_get_press_coords (ClutterGestureAction *action,
guint device,
gfloat *press_x,
diff --git a/clutter/clutter.symbols b/clutter/clutter.symbols
index 5c65e96..106f82d 100644
--- a/clutter/clutter.symbols
+++ b/clutter/clutter.symbols
@@ -695,9 +695,11 @@ clutter_geometry_get_type
clutter_geometry_intersects
clutter_geometry_union
clutter_gesture_action_get_motion_coords
+clutter_gesture_action_get_n_touch_points
clutter_gesture_action_get_press_coords
clutter_gesture_action_get_release_coords
clutter_gesture_action_get_type
+clutter_gesture_action_set_n_touch_points
clutter_gesture_action_new
clutter_get_accessibility_enabled
clutter_get_actor_by_gid
diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt
index cdb74a1..7f93e7c 100644
--- a/doc/reference/clutter/clutter-sections.txt
+++ b/doc/reference/clutter/clutter-sections.txt
@@ -2918,6 +2918,8 @@ clutter_gesture_action_new
clutter_gesture_action_get_press_coords
clutter_gesture_action_get_motion_coords
clutter_gesture_action_get_release_coords
+clutter_gesture_action_get_n_touch_points
+clutter_gesture_action_set_n_touch_points
<SUBSECTION Standard>
CLUTTER_GESTURE_ACTION
CLUTTER_GESTURE_ACTION_CLASS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]