StButton: fix hover and grab tracking
Use StWidget:track-hover rather than doing it ourselves. Don't assume that hover is always TRUE after an enter_event or FALSE after a leave_event, since we have a pointer grab and will be getting other actors' events. Don't ungrab the pointer when it leaves the button, since that destroys the whole point of getting a grab in the first place. Only consider the button to have been clicked when it has both grab (meaning the mouse was pressed over the button) and hover (meaning the mouse was released over the button). Also remove the virtual pressed/released methods, which weren't being used anyway. https://bugzilla.gnome.org/show_bug.cgi?id=633853
This commit is contained in:
parent
4c6dd64e87
commit
4f1f226828
@ -72,9 +72,9 @@ struct _StButtonPrivate
|
|||||||
gchar *text;
|
gchar *text;
|
||||||
|
|
||||||
guint is_pressed : 1;
|
guint is_pressed : 1;
|
||||||
guint is_hover : 1;
|
|
||||||
guint is_checked : 1;
|
guint is_checked : 1;
|
||||||
guint is_toggle : 1;
|
guint is_toggle : 1;
|
||||||
|
guint has_grab : 1;
|
||||||
|
|
||||||
gint spacing;
|
gint spacing;
|
||||||
};
|
};
|
||||||
@ -123,15 +123,32 @@ st_button_style_changed (StWidget *widget)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
st_button_real_pressed (StButton *button)
|
st_button_press (StButton *button)
|
||||||
{
|
{
|
||||||
|
if (button->priv->is_pressed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
button->priv->is_pressed = TRUE;
|
||||||
st_widget_add_style_pseudo_class (ST_WIDGET (button), "active");
|
st_widget_add_style_pseudo_class (ST_WIDGET (button), "active");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
st_button_real_released (StButton *button)
|
st_button_release (StButton *button,
|
||||||
|
gboolean clicked)
|
||||||
{
|
{
|
||||||
|
if (!button->priv->is_pressed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
button->priv->is_pressed = FALSE;
|
||||||
st_widget_remove_style_pseudo_class (ST_WIDGET (button), "active");
|
st_widget_remove_style_pseudo_class (ST_WIDGET (button), "active");
|
||||||
|
|
||||||
|
if (clicked)
|
||||||
|
{
|
||||||
|
if (button->priv->is_toggle)
|
||||||
|
st_button_set_checked (button, !button->priv->is_checked);
|
||||||
|
|
||||||
|
g_signal_emit (button, button_signals[CLICKED], 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -143,14 +160,10 @@ st_button_button_press (ClutterActor *actor,
|
|||||||
if (event->button == 1)
|
if (event->button == 1)
|
||||||
{
|
{
|
||||||
StButton *button = ST_BUTTON (actor);
|
StButton *button = ST_BUTTON (actor);
|
||||||
StButtonClass *klass = ST_BUTTON_GET_CLASS (button);
|
|
||||||
|
|
||||||
button->priv->is_pressed = TRUE;
|
|
||||||
|
|
||||||
clutter_grab_pointer (actor);
|
clutter_grab_pointer (actor);
|
||||||
|
button->priv->has_grab = TRUE;
|
||||||
if (klass->pressed)
|
st_button_press (button);
|
||||||
klass->pressed (button);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -165,25 +178,17 @@ st_button_button_release (ClutterActor *actor,
|
|||||||
if (event->button == 1)
|
if (event->button == 1)
|
||||||
{
|
{
|
||||||
StButton *button = ST_BUTTON (actor);
|
StButton *button = ST_BUTTON (actor);
|
||||||
StButtonClass *klass = ST_BUTTON_GET_CLASS (button);
|
gboolean is_click;
|
||||||
|
|
||||||
if (!button->priv->is_pressed)
|
is_click = button->priv->has_grab && st_widget_get_hover (ST_WIDGET (button));
|
||||||
return FALSE;
|
st_button_release (button, is_click);
|
||||||
|
|
||||||
clutter_ungrab_pointer ();
|
if (button->priv->has_grab)
|
||||||
|
|
||||||
if (button->priv->is_toggle)
|
|
||||||
{
|
{
|
||||||
st_button_set_checked (button, !button->priv->is_checked);
|
button->priv->has_grab = FALSE;
|
||||||
|
clutter_ungrab_pointer ();
|
||||||
}
|
}
|
||||||
|
|
||||||
button->priv->is_pressed = FALSE;
|
|
||||||
|
|
||||||
if (klass->released)
|
|
||||||
klass->released (button);
|
|
||||||
|
|
||||||
g_signal_emit (button, button_signals[CLICKED], 0);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,12 +200,19 @@ st_button_enter (ClutterActor *actor,
|
|||||||
ClutterCrossingEvent *event)
|
ClutterCrossingEvent *event)
|
||||||
{
|
{
|
||||||
StButton *button = ST_BUTTON (actor);
|
StButton *button = ST_BUTTON (actor);
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
st_widget_add_style_pseudo_class (ST_WIDGET (button), "hover");
|
ret = CLUTTER_ACTOR_CLASS (st_button_parent_class)->enter_event (actor, event);
|
||||||
|
|
||||||
button->priv->is_hover = TRUE;
|
if (button->priv->has_grab)
|
||||||
|
{
|
||||||
|
if (st_widget_get_hover (ST_WIDGET (button)))
|
||||||
|
st_button_press (button);
|
||||||
|
else
|
||||||
|
st_button_release (button, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
return CLUTTER_ACTOR_CLASS (st_button_parent_class)->enter_event (actor, event);
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -208,24 +220,19 @@ st_button_leave (ClutterActor *actor,
|
|||||||
ClutterCrossingEvent *event)
|
ClutterCrossingEvent *event)
|
||||||
{
|
{
|
||||||
StButton *button = ST_BUTTON (actor);
|
StButton *button = ST_BUTTON (actor);
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
button->priv->is_hover = FALSE;
|
ret = CLUTTER_ACTOR_CLASS (st_button_parent_class)->leave_event (actor, event);
|
||||||
|
|
||||||
if (button->priv->is_pressed)
|
if (button->priv->has_grab)
|
||||||
{
|
{
|
||||||
StButtonClass *klass = ST_BUTTON_GET_CLASS (button);
|
if (st_widget_get_hover (ST_WIDGET (button)))
|
||||||
|
st_button_press (button);
|
||||||
clutter_ungrab_pointer ();
|
else
|
||||||
|
st_button_release (button, FALSE);
|
||||||
button->priv->is_pressed = FALSE;
|
|
||||||
|
|
||||||
if (klass->released)
|
|
||||||
klass->released (button);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
st_widget_remove_style_pseudo_class (ST_WIDGET (button), "hover");
|
return ret;
|
||||||
|
|
||||||
return CLUTTER_ACTOR_CLASS (st_button_parent_class)->leave_event (actor, event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -302,9 +309,6 @@ st_button_class_init (StButtonClass *klass)
|
|||||||
|
|
||||||
g_type_class_add_private (klass, sizeof (StButtonPrivate));
|
g_type_class_add_private (klass, sizeof (StButtonPrivate));
|
||||||
|
|
||||||
klass->pressed = st_button_real_pressed;
|
|
||||||
klass->released = st_button_real_released;
|
|
||||||
|
|
||||||
gobject_class->set_property = st_button_set_property;
|
gobject_class->set_property = st_button_set_property;
|
||||||
gobject_class->get_property = st_button_get_property;
|
gobject_class->get_property = st_button_get_property;
|
||||||
gobject_class->finalize = st_button_finalize;
|
gobject_class->finalize = st_button_finalize;
|
||||||
@ -361,6 +365,7 @@ st_button_init (StButton *button)
|
|||||||
button->priv->spacing = 6;
|
button->priv->spacing = 6;
|
||||||
|
|
||||||
clutter_actor_set_reactive (CLUTTER_ACTOR (button), TRUE);
|
clutter_actor_set_reactive (CLUTTER_ACTOR (button), TRUE);
|
||||||
|
st_widget_set_track_hover (ST_WIDGET (button), TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,8 +66,6 @@ struct _StButtonClass
|
|||||||
StBinClass parent_class;
|
StBinClass parent_class;
|
||||||
|
|
||||||
/* vfuncs, not signals */
|
/* vfuncs, not signals */
|
||||||
void (* pressed) (StButton *button);
|
|
||||||
void (* released) (StButton *button);
|
|
||||||
void (* transition) (StButton *button);
|
void (* transition) (StButton *button);
|
||||||
|
|
||||||
/* signals */
|
/* signals */
|
||||||
|
Loading…
Reference in New Issue
Block a user