mirror of
https://github.com/brl/mutter.git
synced 2024-11-29 19:40:43 -05:00
click-action: Add support for long press detection
A long press is a special form of click action; the default implementation uses a single signal with multiple states: query, action and cancel. On click we use the "query" state to check whether the ClutterClickAction supports long presses; if the callback returns TRUE then we install a timeout and we either emit the "activate" state when the timeout expires or we emit the "cancel" state if the pointer leaves the actor, or if the pointer moves outside a certain threshold. If the long press reached the "activate" state then we skip the clicked signal emission.
This commit is contained in:
parent
93207d08f8
commit
23a9980c72
@ -45,6 +45,50 @@
|
|||||||
* g_signal_connect (action, "clicked", G_CALLBACK (on_clicked), NULL);
|
* g_signal_connect (action, "clicked", G_CALLBACK (on_clicked), NULL);
|
||||||
* ]|
|
* ]|
|
||||||
*
|
*
|
||||||
|
* #ClutterClickAction also supports long press gestures: a long press is
|
||||||
|
* activated if the pointer remains pressed within a certain threshold (as
|
||||||
|
* defined by the #ClutterClickAction:long-press-threshold property) for a
|
||||||
|
* minimum amount of time (as the defined by the
|
||||||
|
* #ClutterClickAction:long-press-duration property).
|
||||||
|
* The #ClutterClickAction::long-press signal is emitted multiple times,
|
||||||
|
* using different #ClutterLongPressState values; to handle long presses
|
||||||
|
* you should connect to the #ClutterClickAction::long-press signal and
|
||||||
|
* handle the different states:
|
||||||
|
*
|
||||||
|
* |[
|
||||||
|
* static gboolean
|
||||||
|
* on_long_press (ClutterClickAction *action,
|
||||||
|
* ClutterActor *actor,
|
||||||
|
* ClutterLongPressState state)
|
||||||
|
* {
|
||||||
|
* switch (state)
|
||||||
|
* {
|
||||||
|
* case CLUTTER_LONG_PRESS_QUERY:
|
||||||
|
* /* return TRUE if the actor should support long press
|
||||||
|
* * gestures, and FALSE otherwise; this state will be
|
||||||
|
* * emitted on button presses
|
||||||
|
* */
|
||||||
|
* return TRUE;
|
||||||
|
*
|
||||||
|
* case CLUTTER_LONG_PRESS_ACTIVATE:
|
||||||
|
* /* this state is emitted if the minimum duration has
|
||||||
|
* * been reached without the gesture being cancelled.
|
||||||
|
* * the return value is not used
|
||||||
|
* */
|
||||||
|
* return TRUE;
|
||||||
|
*
|
||||||
|
* case CLUTTER_LONG_PRESS_CANCEL:
|
||||||
|
* /* this state is emitted if the long press was cancelled;
|
||||||
|
* * for instance, the pointer went outside the actor or the
|
||||||
|
* * allowed threshold, or the button was released before
|
||||||
|
* * the minimum duration was reached. the return value is
|
||||||
|
* * not used
|
||||||
|
* */
|
||||||
|
* return FALSE;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ]|
|
||||||
|
*
|
||||||
* #ClutterClickAction is available since Clutter 1.4
|
* #ClutterClickAction is available since Clutter 1.4
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -64,10 +108,17 @@ struct _ClutterClickActionPrivate
|
|||||||
ClutterActor *stage;
|
ClutterActor *stage;
|
||||||
|
|
||||||
guint event_id;
|
guint event_id;
|
||||||
gulong capture_id;
|
guint capture_id;
|
||||||
|
guint long_press_id;
|
||||||
|
|
||||||
|
gint long_press_threshold;
|
||||||
|
gint long_press_duration;
|
||||||
|
gint drag_threshold;
|
||||||
|
|
||||||
guint press_button;
|
guint press_button;
|
||||||
ClutterModifierType modifier_state;
|
ClutterModifierType modifier_state;
|
||||||
|
gfloat press_x;
|
||||||
|
gfloat press_y;
|
||||||
|
|
||||||
guint is_held : 1;
|
guint is_held : 1;
|
||||||
guint is_pressed : 1;
|
guint is_pressed : 1;
|
||||||
@ -79,15 +130,18 @@ enum
|
|||||||
|
|
||||||
PROP_HELD,
|
PROP_HELD,
|
||||||
PROP_PRESSED,
|
PROP_PRESSED,
|
||||||
|
PROP_LONG_PRESS_THRESHOLD,
|
||||||
|
PROP_LONG_PRESS_DURATION,
|
||||||
|
|
||||||
PROP_LAST
|
PROP_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
static GParamSpec *obj_props[PROP_LAST];
|
static GParamSpec *obj_props[PROP_LAST] = { NULL, };
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
CLICKED,
|
CLICKED,
|
||||||
|
LONG_PRESS,
|
||||||
|
|
||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
};
|
};
|
||||||
@ -107,6 +161,8 @@ click_action_set_pressed (ClutterClickAction *action,
|
|||||||
{
|
{
|
||||||
ClutterClickActionPrivate *priv = action->priv;
|
ClutterClickActionPrivate *priv = action->priv;
|
||||||
|
|
||||||
|
is_pressed = !!is_pressed;
|
||||||
|
|
||||||
if (priv->is_pressed == is_pressed)
|
if (priv->is_pressed == is_pressed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -114,6 +170,107 @@ click_action_set_pressed (ClutterClickAction *action,
|
|||||||
g_object_notify_by_pspec (G_OBJECT (action), obj_props[PROP_PRESSED]);
|
g_object_notify_by_pspec (G_OBJECT (action), obj_props[PROP_PRESSED]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
click_action_set_held (ClutterClickAction *action,
|
||||||
|
gboolean is_held)
|
||||||
|
{
|
||||||
|
ClutterClickActionPrivate *priv = action->priv;
|
||||||
|
|
||||||
|
is_held = !!is_held;
|
||||||
|
|
||||||
|
if (priv->is_held == is_held)
|
||||||
|
return;
|
||||||
|
|
||||||
|
priv->is_held = is_held;
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (action), obj_props[PROP_HELD]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
click_action_emit_long_press (gpointer data)
|
||||||
|
{
|
||||||
|
ClutterClickAction *action = data;
|
||||||
|
ClutterClickActionPrivate *priv = action->priv;
|
||||||
|
ClutterActor *actor;
|
||||||
|
gboolean result;
|
||||||
|
|
||||||
|
priv->long_press_id = 0;
|
||||||
|
|
||||||
|
actor = clutter_actor_meta_get_actor (data);
|
||||||
|
|
||||||
|
g_signal_emit (action, click_signals[LONG_PRESS], 0,
|
||||||
|
actor,
|
||||||
|
CLUTTER_LONG_PRESS_ACTIVATE,
|
||||||
|
&result);
|
||||||
|
|
||||||
|
if (priv->capture_id != 0)
|
||||||
|
{
|
||||||
|
g_signal_handler_disconnect (priv->stage, priv->capture_id);
|
||||||
|
priv->capture_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
click_action_set_pressed (action, FALSE);
|
||||||
|
click_action_set_held (action, FALSE);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
click_action_query_long_press (ClutterClickAction *action)
|
||||||
|
{
|
||||||
|
ClutterClickActionPrivate *priv = action->priv;
|
||||||
|
ClutterActor *actor;
|
||||||
|
gboolean result = FALSE;
|
||||||
|
gint timeout;
|
||||||
|
|
||||||
|
if (priv->long_press_duration < 0)
|
||||||
|
{
|
||||||
|
ClutterSettings *settings = clutter_settings_get_default ();
|
||||||
|
|
||||||
|
g_object_get (settings,
|
||||||
|
"long-press-duration", &timeout,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
timeout = priv->long_press_duration;
|
||||||
|
|
||||||
|
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
|
||||||
|
|
||||||
|
g_signal_emit (action, click_signals[LONG_PRESS], 0,
|
||||||
|
actor,
|
||||||
|
CLUTTER_LONG_PRESS_QUERY,
|
||||||
|
&result);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
priv->long_press_id =
|
||||||
|
clutter_threads_add_timeout (timeout,
|
||||||
|
click_action_emit_long_press,
|
||||||
|
action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
click_action_cancel_long_press (ClutterClickAction *action)
|
||||||
|
{
|
||||||
|
ClutterClickActionPrivate *priv = action->priv;
|
||||||
|
|
||||||
|
if (priv->long_press_id != 0)
|
||||||
|
{
|
||||||
|
ClutterActor *actor;
|
||||||
|
gboolean result;
|
||||||
|
|
||||||
|
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
|
||||||
|
|
||||||
|
g_source_remove (priv->long_press_id);
|
||||||
|
priv->long_press_id = 0;
|
||||||
|
|
||||||
|
g_signal_emit (action, click_signals[LONG_PRESS], 0,
|
||||||
|
actor,
|
||||||
|
CLUTTER_LONG_PRESS_CANCEL,
|
||||||
|
&result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
on_event (ClutterActor *actor,
|
on_event (ClutterActor *actor,
|
||||||
ClutterEvent *event,
|
ClutterEvent *event,
|
||||||
@ -136,9 +293,20 @@ on_event (ClutterActor *actor,
|
|||||||
if (!clutter_actor_contains (actor, clutter_event_get_source (event)))
|
if (!clutter_actor_contains (actor, clutter_event_get_source (event)))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
priv->is_held = TRUE;
|
|
||||||
priv->press_button = clutter_event_get_button (event);
|
priv->press_button = clutter_event_get_button (event);
|
||||||
priv->modifier_state = clutter_event_get_state (event);
|
priv->modifier_state = clutter_event_get_state (event);
|
||||||
|
clutter_event_get_coords (event, &priv->press_x, &priv->press_y);
|
||||||
|
|
||||||
|
if (priv->long_press_threshold < 0)
|
||||||
|
{
|
||||||
|
ClutterSettings *settings = clutter_settings_get_default ();
|
||||||
|
|
||||||
|
g_object_get (settings,
|
||||||
|
"dnd-drag-threshold", &priv->drag_threshold,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
priv->drag_threshold = priv->long_press_threshold;
|
||||||
|
|
||||||
if (priv->stage == NULL)
|
if (priv->stage == NULL)
|
||||||
priv->stage = clutter_actor_get_stage (actor);
|
priv->stage = clutter_actor_get_stage (actor);
|
||||||
@ -148,6 +316,8 @@ on_event (ClutterActor *actor,
|
|||||||
action);
|
action);
|
||||||
|
|
||||||
click_action_set_pressed (action, TRUE);
|
click_action_set_pressed (action, TRUE);
|
||||||
|
click_action_set_held (action, TRUE);
|
||||||
|
click_action_query_long_press (action);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLUTTER_ENTER:
|
case CLUTTER_ENTER:
|
||||||
@ -156,6 +326,7 @@ on_event (ClutterActor *actor,
|
|||||||
|
|
||||||
case CLUTTER_LEAVE:
|
case CLUTTER_LEAVE:
|
||||||
click_action_set_pressed (action, priv->is_held);
|
click_action_set_pressed (action, priv->is_held);
|
||||||
|
click_action_cancel_long_press (action);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -186,7 +357,8 @@ on_captured_event (ClutterActor *stage,
|
|||||||
clutter_event_get_click_count (event) != 1)
|
clutter_event_get_click_count (event) != 1)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
priv->is_held = FALSE;
|
click_action_set_held (action, FALSE);
|
||||||
|
click_action_cancel_long_press (action);
|
||||||
|
|
||||||
/* disconnect the capture */
|
/* disconnect the capture */
|
||||||
if (priv->capture_id != 0)
|
if (priv->capture_id != 0)
|
||||||
@ -195,6 +367,12 @@ on_captured_event (ClutterActor *stage,
|
|||||||
priv->capture_id = 0;
|
priv->capture_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priv->long_press_id != 0)
|
||||||
|
{
|
||||||
|
g_source_remove (priv->long_press_id);
|
||||||
|
priv->long_press_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!clutter_actor_contains (actor, clutter_event_get_source (event)))
|
if (!clutter_actor_contains (actor, clutter_event_get_source (event)))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@ -218,6 +396,25 @@ on_captured_event (ClutterActor *stage,
|
|||||||
g_signal_emit (action, click_signals[CLICKED], 0, actor);
|
g_signal_emit (action, click_signals[CLICKED], 0, actor);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CLUTTER_MOTION:
|
||||||
|
{
|
||||||
|
gfloat motion_x, motion_y;
|
||||||
|
gfloat delta_x, delta_y;
|
||||||
|
|
||||||
|
if (!priv->is_held)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
clutter_event_get_coords (event, &motion_x, &motion_y);
|
||||||
|
|
||||||
|
delta_x = ABS (motion_x - priv->press_x);
|
||||||
|
delta_y = ABS (motion_y - priv->press_y);
|
||||||
|
|
||||||
|
if (delta_x > priv->drag_threshold ||
|
||||||
|
delta_y > priv->drag_threshold)
|
||||||
|
click_action_cancel_long_press (action);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -229,7 +426,8 @@ static void
|
|||||||
clutter_click_action_set_actor (ClutterActorMeta *meta,
|
clutter_click_action_set_actor (ClutterActorMeta *meta,
|
||||||
ClutterActor *actor)
|
ClutterActor *actor)
|
||||||
{
|
{
|
||||||
ClutterClickActionPrivate *priv = CLUTTER_CLICK_ACTION (meta)->priv;
|
ClutterClickAction *action = CLUTTER_CLICK_ACTION (meta);
|
||||||
|
ClutterClickActionPrivate *priv = action->priv;
|
||||||
|
|
||||||
if (priv->event_id != 0)
|
if (priv->event_id != 0)
|
||||||
{
|
{
|
||||||
@ -246,14 +444,47 @@ clutter_click_action_set_actor (ClutterActorMeta *meta,
|
|||||||
priv->stage = NULL;
|
priv->stage = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priv->long_press_id != 0)
|
||||||
|
{
|
||||||
|
g_source_remove (priv->long_press_id);
|
||||||
|
priv->long_press_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
click_action_set_pressed (action, FALSE);
|
||||||
|
click_action_set_held (action, FALSE);
|
||||||
|
|
||||||
if (actor != NULL)
|
if (actor != NULL)
|
||||||
priv->event_id = g_signal_connect (actor, "event",
|
priv->event_id = g_signal_connect (actor, "event",
|
||||||
G_CALLBACK (on_event),
|
G_CALLBACK (on_event),
|
||||||
meta);
|
action);
|
||||||
|
|
||||||
CLUTTER_ACTOR_META_CLASS (clutter_click_action_parent_class)->set_actor (meta, actor);
|
CLUTTER_ACTOR_META_CLASS (clutter_click_action_parent_class)->set_actor (meta, actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_click_action_set_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
ClutterClickActionPrivate *priv = CLUTTER_CLICK_ACTION (gobject)->priv;
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_LONG_PRESS_DURATION:
|
||||||
|
priv->long_press_duration = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_LONG_PRESS_THRESHOLD:
|
||||||
|
priv->long_press_threshold = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_click_action_get_property (GObject *gobject,
|
clutter_click_action_get_property (GObject *gobject,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
@ -272,6 +503,14 @@ clutter_click_action_get_property (GObject *gobject,
|
|||||||
g_value_set_boolean (value, priv->is_pressed);
|
g_value_set_boolean (value, priv->is_pressed);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_LONG_PRESS_DURATION:
|
||||||
|
g_value_set_int (value, priv->long_press_duration);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_LONG_PRESS_THRESHOLD:
|
||||||
|
g_value_set_int (value, priv->long_press_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;
|
||||||
@ -288,6 +527,7 @@ clutter_click_action_class_init (ClutterClickActionClass *klass)
|
|||||||
|
|
||||||
meta_class->set_actor = clutter_click_action_set_actor;
|
meta_class->set_actor = clutter_click_action_set_actor;
|
||||||
|
|
||||||
|
gobject_class->set_property = clutter_click_action_set_property;
|
||||||
gobject_class->get_property = clutter_click_action_get_property;
|
gobject_class->get_property = clutter_click_action_get_property;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -318,6 +558,44 @@ clutter_click_action_class_init (ClutterClickActionClass *klass)
|
|||||||
FALSE,
|
FALSE,
|
||||||
CLUTTER_PARAM_READABLE);
|
CLUTTER_PARAM_READABLE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterClickAction:long-press-duration:
|
||||||
|
*
|
||||||
|
* The minimum duration of a press for it to be recognized as a long
|
||||||
|
* press gesture, in milliseconds.
|
||||||
|
*
|
||||||
|
* A value of -1 will make the #ClutterClickAction use the value of
|
||||||
|
* the #ClutterSettings:long-press-duration property.
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
*/
|
||||||
|
obj_props[PROP_LONG_PRESS_DURATION] =
|
||||||
|
g_param_spec_int ("long-press-duration",
|
||||||
|
P_("Long Press Duration"),
|
||||||
|
P_("The minimum duration of a long press to recognize the gesture"),
|
||||||
|
-1, G_MAXINT,
|
||||||
|
-1,
|
||||||
|
CLUTTER_PARAM_READWRITE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterClickAction:long-press-threshold:
|
||||||
|
*
|
||||||
|
* The maximum allowed distance that can be covered (on both axes) before
|
||||||
|
* a long press gesture is cancelled, in pixels.
|
||||||
|
*
|
||||||
|
* A value of -1 will make the #ClutterClickAction use the value of
|
||||||
|
* the #ClutterSettings:dnd-drag-threshold property.
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
*/
|
||||||
|
obj_props[PROP_LONG_PRESS_THRESHOLD] =
|
||||||
|
g_param_spec_int ("long-press-threshold",
|
||||||
|
P_("Long Press Threshold"),
|
||||||
|
P_("The maximum threshold before a long press is cancelled"),
|
||||||
|
-1, G_MAXINT,
|
||||||
|
-1,
|
||||||
|
CLUTTER_PARAM_READWRITE);
|
||||||
|
|
||||||
g_object_class_install_properties (gobject_class,
|
g_object_class_install_properties (gobject_class,
|
||||||
PROP_LAST,
|
PROP_LAST,
|
||||||
obj_props);
|
obj_props);
|
||||||
@ -342,6 +620,44 @@ clutter_click_action_class_init (ClutterClickActionClass *klass)
|
|||||||
_clutter_marshal_VOID__OBJECT,
|
_clutter_marshal_VOID__OBJECT,
|
||||||
G_TYPE_NONE, 1,
|
G_TYPE_NONE, 1,
|
||||||
CLUTTER_TYPE_ACTOR);
|
CLUTTER_TYPE_ACTOR);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterClickAction::long-press:
|
||||||
|
* @action: the #ClutterClickAction that emitted the signal
|
||||||
|
* @actor: the #ClutterActor attached to the @action
|
||||||
|
* @state: the long press state
|
||||||
|
*
|
||||||
|
* The ::long-press signal is emitted during the long press gesture
|
||||||
|
* handling.
|
||||||
|
*
|
||||||
|
* This signal can be emitted multiple times with different states.
|
||||||
|
*
|
||||||
|
* The %CLUTTER_LONG_PRESS_QUERY state will be emitted on button presses,
|
||||||
|
* and its return value will determine whether the long press handling
|
||||||
|
* should be initiated. If the signal handlers will return %TRUE, the
|
||||||
|
* %CLUTTER_LONG_PRESS_QUERY state will be followed either by a signal
|
||||||
|
* emission with the %CLUTTER_LONG_PRESS_ACTIVATE state if the long press
|
||||||
|
* constraints were respected, or by a signal emission with the
|
||||||
|
* %CLUTTER_LONG_PRESS_CANCEL state if the long press was cancelled.
|
||||||
|
*
|
||||||
|
* It is possible to forcibly cancel a long press detection using
|
||||||
|
* clutter_click_action_release().
|
||||||
|
*
|
||||||
|
* Return value: Only the %CLUTTER_LONG_PRESS_QUERY state uses the
|
||||||
|
* returned value of the handler; other states will ignore it
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
*/
|
||||||
|
click_signals[LONG_PRESS] =
|
||||||
|
g_signal_new (I_("long-press"),
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (ClutterClickActionClass, long_press),
|
||||||
|
NULL, NULL,
|
||||||
|
_clutter_marshal_BOOLEAN__OBJECT_ENUM,
|
||||||
|
G_TYPE_BOOLEAN, 2,
|
||||||
|
CLUTTER_TYPE_ACTOR,
|
||||||
|
CLUTTER_TYPE_LONG_PRESS_STATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -349,6 +665,9 @@ clutter_click_action_init (ClutterClickAction *self)
|
|||||||
{
|
{
|
||||||
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, CLUTTER_TYPE_CLICK_ACTION,
|
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, CLUTTER_TYPE_CLICK_ACTION,
|
||||||
ClutterClickActionPrivate);
|
ClutterClickActionPrivate);
|
||||||
|
|
||||||
|
self->priv->long_press_threshold = -1;
|
||||||
|
self->priv->long_press_duration = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -373,6 +692,9 @@ clutter_click_action_new (void)
|
|||||||
* Emulates a release of the pointer button, which ungrabs the pointer
|
* Emulates a release of the pointer button, which ungrabs the pointer
|
||||||
* and unsets the #ClutterClickAction:pressed state.
|
* and unsets the #ClutterClickAction:pressed state.
|
||||||
*
|
*
|
||||||
|
* This function will also cancel the long press gesture if one was
|
||||||
|
* initiated.
|
||||||
|
*
|
||||||
* This function is useful to break a grab, for instance after a certain
|
* This function is useful to break a grab, for instance after a certain
|
||||||
* amount of time has passed.
|
* amount of time has passed.
|
||||||
*
|
*
|
||||||
@ -390,8 +712,6 @@ clutter_click_action_release (ClutterClickAction *action)
|
|||||||
if (!priv->is_held)
|
if (!priv->is_held)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
priv->is_held = FALSE;
|
|
||||||
|
|
||||||
/* disconnect the capture */
|
/* disconnect the capture */
|
||||||
if (priv->capture_id != 0)
|
if (priv->capture_id != 0)
|
||||||
{
|
{
|
||||||
@ -399,6 +719,8 @@ clutter_click_action_release (ClutterClickAction *action)
|
|||||||
priv->capture_id = 0;
|
priv->capture_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
click_action_cancel_long_press (action);
|
||||||
|
click_action_set_held (action, FALSE);
|
||||||
click_action_set_pressed (action, FALSE);
|
click_action_set_pressed (action, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,3 +759,27 @@ clutter_click_action_get_state (ClutterClickAction *action)
|
|||||||
|
|
||||||
return action->priv->modifier_state;
|
return action->priv->modifier_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_click_action_get_coords:
|
||||||
|
* @action: a #ClutterClickAction
|
||||||
|
* @press_x: (out): return location for the X coordinate, or %NULL
|
||||||
|
* @press_y: (out): return location for the Y coordinate, or %NULL
|
||||||
|
*
|
||||||
|
* Retrieves the screen coordinates of the button press.
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clutter_click_action_get_coords (ClutterClickAction *action,
|
||||||
|
gfloat *press_x,
|
||||||
|
gfloat *press_y)
|
||||||
|
{
|
||||||
|
g_return_if_fail (CLUTTER_IS_ACTION (action));
|
||||||
|
|
||||||
|
if (press_x != NULL)
|
||||||
|
*press_x = action->priv->press_x;
|
||||||
|
|
||||||
|
if (press_y != NULL)
|
||||||
|
*press_y = action->priv->press_y;
|
||||||
|
}
|
||||||
|
@ -48,6 +48,23 @@ typedef struct _ClutterClickAction ClutterClickAction;
|
|||||||
typedef struct _ClutterClickActionPrivate ClutterClickActionPrivate;
|
typedef struct _ClutterClickActionPrivate ClutterClickActionPrivate;
|
||||||
typedef struct _ClutterClickActionClass ClutterClickActionClass;
|
typedef struct _ClutterClickActionClass ClutterClickActionClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterLongPressState:
|
||||||
|
* @CLUTTER_LONG_PRESS_QUERY: Queries the action whether it supports
|
||||||
|
* long presses
|
||||||
|
* @CLUTTER_LONG_PRESS_ACTIVATE: Activates the action on a long press
|
||||||
|
* @CLUTTER_LONG_PRESS_CANCEL: The long press was cancelled
|
||||||
|
*
|
||||||
|
* The states for the #ClutterClikAction::long-press signal.
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
*/
|
||||||
|
typedef enum { /*< prefix=CLUTTER_LONG_PRESS >*/
|
||||||
|
CLUTTER_LONG_PRESS_QUERY,
|
||||||
|
CLUTTER_LONG_PRESS_ACTIVATE,
|
||||||
|
CLUTTER_LONG_PRESS_CANCEL
|
||||||
|
} ClutterLongPressState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ClutterClickAction:
|
* ClutterClickAction:
|
||||||
*
|
*
|
||||||
@ -67,6 +84,7 @@ struct _ClutterClickAction
|
|||||||
/**
|
/**
|
||||||
* ClutterClickActionClass:
|
* ClutterClickActionClass:
|
||||||
* @clicked: class handler for the #ClutterClickAction::clicked signal
|
* @clicked: class handler for the #ClutterClickAction::clicked signal
|
||||||
|
* @long_press: class handler for the #ClutterClickAction::long-press signal
|
||||||
*
|
*
|
||||||
* The <structname>ClutterClickActionClass</structname> structure
|
* The <structname>ClutterClickActionClass</structname> structure
|
||||||
* contains only private data
|
* contains only private data
|
||||||
@ -82,6 +100,10 @@ struct _ClutterClickActionClass
|
|||||||
void (* clicked) (ClutterClickAction *action,
|
void (* clicked) (ClutterClickAction *action,
|
||||||
ClutterActor *actor);
|
ClutterActor *actor);
|
||||||
|
|
||||||
|
gboolean (* long_press) (ClutterClickAction *action,
|
||||||
|
ClutterActor *actor,
|
||||||
|
ClutterLongPressState state);
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
void (* _clutter_click_action1) (void);
|
void (* _clutter_click_action1) (void);
|
||||||
void (* _clutter_click_action2) (void);
|
void (* _clutter_click_action2) (void);
|
||||||
@ -94,10 +116,14 @@ struct _ClutterClickActionClass
|
|||||||
|
|
||||||
GType clutter_click_action_get_type (void) G_GNUC_CONST;
|
GType clutter_click_action_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
ClutterAction *clutter_click_action_new (void);
|
ClutterAction * clutter_click_action_new (void);
|
||||||
|
|
||||||
guint clutter_click_action_get_button (ClutterClickAction *action);
|
guint clutter_click_action_get_button (ClutterClickAction *action);
|
||||||
ClutterModifierType clutter_click_action_get_state (ClutterClickAction *action);
|
ClutterModifierType clutter_click_action_get_state (ClutterClickAction *action);
|
||||||
|
void clutter_click_action_get_coords (ClutterClickAction *action,
|
||||||
|
gfloat *press_x,
|
||||||
|
gfloat *press_y);
|
||||||
|
|
||||||
void clutter_click_action_release (ClutterClickAction *action);
|
void clutter_click_action_release (ClutterClickAction *action);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
BOOLEAN:BOXED
|
BOOLEAN:BOXED
|
||||||
|
BOOLEAN:OBJECT,ENUM
|
||||||
BOOLEAN:STRING,UINT,FLAGS
|
BOOLEAN:STRING,UINT,FLAGS
|
||||||
BOXED:UINT,UINT
|
BOXED:UINT,UINT
|
||||||
DOUBLE:VOID
|
DOUBLE:VOID
|
||||||
|
Loading…
Reference in New Issue
Block a user