From 135cd40928a71299c9a38a6bad5865d0c7a08aed Mon Sep 17 00:00:00 2001 From: Bilal Elmoussaoui Date: Fri, 2 Aug 2024 14:38:35 +0200 Subject: [PATCH] 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: --- clutter/clutter/cally/cally-stage.c | 78 ----------------------------- clutter/clutter/clutter-stage.c | 42 ++++++++++++++-- 2 files changed, 37 insertions(+), 83 deletions(-) diff --git a/clutter/clutter/cally/cally-stage.c b/clutter/clutter/cally/cally-stage.c index 7e9b3df47..f61b8fbff 100644 --- a/clutter/clutter/cally/cally-stage.c +++ b/clutter/clutter/cally/cally-stage.c @@ -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); } diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c index 6d781f716..d75159f37 100644 --- a/clutter/clutter/clutter-stage.c +++ b/clutter/clutter/clutter-stage.c @@ -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]); }