1
0
Fork 0
mutter-performance-source/clutter/clutter/clutter-swipe-action.c

229 lines
6.7 KiB
C

/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2010 Intel Corporation.
* Copyright (C) 2011 Robert Bosch Car Multimedia GmbH.
*
* 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>
*
* Based on ClutterDragAction, written by:
* Emmanuele Bassi <ebassi@linux.intel.com>
*/
/**
* ClutterSwipeAction:
*
* Action for swipe gestures
*
* #ClutterSwipeAction is a sub-class of [class@GestureAction] that implements
* the logic for recognizing swipe gestures.
*/
#include "config.h"
#include "clutter/clutter-swipe-action.h"
#include "clutter/clutter-debug.h"
#include "clutter/clutter-enum-types.h"
#include "clutter/clutter-marshal.h"
#include "clutter/clutter-private.h"
typedef struct _ClutterSwipeActionPrivate
{
ClutterSwipeDirection h_direction;
ClutterSwipeDirection v_direction;
float distance_x, distance_y;
} ClutterSwipeActionPrivate;
enum
{
SWIPE,
LAST_SIGNAL
};
static guint swipe_signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE_WITH_PRIVATE (ClutterSwipeAction, clutter_swipe_action, CLUTTER_TYPE_GESTURE_ACTION)
static gboolean
gesture_begin (ClutterGestureAction *action,
ClutterActor *actor)
{
ClutterSwipeActionPrivate *priv =
clutter_swipe_action_get_instance_private (CLUTTER_SWIPE_ACTION (action));
/* reset the state at the beginning of a new gesture */
priv->h_direction = 0;
priv->v_direction = 0;
g_object_get (action,
"threshold-trigger-distance-x", &priv->distance_x,
"threshold-trigger-distance-y", &priv->distance_y,
NULL);
return TRUE;
}
static gboolean
gesture_progress (ClutterGestureAction *action,
ClutterActor *actor)
{
ClutterSwipeActionPrivate *priv =
clutter_swipe_action_get_instance_private (CLUTTER_SWIPE_ACTION (action));
gfloat press_x, press_y;
gfloat motion_x, motion_y;
gfloat delta_x, delta_y;
ClutterSwipeDirection h_direction = 0, v_direction = 0;
clutter_gesture_action_get_press_coords (action,
0,
&press_x,
&press_y);
clutter_gesture_action_get_motion_coords (action,
0,
&motion_x,
&motion_y);
delta_x = press_x - motion_x;
delta_y = press_y - motion_y;
if (delta_x >= priv->distance_x)
h_direction = CLUTTER_SWIPE_DIRECTION_RIGHT;
else if (delta_x < -priv->distance_x)
h_direction = CLUTTER_SWIPE_DIRECTION_LEFT;
if (delta_y >= priv->distance_y)
v_direction = CLUTTER_SWIPE_DIRECTION_DOWN;
else if (delta_y < -priv->distance_y)
v_direction = CLUTTER_SWIPE_DIRECTION_UP;
/* cancel gesture on direction reversal */
if (priv->h_direction == 0)
priv->h_direction = h_direction;
if (priv->v_direction == 0)
priv->v_direction = v_direction;
if (priv->h_direction != h_direction)
return FALSE;
if (priv->v_direction != v_direction)
return FALSE;
return TRUE;
}
static void
gesture_end (ClutterGestureAction *action,
ClutterActor *actor)
{
ClutterSwipeActionPrivate *priv =
clutter_swipe_action_get_instance_private (CLUTTER_SWIPE_ACTION (action));
gfloat press_x, press_y;
gfloat release_x, release_y;
ClutterSwipeDirection direction = 0;
const ClutterEvent *last_event;
clutter_gesture_action_get_press_coords (action,
0,
&press_x, &press_y);
/* Check the last event instead of get_release_coords(), this
* might not be the sequence that finished on multi-finger swipes.
*/
last_event = clutter_gesture_action_get_last_event (action, 0);
clutter_event_get_coords (last_event, &release_x, &release_y);
if (release_x - press_x > priv->distance_x)
direction |= CLUTTER_SWIPE_DIRECTION_RIGHT;
else if (press_x - release_x > priv->distance_x)
direction |= CLUTTER_SWIPE_DIRECTION_LEFT;
if (release_y - press_y > priv->distance_y)
direction |= CLUTTER_SWIPE_DIRECTION_DOWN;
else if (press_y - release_y > priv->distance_y)
direction |= CLUTTER_SWIPE_DIRECTION_UP;
g_signal_emit (action, swipe_signals[SWIPE], 0, actor, direction);
}
static void
clutter_swipe_action_constructed (GObject *object)
{
clutter_gesture_action_set_threshold_trigger_edge (CLUTTER_GESTURE_ACTION (object),
CLUTTER_GESTURE_TRIGGER_EDGE_AFTER);
}
static void
clutter_swipe_action_class_init (ClutterSwipeActionClass *klass)
{
ClutterGestureActionClass *gesture_class =
CLUTTER_GESTURE_ACTION_CLASS (klass);
GObjectClass *object_class =
G_OBJECT_CLASS (klass);
object_class->constructed = clutter_swipe_action_constructed;
gesture_class->gesture_begin = gesture_begin;
gesture_class->gesture_progress = gesture_progress;
gesture_class->gesture_end = gesture_end;
/**
* ClutterSwipeAction::swipe:
* @action: the #ClutterSwipeAction that emitted the signal
* @actor: the #ClutterActor attached to the @action
* @direction: the main direction of the swipe gesture
*
* The signal is emitted when a swipe gesture is recognized on the
* attached actor.
*
* Return value: %TRUE if the swipe should continue, and %FALSE if
* the swipe should be cancelled.
*/
swipe_signals[SWIPE] =
g_signal_new (I_("swipe"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, g_signal_accumulator_true_handled, NULL,
_clutter_marshal_BOOLEAN__OBJECT_FLAGS,
G_TYPE_BOOLEAN, 2,
CLUTTER_TYPE_ACTOR,
CLUTTER_TYPE_SWIPE_DIRECTION);
}
static void
clutter_swipe_action_init (ClutterSwipeAction *self)
{
}
/**
* clutter_swipe_action_new:
*
* Creates a new #ClutterSwipeAction instance
*
* Return value: the newly created #ClutterSwipeAction
*/
ClutterAction *
clutter_swipe_action_new (void)
{
return g_object_new (CLUTTER_TYPE_SWIPE_ACTION, NULL);
}