clutter/stage: Emit accessibility focus state change
Allows us to get rid of CallyStage trying to track what is already tracked in ClutterStage and simplify the whole thing Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3917>
This commit is contained in:
parent
7571ae6f05
commit
135cd40928
2 changed files with 37 additions and 83 deletions
|
@ -44,16 +44,10 @@ static AtkStateSet* cally_stage_ref_state_set (AtkObject *obj);
|
|||
/* AtkWindow */
|
||||
static void cally_stage_window_interface_init (AtkWindowIface *iface);
|
||||
|
||||
typedef struct _CallyStagePrivate
|
||||
{
|
||||
/* NULL means that the stage will receive the focus */
|
||||
ClutterActor *key_focus;
|
||||
} CallyStagePrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (CallyStage,
|
||||
cally_stage,
|
||||
CALLY_TYPE_ACTOR,
|
||||
G_ADD_PRIVATE (CallyStage)
|
||||
G_IMPLEMENT_INTERFACE (ATK_TYPE_WINDOW,
|
||||
cally_stage_window_interface_init));
|
||||
|
||||
|
@ -97,86 +91,14 @@ cally_stage_new (ClutterActor *actor)
|
|||
return accessible;
|
||||
}
|
||||
|
||||
static void
|
||||
cally_stage_notify_key_focus_cb (ClutterStage *stage,
|
||||
GParamSpec *pspec,
|
||||
CallyStage *self)
|
||||
{
|
||||
ClutterActor *key_focus = NULL;
|
||||
AtkObject *new = NULL;
|
||||
CallyStagePrivate *priv = cally_stage_get_instance_private (self);
|
||||
|
||||
if (!clutter_stage_is_active (stage))
|
||||
return;
|
||||
|
||||
key_focus = clutter_stage_get_key_focus (stage);
|
||||
|
||||
if (key_focus != priv->key_focus)
|
||||
{
|
||||
AtkObject *old = NULL;
|
||||
|
||||
if (priv->key_focus != NULL)
|
||||
{
|
||||
if (priv->key_focus != CLUTTER_ACTOR (stage))
|
||||
{
|
||||
g_object_remove_weak_pointer (G_OBJECT (priv->key_focus),
|
||||
(gpointer *) &priv->key_focus);
|
||||
}
|
||||
old = clutter_actor_get_accessible (priv->key_focus);
|
||||
}
|
||||
else
|
||||
old = clutter_actor_get_accessible (CLUTTER_ACTOR (stage));
|
||||
|
||||
atk_object_notify_state_change (old,
|
||||
ATK_STATE_FOCUSED,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
/* we keep notifying the focus gain without checking previous
|
||||
* key-focus to avoid some missing events due timing
|
||||
*/
|
||||
priv->key_focus = key_focus;
|
||||
|
||||
if (key_focus != NULL)
|
||||
{
|
||||
/* ensure that if the key focus goes away, the field inside
|
||||
* CallyStage is reset. see bug:
|
||||
*
|
||||
* https://bugzilla.gnome.org/show_bug.cgi?id=692706
|
||||
*
|
||||
* we remove the weak pointer above.
|
||||
*/
|
||||
if (key_focus != CLUTTER_ACTOR (stage))
|
||||
{
|
||||
g_object_add_weak_pointer (G_OBJECT (priv->key_focus),
|
||||
(gpointer *) &priv->key_focus);
|
||||
}
|
||||
|
||||
new = clutter_actor_get_accessible (key_focus);
|
||||
}
|
||||
else
|
||||
new = clutter_actor_get_accessible (CLUTTER_ACTOR (stage));
|
||||
|
||||
atk_object_notify_state_change (new,
|
||||
ATK_STATE_FOCUSED,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
cally_stage_real_initialize (AtkObject *obj,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterStage *stage = NULL;
|
||||
|
||||
g_return_if_fail (CALLY_IS_STAGE (obj));
|
||||
|
||||
ATK_OBJECT_CLASS (cally_stage_parent_class)->initialize (obj, data);
|
||||
|
||||
stage = CLUTTER_STAGE (CALLY_GET_CLUTTER_ACTOR (obj));
|
||||
|
||||
g_signal_connect (stage, "notify::key-focus",
|
||||
G_CALLBACK (cally_stage_notify_key_focus_cb), obj);
|
||||
|
||||
atk_object_set_role (obj, ATK_ROLE_WINDOW);
|
||||
}
|
||||
|
||||
|
|
|
@ -620,12 +620,24 @@ clutter_stage_emit_key_focus_event (ClutterStage *stage,
|
|||
gboolean focus_in)
|
||||
{
|
||||
ClutterStagePrivate *priv = clutter_stage_get_instance_private (stage);
|
||||
AtkObject *old_accessible, *new_accessible = NULL;
|
||||
|
||||
if (priv->key_focused_actor == NULL)
|
||||
return;
|
||||
|
||||
old_accessible = clutter_actor_get_accessible (priv->key_focused_actor);
|
||||
new_accessible = clutter_actor_get_accessible (CLUTTER_ACTOR (stage));
|
||||
|
||||
_clutter_actor_set_has_key_focus (CLUTTER_ACTOR (stage), focus_in);
|
||||
|
||||
if (old_accessible)
|
||||
atk_object_notify_state_change (old_accessible,
|
||||
ATK_STATE_FOCUSED,
|
||||
!focus_in);
|
||||
if (new_accessible)
|
||||
atk_object_notify_state_change (new_accessible,
|
||||
ATK_STATE_FOCUSED,
|
||||
focus_in);
|
||||
g_object_notify_by_pspec (G_OBJECT (stage), obj_props[PROP_KEY_FOCUS]);
|
||||
}
|
||||
|
||||
|
@ -2064,9 +2076,10 @@ clutter_stage_get_title (ClutterStage *stage)
|
|||
*/
|
||||
void
|
||||
clutter_stage_set_key_focus (ClutterStage *stage,
|
||||
ClutterActor *actor)
|
||||
ClutterActor *actor)
|
||||
{
|
||||
ClutterStagePrivate *priv;
|
||||
AtkObject *old_accessible, *new_accessible = NULL;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||
g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor));
|
||||
|
@ -2088,6 +2101,7 @@ clutter_stage_set_key_focus (ClutterStage *stage,
|
|||
ClutterActor *old_focused_actor;
|
||||
|
||||
old_focused_actor = priv->key_focused_actor;
|
||||
old_accessible = clutter_actor_get_accessible (old_focused_actor);
|
||||
|
||||
/* set key_focused_actor to NULL before emitting the signal or someone
|
||||
* might hide the previously focused actor in the signal handler
|
||||
|
@ -2097,8 +2111,10 @@ clutter_stage_set_key_focus (ClutterStage *stage,
|
|||
_clutter_actor_set_has_key_focus (old_focused_actor, FALSE);
|
||||
}
|
||||
else
|
||||
_clutter_actor_set_has_key_focus (CLUTTER_ACTOR (stage), FALSE);
|
||||
|
||||
{
|
||||
old_accessible = clutter_actor_get_accessible (CLUTTER_ACTOR (stage));
|
||||
_clutter_actor_set_has_key_focus (CLUTTER_ACTOR (stage), FALSE);
|
||||
}
|
||||
/* Note, if someone changes key focus in focus-out signal handler we'd be
|
||||
* overriding the latter call below moving the focus where it was originally
|
||||
* intended. The order of events would be:
|
||||
|
@ -2117,11 +2133,27 @@ clutter_stage_set_key_focus (ClutterStage *stage,
|
|||
(actor && clutter_actor_contains (priv->topmost_grab->actor, actor)))
|
||||
{
|
||||
if (actor != NULL)
|
||||
_clutter_actor_set_has_key_focus (actor, TRUE);
|
||||
{
|
||||
new_accessible = clutter_actor_get_accessible (actor);
|
||||
_clutter_actor_set_has_key_focus (actor, TRUE);
|
||||
}
|
||||
else
|
||||
_clutter_actor_set_has_key_focus (CLUTTER_ACTOR (stage), TRUE);
|
||||
{
|
||||
new_accessible = clutter_actor_get_accessible (CLUTTER_ACTOR (stage));
|
||||
_clutter_actor_set_has_key_focus (CLUTTER_ACTOR (stage), TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
if (old_accessible)
|
||||
atk_object_notify_state_change (old_accessible,
|
||||
ATK_STATE_FOCUSED,
|
||||
FALSE);
|
||||
if (new_accessible)
|
||||
atk_object_notify_state_change (new_accessible,
|
||||
ATK_STATE_FOCUSED,
|
||||
TRUE);
|
||||
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (stage), obj_props[PROP_KEY_FOCUS]);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue