diff --git a/gtk/gtkatcontext.c b/gtk/gtkatcontext.c index 922ca94668..2d6908cd7a 100644 --- a/gtk/gtkatcontext.c +++ b/gtk/gtkatcontext.c @@ -40,6 +40,13 @@ #include "gtktestatcontextprivate.h" #include "gtktypebuiltins.h" +#include "gtkbutton.h" +#include "gtktogglebutton.h" +#include "gtkmenubutton.h" +#include "gtkdropdown.h" +#include "gtkcolordialogbutton.h" +#include "gtkfontdialogbutton.h" + #if defined(GDK_WINDOWING_X11) || defined(GDK_WINDOWING_WAYLAND) #include "a11y/gtkatspicontextprivate.h" #endif @@ -1176,6 +1183,47 @@ static GtkAccessibleRole name_forbidden[] = { GTK_ACCESSIBLE_ROLE_NONE, }; +static gboolean +is_nested_button (GtkATContext *self) +{ + GtkAccessible *accessible; + GtkWidget *widget, *parent; + + accessible = gtk_at_context_get_accessible (self); + + if (!GTK_IS_WIDGET (accessible)) + return FALSE; + + widget = GTK_WIDGET (accessible); + parent = gtk_widget_get_parent (widget); + + if ((GTK_IS_TOGGLE_BUTTON (widget) && GTK_IS_DROP_DOWN (parent)) || + (GTK_IS_TOGGLE_BUTTON (widget) && GTK_IS_MENU_BUTTON (parent)) || + (GTK_IS_BUTTON (widget) && GTK_IS_COLOR_DIALOG_BUTTON (parent)) || + (GTK_IS_BUTTON (widget) && GTK_IS_FONT_DIALOG_BUTTON (parent))) + return TRUE; + + return FALSE; +} + +static GtkATContext * +get_parent_context (GtkATContext *self) +{ + GtkAccessible *accessible, *parent; + + accessible = gtk_at_context_get_accessible (self); + parent = gtk_accessible_get_accessible_parent (accessible); + if (parent) + { + GtkATContext *context = gtk_accessible_get_at_context (parent); + g_object_unref (parent); + return context; + } + + return g_object_ref (self); +} + + /*< private > * gtk_at_context_get_name: * @self: a `GtkATContext` @@ -1189,6 +1237,8 @@ static GtkAccessibleRole name_forbidden[] = { char * gtk_at_context_get_name (GtkATContext *self) { + GtkATContext *parent = NULL; + g_return_val_if_fail (GTK_IS_AT_CONTEXT (self), NULL); for (unsigned int i = 0; i < G_N_ELEMENTS (name_forbidden); i++) @@ -1197,6 +1247,18 @@ gtk_at_context_get_name (GtkATContext *self) return g_strdup (""); } + /* We special case this here since it is a common pattern: + * We have a 'wrapper' object, like a GtkDropdown which + * contains a toggle button. The dropdown appears in the + * ui file and carries all the a11y attributes, but the + * focus ends up on the toggle button. + */ + if (is_nested_button (self)) + { + parent = get_parent_context (self); + self = parent; + } + GPtrArray *names = g_ptr_array_new (); gtk_at_context_get_name_accumulate (self, names, TRUE); @@ -1204,6 +1266,7 @@ gtk_at_context_get_name (GtkATContext *self) if (names->len == 0) { g_ptr_array_unref (names); + g_clear_object (&parent); return g_strdup (""); } @@ -1218,6 +1281,8 @@ gtk_at_context_get_name (GtkATContext *self) g_ptr_array_unref (names); + g_clear_object (&parent); + return g_string_free (res, FALSE); } @@ -1234,6 +1299,8 @@ gtk_at_context_get_name (GtkATContext *self) char * gtk_at_context_get_description (GtkATContext *self) { + GtkATContext *parent = NULL; + g_return_val_if_fail (GTK_IS_AT_CONTEXT (self), NULL); for (unsigned int i = 0; i < G_N_ELEMENTS (name_forbidden); i++) @@ -1242,6 +1309,18 @@ gtk_at_context_get_description (GtkATContext *self) return g_strdup (""); } + /* We special case this here since it is a common pattern: + * We have a 'wrapper' object, like a GtkDropdown which + * contains a toggle button. The dropdown appears in the + * ui file and carries all the a11y attributes, but the + * focus ends up on the toggle button. + */ + if (is_nested_button (self)) + { + parent = get_parent_context (self); + self = parent; + } + GPtrArray *names = g_ptr_array_new (); gtk_at_context_get_description_accumulate (self, names, TRUE); @@ -1249,6 +1328,7 @@ gtk_at_context_get_description (GtkATContext *self) if (names->len == 0) { g_ptr_array_unref (names); + g_clear_object (&parent); return g_strdup (""); } @@ -1263,6 +1343,7 @@ gtk_at_context_get_description (GtkATContext *self) g_ptr_array_unref (names); + g_clear_object (&parent); return g_string_free (res, FALSE); } diff --git a/gtk/gtkcolordialogbutton.c b/gtk/gtkcolordialogbutton.c index 8fdb630396..dce03690d1 100644 --- a/gtk/gtkcolordialogbutton.c +++ b/gtk/gtkcolordialogbutton.c @@ -110,9 +110,7 @@ gtk_color_dialog_button_init (GtkColorDialogButton *self) self->color = GDK_RGBA ("00000000"); - self->button = g_object_new (GTK_TYPE_BUTTON, - "accessible-role", GTK_ACCESSIBLE_ROLE_GENERIC, - NULL); + self->button = gtk_button_new (); g_signal_connect_swapped (self->button, "clicked", G_CALLBACK (button_clicked), self); gtk_widget_set_parent (self->button, GTK_WIDGET (self)); @@ -282,7 +280,6 @@ gtk_color_dialog_button_class_init (GtkColorDialogButtonClass *class) gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT); gtk_widget_class_set_css_name (widget_class, "colorbutton"); - gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_BUTTON); } /* }}} */ diff --git a/gtk/gtkdropdown.c b/gtk/gtkdropdown.c index 105c0817f8..fd07bb1bf2 100644 --- a/gtk/gtkdropdown.c +++ b/gtk/gtkdropdown.c @@ -695,10 +695,7 @@ setup_item (GtkSignalListItemFactory *factory, label = gtk_label_new (NULL); gtk_label_set_xalign (GTK_LABEL (label), 0.0); gtk_box_append (GTK_BOX (box), label); - icon = g_object_new (GTK_TYPE_IMAGE, - "icon-name", "object-select-symbolic", - "accessible-role", GTK_ACCESSIBLE_ROLE_NONE, - NULL); + icon = gtk_image_new_from_icon_name ("object-select-symbolic"); gtk_box_append (GTK_BOX (box), icon); gtk_list_item_set_child (list_item, box); } diff --git a/gtk/ui/gtkdropdown.ui b/gtk/ui/gtkdropdown.ui index 7fc72f2ddc..cf86ccfede 100644 --- a/gtk/ui/gtkdropdown.ui +++ b/gtk/ui/gtkdropdown.ui @@ -3,7 +3,6 @@