clutter/stage-manager: Emit accessibility events
Instead of making CallyRoot do that and have to duplicate the list of stages internally... Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3917>
This commit is contained in:
parent
135cd40928
commit
d4c73c8341
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* CallyRoot:
|
* CallyRoot:
|
||||||
*
|
*
|
||||||
* Root object for the Cally toolkit
|
* Root object for the Cally toolkit
|
||||||
*
|
*
|
||||||
* #CallyRoot is the root object of the accessibility tree-like
|
* #CallyRoot is the root object of the accessibility tree-like
|
||||||
@ -41,10 +41,6 @@
|
|||||||
#include "clutter/clutter-stage-private.h"
|
#include "clutter/clutter-stage-private.h"
|
||||||
#include "clutter/clutter-stage-manager.h"
|
#include "clutter/clutter-stage-manager.h"
|
||||||
|
|
||||||
|
|
||||||
/* GObject */
|
|
||||||
static void cally_root_finalize (GObject *object);
|
|
||||||
|
|
||||||
/* AtkObject.h */
|
/* AtkObject.h */
|
||||||
static void cally_root_initialize (AtkObject *accessible,
|
static void cally_root_initialize (AtkObject *accessible,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
@ -54,39 +50,13 @@ static AtkObject * cally_root_ref_child (AtkObject *obj,
|
|||||||
static AtkObject * cally_root_get_parent (AtkObject *obj);
|
static AtkObject * cally_root_get_parent (AtkObject *obj);
|
||||||
static const char * cally_root_get_name (AtkObject *obj);
|
static const char * cally_root_get_name (AtkObject *obj);
|
||||||
|
|
||||||
/* Private */
|
G_DEFINE_TYPE (CallyRoot, cally_root, ATK_TYPE_GOBJECT_ACCESSIBLE)
|
||||||
static void cally_util_stage_added_cb (ClutterStageManager *stage_manager,
|
|
||||||
ClutterStage *stage,
|
|
||||||
gpointer data);
|
|
||||||
static void cally_util_stage_removed_cb (ClutterStageManager *stage_manager,
|
|
||||||
ClutterStage *stage,
|
|
||||||
gpointer data);
|
|
||||||
|
|
||||||
typedef struct _CallyRootPrivate
|
|
||||||
{
|
|
||||||
/* We save the CallyStage objects. Other option could save the stage
|
|
||||||
* list, and then just get the a11y object on the ref_child, etc. But
|
|
||||||
* the ref_child is more common that the init and the stage-add,
|
|
||||||
* stage-remove, so we avoid getting the accessible object
|
|
||||||
* constantly
|
|
||||||
*/
|
|
||||||
GSList *stage_list;
|
|
||||||
|
|
||||||
/* signals id */
|
|
||||||
gulong stage_added_id;
|
|
||||||
gulong stage_removed_id;
|
|
||||||
} CallyRootPrivate;
|
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE (CallyRoot, cally_root, ATK_TYPE_GOBJECT_ACCESSIBLE)
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cally_root_class_init (CallyRootClass *klass)
|
cally_root_class_init (CallyRootClass *klass)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
||||||
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
gobject_class->finalize = cally_root_finalize;
|
|
||||||
|
|
||||||
/* AtkObject */
|
/* AtkObject */
|
||||||
class->get_n_children = cally_root_get_n_children;
|
class->get_n_children = cally_root_get_n_children;
|
||||||
class->ref_child = cally_root_ref_child;
|
class->ref_child = cally_root_ref_child;
|
||||||
@ -98,11 +68,6 @@ cally_root_class_init (CallyRootClass *klass)
|
|||||||
static void
|
static void
|
||||||
cally_root_init (CallyRoot *root)
|
cally_root_init (CallyRoot *root)
|
||||||
{
|
{
|
||||||
CallyRootPrivate *priv = cally_root_get_instance_private (root);
|
|
||||||
|
|
||||||
priv->stage_list = NULL;
|
|
||||||
priv->stage_added_id = 0;
|
|
||||||
priv->stage_removed_id = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -129,31 +94,6 @@ cally_root_new (void)
|
|||||||
return accessible;
|
return accessible;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
cally_root_finalize (GObject *object)
|
|
||||||
{
|
|
||||||
CallyRoot *root = CALLY_ROOT (object);
|
|
||||||
GObject *stage_manager = NULL;
|
|
||||||
CallyRootPrivate *priv;
|
|
||||||
|
|
||||||
g_return_if_fail (CALLY_IS_ROOT (object));
|
|
||||||
|
|
||||||
priv = cally_root_get_instance_private (root);
|
|
||||||
if (priv->stage_list)
|
|
||||||
{
|
|
||||||
g_slist_free (priv->stage_list);
|
|
||||||
priv->stage_list = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
stage_manager = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (root));
|
|
||||||
|
|
||||||
g_clear_signal_handler (&priv->stage_added_id, stage_manager);
|
|
||||||
|
|
||||||
g_clear_signal_handler (&priv->stage_removed_id, stage_manager);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (cally_root_parent_class)->finalize (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* AtkObject.h */
|
/* AtkObject.h */
|
||||||
static void
|
static void
|
||||||
cally_root_initialize (AtkObject *accessible,
|
cally_root_initialize (AtkObject *accessible,
|
||||||
@ -165,8 +105,6 @@ cally_root_initialize (AtkObject *accessible,
|
|||||||
ClutterStage *clutter_stage = NULL;
|
ClutterStage *clutter_stage = NULL;
|
||||||
AtkObject *cally_stage = NULL;
|
AtkObject *cally_stage = NULL;
|
||||||
CallyRoot *root = CALLY_ROOT (accessible);
|
CallyRoot *root = CALLY_ROOT (accessible);
|
||||||
CallyRootPrivate *priv = cally_root_get_instance_private (root);
|
|
||||||
|
|
||||||
|
|
||||||
accessible->role = ATK_ROLE_APPLICATION;
|
accessible->role = ATK_ROLE_APPLICATION;
|
||||||
accessible->accessible_parent = NULL;
|
accessible->accessible_parent = NULL;
|
||||||
@ -181,18 +119,8 @@ cally_root_initialize (AtkObject *accessible,
|
|||||||
cally_stage = clutter_actor_get_accessible (CLUTTER_ACTOR (clutter_stage));
|
cally_stage = clutter_actor_get_accessible (CLUTTER_ACTOR (clutter_stage));
|
||||||
|
|
||||||
atk_object_set_parent (cally_stage, ATK_OBJECT (root));
|
atk_object_set_parent (cally_stage, ATK_OBJECT (root));
|
||||||
|
|
||||||
priv->stage_list = g_slist_append (priv->stage_list, cally_stage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->stage_added_id =
|
|
||||||
g_signal_connect (G_OBJECT (stage_manager), "stage-added",
|
|
||||||
G_CALLBACK (cally_util_stage_added_cb), root);
|
|
||||||
|
|
||||||
priv->stage_removed_id =
|
|
||||||
g_signal_connect (G_OBJECT (stage_manager), "stage-removed",
|
|
||||||
G_CALLBACK (cally_util_stage_removed_cb), root);
|
|
||||||
|
|
||||||
ATK_OBJECT_CLASS (cally_root_parent_class)->initialize (accessible, data);
|
ATK_OBJECT_CLASS (cally_root_parent_class)->initialize (accessible, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,9 +129,12 @@ static gint
|
|||||||
cally_root_get_n_children (AtkObject *obj)
|
cally_root_get_n_children (AtkObject *obj)
|
||||||
{
|
{
|
||||||
CallyRoot *root = CALLY_ROOT (obj);
|
CallyRoot *root = CALLY_ROOT (obj);
|
||||||
CallyRootPrivate *priv = cally_root_get_instance_private (root);
|
GObject *stage_manager =
|
||||||
|
atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (root));
|
||||||
|
const GSList *stages =
|
||||||
|
clutter_stage_manager_peek_stages (CLUTTER_STAGE_MANAGER (stage_manager));
|
||||||
|
|
||||||
return g_slist_length (priv->stage_list);
|
return g_slist_length ((GSList *)stages);
|
||||||
}
|
}
|
||||||
|
|
||||||
static AtkObject*
|
static AtkObject*
|
||||||
@ -211,25 +142,26 @@ cally_root_ref_child (AtkObject *obj,
|
|||||||
gint i)
|
gint i)
|
||||||
{
|
{
|
||||||
CallyRoot *cally_root = CALLY_ROOT (obj);
|
CallyRoot *cally_root = CALLY_ROOT (obj);
|
||||||
CallyRootPrivate *priv = cally_root_get_instance_private (cally_root);
|
GObject *stage_manager =
|
||||||
GSList *stage_list = NULL;
|
atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (cally_root));
|
||||||
gint num = 0;
|
const GSList *stages =
|
||||||
AtkObject *item = NULL;
|
clutter_stage_manager_peek_stages (CLUTTER_STAGE_MANAGER (stage_manager));
|
||||||
|
gint n_stages = g_slist_length ((GSList *)stages);
|
||||||
|
ClutterStage *item = NULL;
|
||||||
|
AtkObject *accessible_item = NULL;
|
||||||
|
|
||||||
stage_list = priv->stage_list;
|
g_return_val_if_fail ((i < n_stages)&&(i >= 0), NULL);
|
||||||
num = g_slist_length (stage_list);
|
|
||||||
|
|
||||||
g_return_val_if_fail ((i < num)&&(i >= 0), NULL);
|
item = g_slist_nth_data ((GSList *)stages, i);
|
||||||
|
|
||||||
item = g_slist_nth_data (stage_list, i);
|
|
||||||
if (!item)
|
if (!item)
|
||||||
{
|
return NULL;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_object_ref (item);
|
accessible_item = clutter_actor_get_accessible (CLUTTER_ACTOR (item));
|
||||||
|
if (accessible_item)
|
||||||
|
g_object_ref (accessible_item);
|
||||||
|
|
||||||
return item;
|
/* TODO: cache the accessible object */
|
||||||
|
return accessible_item;
|
||||||
}
|
}
|
||||||
|
|
||||||
static AtkObject*
|
static AtkObject*
|
||||||
@ -243,52 +175,3 @@ cally_root_get_name (AtkObject *obj)
|
|||||||
{
|
{
|
||||||
return g_get_prgname ();
|
return g_get_prgname ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------- PRIVATE --------------------------------- */
|
|
||||||
|
|
||||||
static void
|
|
||||||
cally_util_stage_added_cb (ClutterStageManager *stage_manager,
|
|
||||||
ClutterStage *stage,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
CallyRoot *root = CALLY_ROOT (data);
|
|
||||||
AtkObject *cally_stage = NULL;
|
|
||||||
CallyRootPrivate *priv = cally_root_get_instance_private (root);
|
|
||||||
|
|
||||||
gint index = -1;
|
|
||||||
|
|
||||||
cally_stage = clutter_actor_get_accessible (CLUTTER_ACTOR (stage));
|
|
||||||
|
|
||||||
atk_object_set_parent (cally_stage, ATK_OBJECT (root));
|
|
||||||
|
|
||||||
priv->stage_list = g_slist_append (priv->stage_list, cally_stage);
|
|
||||||
|
|
||||||
index = g_slist_index (priv->stage_list, cally_stage);
|
|
||||||
g_signal_emit_by_name (root, "children_changed::add",
|
|
||||||
index, cally_stage, NULL);
|
|
||||||
g_signal_emit_by_name (cally_stage, "create", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cally_util_stage_removed_cb (ClutterStageManager *stage_manager,
|
|
||||||
ClutterStage *stage,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
CallyRoot *root = CALLY_ROOT (data);
|
|
||||||
AtkObject *cally_stage = NULL;
|
|
||||||
CallyRootPrivate *priv
|
|
||||||
= cally_root_get_instance_private (root);
|
|
||||||
gint index = -1;
|
|
||||||
|
|
||||||
cally_stage = clutter_actor_get_accessible (CLUTTER_ACTOR (stage));
|
|
||||||
|
|
||||||
index = g_slist_index (priv->stage_list, cally_stage);
|
|
||||||
|
|
||||||
priv->stage_list = g_slist_remove (priv->stage_list,
|
|
||||||
cally_stage);
|
|
||||||
|
|
||||||
index = g_slist_index (priv->stage_list, cally_stage);
|
|
||||||
g_signal_emit_by_name (root, "children_changed::remove",
|
|
||||||
index, cally_stage, NULL);
|
|
||||||
g_signal_emit_by_name (cally_stage, "destroy", 0);
|
|
||||||
}
|
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* ClutterStageManager:
|
* ClutterStageManager:
|
||||||
*
|
*
|
||||||
* Maintains the list of stages
|
* Maintains the list of stages
|
||||||
*
|
*
|
||||||
* #ClutterStageManager is a singleton object, owned by Clutter, which
|
* #ClutterStageManager is a singleton object, owned by Clutter, which
|
||||||
@ -239,6 +239,11 @@ _clutter_stage_manager_add_stage (ClutterStageManager *stage_manager,
|
|||||||
{
|
{
|
||||||
ClutterStageManagerPrivate *priv =
|
ClutterStageManagerPrivate *priv =
|
||||||
clutter_stage_manager_get_instance_private (stage_manager);
|
clutter_stage_manager_get_instance_private (stage_manager);
|
||||||
|
AtkObject *stage_accessible = clutter_actor_get_accessible (CLUTTER_ACTOR (stage));
|
||||||
|
AtkObject *stage_manager_accessible =
|
||||||
|
atk_gobject_accessible_for_object (G_OBJECT (stage_manager));
|
||||||
|
int index = -1;
|
||||||
|
|
||||||
if (g_slist_find (priv->stages, stage))
|
if (g_slist_find (priv->stages, stage))
|
||||||
{
|
{
|
||||||
g_warning ("Trying to add a stage to the list of managed stages, "
|
g_warning ("Trying to add a stage to the list of managed stages, "
|
||||||
@ -249,6 +254,15 @@ _clutter_stage_manager_add_stage (ClutterStageManager *stage_manager,
|
|||||||
g_object_ref_sink (stage);
|
g_object_ref_sink (stage);
|
||||||
|
|
||||||
priv->stages = g_slist_append (priv->stages, stage);
|
priv->stages = g_slist_append (priv->stages, stage);
|
||||||
|
index = g_slist_index (priv->stages, stage);
|
||||||
|
|
||||||
|
if (stage_accessible && stage_manager_accessible)
|
||||||
|
{
|
||||||
|
atk_object_set_parent (stage_accessible, stage_manager_accessible);
|
||||||
|
g_signal_emit_by_name (stage_manager_accessible, "children_changed::add",
|
||||||
|
index, stage_accessible, NULL);
|
||||||
|
g_signal_emit_by_name (stage_manager_accessible, "create", 0);
|
||||||
|
}
|
||||||
|
|
||||||
g_signal_emit (stage_manager, manager_signals[STAGE_ADDED], 0, stage);
|
g_signal_emit (stage_manager, manager_signals[STAGE_ADDED], 0, stage);
|
||||||
}
|
}
|
||||||
@ -259,12 +273,17 @@ _clutter_stage_manager_remove_stage (ClutterStageManager *stage_manager,
|
|||||||
{
|
{
|
||||||
ClutterStageManagerPrivate *priv =
|
ClutterStageManagerPrivate *priv =
|
||||||
clutter_stage_manager_get_instance_private (stage_manager);
|
clutter_stage_manager_get_instance_private (stage_manager);
|
||||||
|
AtkObject *stage_accessible = clutter_actor_get_accessible (CLUTTER_ACTOR (stage));
|
||||||
|
AtkObject *stage_manager_accessible =
|
||||||
|
atk_gobject_accessible_for_object (G_OBJECT (stage_manager));
|
||||||
|
int index = -1;
|
||||||
/* this might be called multiple times from a ::dispose, so it
|
/* this might be called multiple times from a ::dispose, so it
|
||||||
* needs to just return without warning
|
* needs to just return without warning
|
||||||
*/
|
*/
|
||||||
if (!g_slist_find (priv->stages, stage))
|
if (!g_slist_find (priv->stages, stage))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
index = g_slist_index (priv->stages, stage);
|
||||||
priv->stages = g_slist_remove (priv->stages, stage);
|
priv->stages = g_slist_remove (priv->stages, stage);
|
||||||
|
|
||||||
/* if the default stage is being destroyed then we unset the pointer */
|
/* if the default stage is being destroyed then we unset the pointer */
|
||||||
@ -273,5 +292,13 @@ _clutter_stage_manager_remove_stage (ClutterStageManager *stage_manager,
|
|||||||
|
|
||||||
g_signal_emit (stage_manager, manager_signals[STAGE_REMOVED], 0, stage);
|
g_signal_emit (stage_manager, manager_signals[STAGE_REMOVED], 0, stage);
|
||||||
|
|
||||||
|
if (stage_manager_accessible && stage_accessible)
|
||||||
|
{
|
||||||
|
atk_object_set_parent (stage_accessible, NULL);
|
||||||
|
g_signal_emit_by_name (stage_manager_accessible, "children_changed::remove",
|
||||||
|
index, stage_accessible, NULL);
|
||||||
|
g_signal_emit_by_name (stage_accessible, "destroy", 0);
|
||||||
|
}
|
||||||
|
|
||||||
g_object_unref (stage);
|
g_object_unref (stage);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user