250 lines
7.3 KiB
C
250 lines
7.3 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>
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* SECTION:clutter-swipe-action
|
||
|
* @Title: ClutterSwipeAction
|
||
|
* @Short_Description: Action for swipe gestures
|
||
|
*
|
||
|
* #ClutterSwipeAction is a sub-class of #ClutterAction that implements
|
||
|
* the logic for recognizing swipe gestures. It listens for low level events
|
||
|
* such as #ClutterButtonEvent and #ClutterMotionEvent on the stage to raise
|
||
|
* the signals #ClutterSwipeAction::swipe-begin, #ClutterSwipeAction::swipe-motion and
|
||
|
* #ClutterSwipeAction::swipe-end.
|
||
|
*
|
||
|
* To use #ClutterSwipeAction you just need to apply it to a #ClutterActor
|
||
|
* using clutter_actor_add_action() and connect to the signals:
|
||
|
*
|
||
|
* |[
|
||
|
* ClutterAction *action = clutter_swipe_action_new ();
|
||
|
*
|
||
|
* clutter_actor_add_action (actor, action);
|
||
|
*
|
||
|
* g_signal_connect (action, "swipe-begin", G_CALLBACK (on_swipe_begin), NULL);
|
||
|
* g_signal_connect (action, "swipe-motion", G_CALLBACK (on_swipe_motion), NULL);
|
||
|
* g_signal_connect (action, "swipe-end", G_CALLBACK (on_swipe_end), NULL);
|
||
|
* ]|
|
||
|
*
|
||
|
* Since: 1.8
|
||
|
*/
|
||
|
|
||
|
#ifdef HAVE_CONFIG_H
|
||
|
#include "config.h"
|
||
|
#endif
|
||
|
|
||
|
#include "clutter-swipe-action.h"
|
||
|
|
||
|
#include "clutter-debug.h"
|
||
|
#include "clutter-enum-types.h"
|
||
|
#include "clutter-marshal.h"
|
||
|
#include "clutter-private.h"
|
||
|
|
||
|
struct _ClutterSwipeActionPrivate
|
||
|
{
|
||
|
ClutterSwipeDirection h_direction;
|
||
|
ClutterSwipeDirection v_direction;
|
||
|
gfloat last_motion_x;
|
||
|
gfloat last_motion_y;
|
||
|
};
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
SWEPT,
|
||
|
|
||
|
LAST_SIGNAL
|
||
|
};
|
||
|
|
||
|
static guint swipe_signals[LAST_SIGNAL] = { 0, };
|
||
|
|
||
|
G_DEFINE_TYPE (ClutterSwipeAction, clutter_swipe_action,
|
||
|
CLUTTER_TYPE_GESTURE_ACTION);
|
||
|
|
||
|
static gboolean
|
||
|
gesture_begin (ClutterGestureAction *action,
|
||
|
ClutterActor *actor)
|
||
|
{
|
||
|
ClutterSwipeActionPrivate *priv = CLUTTER_SWIPE_ACTION (action)->priv;
|
||
|
|
||
|
priv->h_direction = 0;
|
||
|
priv->v_direction = 0;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
gesture_progress (ClutterGestureAction *action,
|
||
|
ClutterActor *actor)
|
||
|
{
|
||
|
ClutterSwipeActionPrivate *priv = CLUTTER_SWIPE_ACTION (action)->priv;
|
||
|
gfloat press_x, press_y;
|
||
|
gfloat motion_x, motion_y;
|
||
|
gfloat delta_x, delta_y;
|
||
|
ClutterSwipeDirection h_direction = 0, v_direction = 0;
|
||
|
ClutterSettings *settings = clutter_settings_get_default ();
|
||
|
gint drag_threshold;
|
||
|
|
||
|
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;
|
||
|
|
||
|
g_object_get (settings,
|
||
|
"dnd-drag-threshold", &drag_threshold,
|
||
|
NULL);
|
||
|
|
||
|
if (delta_x >= drag_threshold)
|
||
|
h_direction = CLUTTER_SWIPE_DIRECTION_RIGHT;
|
||
|
else if (delta_x < -drag_threshold)
|
||
|
h_direction = CLUTTER_SWIPE_DIRECTION_LEFT;
|
||
|
|
||
|
if (delta_y >= drag_threshold)
|
||
|
v_direction = CLUTTER_SWIPE_DIRECTION_DOWN;
|
||
|
else if (delta_y < -drag_threshold)
|
||
|
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)
|
||
|
{
|
||
|
gfloat press_x, press_y;
|
||
|
gfloat release_x, release_y;
|
||
|
ClutterSwipeDirection direction = 0;
|
||
|
ClutterSettings *settings = clutter_settings_get_default ();
|
||
|
gint drag_threshold;
|
||
|
|
||
|
clutter_gesture_action_get_press_coords (CLUTTER_GESTURE_ACTION (action),
|
||
|
0,
|
||
|
&press_x, &press_y);
|
||
|
|
||
|
clutter_gesture_action_get_release_coords (CLUTTER_GESTURE_ACTION (action),
|
||
|
0,
|
||
|
&release_x, &release_y);
|
||
|
|
||
|
g_object_get (settings,
|
||
|
"dnd-drag-threshold", &drag_threshold,
|
||
|
NULL);
|
||
|
|
||
|
if (release_x - press_x > drag_threshold)
|
||
|
direction |= CLUTTER_SWIPE_DIRECTION_RIGHT;
|
||
|
else if (press_x - release_x > drag_threshold)
|
||
|
direction |= CLUTTER_SWIPE_DIRECTION_LEFT;
|
||
|
|
||
|
if (release_y - press_y > drag_threshold)
|
||
|
direction |= CLUTTER_SWIPE_DIRECTION_DOWN;
|
||
|
else if (press_y - release_y > drag_threshold)
|
||
|
direction |= CLUTTER_SWIPE_DIRECTION_UP;
|
||
|
|
||
|
g_signal_emit (action, swipe_signals[SWEPT], 0, actor, direction);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
clutter_swipe_action_class_init (ClutterSwipeActionClass *klass)
|
||
|
{
|
||
|
ClutterGestureActionClass *gesture_class =
|
||
|
CLUTTER_GESTURE_ACTION_CLASS (klass);
|
||
|
|
||
|
g_type_class_add_private (klass, sizeof (ClutterSwipeActionPrivate));
|
||
|
|
||
|
gesture_class->gesture_begin = gesture_begin;
|
||
|
gesture_class->gesture_progress = gesture_progress;
|
||
|
gesture_class->gesture_end = gesture_end;
|
||
|
|
||
|
/**
|
||
|
* ClutterSwipeAction::swept:
|
||
|
* @action: the #ClutterSwipeAction that emitted the signal
|
||
|
* @actor: the #ClutterActor attached to the @action
|
||
|
* @direction: the main direction of the swipe gesture
|
||
|
*
|
||
|
* The ::swept signal is emitted when a swipe gesture is recognized on the
|
||
|
* attached actor.
|
||
|
*
|
||
|
* Since: 1.8
|
||
|
*/
|
||
|
swipe_signals[SWEPT] =
|
||
|
g_signal_new (I_("swept"),
|
||
|
G_TYPE_FROM_CLASS (klass),
|
||
|
G_SIGNAL_RUN_LAST,
|
||
|
G_STRUCT_OFFSET (ClutterSwipeActionClass, swept),
|
||
|
NULL, NULL,
|
||
|
_clutter_marshal_VOID__OBJECT_INT,
|
||
|
G_TYPE_NONE, 2,
|
||
|
CLUTTER_TYPE_ACTOR,
|
||
|
G_TYPE_INT);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
clutter_swipe_action_init (ClutterSwipeAction *self)
|
||
|
{
|
||
|
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, CLUTTER_TYPE_SWIPE_ACTION,
|
||
|
ClutterSwipeActionPrivate);
|
||
|
|
||
|
clutter_gesture_action_set_required_devices (CLUTTER_GESTURE_ACTION (self),
|
||
|
1);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* clutter_swipe_action_new:
|
||
|
*
|
||
|
* Creates a new #ClutterSwipeAction instance
|
||
|
*
|
||
|
* Return value: the newly created #ClutterSwipeAction
|
||
|
*
|
||
|
* Since: 1.8
|
||
|
*/
|
||
|
ClutterAction *
|
||
|
clutter_swipe_action_new (void)
|
||
|
{
|
||
|
return g_object_new (CLUTTER_TYPE_SWIPE_ACTION, NULL);
|
||
|
}
|