GestureActions: Add per-action thresholds
Instead of relying on the dnd drag threshold, add per-action horizontal and vertical thresholds. Use them in the swipe action as well. https://bugzilla.gnome.org/show_bug.cgi?id=724242
This commit is contained in:
parent
54e2657cb0
commit
32b3d27bb9
@ -124,6 +124,7 @@ struct _ClutterGestureActionPrivate
|
|||||||
gulong stage_capture_id;
|
gulong stage_capture_id;
|
||||||
|
|
||||||
ClutterGestureTriggerEdge edge;
|
ClutterGestureTriggerEdge edge;
|
||||||
|
float distance_x, distance_y;
|
||||||
|
|
||||||
guint in_gesture : 1;
|
guint in_gesture : 1;
|
||||||
};
|
};
|
||||||
@ -134,6 +135,8 @@ enum
|
|||||||
|
|
||||||
PROP_N_TOUCH_POINTS,
|
PROP_N_TOUCH_POINTS,
|
||||||
PROP_THRESHOLD_TRIGGER_EDGE,
|
PROP_THRESHOLD_TRIGGER_EDGE,
|
||||||
|
PROP_THRESHOLD_TRIGGER_DISTANCE_X,
|
||||||
|
PROP_THRESHOLD_TRIGGER_DISTANCE_Y,
|
||||||
|
|
||||||
PROP_LAST
|
PROP_LAST
|
||||||
};
|
};
|
||||||
@ -265,7 +268,7 @@ gesture_update_release_point (GesturePoint *point,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
gesture_get_threshold (void)
|
gesture_get_default_threshold (void)
|
||||||
{
|
{
|
||||||
gint threshold;
|
gint threshold;
|
||||||
ClutterSettings *settings = clutter_settings_get_default ();
|
ClutterSettings *settings = clutter_settings_get_default ();
|
||||||
@ -274,15 +277,18 @@ gesture_get_threshold (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gesture_point_pass_threshold (GesturePoint *point, ClutterEvent *event)
|
gesture_point_pass_threshold (ClutterGestureAction *action,
|
||||||
|
GesturePoint *point,
|
||||||
|
ClutterEvent *event)
|
||||||
{
|
{
|
||||||
gint drag_threshold = gesture_get_threshold ();
|
float threshold_x, threshold_y;
|
||||||
gfloat motion_x, motion_y;
|
gfloat motion_x, motion_y;
|
||||||
|
|
||||||
clutter_event_get_coords (event, &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) < drag_threshold) &&
|
if ((fabsf (point->press_y - motion_y) < threshold_y) &&
|
||||||
(fabsf (point->press_x - motion_x) < drag_threshold))
|
(fabsf (point->press_x - motion_x) < threshold_x))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -352,7 +358,8 @@ stage_captured_event_cb (ClutterActor *stage,
|
|||||||
{
|
{
|
||||||
ClutterGestureActionPrivate *priv = action->priv;
|
ClutterGestureActionPrivate *priv = action->priv;
|
||||||
ClutterActor *actor;
|
ClutterActor *actor;
|
||||||
gint position, drag_threshold;
|
gint position;
|
||||||
|
float threshold_x, threshold_y;
|
||||||
gboolean return_value;
|
gboolean return_value;
|
||||||
GesturePoint *point;
|
GesturePoint *point;
|
||||||
|
|
||||||
@ -391,7 +398,7 @@ stage_captured_event_cb (ClutterActor *stage,
|
|||||||
/* Wait until the drag threshold has been exceeded
|
/* Wait until the drag threshold has been exceeded
|
||||||
* before starting _TRIGGER_EDGE_AFTER gestures. */
|
* before starting _TRIGGER_EDGE_AFTER gestures. */
|
||||||
if (priv->edge == CLUTTER_GESTURE_TRIGGER_EDGE_AFTER &&
|
if (priv->edge == CLUTTER_GESTURE_TRIGGER_EDGE_AFTER &&
|
||||||
gesture_point_pass_threshold (point, event))
|
gesture_point_pass_threshold (action, point, event))
|
||||||
{
|
{
|
||||||
gesture_update_motion_point (point, event);
|
gesture_update_motion_point (point, event);
|
||||||
return CLUTTER_EVENT_PROPAGATE;
|
return CLUTTER_EVENT_PROPAGATE;
|
||||||
@ -420,10 +427,10 @@ stage_captured_event_cb (ClutterActor *stage,
|
|||||||
|
|
||||||
/* Check if a _TRIGGER_EDGE_BEFORE gesture needs to be cancelled because
|
/* Check if a _TRIGGER_EDGE_BEFORE gesture needs to be cancelled because
|
||||||
* the drag threshold has been exceeded. */
|
* the drag threshold has been exceeded. */
|
||||||
drag_threshold = gesture_get_threshold ();
|
clutter_gesture_action_get_threshold_trigger_distance (action, &threshold_x, &threshold_y);
|
||||||
if (priv->edge == CLUTTER_GESTURE_TRIGGER_EDGE_BEFORE &&
|
if (priv->edge == CLUTTER_GESTURE_TRIGGER_EDGE_BEFORE &&
|
||||||
((fabsf (point->press_y - point->last_motion_y) > drag_threshold) ||
|
((fabsf (point->press_y - point->last_motion_y) > threshold_y) ||
|
||||||
(fabsf (point->press_x - point->last_motion_x) > drag_threshold)))
|
(fabsf (point->press_x - point->last_motion_x) > threshold_x)))
|
||||||
{
|
{
|
||||||
cancel_gesture (action);
|
cancel_gesture (action);
|
||||||
return CLUTTER_EVENT_PROPAGATE;
|
return CLUTTER_EVENT_PROPAGATE;
|
||||||
@ -571,6 +578,14 @@ clutter_gesture_action_set_property (GObject *gobject,
|
|||||||
clutter_gesture_action_set_threshold_trigger_edge (self, g_value_get_enum (value));
|
clutter_gesture_action_set_threshold_trigger_edge (self, g_value_get_enum (value));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_THRESHOLD_TRIGGER_DISTANCE_X:
|
||||||
|
clutter_gesture_action_set_threshold_trigger_distance (self, g_value_get_float (value), self->priv->distance_y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_THRESHOLD_TRIGGER_DISTANCE_Y:
|
||||||
|
clutter_gesture_action_set_threshold_trigger_distance (self, self->priv->distance_x, g_value_get_float (value));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -595,6 +610,20 @@ clutter_gesture_action_get_property (GObject *gobject,
|
|||||||
g_value_set_enum (value, self->priv->edge);
|
g_value_set_enum (value, self->priv->edge);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_THRESHOLD_TRIGGER_DISTANCE_X:
|
||||||
|
if (self->priv->distance_x > 0.0)
|
||||||
|
g_value_set_float (value, self->priv->distance_x);
|
||||||
|
else
|
||||||
|
g_value_set_float (value, gesture_get_default_threshold ());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_THRESHOLD_TRIGGER_DISTANCE_Y:
|
||||||
|
if (self->priv->distance_y > 0.0)
|
||||||
|
g_value_set_float (value, self->priv->distance_y);
|
||||||
|
else
|
||||||
|
g_value_set_float (value, gesture_get_default_threshold ());
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -659,6 +688,44 @@ clutter_gesture_action_class_init (ClutterGestureActionClass *klass)
|
|||||||
CLUTTER_PARAM_READWRITE |
|
CLUTTER_PARAM_READWRITE |
|
||||||
G_PARAM_CONSTRUCT_ONLY);
|
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,
|
g_object_class_install_properties (gobject_class,
|
||||||
PROP_LAST,
|
PROP_LAST,
|
||||||
gesture_props);
|
gesture_props);
|
||||||
@ -1030,16 +1097,17 @@ clutter_gesture_action_set_n_touch_points (ClutterGestureAction *action,
|
|||||||
{
|
{
|
||||||
ClutterActor *actor =
|
ClutterActor *actor =
|
||||||
clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
|
clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
|
||||||
gint i, drag_threshold;
|
gint i;
|
||||||
|
float threshold_x, threshold_y;
|
||||||
|
|
||||||
drag_threshold = gesture_get_threshold ();
|
clutter_gesture_action_get_threshold_trigger_distance (action, &threshold_x, &threshold_y);
|
||||||
|
|
||||||
for (i = 0; i < priv->points->len; i++)
|
for (i = 0; i < priv->points->len; i++)
|
||||||
{
|
{
|
||||||
GesturePoint *point = &g_array_index (priv->points, GesturePoint, i);
|
GesturePoint *point = &g_array_index (priv->points, GesturePoint, i);
|
||||||
|
|
||||||
if ((ABS (point->press_y - point->last_motion_y) >= drag_threshold) ||
|
if ((fabsf (point->press_y - point->last_motion_y) >= threshold_y) ||
|
||||||
(ABS (point->press_x - point->last_motion_x) >= drag_threshold))
|
(fabsf (point->press_x - point->last_motion_x) >= threshold_x))
|
||||||
{
|
{
|
||||||
begin_gesture (action, actor);
|
begin_gesture (action, actor);
|
||||||
break;
|
break;
|
||||||
@ -1200,3 +1268,70 @@ clutter_gesture_action_get_threshold_trigger_egde (ClutterGestureAction *action)
|
|||||||
|
|
||||||
return action->priv->edge;
|
return action->priv->edge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
|
||||||
|
|
||||||
|
if (fabsf (x - action->priv->distance_x) > FLOAT_EPSILON)
|
||||||
|
{
|
||||||
|
action->priv->distance_x = x;
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (action), gesture_props[PROP_THRESHOLD_TRIGGER_DISTANCE_X]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fabsf (y - action->priv->distance_y) > FLOAT_EPSILON)
|
||||||
|
{
|
||||||
|
action->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)
|
||||||
|
{
|
||||||
|
g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
|
||||||
|
|
||||||
|
if (x != NULL)
|
||||||
|
{
|
||||||
|
if (action->priv->distance_x > 0.0)
|
||||||
|
*x = action->priv->distance_x;
|
||||||
|
else
|
||||||
|
*x = gesture_get_default_threshold ();
|
||||||
|
}
|
||||||
|
if (y != NULL)
|
||||||
|
{
|
||||||
|
if (action->priv->distance_y > 0.0)
|
||||||
|
*y = action->priv->distance_y;
|
||||||
|
else
|
||||||
|
*y = gesture_get_default_threshold ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -155,6 +155,16 @@ void clutter_gesture_action_set_threshold_trigger_edg
|
|||||||
CLUTTER_AVAILABLE_IN_1_18
|
CLUTTER_AVAILABLE_IN_1_18
|
||||||
ClutterGestureTriggerEdge clutter_gesture_action_get_threshold_trigger_egde (ClutterGestureAction *action);
|
ClutterGestureTriggerEdge clutter_gesture_action_get_threshold_trigger_egde (ClutterGestureAction *action);
|
||||||
|
|
||||||
|
CLUTTER_AVAILABLE_IN_1_18
|
||||||
|
void clutter_gesture_action_set_threshold_trigger_distance (ClutterGestureAction *action,
|
||||||
|
float x,
|
||||||
|
float y);
|
||||||
|
|
||||||
|
CLUTTER_AVAILABLE_IN_1_18
|
||||||
|
void clutter_gesture_action_get_threshold_trigger_distance (ClutterGestureAction *action,
|
||||||
|
float *x,
|
||||||
|
float *y);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_GESTURE_ACTION_H__ */
|
#endif /* __CLUTTER_GESTURE_ACTION_H__ */
|
||||||
|
@ -54,7 +54,7 @@ struct _ClutterSwipeActionPrivate
|
|||||||
ClutterSwipeDirection h_direction;
|
ClutterSwipeDirection h_direction;
|
||||||
ClutterSwipeDirection v_direction;
|
ClutterSwipeDirection v_direction;
|
||||||
|
|
||||||
int threshold;
|
float distance_x, distance_y;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -74,13 +74,15 @@ gesture_begin (ClutterGestureAction *action,
|
|||||||
ClutterActor *actor)
|
ClutterActor *actor)
|
||||||
{
|
{
|
||||||
ClutterSwipeActionPrivate *priv = CLUTTER_SWIPE_ACTION (action)->priv;
|
ClutterSwipeActionPrivate *priv = CLUTTER_SWIPE_ACTION (action)->priv;
|
||||||
ClutterSettings *settings = clutter_settings_get_default ();
|
|
||||||
|
|
||||||
/* reset the state at the beginning of a new gesture */
|
/* reset the state at the beginning of a new gesture */
|
||||||
priv->h_direction = 0;
|
priv->h_direction = 0;
|
||||||
priv->v_direction = 0;
|
priv->v_direction = 0;
|
||||||
|
|
||||||
g_object_get (settings, "dnd-drag-threshold", &priv->threshold, NULL);
|
g_object_get (action,
|
||||||
|
"threshold-trigger-distance-x", &priv->distance_x,
|
||||||
|
"threshold-trigger-distance-y", &priv->distance_y,
|
||||||
|
NULL);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -108,14 +110,14 @@ gesture_progress (ClutterGestureAction *action,
|
|||||||
delta_x = press_x - motion_x;
|
delta_x = press_x - motion_x;
|
||||||
delta_y = press_y - motion_y;
|
delta_y = press_y - motion_y;
|
||||||
|
|
||||||
if (delta_x >= priv->threshold)
|
if (delta_x >= priv->distance_x)
|
||||||
h_direction = CLUTTER_SWIPE_DIRECTION_RIGHT;
|
h_direction = CLUTTER_SWIPE_DIRECTION_RIGHT;
|
||||||
else if (delta_x < -priv->threshold)
|
else if (delta_x < -priv->distance_x)
|
||||||
h_direction = CLUTTER_SWIPE_DIRECTION_LEFT;
|
h_direction = CLUTTER_SWIPE_DIRECTION_LEFT;
|
||||||
|
|
||||||
if (delta_y >= priv->threshold)
|
if (delta_y >= priv->distance_y)
|
||||||
v_direction = CLUTTER_SWIPE_DIRECTION_DOWN;
|
v_direction = CLUTTER_SWIPE_DIRECTION_DOWN;
|
||||||
else if (delta_y < -priv->threshold)
|
else if (delta_y < -priv->distance_y)
|
||||||
v_direction = CLUTTER_SWIPE_DIRECTION_UP;
|
v_direction = CLUTTER_SWIPE_DIRECTION_UP;
|
||||||
|
|
||||||
/* cancel gesture on direction reversal */
|
/* cancel gesture on direction reversal */
|
||||||
@ -152,14 +154,14 @@ gesture_end (ClutterGestureAction *action,
|
|||||||
0,
|
0,
|
||||||
&release_x, &release_y);
|
&release_x, &release_y);
|
||||||
|
|
||||||
if (release_x - press_x > priv->threshold)
|
if (release_x - press_x > priv->distance_y)
|
||||||
direction |= CLUTTER_SWIPE_DIRECTION_RIGHT;
|
direction |= CLUTTER_SWIPE_DIRECTION_RIGHT;
|
||||||
else if (press_x - release_x > priv->threshold)
|
else if (press_x - release_x > priv->distance_x)
|
||||||
direction |= CLUTTER_SWIPE_DIRECTION_LEFT;
|
direction |= CLUTTER_SWIPE_DIRECTION_LEFT;
|
||||||
|
|
||||||
if (release_y - press_y > priv->threshold)
|
if (release_y - press_y > priv->distance_y)
|
||||||
direction |= CLUTTER_SWIPE_DIRECTION_DOWN;
|
direction |= CLUTTER_SWIPE_DIRECTION_DOWN;
|
||||||
else if (press_y - release_y > priv->threshold)
|
else if (press_y - release_y > priv->distance_y)
|
||||||
direction |= CLUTTER_SWIPE_DIRECTION_UP;
|
direction |= CLUTTER_SWIPE_DIRECTION_UP;
|
||||||
|
|
||||||
/* XXX:2.0 remove */
|
/* XXX:2.0 remove */
|
||||||
|
Loading…
Reference in New Issue
Block a user