From bd986f95342ebf9c98ce87760c13d1bbafb26a7d Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Mon, 19 Mar 2018 14:11:16 +0100 Subject: [PATCH] gtkbuilder: add accessibility role declaration This allows to override the role declared to the atk stack. For instance, allows to tell the accessibility stack that a label is just a message in a message box. Fixes #109 --- demos/gtk-demo/listbox.ui | 3 ++ demos/widget-factory/widget-factory.ui | 6 +++ gtk/gtkwidget.c | 46 ++++++++++++++++ testsuite/a11y/label-static.txt | 75 ++++++++++++++++++++++++++ testsuite/a11y/label-static.ui | 17 ++++++ testsuite/gtk/builder.c | 22 ++++++++ 6 files changed, 169 insertions(+) create mode 100644 testsuite/a11y/label-static.txt create mode 100644 testsuite/a11y/label-static.ui diff --git a/demos/gtk-demo/listbox.ui b/demos/gtk-demo/listbox.ui index 76b49b285d..606a520224 100644 --- a/demos/gtk-demo/listbox.ui +++ b/demos/gtk-demo/listbox.ui @@ -98,6 +98,9 @@ 0 Message 1 + + + 1 diff --git a/demos/widget-factory/widget-factory.ui b/demos/widget-factory/widget-factory.ui index 8474d08d76..f8ab748010 100644 --- a/demos/widget-factory/widget-factory.ui +++ b/demos/widget-factory/widget-factory.ui @@ -3274,6 +3274,9 @@ bad things might happen. 20 To free the princess, you have to slay the dragon. + + + @@ -3551,6 +3554,9 @@ bad things might happen. No updates at this time + + + diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 902894bec8..f78add8c09 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -10685,6 +10685,7 @@ typedef struct GtkBuilder *builder; GSList *actions; GSList *relations; + AtkRole role; } AccessibilitySubParserData; static void @@ -10764,6 +10765,45 @@ accessibility_start_element (GMarkupParseContext *context, data->actions = g_slist_prepend (data->actions, action); } + else if (strcmp (element_name, "role") == 0) + { + const gchar *type; + AtkRole role; + + if (!_gtk_builder_check_parent (data->builder, context, "accessibility", error)) + return; + + if (data->role != ATK_ROLE_INVALID) + { + g_set_error (error, + GTK_BUILDER_ERROR, + GTK_BUILDER_ERROR_INVALID_VALUE, + "Duplicate accessibility role definition"); + _gtk_builder_prefix_error (data->builder, context, error); + return; + } + + if (!g_markup_collect_attributes (element_name, names, values, error, + G_MARKUP_COLLECT_STRING, "type", &type, + G_MARKUP_COLLECT_INVALID)) + { + _gtk_builder_prefix_error (data->builder, context, error); + return; + } + + role = atk_role_for_name (type); + if (role == ATK_ROLE_INVALID) + { + g_set_error (error, + GTK_BUILDER_ERROR, + GTK_BUILDER_ERROR_INVALID_VALUE, + "No such role type: '%s'", type); + _gtk_builder_prefix_error (data->builder, context, error); + return; + } + + data->role = role; + } else if (strcmp (element_name, "accessibility") == 0) { if (!_gtk_builder_check_parent (data->builder, context, "object", error)) @@ -11108,6 +11148,12 @@ gtk_widget_buildable_custom_finished (GtkBuildable *buildable, g_object_set_qdata (G_OBJECT (buildable), quark_builder_atk_relations, a11y_data->relations); + if (a11y_data->role != ATK_ROLE_INVALID) + { + AtkObject *accessible = gtk_widget_get_accessible (GTK_WIDGET (buildable)); + atk_object_set_role (accessible, a11y_data->role); + } + g_slice_free (AccessibilitySubParserData, a11y_data); } else if (strcmp (tagname, "style") == 0) diff --git a/testsuite/a11y/label-static.txt b/testsuite/a11y/label-static.txt new file mode 100644 index 0000000000..cfffa4c8ed --- /dev/null +++ b/testsuite/a11y/label-static.txt @@ -0,0 +1,75 @@ +window1 + "window" + index: 0 + state: enabled resizable sensitive showing visible + toolkit: gtk + window-type: normal + + layer: window + alpha: 1 + label1 + "static" + parent: window1 + index: 0 + name: Go to the GTK+ website or >google it + state: enabled focusable multi-line sensitive has-tooltip + toolkit: gtk + + layer: widget + alpha: 1 + + text: Go to the GTK+ website or >google it + character count: 36 + caret offset: 0 + default attributes: bg-color: + bg-full-height: 0 + direction: + editable: false + family-name: + fg-color: + indent: 0 + invisible: false + justification: left + language: + left-margin: 0 + pixels-above-lines: 0 + pixels-below-lines: 0 + pixels-inside-wrap: 0 + right-margin: 0 + rise: 0 + scale: 1 + size: + stretch: + strikethrough: false + style: + underline: none + variant: + weight: + wrap-mode: word + + + start index: 10 + end index: 22 + anchors: http://www.gtk.org + + start index: 27 + end index: 36 + anchors: http://www.google.com + unnamed-GtkLabelAccessibleLinkImpl-0 + "link" + parent: label1 + state: enabled focusable multi-line sensitive has-tooltip + + + start index: 10 + end index: 22 + anchors: http://www.gtk.org + unnamed-GtkLabelAccessibleLinkImpl-1 + "link" + parent: label1 + state: enabled focusable multi-line sensitive has-tooltip + + + start index: 27 + end index: 36 + anchors: http://www.google.com diff --git a/testsuite/a11y/label-static.ui b/testsuite/a11y/label-static.ui new file mode 100644 index 0000000000..1e478c0b63 --- /dev/null +++ b/testsuite/a11y/label-static.ui @@ -0,0 +1,17 @@ + + + + + False + popup + + + Go to the <a href="http://www.gtk.org" title="<i>Our</i> website">GTK+ website</a> or <small>><a href="http://www.google.com">google it</a></small> + True + + + + + + + diff --git a/testsuite/gtk/builder.c b/testsuite/gtk/builder.c index 9d5fb822f3..e662570a26 100644 --- a/testsuite/gtk/builder.c +++ b/testsuite/gtk/builder.c @@ -1520,6 +1520,20 @@ test_widget (void) " " " " ""; + const gchar *buffer4 = + "" + " " + " " + " " + " Thelabel" + " False" + " " + " " + " " + " " + " " + " " + ""; GtkBuilder *builder; GObject *window1, *button1, *label1; AtkObject *accessible; @@ -1565,6 +1579,14 @@ test_widget (void) gtk_widget_destroy (GTK_WIDGET (window1)); g_object_unref (builder); + + builder = builder_new_from_string (buffer4, -1, NULL); + label1 = gtk_builder_get_object (builder, "label1"); + + accessible = gtk_widget_get_accessible (GTK_WIDGET (label1)); + g_assert (atk_object_get_role (accessible) == ATK_ROLE_STATIC); + + g_object_unref (builder); } static void