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
@ -44,16 +44,10 @@ static AtkStateSet* cally_stage_ref_state_set (AtkObject *obj);
|
|||||||
/* AtkWindow */
|
/* AtkWindow */
|
||||||
static void cally_stage_window_interface_init (AtkWindowIface *iface);
|
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,
|
G_DEFINE_TYPE_WITH_CODE (CallyStage,
|
||||||
cally_stage,
|
cally_stage,
|
||||||
CALLY_TYPE_ACTOR,
|
CALLY_TYPE_ACTOR,
|
||||||
G_ADD_PRIVATE (CallyStage)
|
|
||||||
G_IMPLEMENT_INTERFACE (ATK_TYPE_WINDOW,
|
G_IMPLEMENT_INTERFACE (ATK_TYPE_WINDOW,
|
||||||
cally_stage_window_interface_init));
|
cally_stage_window_interface_init));
|
||||||
|
|
||||||
@ -97,86 +91,14 @@ cally_stage_new (ClutterActor *actor)
|
|||||||
return accessible;
|
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
|
static void
|
||||||
cally_stage_real_initialize (AtkObject *obj,
|
cally_stage_real_initialize (AtkObject *obj,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
ClutterStage *stage = NULL;
|
|
||||||
|
|
||||||
g_return_if_fail (CALLY_IS_STAGE (obj));
|
g_return_if_fail (CALLY_IS_STAGE (obj));
|
||||||
|
|
||||||
ATK_OBJECT_CLASS (cally_stage_parent_class)->initialize (obj, data);
|
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);
|
atk_object_set_role (obj, ATK_ROLE_WINDOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -620,12 +620,24 @@ clutter_stage_emit_key_focus_event (ClutterStage *stage,
|
|||||||
gboolean focus_in)
|
gboolean focus_in)
|
||||||
{
|
{
|
||||||
ClutterStagePrivate *priv = clutter_stage_get_instance_private (stage);
|
ClutterStagePrivate *priv = clutter_stage_get_instance_private (stage);
|
||||||
|
AtkObject *old_accessible, *new_accessible = NULL;
|
||||||
|
|
||||||
if (priv->key_focused_actor == NULL)
|
if (priv->key_focused_actor == NULL)
|
||||||
return;
|
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);
|
_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]);
|
g_object_notify_by_pspec (G_OBJECT (stage), obj_props[PROP_KEY_FOCUS]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2067,6 +2079,7 @@ clutter_stage_set_key_focus (ClutterStage *stage,
|
|||||||
ClutterActor *actor)
|
ClutterActor *actor)
|
||||||
{
|
{
|
||||||
ClutterStagePrivate *priv;
|
ClutterStagePrivate *priv;
|
||||||
|
AtkObject *old_accessible, *new_accessible = NULL;
|
||||||
|
|
||||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||||
g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor));
|
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;
|
ClutterActor *old_focused_actor;
|
||||||
|
|
||||||
old_focused_actor = priv->key_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
|
/* set key_focused_actor to NULL before emitting the signal or someone
|
||||||
* might hide the previously focused actor in the signal handler
|
* 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);
|
_clutter_actor_set_has_key_focus (old_focused_actor, FALSE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
old_accessible = clutter_actor_get_accessible (CLUTTER_ACTOR (stage));
|
||||||
_clutter_actor_set_has_key_focus (CLUTTER_ACTOR (stage), FALSE);
|
_clutter_actor_set_has_key_focus (CLUTTER_ACTOR (stage), FALSE);
|
||||||
|
}
|
||||||
/* Note, if someone changes key focus in focus-out signal handler we'd be
|
/* 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
|
* overriding the latter call below moving the focus where it was originally
|
||||||
* intended. The order of events would be:
|
* intended. The order of events would be:
|
||||||
@ -2117,10 +2133,26 @@ clutter_stage_set_key_focus (ClutterStage *stage,
|
|||||||
(actor && clutter_actor_contains (priv->topmost_grab->actor, actor)))
|
(actor && clutter_actor_contains (priv->topmost_grab->actor, actor)))
|
||||||
{
|
{
|
||||||
if (actor != NULL)
|
if (actor != NULL)
|
||||||
|
{
|
||||||
|
new_accessible = clutter_actor_get_accessible (actor);
|
||||||
_clutter_actor_set_has_key_focus (actor, TRUE);
|
_clutter_actor_set_has_key_focus (actor, TRUE);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
new_accessible = clutter_actor_get_accessible (CLUTTER_ACTOR (stage));
|
||||||
_clutter_actor_set_has_key_focus (CLUTTER_ACTOR (stage), TRUE);
|
_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]);
|
g_object_notify_by_pspec (G_OBJECT (stage), obj_props[PROP_KEY_FOCUS]);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user