mirror of
https://github.com/brl/mutter.git
synced 2024-12-27 13:22:15 +00:00
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-private.h \
|
||||
$(srcdir)/clutter-flatten-effect.h \
|
||||
$(srcdir)/clutter-gesture-action-private.h \
|
||||
$(srcdir)/clutter-id-pool.h \
|
||||
$(srcdir)/clutter-master-clock.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"
|
||||
#endif
|
||||
|
||||
#include "clutter-gesture-action.h"
|
||||
#include "clutter-gesture-action-private.h"
|
||||
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-enum-types.h"
|
||||
@ -122,6 +122,8 @@ struct _ClutterGestureActionPrivate
|
||||
guint actor_capture_id;
|
||||
gulong stage_capture_id;
|
||||
|
||||
ClutterGestureTriggerEdge edge;
|
||||
|
||||
guint in_gesture : 1;
|
||||
};
|
||||
|
||||
@ -209,6 +211,15 @@ gesture_unregister_point (ClutterGestureAction *action, gint 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
|
||||
cancel_gesture (ClutterGestureAction *action)
|
||||
{
|
||||
@ -227,6 +238,38 @@ cancel_gesture (ClutterGestureAction *action)
|
||||
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
|
||||
stage_captured_event_cb (ClutterActor *stage,
|
||||
ClutterEvent *event,
|
||||
@ -234,7 +277,7 @@ stage_captured_event_cb (ClutterActor *stage,
|
||||
{
|
||||
ClutterGestureActionPrivate *priv = action->priv;
|
||||
ClutterActor *actor;
|
||||
gint position;
|
||||
gint position, drag_threshold;
|
||||
gboolean return_value;
|
||||
GesturePoint *point;
|
||||
gfloat motion_x, motion_y;
|
||||
@ -272,40 +315,18 @@ stage_captured_event_cb (ClutterActor *stage,
|
||||
if (priv->points->len < priv->requested_nb_points)
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
drag_threshold = gesture_get_threshold (action);
|
||||
|
||||
if (!priv->in_gesture)
|
||||
{
|
||||
gint drag_threshold;
|
||||
ClutterSettings *settings = clutter_settings_get_default ();
|
||||
/* Wait until the drag threshold has been exceeded
|
||||
* before starting _TRIGGER_EDGE_AFTER gestures. */
|
||||
if (priv->edge == CLUTTER_GESTURE_TRIGGER_EDGE_AFTER &&
|
||||
(fabsf (point->press_y - motion_y) < drag_threshold) &&
|
||||
(fabsf (point->press_x - motion_x) < drag_threshold))
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
g_object_get (settings,
|
||||
"dnd-drag-threshold", &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;
|
||||
|
||||
g_signal_emit (action, gesture_signals[GESTURE_BEGIN], 0, actor,
|
||||
&return_value);
|
||||
if (!return_value)
|
||||
{
|
||||
cancel_gesture (action);
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!begin_gesture(action, actor))
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
@ -325,6 +346,16 @@ stage_captured_event_cb (ClutterActor *stage,
|
||||
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. */
|
||||
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;
|
||||
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
@ -400,6 +431,11 @@ actor_captured_event_cb (ClutterActor *actor,
|
||||
G_CALLBACK (stage_captured_event_cb),
|
||||
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;
|
||||
}
|
||||
|
||||
@ -448,6 +484,26 @@ default_event_handler (ClutterGestureAction *action,
|
||||
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
|
||||
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->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)
|
||||
cancel_gesture (action);
|
||||
}
|
||||
else
|
||||
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));
|
||||
ClutterSettings *settings = clutter_settings_get_default ();
|
||||
gint i, drag_threshold;
|
||||
|
||||
g_object_get (settings,
|
||||
"dnd-drag-threshold", &drag_threshold,
|
||||
NULL);
|
||||
drag_threshold = gesture_get_threshold (action);
|
||||
|
||||
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) ||
|
||||
(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);
|
||||
|
||||
begin_gesture (action, actor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user