From: Lukáš Tyrychtr Date: Tue, 14 Feb 2023 13:09:54 +0000 (+0100) Subject: Allow setting accessible parent and sibling explicitly X-Git-Tag: archive/raspbian/4.12.3+ds-1+rpi1~1^2^2^2~22^2~6^2~54^2~4 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=5f72b51105f3072e14e5c3065e6c8eb7cce2d33d;p=gtk4.git Allow setting accessible parent and sibling explicitly This allows to maintain the correct a11y hierarchy even when it contains objects which are only GtkAccessibles. --- diff --git a/gtk/gtkaccessible.c b/gtk/gtkaccessible.c index 7143c14006..7d1da7d398 100644 --- a/gtk/gtkaccessible.c +++ b/gtk/gtkaccessible.c @@ -45,6 +45,11 @@ * [vfunc@Gtk.Accessible.get_next_accessible_sibling] virtual functions. * Note that you can not create a top-level accessible object as of now, * which means that you must always have a parent accessible object. + * Also note that when an accessible object does not correspond to a widget, + * and it has children, whose implementation you don't control, + * it is necessary to ensure the correct shape of the a11y tree + * by calling gtk_accessible_set_accessible_parent() and + * gtk_accessible_set_next_accessible_sibling() as appropriate. */ #include "config.h" @@ -115,7 +120,43 @@ gtk_accessible_get_accessible_parent (GtkAccessible *self) { g_return_val_if_fail (GTK_IS_ACCESSIBLE (self), NULL); - return GTK_ACCESSIBLE_GET_IFACE (self)->get_accessible_parent (self); + GtkATContext *context; + GtkAccessible *parent = NULL; + + context = gtk_accessible_get_at_context (self); + if (context != NULL) + parent = gtk_at_context_get_accessible_parent (context); + + if (parent != NULL) + return parent; + else + return GTK_ACCESSIBLE_GET_IFACE (self)->get_accessible_parent (self); +} + +/** + * gtk_accessible_set_accessible_parent: + * @self: a `GtkAccessible` + * @parent: the parent `GtkAccessible` + * @next_sibling: the next accessible sibling of this `GtkAccessible` + * + * Sets the parent and next sibling accessible of an accessible object + * + * Since: 4.10 + */ +void +gtk_accessible_set_accessible_parent (GtkAccessible *self, + GtkAccessible *parent, + GtkAccessible *next_sibling) +{ + g_return_if_fail (GTK_IS_ACCESSIBLE (self)); + GtkATContext *context; + + context = gtk_accessible_get_at_context (self); + if (context != NULL) + { + gtk_at_context_set_accessible_parent (context, parent); + gtk_at_context_set_next_accessible_sibling (context, next_sibling); + } } /** @@ -151,7 +192,13 @@ gtk_accessible_get_next_accessible_sibling (GtkAccessible *self) { g_return_val_if_fail (GTK_IS_ACCESSIBLE (self), NULL); - return GTK_ACCESSIBLE_GET_IFACE (self)->get_next_accessible_sibling (self); + GtkATContext *context; + + context = gtk_accessible_get_at_context (self); + if (context != NULL && gtk_at_context_get_accessible_parent (context) != NULL) + return gtk_at_context_get_next_accessible_sibling (context); + else + return GTK_ACCESSIBLE_GET_IFACE (self)->get_next_accessible_sibling (self); } /** diff --git a/gtk/gtkaccessible.h b/gtk/gtkaccessible.h index 713a9b5ccf..b9bb5476a5 100644 --- a/gtk/gtkaccessible.h +++ b/gtk/gtkaccessible.h @@ -164,6 +164,11 @@ gboolean gtk_accessible_get_platform_state (GtkAccessible *self, GDK_AVAILABLE_IN_4_10 GtkAccessible * gtk_accessible_get_accessible_parent (GtkAccessible *self); +GDK_AVAILABLE_IN_4_10 +void gtk_accessible_set_accessible_parent (GtkAccessible *self, + GtkAccessible *parent, + GtkAccessible *next_sibling); + GDK_AVAILABLE_IN_4_10 GtkAccessible * gtk_accessible_get_first_accessible_child (GtkAccessible *self); diff --git a/gtk/gtkatcontext.c b/gtk/gtkatcontext.c index 07d330d59e..040bc43850 100644 --- a/gtk/gtkatcontext.c +++ b/gtk/gtkatcontext.c @@ -447,6 +447,80 @@ gtk_at_context_get_accessible_role (GtkATContext *self) return self->accessible_role; } +/*< private > + * gtk_at_context_get_accessible_parent: + * @self: a `GtkAtContext` + * + * Retrieves the parent accessible object of the given `GtkAtContext`. + * + * Returns: (nullable) (transfer none): the parent accessible object, or `NULL` if not set. + */ +GtkAccessible * +gtk_at_context_get_accessible_parent (GtkATContext *self) +{ + g_return_val_if_fail (GTK_IS_AT_CONTEXT (self), NULL); + + return self->accessible_parent; +} + +/*< private > + * gtk_at_context_set_accessible_parent: + * @self: a `GtkAtContext` + * @parent: the parent `GtkAccessible` to set + * + * Sets the parent accessible object of the given `GtkAtContext`. + */ +void +gtk_at_context_set_accessible_parent (GtkATContext *self, + GtkAccessible *parent) +{ + g_return_if_fail (GTK_IS_AT_CONTEXT (self)); + + if (self->accessible_parent != parent) + { + if (self->accessible_parent != NULL) + g_object_unref (self->accessible_parent); + self->accessible_parent = g_object_ref (parent); + } +} + +/*< private > + * gtk_at_context_get_next_accessible_sibling: + * @self: a `GtkAtContext` + * + * Retrieves the next accessible sibling of the given `GtkAtContext`. + * + * Returns: (nullable) (transfer none): the next accessible sibling. + */ +GtkAccessible * +gtk_at_context_get_next_accessible_sibling (GtkATContext *self) +{ + g_return_val_if_fail (GTK_IS_AT_CONTEXT (self), NULL); + + return self->next_accessible_sibling; +} + +/*< private > + * gtk_at_context_set_next_accessible_sibling: + * @self: a `GtkAtContext` + * @sibling: (nullable): the next accessible sibling + * + * Sets the next accessible sibling object of the given `GtkAtContext`. + */ +void +gtk_at_context_set_next_accessible_sibling (GtkATContext *self, + GtkAccessible *sibling) +{ + g_return_if_fail (GTK_IS_AT_CONTEXT (self)); + + if (self->next_accessible_sibling != sibling) + { + if (self->next_accessible_sibling != NULL) + g_object_unref (self->next_accessible_sibling); + self->next_accessible_sibling = g_object_ref (sibling); + } +} + /*< private > * gtk_at_context_set_display: * @self: a `GtkATContext` diff --git a/gtk/gtkatcontextprivate.h b/gtk/gtkatcontextprivate.h index c0acfc7793..e7ea717243 100644 --- a/gtk/gtkatcontextprivate.h +++ b/gtk/gtkatcontextprivate.h @@ -87,6 +87,8 @@ struct _GtkATContext GtkAccessibleRole accessible_role; GtkAccessible *accessible; + GtkAccessible *accessible_parent; + GtkAccessible *next_accessible_sibling; GdkDisplay *display; GtkAccessibleAttributeSet *states; @@ -179,4 +181,15 @@ const char * gtk_accessible_property_get_attribute_name (GtkAccessiblePr const char * gtk_accessible_relation_get_attribute_name (GtkAccessibleRelation relation); const char * gtk_accessible_state_get_attribute_name (GtkAccessibleState state); +GtkAccessible * +gtk_at_context_get_accessible_parent (GtkATContext *self); +void +gtk_at_context_set_accessible_parent (GtkATContext *self, + GtkAccessible *parent); +GtkAccessible * +gtk_at_context_get_next_accessible_sibling (GtkATContext *self); +void +gtk_at_context_set_next_accessible_sibling (GtkATContext *self, + GtkAccessible *sibling); + G_END_DECLS