gesture-action: Let subclasses override the GestureTriggerEdge handling
Let gesture subclasses override how the drag threshold should be handled: • CLUTTER_GESTURE_TRIGGER_NONE tells GestureAction that the gesture must begin immediately and there's no drag limit that will cause its cancellation; • CLUTTER_GESTURE_TRIGGER_AFTER is the default GestureAction behaviour, where it needs to wait until the drag threshold has been exceeded before considering the gesture valid; • CLUTTER_GESTURE_TRIGGER_BEFORE will make GestureAction cancel the gesture once the drag exceed the configured threshold. For example, ZoomAction and RotateAction could set CLUTTER_GESTURE_TRIGGER_NONE since the use of two fingers makes the begin of the action more self-evident, while an hypothetical Tap gesture may use CLUTTER_GESTURE_TRIGGER_BEFORE to cancel the tap if the pointer moves too much. https://bugzilla.gnome.org/show_bug.cgi?id=685028
This commit is contained in:
parent
cbab0a62ad
commit
abcf1d589f
@ -226,6 +226,7 @@ source_h_priv = \
|
|||||||
$(srcdir)/clutter-event-translator.h \
|
$(srcdir)/clutter-event-translator.h \
|
||||||
$(srcdir)/clutter-event-private.h \
|
$(srcdir)/clutter-event-private.h \
|
||||||
$(srcdir)/clutter-flatten-effect.h \
|
$(srcdir)/clutter-flatten-effect.h \
|
||||||
|
$(srcdir)/clutter-gesture-action-private.h \
|
||||||
$(srcdir)/clutter-id-pool.h \
|
$(srcdir)/clutter-id-pool.h \
|
||||||
$(srcdir)/clutter-master-clock.h \
|
$(srcdir)/clutter-master-clock.h \
|
||||||
$(srcdir)/clutter-model-private.h \
|
$(srcdir)/clutter-model-private.h \
|
||||||
|
59
clutter/clutter-gesture-action-private.h
Normal file
59
clutter/clutter-gesture-action-private.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Collabora Ltd..
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CLUTTER_GESTURE_ACTION_PRIVATE_H__
|
||||||
|
#define __CLUTTER_GESTURE_ACTION_PRIVATE_H__
|
||||||
|
|
||||||
|
#include <clutter/clutter-gesture-action.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
/*< private >
|
||||||
|
* ClutterGestureTriggerEdge:
|
||||||
|
* @CLUTTER_GESTURE_TRIGGER_NONE: Tell #ClutterGestureAction that
|
||||||
|
* the gesture must begin immediately and there's no drag limit that
|
||||||
|
* will cause its cancellation;
|
||||||
|
* @CLUTTER_GESTURE_TRIGGER_AFTER: Tell #ClutterGestureAction that
|
||||||
|
* it needs to wait until the drag threshold has been exceeded before
|
||||||
|
* considering that the gesture has begun;
|
||||||
|
* @CLUTTER_GESTURE_TRIGGER_BEFORE: Tell #ClutterGestureAction that
|
||||||
|
* the gesture must begin immegiately and that it must be cancelled
|
||||||
|
* once the drag exceed the configured threshold.
|
||||||
|
*
|
||||||
|
* Enum passed to the _clutter_gesture_action_set_threshold_trigger_edge()
|
||||||
|
* function.
|
||||||
|
*
|
||||||
|
* Since: 1.14
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CLUTTER_GESTURE_TRIGGER_EDGE_NONE = 0,
|
||||||
|
CLUTTER_GESTURE_TRIGGER_EDGE_AFTER,
|
||||||
|
CLUTTER_GESTURE_TRIGGER_EDGE_BEFORE
|
||||||
|
} ClutterGestureTriggerEdge;
|
||||||
|
|
||||||
|
|
||||||
|
void _clutter_gesture_action_set_threshold_trigger_edge (ClutterGestureAction *action,
|
||||||
|
ClutterGestureTriggerEdge edge);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __CLUTTER_GESTURE_ACTION_PRIVATE_H__ */
|
@ -87,7 +87,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "clutter-gesture-action.h"
|
#include "clutter-gesture-action-private.h"
|
||||||
|
|
||||||
#include "clutter-debug.h"
|
#include "clutter-debug.h"
|
||||||
#include "clutter-enum-types.h"
|
#include "clutter-enum-types.h"
|
||||||
@ -122,6 +122,8 @@ struct _ClutterGestureActionPrivate
|
|||||||
guint actor_capture_id;
|
guint actor_capture_id;
|
||||||
gulong stage_capture_id;
|
gulong stage_capture_id;
|
||||||
|
|
||||||
|
ClutterGestureTriggerEdge edge;
|
||||||
|
|
||||||
guint in_gesture : 1;
|
guint in_gesture : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -209,6 +211,15 @@ gesture_unregister_point (ClutterGestureAction *action, gint position)
|
|||||||
g_array_remove_index (priv->points, position);
|
g_array_remove_index (priv->points, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
gesture_get_threshold (ClutterGestureAction *action)
|
||||||
|
{
|
||||||
|
gint threshold;
|
||||||
|
ClutterSettings *settings = clutter_settings_get_default ();
|
||||||
|
g_object_get (settings, "dnd-drag-threshold", &threshold, NULL);
|
||||||
|
return threshold;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cancel_gesture (ClutterGestureAction *action)
|
cancel_gesture (ClutterGestureAction *action)
|
||||||
{
|
{
|
||||||
@ -227,6 +238,38 @@ cancel_gesture (ClutterGestureAction *action)
|
|||||||
g_signal_emit (action, gesture_signals[GESTURE_CANCEL], 0, actor);
|
g_signal_emit (action, gesture_signals[GESTURE_CANCEL], 0, actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
begin_gesture (ClutterGestureAction *action,
|
||||||
|
ClutterActor *actor)
|
||||||
|
{
|
||||||
|
ClutterGestureActionPrivate *priv = action->priv;
|
||||||
|
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
|
static gboolean
|
||||||
stage_captured_event_cb (ClutterActor *stage,
|
stage_captured_event_cb (ClutterActor *stage,
|
||||||
ClutterEvent *event,
|
ClutterEvent *event,
|
||||||
@ -234,7 +277,7 @@ stage_captured_event_cb (ClutterActor *stage,
|
|||||||
{
|
{
|
||||||
ClutterGestureActionPrivate *priv = action->priv;
|
ClutterGestureActionPrivate *priv = action->priv;
|
||||||
ClutterActor *actor;
|
ClutterActor *actor;
|
||||||
gint position;
|
gint position, drag_threshold;
|
||||||
gboolean return_value;
|
gboolean return_value;
|
||||||
GesturePoint *point;
|
GesturePoint *point;
|
||||||
gfloat motion_x, motion_y;
|
gfloat motion_x, motion_y;
|
||||||
@ -272,40 +315,18 @@ stage_captured_event_cb (ClutterActor *stage,
|
|||||||
if (priv->points->len < priv->requested_nb_points)
|
if (priv->points->len < priv->requested_nb_points)
|
||||||
return CLUTTER_EVENT_PROPAGATE;
|
return CLUTTER_EVENT_PROPAGATE;
|
||||||
|
|
||||||
|
drag_threshold = gesture_get_threshold (action);
|
||||||
|
|
||||||
if (!priv->in_gesture)
|
if (!priv->in_gesture)
|
||||||
{
|
{
|
||||||
gint drag_threshold;
|
/* Wait until the drag threshold has been exceeded
|
||||||
ClutterSettings *settings = clutter_settings_get_default ();
|
* before starting _TRIGGER_EDGE_AFTER gestures. */
|
||||||
|
if (priv->edge == CLUTTER_GESTURE_TRIGGER_EDGE_AFTER &&
|
||||||
g_object_get (settings,
|
(fabsf (point->press_y - motion_y) < drag_threshold) &&
|
||||||
"dnd-drag-threshold", &drag_threshold,
|
(fabsf (point->press_x - motion_x) < drag_threshold))
|
||||||
NULL);
|
|
||||||
|
|
||||||
if ((ABS (point->press_y - motion_y) >= drag_threshold) ||
|
|
||||||
(ABS (point->press_x - motion_x) >= drag_threshold))
|
|
||||||
{
|
|
||||||
priv->in_gesture = TRUE;
|
|
||||||
|
|
||||||
if (!CLUTTER_GESTURE_ACTION_GET_CLASS (action)->gesture_prepare (action, actor))
|
|
||||||
{
|
|
||||||
cancel_gesture (action);
|
|
||||||
return CLUTTER_EVENT_PROPAGATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* clutter_gesture_action_cancel() may have been called during
|
|
||||||
* gesture_prepare(), check that the gesture is still active. */
|
|
||||||
if (!priv->in_gesture)
|
|
||||||
return CLUTTER_EVENT_PROPAGATE;
|
return CLUTTER_EVENT_PROPAGATE;
|
||||||
|
|
||||||
g_signal_emit (action, gesture_signals[GESTURE_BEGIN], 0, actor,
|
if (!begin_gesture(action, actor))
|
||||||
&return_value);
|
|
||||||
if (!return_value)
|
|
||||||
{
|
|
||||||
cancel_gesture (action);
|
|
||||||
return CLUTTER_EVENT_PROPAGATE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return CLUTTER_EVENT_PROPAGATE;
|
return CLUTTER_EVENT_PROPAGATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,6 +346,16 @@ stage_captured_event_cb (ClutterActor *stage,
|
|||||||
cancel_gesture (action);
|
cancel_gesture (action);
|
||||||
return CLUTTER_EVENT_PROPAGATE;
|
return CLUTTER_EVENT_PROPAGATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if a _TRIGGER_EDGE_BEFORE gesture needs to be cancelled because
|
||||||
|
* the drag threshold has been exceeded. */
|
||||||
|
if (priv->edge == CLUTTER_GESTURE_TRIGGER_EDGE_BEFORE &&
|
||||||
|
((fabsf (point->press_y - motion_y) > drag_threshold) ||
|
||||||
|
(fabsf (point->press_x - motion_x) > drag_threshold)))
|
||||||
|
{
|
||||||
|
cancel_gesture (action);
|
||||||
|
return CLUTTER_EVENT_PROPAGATE;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLUTTER_BUTTON_RELEASE:
|
case CLUTTER_BUTTON_RELEASE:
|
||||||
@ -400,6 +431,11 @@ actor_captured_event_cb (ClutterActor *actor,
|
|||||||
G_CALLBACK (stage_captured_event_cb),
|
G_CALLBACK (stage_captured_event_cb),
|
||||||
action);
|
action);
|
||||||
|
|
||||||
|
/* Start the gesture immediately if the gesture has no
|
||||||
|
* _TRIGGER_EDGE_AFTER drag threshold. */
|
||||||
|
if (priv->edge != CLUTTER_GESTURE_TRIGGER_EDGE_AFTER)
|
||||||
|
begin_gesture (action, actor);
|
||||||
|
|
||||||
return CLUTTER_EVENT_PROPAGATE;
|
return CLUTTER_EVENT_PROPAGATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,6 +484,26 @@ default_event_handler (ClutterGestureAction *action,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*< private >
|
||||||
|
* _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 can be called by #ClutterGestureAction subclasses that needs
|
||||||
|
* to change the %CLUTTER_GESTURE_TRIGGER_EDGE_AFTER default.
|
||||||
|
*
|
||||||
|
* Since: 1.14
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_clutter_gesture_action_set_threshold_trigger_edge (ClutterGestureAction *action,
|
||||||
|
ClutterGestureTriggerEdge edge)
|
||||||
|
{
|
||||||
|
action->priv->edge = edge;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_gesture_action_class_init (ClutterGestureActionClass *klass)
|
clutter_gesture_action_class_init (ClutterGestureActionClass *klass)
|
||||||
{
|
{
|
||||||
@ -562,6 +618,7 @@ clutter_gesture_action_init (ClutterGestureAction *self)
|
|||||||
|
|
||||||
self->priv->points = g_array_sized_new (FALSE, TRUE, sizeof (GesturePoint), 3);
|
self->priv->points = g_array_sized_new (FALSE, TRUE, sizeof (GesturePoint), 3);
|
||||||
self->priv->requested_nb_points = 1;
|
self->priv->requested_nb_points = 1;
|
||||||
|
self->priv->edge = CLUTTER_GESTURE_TRIGGER_EDGE_AFTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -812,18 +869,15 @@ clutter_gesture_action_set_n_touch_points (ClutterGestureAction *action,
|
|||||||
if (priv->points->len < priv->requested_nb_points)
|
if (priv->points->len < priv->requested_nb_points)
|
||||||
cancel_gesture (action);
|
cancel_gesture (action);
|
||||||
}
|
}
|
||||||
else
|
else if (priv->edge == CLUTTER_GESTURE_TRIGGER_EDGE_AFTER)
|
||||||
{
|
{
|
||||||
if (priv->points->len >= priv->requested_nb_points)
|
if (priv->points->len >= priv->requested_nb_points)
|
||||||
{
|
{
|
||||||
ClutterActor *actor =
|
ClutterActor *actor =
|
||||||
clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
|
clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
|
||||||
ClutterSettings *settings = clutter_settings_get_default ();
|
|
||||||
gint i, drag_threshold;
|
gint i, drag_threshold;
|
||||||
|
|
||||||
g_object_get (settings,
|
drag_threshold = gesture_get_threshold (action);
|
||||||
"dnd-drag-threshold", &drag_threshold,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
for (i = 0; i < priv->points->len; i++)
|
for (i = 0; i < priv->points->len; i++)
|
||||||
{
|
{
|
||||||
@ -832,16 +886,7 @@ clutter_gesture_action_set_n_touch_points (ClutterGestureAction *action,
|
|||||||
if ((ABS (point->press_y - point->last_motion_y) >= drag_threshold) ||
|
if ((ABS (point->press_y - point->last_motion_y) >= drag_threshold) ||
|
||||||
(ABS (point->press_x - point->last_motion_x) >= drag_threshold))
|
(ABS (point->press_x - point->last_motion_x) >= drag_threshold))
|
||||||
{
|
{
|
||||||
gboolean return_value;
|
begin_gesture (action, actor);
|
||||||
|
|
||||||
priv->in_gesture = TRUE;
|
|
||||||
|
|
||||||
g_signal_emit (action, gesture_signals[GESTURE_BEGIN], 0, actor,
|
|
||||||
&return_value);
|
|
||||||
|
|
||||||
if (!return_value)
|
|
||||||
cancel_gesture (action);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user