gtkbuilder: add accessibility role declaration

This allows to override the role declared to the atk stack.  For
instance,

<accessibility>
  <role type="static"/>
</accessibility>

allows to tell the accessibility stack that a label is just a message in
a message box.

Fixes #109
This commit is contained in:
Samuel Thibault 2018-03-19 14:11:16 +01:00
parent 1a1373779f
commit bd986f9534
6 changed files with 169 additions and 0 deletions

View File

@ -98,6 +98,9 @@
<property name="yalign">0</property> <property name="yalign">0</property>
<property name="label" translatable="0">Message</property> <property name="label" translatable="0">Message</property>
<property name="wrap">1</property> <property name="wrap">1</property>
<accessibility>
<role type="static"/>
</accessibility>
</object> </object>
<packing> <packing>
<property name="left-attach">1</property> <property name="left-attach">1</property>

View File

@ -3274,6 +3274,9 @@ bad things might happen.</property>
<object class="GtkLabel"> <object class="GtkLabel">
<property name="margin">20</property> <property name="margin">20</property>
<property name="label" translatable="yes">To free the princess, you have to slay the dragon.</property> <property name="label" translatable="yes">To free the princess, you have to slay the dragon.</property>
<accessibility>
<role type="static"/>
</accessibility>
</object> </object>
</child> </child>
</object> </object>
@ -3551,6 +3554,9 @@ bad things might happen.</property>
<child> <child>
<object class="GtkLabel" id="notebook_info_label"> <object class="GtkLabel" id="notebook_info_label">
<property name="label">No updates at this time</property> <property name="label">No updates at this time</property>
<accessibility>
<role type="static"/>
</accessibility>
</object> </object>
</child> </child>
</object> </object>

View File

@ -10685,6 +10685,7 @@ typedef struct
GtkBuilder *builder; GtkBuilder *builder;
GSList *actions; GSList *actions;
GSList *relations; GSList *relations;
AtkRole role;
} AccessibilitySubParserData; } AccessibilitySubParserData;
static void static void
@ -10764,6 +10765,45 @@ accessibility_start_element (GMarkupParseContext *context,
data->actions = g_slist_prepend (data->actions, action); 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) else if (strcmp (element_name, "accessibility") == 0)
{ {
if (!_gtk_builder_check_parent (data->builder, context, "object", error)) 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, g_object_set_qdata (G_OBJECT (buildable), quark_builder_atk_relations,
a11y_data->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); g_slice_free (AccessibilitySubParserData, a11y_data);
} }
else if (strcmp (tagname, "style") == 0) else if (strcmp (tagname, "style") == 0)

View File

@ -0,0 +1,75 @@
window1
"window"
index: 0
state: enabled resizable sensitive showing visible
toolkit: gtk
window-type: normal
<AtkComponent>
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
<AtkComponent>
layer: widget
alpha: 1
<AtkText>
text: Go to the GTK+ website or >google it
character count: 36
caret offset: 0
default attributes: bg-color: <omitted>
bg-full-height: 0
direction: <omitted>
editable: false
family-name: <omitted>
fg-color: <omitted>
indent: 0
invisible: false
justification: left
language: <omitted>
left-margin: 0
pixels-above-lines: 0
pixels-below-lines: 0
pixels-inside-wrap: 0
right-margin: 0
rise: 0
scale: 1
size: <omitted>
stretch: <omitted>
strikethrough: false
style: <omitted>
underline: none
variant: <omitted>
weight: <omitted>
wrap-mode: word
<AtkHypertext>
<AtkHyperlink>
start index: 10
end index: 22
anchors: http://www.gtk.org
<AtkHyperlink>
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
<AtkHyperlinkImpl>
<AtkHyperlink>
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
<AtkHyperlinkImpl>
<AtkHyperlink>
start index: 27
end index: 36
anchors: http://www.google.com

View File

@ -0,0 +1,17 @@
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<property name="type">popup</property>
<child>
<object class="GtkLabel" id="label1">
<property name="label">Go to the &lt;a href="http://www.gtk.org" title="&lt;i&gt;Our&lt;/i&gt; website"&gt;GTK+ website&lt;/a&gt; or &lt;small&gt;&gt;&lt;a href="http://www.google.com"&gt;google it&lt;/a&gt;&lt;/small&gt;</property>
<property name="use-markup">True</property>
<accessibility>
<role type="static"/>
</accessibility>
</object>
</child>
</object>
</interface>

View File

@ -1520,6 +1520,20 @@ test_widget (void)
" </child>" " </child>"
" </object>" " </object>"
"</interface>"; "</interface>";
const gchar *buffer4 =
"<interface>"
" <object class=\"GtkWindow\" id=\"window1\">"
" <child>"
" <object class=\"GtkLabel\" id=\"label1\">"
" <property name=\"label\">Thelabel</property>"
" <property name=\"can_focus\">False</property>"
" <accessibility>"
" <role type=\"static\"/>"
" </accessibility>"
" </object>"
" </child>"
" </object>"
"</interface>";
GtkBuilder *builder; GtkBuilder *builder;
GObject *window1, *button1, *label1; GObject *window1, *button1, *label1;
AtkObject *accessible; AtkObject *accessible;
@ -1565,6 +1579,14 @@ test_widget (void)
gtk_widget_destroy (GTK_WIDGET (window1)); gtk_widget_destroy (GTK_WIDGET (window1));
g_object_unref (builder); 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 static void