st-button: Handle touch events
On touch events, StButton becomes locked to a single sequence, so no multiple touches can trigger it simultaneously. https://bugzilla.gnome.org/show_bug.cgi?id=733633
This commit is contained in:
parent
ce5cd3bf30
commit
a2f263dcbb
@ -71,6 +71,9 @@ struct _StButtonPrivate
|
|||||||
{
|
{
|
||||||
gchar *text;
|
gchar *text;
|
||||||
|
|
||||||
|
ClutterInputDevice *device;
|
||||||
|
ClutterEventSequence *press_sequence;
|
||||||
|
|
||||||
guint button_mask : 3;
|
guint button_mask : 3;
|
||||||
guint is_toggle : 1;
|
guint is_toggle : 1;
|
||||||
|
|
||||||
@ -128,26 +131,41 @@ st_button_style_changed (StWidget *widget)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
st_button_press (StButton *button,
|
st_button_press (StButton *button,
|
||||||
StButtonMask mask)
|
ClutterInputDevice *device,
|
||||||
|
StButtonMask mask,
|
||||||
|
ClutterEventSequence *sequence)
|
||||||
{
|
{
|
||||||
if (button->priv->pressed == 0)
|
if (button->priv->pressed == 0 || sequence)
|
||||||
st_widget_add_style_pseudo_class (ST_WIDGET (button), "active");
|
st_widget_add_style_pseudo_class (ST_WIDGET (button), "active");
|
||||||
|
|
||||||
button->priv->pressed |= mask;
|
button->priv->pressed |= mask;
|
||||||
|
button->priv->press_sequence = sequence;
|
||||||
|
button->priv->device = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
st_button_release (StButton *button,
|
st_button_release (StButton *button,
|
||||||
|
ClutterInputDevice *device,
|
||||||
StButtonMask mask,
|
StButtonMask mask,
|
||||||
int clicked_button)
|
int clicked_button,
|
||||||
|
ClutterEventSequence *sequence)
|
||||||
{
|
{
|
||||||
|
if ((device && button->priv->device != device) ||
|
||||||
|
(sequence && button->priv->press_sequence != sequence))
|
||||||
|
return;
|
||||||
|
else if (!sequence)
|
||||||
|
{
|
||||||
button->priv->pressed &= ~mask;
|
button->priv->pressed &= ~mask;
|
||||||
|
|
||||||
if (button->priv->pressed != 0)
|
if (button->priv->pressed != 0)
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
button->priv->press_sequence = NULL;
|
||||||
|
button->priv->device = NULL;
|
||||||
st_widget_remove_style_pseudo_class (ST_WIDGET (button), "active");
|
st_widget_remove_style_pseudo_class (ST_WIDGET (button), "active");
|
||||||
|
|
||||||
if (clicked_button)
|
if (clicked_button || sequence)
|
||||||
{
|
{
|
||||||
if (button->priv->is_toggle)
|
if (button->priv->is_toggle)
|
||||||
st_button_set_checked (button, !button->priv->is_checked);
|
st_button_set_checked (button, !button->priv->is_checked);
|
||||||
@ -162,6 +180,10 @@ st_button_button_press (ClutterActor *actor,
|
|||||||
{
|
{
|
||||||
StButton *button = ST_BUTTON (actor);
|
StButton *button = ST_BUTTON (actor);
|
||||||
StButtonMask mask = ST_BUTTON_MASK_FROM_BUTTON (event->button);
|
StButtonMask mask = ST_BUTTON_MASK_FROM_BUTTON (event->button);
|
||||||
|
ClutterInputDevice *device = clutter_event_get_device ((ClutterEvent*) event);
|
||||||
|
|
||||||
|
if (button->priv->press_sequence)
|
||||||
|
return CLUTTER_EVENT_PROPAGATE;
|
||||||
|
|
||||||
if (button->priv->button_mask & mask)
|
if (button->priv->button_mask & mask)
|
||||||
{
|
{
|
||||||
@ -169,7 +191,7 @@ st_button_button_press (ClutterActor *actor,
|
|||||||
clutter_grab_pointer (actor);
|
clutter_grab_pointer (actor);
|
||||||
|
|
||||||
button->priv->grabbed |= mask;
|
button->priv->grabbed |= mask;
|
||||||
st_button_press (button, mask);
|
st_button_press (button, device, mask, NULL);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -183,13 +205,14 @@ st_button_button_release (ClutterActor *actor,
|
|||||||
{
|
{
|
||||||
StButton *button = ST_BUTTON (actor);
|
StButton *button = ST_BUTTON (actor);
|
||||||
StButtonMask mask = ST_BUTTON_MASK_FROM_BUTTON (event->button);
|
StButtonMask mask = ST_BUTTON_MASK_FROM_BUTTON (event->button);
|
||||||
|
ClutterInputDevice *device = clutter_event_get_device ((ClutterEvent*) event);
|
||||||
|
|
||||||
if (button->priv->button_mask & mask)
|
if (button->priv->button_mask & mask)
|
||||||
{
|
{
|
||||||
gboolean is_click;
|
gboolean is_click;
|
||||||
|
|
||||||
is_click = button->priv->grabbed && st_widget_get_hover (ST_WIDGET (button));
|
is_click = button->priv->grabbed && st_widget_get_hover (ST_WIDGET (button));
|
||||||
st_button_release (button, mask, is_click ? event->button : 0);
|
st_button_release (button, device, mask, is_click ? event->button : 0, NULL);
|
||||||
|
|
||||||
button->priv->grabbed &= ~mask;
|
button->priv->grabbed &= ~mask;
|
||||||
if (button->priv->grabbed == 0)
|
if (button->priv->grabbed == 0)
|
||||||
@ -201,6 +224,39 @@ st_button_button_release (ClutterActor *actor,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
st_button_touch_event (ClutterActor *actor,
|
||||||
|
ClutterTouchEvent *event)
|
||||||
|
{
|
||||||
|
StButton *button = ST_BUTTON (actor);
|
||||||
|
StButtonMask mask = ST_BUTTON_MASK_FROM_BUTTON (1);
|
||||||
|
ClutterEventSequence *sequence;
|
||||||
|
ClutterInputDevice *device;
|
||||||
|
|
||||||
|
if (button->priv->pressed != 0)
|
||||||
|
return CLUTTER_EVENT_PROPAGATE;
|
||||||
|
|
||||||
|
device = clutter_event_get_device ((ClutterEvent*) event);
|
||||||
|
sequence = clutter_event_get_event_sequence ((ClutterEvent*) event);
|
||||||
|
|
||||||
|
if (event->type == CLUTTER_TOUCH_BEGIN && !button->priv->press_sequence)
|
||||||
|
{
|
||||||
|
clutter_input_device_sequence_grab (device, sequence, actor);
|
||||||
|
st_button_press (button, device, 0, sequence);
|
||||||
|
return CLUTTER_EVENT_STOP;
|
||||||
|
}
|
||||||
|
else if (event->type == CLUTTER_TOUCH_END &&
|
||||||
|
button->priv->device == device &&
|
||||||
|
button->priv->press_sequence == sequence)
|
||||||
|
{
|
||||||
|
st_button_release (button, device, mask, 0, sequence);
|
||||||
|
clutter_input_device_sequence_ungrab (device, sequence);
|
||||||
|
return CLUTTER_EVENT_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CLUTTER_EVENT_PROPAGATE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
st_button_key_press (ClutterActor *actor,
|
st_button_key_press (ClutterActor *actor,
|
||||||
ClutterKeyEvent *event)
|
ClutterKeyEvent *event)
|
||||||
@ -213,7 +269,7 @@ st_button_key_press (ClutterActor *actor,
|
|||||||
event->keyval == CLUTTER_KEY_Return ||
|
event->keyval == CLUTTER_KEY_Return ||
|
||||||
event->keyval == CLUTTER_KEY_KP_Enter)
|
event->keyval == CLUTTER_KEY_KP_Enter)
|
||||||
{
|
{
|
||||||
st_button_press (button, ST_BUTTON_ONE);
|
st_button_press (button, NULL, ST_BUTTON_ONE, NULL);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -236,7 +292,7 @@ st_button_key_release (ClutterActor *actor,
|
|||||||
gboolean is_click;
|
gboolean is_click;
|
||||||
|
|
||||||
is_click = (button->priv->pressed & ST_BUTTON_ONE);
|
is_click = (button->priv->pressed & ST_BUTTON_ONE);
|
||||||
st_button_release (button, ST_BUTTON_ONE, is_click ? 1 : 0);
|
st_button_release (button, NULL, ST_BUTTON_ONE, is_click ? 1 : 0, NULL);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -252,7 +308,7 @@ st_button_key_focus_out (ClutterActor *actor)
|
|||||||
/* If we lose focus between a key press and release, undo the press */
|
/* If we lose focus between a key press and release, undo the press */
|
||||||
if ((button->priv->pressed & ST_BUTTON_ONE) &&
|
if ((button->priv->pressed & ST_BUTTON_ONE) &&
|
||||||
!(button->priv->grabbed & ST_BUTTON_ONE))
|
!(button->priv->grabbed & ST_BUTTON_ONE))
|
||||||
st_button_release (button, ST_BUTTON_ONE, 0);
|
st_button_release (button, NULL, ST_BUTTON_ONE, 0, NULL);
|
||||||
|
|
||||||
CLUTTER_ACTOR_CLASS (st_button_parent_class)->key_focus_out (actor);
|
CLUTTER_ACTOR_CLASS (st_button_parent_class)->key_focus_out (actor);
|
||||||
}
|
}
|
||||||
@ -269,9 +325,11 @@ st_button_enter (ClutterActor *actor,
|
|||||||
if (button->priv->grabbed)
|
if (button->priv->grabbed)
|
||||||
{
|
{
|
||||||
if (st_widget_get_hover (ST_WIDGET (button)))
|
if (st_widget_get_hover (ST_WIDGET (button)))
|
||||||
st_button_press (button, button->priv->grabbed);
|
st_button_press (button, button->priv->device,
|
||||||
|
button->priv->grabbed, NULL);
|
||||||
else
|
else
|
||||||
st_button_release (button, button->priv->grabbed, 0);
|
st_button_release (button, button->priv->device,
|
||||||
|
button->priv->grabbed, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -289,9 +347,11 @@ st_button_leave (ClutterActor *actor,
|
|||||||
if (button->priv->grabbed)
|
if (button->priv->grabbed)
|
||||||
{
|
{
|
||||||
if (st_widget_get_hover (ST_WIDGET (button)))
|
if (st_widget_get_hover (ST_WIDGET (button)))
|
||||||
st_button_press (button, button->priv->grabbed);
|
st_button_press (button, button->priv->device,
|
||||||
|
button->priv->grabbed, NULL);
|
||||||
else
|
else
|
||||||
st_button_release (button, button->priv->grabbed, 0);
|
st_button_release (button, button->priv->device,
|
||||||
|
button->priv->grabbed, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -391,6 +451,7 @@ st_button_class_init (StButtonClass *klass)
|
|||||||
actor_class->key_focus_out = st_button_key_focus_out;
|
actor_class->key_focus_out = st_button_key_focus_out;
|
||||||
actor_class->enter_event = st_button_enter;
|
actor_class->enter_event = st_button_enter;
|
||||||
actor_class->leave_event = st_button_leave;
|
actor_class->leave_event = st_button_leave;
|
||||||
|
actor_class->touch_event = st_button_touch_event;
|
||||||
|
|
||||||
widget_class->style_changed = st_button_style_changed;
|
widget_class->style_changed = st_button_style_changed;
|
||||||
widget_class->get_accessible_type = st_button_accessible_get_type;
|
widget_class->get_accessible_type = st_button_accessible_get_type;
|
||||||
@ -679,13 +740,24 @@ void
|
|||||||
st_button_fake_release (StButton *button)
|
st_button_fake_release (StButton *button)
|
||||||
{
|
{
|
||||||
if (button->priv->pressed)
|
if (button->priv->pressed)
|
||||||
st_button_release (button, button->priv->pressed, 0);
|
st_button_release (button, button->priv->device,
|
||||||
|
button->priv->pressed, 0, NULL);
|
||||||
|
|
||||||
if (button->priv->grabbed)
|
if (button->priv->grabbed)
|
||||||
{
|
{
|
||||||
button->priv->grabbed = 0;
|
button->priv->grabbed = 0;
|
||||||
clutter_ungrab_pointer ();
|
clutter_ungrab_pointer ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (button->priv->device &&
|
||||||
|
button->priv->press_sequence)
|
||||||
|
{
|
||||||
|
clutter_input_device_sequence_ungrab (button->priv->device,
|
||||||
|
button->priv->press_sequence);
|
||||||
|
button->priv->press_sequence = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
button->priv->device = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
Loading…
Reference in New Issue
Block a user