1
0
Fork 0

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:
Bilal Elmoussaoui 2024-08-02 14:38:35 +02:00 committed by Marge Bot
parent 7571ae6f05
commit 135cd40928
2 changed files with 37 additions and 83 deletions

View file

@ -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);
}

View file

@ -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]);
}