summaryrefslogtreecommitdiff
path: root/clutter/clutter/clutter-gesture-action.c
diff options
context:
space:
mode:
Diffstat (limited to 'clutter/clutter/clutter-gesture-action.c')
-rw-r--r--clutter/clutter/clutter-gesture-action.c1455
1 files changed, 0 insertions, 1455 deletions
diff --git a/clutter/clutter/clutter-gesture-action.c b/clutter/clutter/clutter-gesture-action.c
deleted file mode 100644
index f938a549a..000000000
--- a/clutter/clutter/clutter-gesture-action.c
+++ /dev/null
@@ -1,1455 +0,0 @@
-/*
- * Clutter.
- *
- * An OpenGL based 'interactive canvas' library.
- *
- * 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- * Tomeu Vizoso <tomeu.vizoso@collabora.co.uk>
- */
-
-/**
- * SECTION:clutter-gesture-action
- * @Title: ClutterGestureAction
- * @Short_Description: Action for gesture gestures
- *
- * #ClutterGestureAction is a sub-class of #ClutterAction that implements
- * the logic for recognizing gesture gestures. It listens for low level events
- * such as #ClutterButtonEvent and #ClutterMotionEvent on the stage to raise
- * the #ClutterGestureAction::gesture-begin, #ClutterGestureAction::gesture-progress,
- * and #ClutterGestureAction::gesture-end signals.
- *
- * To use #ClutterGestureAction you just need to apply it to a #ClutterActor
- * using clutter_actor_add_action() and connect to the signals:
- *
- * |[<!-- language="C" -->
- * ClutterAction *action = clutter_gesture_action_new ();
- *
- * clutter_actor_add_action (actor, action);
- *
- * g_signal_connect (action, "gesture-begin", G_CALLBACK (on_gesture_begin), NULL);
- * g_signal_connect (action, "gesture-progress", G_CALLBACK (on_gesture_progress), NULL);
- * g_signal_connect (action, "gesture-end", G_CALLBACK (on_gesture_end), NULL);
- * ]|
- *
- * ## Creating Gesture actions
- *
- * A #ClutterGestureAction provides four separate states that can be
- * used to recognize or ignore gestures when writing a new action class:
- *
- * - Prepare -> Cancel
- * - Prepare -> Begin -> Cancel
- * - Prepare -> Begin -> End
- * - Prepare -> Begin -> Progress -> Cancel
- * - Prepare -> Begin -> Progress -> End
- *
- * Each #ClutterGestureAction starts in the "prepare" state, and calls
- * the #ClutterGestureActionClass.gesture_prepare() virtual function; this
- * state can be used to reset the internal state of a #ClutterGestureAction
- * subclass, but it can also immediately cancel a gesture without going
- * through the rest of the states.
- *
- * The "begin" state follows the "prepare" state, and calls the
- * #ClutterGestureActionClass.gesture_begin() virtual function. This state
- * signals the start of a gesture recognizing process. From the "begin" state
- * the gesture recognition process can successfully end, by going to the
- * "end" state; it can continue in the "progress" state, in case of a
- * continuous gesture; or it can be terminated, by moving to the "cancel"
- * state.
- *
- * In case of continuous gestures, the #ClutterGestureAction will use
- * the "progress" state, calling the #ClutterGestureActionClass.gesture_progress()
- * virtual function; the "progress" state will continue until the end of the
- * gesture, in which case the "end" state will be reached, or until the
- * gesture is cancelled, in which case the "cancel" gesture will be used
- * instead.
- *
- * Since: 1.8
- */
-
-#include "clutter-build-config.h"
-
-#include "clutter-gesture-action-private.h"
-
-#include "clutter-debug.h"
-#include "clutter-enum-types.h"
-#include "clutter-marshal.h"
-#include "clutter-private.h"
-
-#include <math.h>
-
-#define MAX_GESTURE_POINTS (10)
-#define FLOAT_EPSILON (1e-15)
-
-typedef struct
-{
- ClutterInputDevice *device;
- ClutterEventSequence *sequence;
- ClutterEvent *last_event;
-
- gfloat press_x, press_y;
- gint64 last_motion_time;
- gfloat last_motion_x, last_motion_y;
- gint64 last_delta_time;
- gfloat last_delta_x, last_delta_y;
- gfloat release_x, release_y;
-} GesturePoint;
-
-struct _ClutterGestureActionPrivate
-{
- ClutterActor *stage;
-
- gint requested_nb_points;
- GArray *points;
-
- gulong actor_capture_id;
- gulong stage_capture_id;
-
- ClutterGestureTriggerEdge edge;
- float distance_x, distance_y;
-
- guint in_gesture : 1;
-};
-
-enum
-{
- PROP_0,
-
- PROP_N_TOUCH_POINTS,
- PROP_THRESHOLD_TRIGGER_EDGE,
- PROP_THRESHOLD_TRIGGER_DISTANCE_X,
- PROP_THRESHOLD_TRIGGER_DISTANCE_Y,
-
- PROP_LAST
-};
-
-enum
-{
- GESTURE_BEGIN,
- GESTURE_PROGRESS,
- GESTURE_END,
- GESTURE_CANCEL,
-
- LAST_SIGNAL
-};
-
-static GParamSpec *gesture_props[PROP_LAST];
-static guint gesture_signals[LAST_SIGNAL] = { 0, };
-
-G_DEFINE_TYPE_WITH_PRIVATE (ClutterGestureAction, clutter_gesture_action, CLUTTER_TYPE_ACTION)
-
-static GesturePoint *
-gesture_register_point (ClutterGestureAction *action, ClutterEvent *event)
-{
- ClutterGestureActionPrivate *priv =
- clutter_gesture_action_get_instance_private (action);
- 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->last_event = clutter_event_copy (event);
- 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;
- point->last_motion_time = clutter_event_get_time (event);
-
- point->last_delta_x = point->last_delta_y = 0;
- point->last_delta_time = 0;
-
- 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 =
- clutter_gesture_action_get_instance_private (action);
- 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 =
- clutter_gesture_action_get_instance_private (action);
-
- if (priv->points->len == 0)
- return;
-
- g_array_remove_index (priv->points, position);
-}
-
-static void
-gesture_update_motion_point (GesturePoint *point,
- ClutterEvent *event)
-{
- gfloat motion_x, motion_y;
- gint64 _time;
-
- clutter_event_get_coords (event, &motion_x, &motion_y);
-
- clutter_event_free (point->last_event);
- point->last_event = clutter_event_copy (event);
-
- point->last_delta_x = motion_x - point->last_motion_x;
- point->last_delta_y = motion_y - point->last_motion_y;
- point->last_motion_x = motion_x;
- point->last_motion_y = motion_y;
-
- _time = clutter_event_get_time (event);
- point->last_delta_time = _time - point->last_motion_time;
- point->last_motion_time = _time;
-}
-
-static void
-gesture_update_release_point (GesturePoint *point,
- ClutterEvent *event)
-{
- gint64 _time;
-
- clutter_event_get_coords (event, &point->release_x, &point->release_y);
-
- clutter_event_free (point->last_event);
- point->last_event = clutter_event_copy (event);
-
- /* Treat the release event as the continuation of the last motion,
- * in case the user keeps the pointer still for a while before
- * releasing it. */
- _time = clutter_event_get_time (event);
- point->last_delta_time += _time - point->last_motion_time;
-}
-
-static gint
-gesture_get_default_threshold (void)
-{
- gint threshold;
- ClutterSettings *settings = clutter_settings_get_default ();
- g_object_get (settings, "dnd-drag-threshold", &threshold, NULL);
- return threshold;
-}
-
-static gboolean
-gesture_point_pass_threshold (ClutterGestureAction *action,
- GesturePoint *point,
- ClutterEvent *event)
-{
- float threshold_x, threshold_y;
- gfloat motion_x, motion_y;
-
- clutter_event_get_coords (event, &motion_x, &motion_y);
- clutter_gesture_action_get_threshold_trigger_distance (action, &threshold_x, &threshold_y);
-
- if ((fabsf (point->press_y - motion_y) < threshold_y) &&
- (fabsf (point->press_x - motion_x) < threshold_x))
- return TRUE;
- return FALSE;
-}
-
-static void
-gesture_point_unset (GesturePoint *point)
-{
- clutter_event_free (point->last_event);
-}
-
-static void
-cancel_gesture (ClutterGestureAction *action)
-{
- ClutterGestureActionPrivate *priv =
- clutter_gesture_action_get_instance_private (action);
- ClutterActor *actor;
-
- priv->in_gesture = FALSE;
-
- g_clear_signal_handler (&priv->stage_capture_id, priv->stage);
-
- actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
- g_signal_emit (action, gesture_signals[GESTURE_CANCEL], 0, actor);
-
- g_array_set_size (priv->points, 0);
-}
-
-static gboolean
-begin_gesture (ClutterGestureAction *action,
- ClutterActor *actor)
-{
- ClutterGestureActionPrivate *priv =
- clutter_gesture_action_get_instance_private (action);
- gboolean return_value;
-
- priv->in_gesture = TRUE;
-
- if (!CLUTTER_GESTURE_ACTION_GET_CLASS (action)->gesture_prepare (action, actor))
- {
- cancel_gesture (action);
- return FALSE;
- }
-
- /* clutter_gesture_action_cancel() may have been called during
- * gesture_prepare(), check that the gesture is still active. */
- if (!priv->in_gesture)
- return FALSE;
-
- g_signal_emit (action, gesture_signals[GESTURE_BEGIN], 0, actor,
- &return_value);
-
- if (!return_value)
- {
- cancel_gesture (action);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
-stage_captured_event_cb (ClutterActor *stage,
- ClutterEvent *event,
- ClutterGestureAction *action)
-{
- ClutterGestureActionPrivate *priv =
- clutter_gesture_action_get_instance_private (action);
- ClutterActor *actor;
- gint position;
- float threshold_x, threshold_y;
- gboolean return_value;
- GesturePoint *point;
- ClutterEventType event_type;
-
- event_type = clutter_event_type (event);
- if (event_type != CLUTTER_TOUCH_CANCEL &&
- event_type != CLUTTER_TOUCH_UPDATE &&
- event_type != CLUTTER_TOUCH_END &&
- event_type != CLUTTER_MOTION &&
- event_type != CLUTTER_BUTTON_RELEASE)
- return CLUTTER_EVENT_PROPAGATE;
-
- if ((point = gesture_find_point (action, event, &position)) == NULL)
- return CLUTTER_EVENT_PROPAGATE;
-
- actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
-
- switch (clutter_event_type (event))
- {
- case CLUTTER_MOTION:
- {
- ClutterModifierType mods = clutter_event_get_state (event);
-
- /* we might miss a button-release event in case of grabs,
- * so we need to check whether the button is still down
- * during a motion event
- */
- if (!(mods & CLUTTER_BUTTON1_MASK))
- {
- cancel_gesture (action);
- return CLUTTER_EVENT_PROPAGATE;
- }
- }
- /* Follow same code path as a touch event update */
-
- case CLUTTER_TOUCH_UPDATE:
- if (!priv->in_gesture)
- {
- if (priv->points->len < priv->requested_nb_points)
- {
- gesture_update_motion_point (point, event);
- return CLUTTER_EVENT_PROPAGATE;
- }
-
- /* Wait until the drag threshold has been exceeded
- * before starting _TRIGGER_EDGE_AFTER gestures. */
- if (priv->edge == CLUTTER_GESTURE_TRIGGER_EDGE_AFTER &&
- gesture_point_pass_threshold (action, point, event))
- {
- gesture_update_motion_point (point, event);
- return CLUTTER_EVENT_PROPAGATE;
- }
-
- gesture_update_motion_point (point, event);
-
- if (!begin_gesture (action, actor))
- return CLUTTER_EVENT_PROPAGATE;
-
- if ((point = gesture_find_point (action, event, &position)) == NULL)
- return CLUTTER_EVENT_PROPAGATE;
- }
-
- gesture_update_motion_point (point, event);
-
- g_signal_emit (action, gesture_signals[GESTURE_PROGRESS], 0, actor,
- &return_value);
- if (!return_value)
- {
- cancel_gesture (action);
- return CLUTTER_EVENT_PROPAGATE;
- }
-
- /* Check if a _TRIGGER_EDGE_BEFORE gesture needs to be cancelled because
- * the drag threshold has been exceeded. */
- clutter_gesture_action_get_threshold_trigger_distance (action, &threshold_x, &threshold_y);
- if (priv->edge == CLUTTER_GESTURE_TRIGGER_EDGE_BEFORE &&
- ((fabsf (point->press_y - point->last_motion_y) > threshold_y) ||
- (fabsf (point->press_x - point->last_motion_x) > threshold_x)))
- {
- cancel_gesture (action);
- return CLUTTER_EVENT_PROPAGATE;
- }
- break;
-
- case CLUTTER_BUTTON_RELEASE:
- case CLUTTER_TOUCH_END:
- {
- gesture_update_release_point (point, event);
-
- if (priv->in_gesture &&
- ((priv->points->len - 1) < priv->requested_nb_points))
- {
- priv->in_gesture = FALSE;
- g_signal_emit (action, gesture_signals[GESTURE_END], 0, actor);
- }
-
- gesture_unregister_point (action, position);
- }
- break;
-
- case CLUTTER_TOUCH_CANCEL:
- {
- gesture_update_release_point (point, event);
-
- if (priv->in_gesture)
- {
- priv->in_gesture = FALSE;
- cancel_gesture (action);
- }
-
- gesture_unregister_point (action, position);
- }
- break;
-
- default:
- break;
- }
-
- if (priv->points->len == 0)
- g_clear_signal_handler (&priv->stage_capture_id, priv->stage);
-
- return CLUTTER_EVENT_PROPAGATE;
-}
-
-static gboolean
-actor_captured_event_cb (ClutterActor *actor,
- ClutterEvent *event,
- ClutterGestureAction *action)
-{
- ClutterGestureActionPrivate *priv =
- clutter_gesture_action_get_instance_private (action);
- GesturePoint *point G_GNUC_UNUSED;
-
- 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;
-
- point = gesture_register_point (action, event);
-
- if (priv->stage == NULL)
- priv->stage = clutter_actor_get_stage (actor);
-
- 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);
-
- /* Start the gesture immediately if the gesture has no
- * _TRIGGER_EDGE_AFTER drag threshold. */
- if ((priv->points->len >= priv->requested_nb_points) &&
- (priv->edge != CLUTTER_GESTURE_TRIGGER_EDGE_AFTER))
- begin_gesture (action, actor);
-
- return CLUTTER_EVENT_PROPAGATE;
-}
-
-static void
-clutter_gesture_action_set_actor (ClutterActorMeta *meta,
- ClutterActor *actor)
-{
- ClutterGestureActionPrivate *priv =
- clutter_gesture_action_get_instance_private (CLUTTER_GESTURE_ACTION (meta));
- ClutterActorMetaClass *meta_class =
- CLUTTER_ACTOR_META_CLASS (clutter_gesture_action_parent_class);
-
- if (priv->actor_capture_id != 0)
- {
- ClutterActor *old_actor = clutter_actor_meta_get_actor (meta);
-
- if (old_actor != NULL)
- g_clear_signal_handler (&priv->actor_capture_id, old_actor);
-
- priv->actor_capture_id = 0;
- }
-
- if (priv->stage_capture_id != 0)
- {
- if (priv->stage != NULL)
- g_clear_signal_handler (&priv->stage_capture_id, priv->stage);
-
- priv->stage_capture_id = 0;
- priv->stage = NULL;
- }
-
- if (actor != NULL)
- {
- priv->actor_capture_id =
- g_signal_connect (actor, "captured-event",
- G_CALLBACK (actor_captured_event_cb),
- meta);
- }
-
- meta_class->set_actor (meta, actor);
-}
-
-static void
-clutter_gesture_action_set_enabled (ClutterActorMeta *meta,
- gboolean is_enabled)
-{
- ClutterActorMetaClass *meta_class =
- CLUTTER_ACTOR_META_CLASS (clutter_gesture_action_parent_class);
- ClutterGestureAction *gesture_action = CLUTTER_GESTURE_ACTION (meta);
- ClutterGestureActionPrivate *priv =
- clutter_gesture_action_get_instance_private (gesture_action);
-
- if (!is_enabled)
- {
- if (priv->in_gesture)
- cancel_gesture (gesture_action);
- else
- g_array_set_size (priv->points, 0);
- }
-
- meta_class->set_enabled (meta, is_enabled);
-}
-
-static gboolean
-default_event_handler (ClutterGestureAction *action,
- ClutterActor *actor)
-{
- return TRUE;
-}
-
-static void
-clutter_gesture_action_set_property (GObject *gobject,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- ClutterGestureAction *self = CLUTTER_GESTURE_ACTION (gobject);
- ClutterGestureActionPrivate *priv =
- clutter_gesture_action_get_instance_private (self);
-
- switch (prop_id)
- {
- case PROP_N_TOUCH_POINTS:
- clutter_gesture_action_set_n_touch_points (self, g_value_get_int (value));
- break;
-
- case PROP_THRESHOLD_TRIGGER_EDGE:
- clutter_gesture_action_set_threshold_trigger_edge (self, g_value_get_enum (value));
- break;
-
- case PROP_THRESHOLD_TRIGGER_DISTANCE_X:
- clutter_gesture_action_set_threshold_trigger_distance (self,
- g_value_get_float (value),
- priv->distance_y);
- break;
-
- case PROP_THRESHOLD_TRIGGER_DISTANCE_Y:
- clutter_gesture_action_set_threshold_trigger_distance (self,
- priv->distance_x,
- g_value_get_float (value));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
- break;
- }
-}
-
-static void
-clutter_gesture_action_get_property (GObject *gobject,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- ClutterGestureActionPrivate *priv =
- clutter_gesture_action_get_instance_private (CLUTTER_GESTURE_ACTION (gobject));
-
- switch (prop_id)
- {
- case PROP_N_TOUCH_POINTS:
- g_value_set_int (value, priv->requested_nb_points);
- break;
-
- case PROP_THRESHOLD_TRIGGER_EDGE:
- g_value_set_enum (value, priv->edge);
- break;
-
- case PROP_THRESHOLD_TRIGGER_DISTANCE_X:
- if (priv->distance_x > 0.0)
- g_value_set_float (value, priv->distance_x);
- else
- g_value_set_float (value, gesture_get_default_threshold ());
- break;
-
- case PROP_THRESHOLD_TRIGGER_DISTANCE_Y:
- if (priv->distance_y > 0.0)
- g_value_set_float (value, priv->distance_y);
- else
- g_value_set_float (value, gesture_get_default_threshold ());
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
- break;
- }
-}
-
-static void
-clutter_gesture_action_finalize (GObject *gobject)
-{
- ClutterGestureActionPrivate *priv =
- clutter_gesture_action_get_instance_private (CLUTTER_GESTURE_ACTION (gobject));
-
- g_array_unref (priv->points);
-
- G_OBJECT_CLASS (clutter_gesture_action_parent_class)->finalize (gobject);
-}
-
-static void
-clutter_gesture_action_class_init (ClutterGestureActionClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass);
-
- gobject_class->finalize = clutter_gesture_action_finalize;
- gobject_class->set_property = clutter_gesture_action_set_property;
- gobject_class->get_property = clutter_gesture_action_get_property;
-
- meta_class->set_actor = clutter_gesture_action_set_actor;
- meta_class->set_enabled = clutter_gesture_action_set_enabled;
-
- klass->gesture_begin = default_event_handler;
- klass->gesture_progress = default_event_handler;
- klass->gesture_prepare = default_event_handler;
-
- /**
- * ClutterGestureAction:n-touch-points:
- *
- * Number of touch points to trigger a gesture action.
- *
- * Since: 1.16
- */
- gesture_props[PROP_N_TOUCH_POINTS] =
- g_param_spec_int ("n-touch-points",
- P_("Number touch points"),
- P_("Number of touch points"),
- 1, G_MAXINT, 1,
- CLUTTER_PARAM_READWRITE);
-
- /**
- * ClutterGestureAction:threshold-trigger-edge:
- *
- * The trigger edge to be used by the action to either emit the
- * #ClutterGestureAction::gesture-begin signal or to emit the
- * #ClutterGestureAction::gesture-cancel signal.
- *
- * Since: 1.18
- */
- gesture_props[PROP_THRESHOLD_TRIGGER_EDGE] =
- g_param_spec_enum ("threshold-trigger-edge",
- P_("Threshold Trigger Edge"),
- P_("The trigger edge used by the action"),
- CLUTTER_TYPE_GESTURE_TRIGGER_EDGE,
- CLUTTER_GESTURE_TRIGGER_EDGE_NONE,
- CLUTTER_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY);
-
- /**
- * ClutterGestureAction:threshold-trigger-distance-x:
- *
- * The horizontal trigger distance to be used by the action to either
- * emit the #ClutterGestureAction::gesture-begin signal or to emit
- * the #ClutterGestureAction::gesture-cancel signal.
- *
- * A negative value will be interpreted as the default drag threshold.
- *
- * Since: 1.18
- */
- gesture_props[PROP_THRESHOLD_TRIGGER_DISTANCE_X] =
- g_param_spec_float ("threshold-trigger-distance-x",
- P_("Threshold Trigger Horizontal Distance"),
- P_("The horizontal trigger distance used by the action"),
- -1.0, G_MAXFLOAT, -1.0,
- CLUTTER_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY);
-
- /**
- * ClutterGestureAction:threshold-trigger-distance-y:
- *
- * The vertical trigger distance to be used by the action to either
- * emit the #ClutterGestureAction::gesture-begin signal or to emit
- * the #ClutterGestureAction::gesture-cancel signal.
- *
- * A negative value will be interpreted as the default drag threshold.
- *
- * Since: 1.18
- */
- gesture_props[PROP_THRESHOLD_TRIGGER_DISTANCE_Y] =
- g_param_spec_float ("threshold-trigger-distance-y",
- P_("Threshold Trigger Vertical Distance"),
- P_("The vertical trigger distance used by the action"),
- -1.0, G_MAXFLOAT, -1.0,
- CLUTTER_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY);
-
- g_object_class_install_properties (gobject_class,
- PROP_LAST,
- gesture_props);
-
- /**
- * ClutterGestureAction::gesture-begin:
- * @action: the #ClutterGestureAction that emitted the signal
- * @actor: the #ClutterActor attached to the @action
- *
- * The ::gesture_begin signal is emitted when the #ClutterActor to which
- * a #ClutterGestureAction has been applied starts receiving a gesture.
- *
- * Return value: %TRUE if the gesture should start, and %FALSE if
- * the gesture should be ignored.
- *
- * Since: 1.8
- */
- gesture_signals[GESTURE_BEGIN] =
- g_signal_new (I_("gesture-begin"),
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ClutterGestureActionClass, gesture_begin),
- _clutter_boolean_continue_accumulator, NULL,
- _clutter_marshal_BOOLEAN__OBJECT,
- G_TYPE_BOOLEAN, 1,
- CLUTTER_TYPE_ACTOR);
-
- /**
- * ClutterGestureAction::gesture-progress:
- * @action: the #ClutterGestureAction that emitted the signal
- * @actor: the #ClutterActor attached to the @action
- *
- * The ::gesture-progress signal is emitted for each motion event after
- * the #ClutterGestureAction::gesture-begin signal has been emitted.
- *
- * Return value: %TRUE if the gesture should continue, and %FALSE if
- * the gesture should be cancelled.
- *
- * Since: 1.8
- */
- gesture_signals[GESTURE_PROGRESS] =
- g_signal_new (I_("gesture-progress"),
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ClutterGestureActionClass, gesture_progress),
- _clutter_boolean_continue_accumulator, NULL,
- _clutter_marshal_BOOLEAN__OBJECT,
- G_TYPE_BOOLEAN, 1,
- CLUTTER_TYPE_ACTOR);
-
- /**
- * ClutterGestureAction::gesture-end:
- * @action: the #ClutterGestureAction that emitted the signal
- * @actor: the #ClutterActor attached to the @action
- *
- * The ::gesture-end signal is emitted at the end of the gesture gesture,
- * when the pointer's button is released
- *
- * This signal is emitted if and only if the #ClutterGestureAction::gesture-begin
- * signal has been emitted first.
- *
- * Since: 1.8
- */
- gesture_signals[GESTURE_END] =
- g_signal_new (I_("gesture-end"),
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ClutterGestureActionClass, gesture_end),
- NULL, NULL, NULL,
- G_TYPE_NONE, 1,
- CLUTTER_TYPE_ACTOR);
-
- /**
- * ClutterGestureAction::gesture-cancel:
- * @action: the #ClutterGestureAction that emitted the signal
- * @actor: the #ClutterActor attached to the @action
- *
- * The ::gesture-cancel signal is emitted when the ongoing gesture gets
- * cancelled from the #ClutterGestureAction::gesture-progress signal handler.
- *
- * This signal is emitted if and only if the #ClutterGestureAction::gesture-begin
- * signal has been emitted first.
- *
- * Since: 1.8
- */
- gesture_signals[GESTURE_CANCEL] =
- g_signal_new (I_("gesture-cancel"),
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ClutterGestureActionClass, gesture_cancel),
- NULL, NULL, NULL,
- G_TYPE_NONE, 1,
- CLUTTER_TYPE_ACTOR);
-}
-
-static void
-clutter_gesture_action_init (ClutterGestureAction *self)
-{
- ClutterGestureActionPrivate *priv =
- clutter_gesture_action_get_instance_private (self);
-
- priv->points = g_array_sized_new (FALSE, TRUE, sizeof (GesturePoint), 3);
- g_array_set_clear_func (priv->points, (GDestroyNotify) gesture_point_unset);
-
- priv->requested_nb_points = 1;
- priv->edge = CLUTTER_GESTURE_TRIGGER_EDGE_NONE;
-}
-
-/**
- * clutter_gesture_action_new:
- *
- * Creates a new #ClutterGestureAction instance.
- *
- * Return value: the newly created #ClutterGestureAction
- *
- * Since: 1.8
- */
-ClutterAction *
-clutter_gesture_action_new (void)
-{
- return g_object_new (CLUTTER_TYPE_GESTURE_ACTION, NULL);
-}
-
-/**
- * clutter_gesture_action_get_press_coords:
- * @action: a #ClutterGestureAction
- * @point: the touch point index, with 0 being the first touch
- * point received by the action
- * @press_x: (out) (allow-none): return location for the press
- * event's X coordinate
- * @press_y: (out) (allow-none): return location for the press
- * event's Y coordinate
- *
- * Retrieves the coordinates, in stage space, of the press event
- * that started the dragging for a specific touch point.
- *
- * Since: 1.8
- */
-void
-clutter_gesture_action_get_press_coords (ClutterGestureAction *action,
- guint point,
- gfloat *press_x,
- gfloat *press_y)
-{
- ClutterGestureActionPrivate *priv;
-
- g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
-
- priv = clutter_gesture_action_get_instance_private (action);
-
- g_return_if_fail (priv->points->len > point);
-
- if (press_x)
- *press_x = g_array_index (priv->points,
- GesturePoint,
- point).press_x;
-
- if (press_y)
- *press_y = g_array_index (priv->points,
- GesturePoint,
- point).press_y;
-}
-
-/**
- * clutter_gesture_action_get_motion_coords:
- * @action: a #ClutterGestureAction
- * @point: the touch point index, with 0 being the first touch
- * point received by the action
- * @motion_x: (out) (allow-none): return location for the latest motion
- * event's X coordinate
- * @motion_y: (out) (allow-none): return location for the latest motion
- * event's Y coordinate
- *
- * Retrieves the coordinates, in stage space, of the latest motion
- * event during the dragging.
- *
- * Since: 1.8
- */
-void
-clutter_gesture_action_get_motion_coords (ClutterGestureAction *action,
- guint point,
- gfloat *motion_x,
- gfloat *motion_y)
-{
- ClutterGestureActionPrivate *priv;
-
- g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
-
- priv = clutter_gesture_action_get_instance_private (action);
-
- g_return_if_fail (priv->points->len > point);
-
- if (motion_x)
- *motion_x = g_array_index (priv->points,
- GesturePoint,
- point).last_motion_x;
-
- if (motion_y)
- *motion_y = g_array_index (priv->points,
- GesturePoint,
- point).last_motion_y;
-}
-
-/**
- * clutter_gesture_action_get_motion_delta:
- * @action: a #ClutterGestureAction
- * @point: the touch point index, with 0 being the first touch
- * point received by the action
- * @delta_x: (out) (allow-none): return location for the X axis
- * component of the incremental motion delta
- * @delta_y: (out) (allow-none): return location for the Y axis
- * component of the incremental motion delta
- *
- * Retrieves the incremental delta since the last motion event
- * during the dragging.
- *
- * Return value: the distance since last motion event
- *
- * Since: 1.12
- */
-gfloat
-clutter_gesture_action_get_motion_delta (ClutterGestureAction *action,
- guint point,
- gfloat *delta_x,
- gfloat *delta_y)
-{
- ClutterGestureActionPrivate *priv;
- gfloat d_x, d_y;
-
- g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0);
-
- priv = clutter_gesture_action_get_instance_private (action);
-
- g_return_val_if_fail (priv->points->len > point, 0);
-
- d_x = g_array_index (priv->points,
- GesturePoint,
- point).last_delta_x;
- d_y = g_array_index (priv->points,
- GesturePoint,
- point).last_delta_y;
-
- if (delta_x)
- *delta_x = d_x;
-
- if (delta_y)
- *delta_y = d_y;
-
- return sqrt ((d_x * d_x) + (d_y * d_y));
-}
-
-/**
- * clutter_gesture_action_get_release_coords:
- * @action: a #ClutterGestureAction
- * @point: the touch point index, with 0 being the first touch
- * point received by the action
- * @release_x: (out) (allow-none): return location for the X coordinate of
- * the last release
- * @release_y: (out) (allow-none): return location for the Y coordinate of
- * the last release
- *
- * Retrieves the coordinates, in stage space, where the touch point was
- * last released.
- *
- * Since: 1.8
- */
-void
-clutter_gesture_action_get_release_coords (ClutterGestureAction *action,
- guint point,
- gfloat *release_x,
- gfloat *release_y)
-{
- ClutterGestureActionPrivate *priv;
-
- g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
-
- priv = clutter_gesture_action_get_instance_private (action);
-
- g_return_if_fail (priv->points->len > point);
-
- if (release_x)
- *release_x = g_array_index (priv->points,
- GesturePoint,
- point).release_x;
-
- if (release_y)
- *release_y = g_array_index (priv->points,
- GesturePoint,
- point).release_y;
-}
-
-/**
- * clutter_gesture_action_get_velocity:
- * @action: a #ClutterGestureAction
- * @point: the touch point index, with 0 being the first touch
- * point received by the action
- * @velocity_x: (out) (allow-none): return location for the latest motion
- * event's X velocity
- * @velocity_y: (out) (allow-none): return location for the latest motion
- * event's Y velocity
- *
- * Retrieves the velocity, in stage pixels per millisecond, of the
- * latest motion event during the dragging.
- *
- * Since: 1.12
- */
-gfloat
-clutter_gesture_action_get_velocity (ClutterGestureAction *action,
- guint point,
- gfloat *velocity_x,
- gfloat *velocity_y)
-{
- ClutterGestureActionPrivate *priv;
- gfloat d_x, d_y, distance, velocity;
- gint64 d_t;
-
- g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0);
-
- priv = clutter_gesture_action_get_instance_private (action);
-
- g_return_val_if_fail (priv->points->len > point, 0);
-
- distance = clutter_gesture_action_get_motion_delta (action, point,
- &d_x, &d_y);
-
- d_t = g_array_index (priv->points,
- GesturePoint,
- point).last_delta_time;
-
- if (velocity_x)
- *velocity_x = d_t > FLOAT_EPSILON ? d_x / d_t : 0;
-
- if (velocity_y)
- *velocity_y = d_t > FLOAT_EPSILON ? d_y / d_t : 0;
-
- velocity = d_t > FLOAT_EPSILON ? distance / d_t : 0;
- return velocity;
-}
-
-/**
- * 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)
-{
- ClutterGestureActionPrivate *priv;
-
- g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0);
-
- priv = clutter_gesture_action_get_instance_private (action);
-
- return 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 = clutter_gesture_action_get_instance_private (action);
-
- if (priv->requested_nb_points == nb_points)
- return;
-
- priv->requested_nb_points = nb_points;
-
- if (priv->in_gesture)
- {
- if (priv->points->len < priv->requested_nb_points)
- cancel_gesture (action);
- }
- else if (priv->edge == CLUTTER_GESTURE_TRIGGER_EDGE_AFTER)
- {
- if (priv->points->len >= priv->requested_nb_points)
- {
- ClutterActor *actor =
- clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
- gint i;
- float threshold_x, threshold_y;
-
- clutter_gesture_action_get_threshold_trigger_distance (action, &threshold_x, &threshold_y);
-
- for (i = 0; i < priv->points->len; i++)
- {
- GesturePoint *point = &g_array_index (priv->points, GesturePoint, i);
-
- if ((fabsf (point->press_y - point->last_motion_y) >= threshold_y) ||
- (fabsf (point->press_x - point->last_motion_x) >= threshold_x))
- {
- begin_gesture (action, actor);
- break;
- }
- }
- }
- }
-
- g_object_notify_by_pspec (G_OBJECT (action),
- gesture_props[PROP_N_TOUCH_POINTS]);
-}
-
-/**
- * clutter_gesture_action_get_n_current_points:
- * @action: a #ClutterGestureAction
- *
- * Retrieves the number of points currently active.
- *
- * Return value: the number of points currently active.
- *
- * Since: 1.12
- */
-guint
-clutter_gesture_action_get_n_current_points (ClutterGestureAction *action)
-{
- ClutterGestureActionPrivate *priv;
-
- g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0);
-
- priv = clutter_gesture_action_get_instance_private (action);
-
- return priv->points->len;
-}
-
-/**
- * clutter_gesture_action_get_sequence:
- * @action: a #ClutterGestureAction
- * @point: index of a point currently active
- *
- * Retrieves the #ClutterEventSequence of a touch point.
- *
- * Return value: (transfer none): the #ClutterEventSequence of a touch point.
- *
- * Since: 1.12
- */
-ClutterEventSequence *
-clutter_gesture_action_get_sequence (ClutterGestureAction *action,
- guint point)
-{
- ClutterGestureActionPrivate *priv;
-
- g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), NULL);
-
- priv = clutter_gesture_action_get_instance_private (action);
-
- g_return_val_if_fail (priv->points->len > point, NULL);
-
- return g_array_index (priv->points, GesturePoint, point).sequence;
-}
-
-/**
- * clutter_gesture_action_get_device:
- * @action: a #ClutterGestureAction
- * @point: the touch point index, with 0 being the first touch
- * point received by the action
- *
- * Retrieves the #ClutterInputDevice of a touch point.
- *
- * Return value: (transfer none): the #ClutterInputDevice of a touch point.
- *
- * Since: 1.12
- */
-ClutterInputDevice *
-clutter_gesture_action_get_device (ClutterGestureAction *action,
- guint point)
-{
- ClutterGestureActionPrivate *priv;
-
- g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), NULL);
-
- priv = clutter_gesture_action_get_instance_private (action);
-
- g_return_val_if_fail (priv->points->len > point, NULL);
-
- return g_array_index (priv->points, GesturePoint, point).device;
-}
-
-/**
- * clutter_gesture_action_get_last_event:
- * @action: a #ClutterGestureAction
- * @point: index of a point currently active
- *
- * Retrieves a reference to the last #ClutterEvent for a touch point. Call
- * clutter_event_copy() if you need to store the reference somewhere.
- *
- * Return value: (transfer none): the last #ClutterEvent for a touch point.
- *
- * Since: 1.14
- */
-const ClutterEvent *
-clutter_gesture_action_get_last_event (ClutterGestureAction *action,
- guint point)
-{
- GesturePoint *gesture_point;
- ClutterGestureActionPrivate *priv;
-
- g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), NULL);
-
- priv = clutter_gesture_action_get_instance_private (action);
-
- g_return_val_if_fail (priv->points->len > point, NULL);
-
- gesture_point = &g_array_index (priv->points, GesturePoint, point);
-
- return gesture_point->last_event;
-}
-
-/**
- * clutter_gesture_action_cancel:
- * @action: a #ClutterGestureAction
- *
- * Cancel a #ClutterGestureAction before it begins
- *
- * Since: 1.12
- */
-void
-clutter_gesture_action_cancel (ClutterGestureAction *action)
-{
- g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
-
- cancel_gesture (action);
-}
-
-/**
- * clutter_gesture_action_set_threshold_trigger_edge:
- * @action: a #ClutterGestureAction
- * @edge: the %ClutterGestureTriggerEdge
- *
- * Sets the edge trigger for the gesture drag threshold, if any.
- *
- * This function should only be called by sub-classes of
- * #ClutterGestureAction during their construction phase.
- *
- * Since: 1.18
- */
-void
-clutter_gesture_action_set_threshold_trigger_edge (ClutterGestureAction *action,
- ClutterGestureTriggerEdge edge)
-{
- ClutterGestureActionPrivate *priv;
-
- g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
-
- priv = clutter_gesture_action_get_instance_private (action);
-
- if (priv->edge == edge)
- return;
-
- priv->edge = edge;
-
- g_object_notify_by_pspec (G_OBJECT (action), gesture_props[PROP_THRESHOLD_TRIGGER_EDGE]);
-}
-
-/**
- * clutter_gesture_action_get_threshold_trigger_edge:
- * @action: a #ClutterGestureAction
- *
- * Retrieves the edge trigger of the gesture @action, as set using
- * clutter_gesture_action_set_threshold_trigger_edge().
- *
- * Return value: the edge trigger
- *
- * Since: 1.20
- */
-ClutterGestureTriggerEdge
-clutter_gesture_action_get_threshold_trigger_edge (ClutterGestureAction *action)
-{
- ClutterGestureActionPrivate *priv;
-
- g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action),
- CLUTTER_GESTURE_TRIGGER_EDGE_NONE);
-
- priv = clutter_gesture_action_get_instance_private (action);
-
- return priv->edge;
-}
-
-/**
- * clutter_gesture_action_get_threshold_trigger_egde:
- * @action: a #ClutterGestureAction
- *
- * Retrieves the edge trigger of the gesture @action, as set using
- * clutter_gesture_action_set_threshold_trigger_edge().
- *
- * Return value: the edge trigger
- *
- * Since: 1.18
- *
- * Deprecated: 1.20: Use clutter_gesture_action_get_threshold_trigger_edge() instead.
- */
-ClutterGestureTriggerEdge
-clutter_gesture_action_get_threshold_trigger_egde (ClutterGestureAction *action)
-{
- return clutter_gesture_action_get_threshold_trigger_edge (action);
-}
-
-/**
- * clutter_gesture_action_set_threshold_trigger_distance:
- * @action: a #ClutterGestureAction
- * @x: the distance on the horizontal axis
- * @y: the distance on the vertical axis
- *
- * Sets the threshold trigger distance for the gesture drag threshold, if any.
- *
- * This function should only be called by sub-classes of
- * #ClutterGestureAction during their construction phase.
- *
- * Since: 1.18
- */
-void
-clutter_gesture_action_set_threshold_trigger_distance (ClutterGestureAction *action,
- float x,
- float y)
-{
- ClutterGestureActionPrivate *priv;
-
- g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
-
- priv = clutter_gesture_action_get_instance_private (action);
-
- if (fabsf (x - priv->distance_x) > FLOAT_EPSILON)
- {
- priv->distance_x = x;
- g_object_notify_by_pspec (G_OBJECT (action), gesture_props[PROP_THRESHOLD_TRIGGER_DISTANCE_X]);
- }
-
- if (fabsf (y - priv->distance_y) > FLOAT_EPSILON)
- {
- priv->distance_y = y;
- g_object_notify_by_pspec (G_OBJECT (action), gesture_props[PROP_THRESHOLD_TRIGGER_DISTANCE_Y]);
- }
-}
-
-/**
- * clutter_gesture_action_get_threshold_trigger_distance:
- * @action: a #ClutterGestureAction
- * @x: (out) (allow-none): The return location for the horizontal distance, or %NULL
- * @y: (out) (allow-none): The return location for the vertical distance, or %NULL
- *
- * Retrieves the threshold trigger distance of the gesture @action,
- * as set using clutter_gesture_action_set_threshold_trigger_distance().
- *
- * Since: 1.18
- */
-void
-clutter_gesture_action_get_threshold_trigger_distance (ClutterGestureAction *action,
- float *x,
- float *y)
-{
- ClutterGestureActionPrivate *priv;
-
- g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
-
- priv = clutter_gesture_action_get_instance_private (action);
-
- if (x != NULL)
- {
- if (priv->distance_x > 0.0)
- *x = priv->distance_x;
- else
- *x = gesture_get_default_threshold ();
- }
- if (y != NULL)
- {
- if (priv->distance_y > 0.0)
- *y = priv->distance_y;
- else
- *y = gesture_get_default_threshold ();
- }
-}