Skip to content

Latest commit

 

History

History
312 lines (244 loc) · 14.8 KB

HOWTO.md

File metadata and controls

312 lines (244 loc) · 14.8 KB

How to fix gla11y .ui accessibility warnings

Some accessibility checks are automatically performed by the gla11y tool on the .ui files during build time. That will fail the build if new issues are introduced (existing issues are typically suppressed by suppression files). Here are explanations about warnings produced by the tool.

The tool mostly checks for labelling: GtkLabel widgets are usually used to label another widget, and some widgets indeed do not make sense to users without some context. The relation is often obvious visually, but screen readers can not guess that, so the .ui file needs to specify the widgets that labels are intended for, otherwise the labels and the widgets are ''orphan''. The tool looks both for orphan labels and for orphan widgets. Some widgets always need labelling (e.g. GtkEntry), so warnings will always be printed for them. Others may not always need one, and so warnings will only be printed if there are ''orphan'' labels alongside. That means that fixing one relation between a label and a widget may make disappear a lot of warnings about remaining orphan widgets because there are no orphan labels that they could be labelled by any more. Conversely, however, warnings about orphan labels are always printed, even if there are no orphan widgets.

In case of doubt, advice can be sought for on the [email protected] mailing list

Adding a relation between a label and a widget

Once it is determined that a relation is missing between a label (or anything that can be used as a label because it contains text, such as a GtkRadioButton, a GtkCheckButton, or an image with an accessible-name) and a widget, there are two ways to express the relation:

  • The GtkLabel can probably be used to define a keyboard shortcut for the widget (this is by large the most common case). In that case an underscore character should be added in the label to specify the shortcut, and the following xml bits should be added to specify the relation with the widget triggered by the mnemonic, and the accessibility relation will be added automatically:
    <property name="use_underline">True</property>
    <property name="mnemonic_widget">the_widget_id</property> 
  • If it does not make sense to set a keyboard shortcut from the label (for instance because the label is actually for several widgets, or because it is a GtkRadioButton or GtkCheckButton, whose keyboard shortcut is already used to operate it), the accessibility relation should be set by hand by adding the following xml bits to the label:
    <accessibility>
        <relation type="label-for" target="the_widget_id"/>
    </accessibility>

and the following bit to the widget:

    <accessibility>
        <relation type="labelled-by" target="the_label_id"/>
    </accessibility>

Yes, both ''label-for'' and ''labelled-by'' relations need to be set. An error is emitted by the tool if they do not match.

The widgets you want to relate may not have ids yet, but you can freely add some.

After having added a relation between a widget and a label in a .ui file, you can check that the warning has disappeared by running by hand

gla11y path/to/file.ui

Also, you should ideally check that labelling actually works. A simple way is to run

orca -e braille-monitor

and restart the application with the new .ui file. On clicking on the widget which has just received a label, the braille monitor should now show both the content of the widget '''and''' the content of the label. Orca might also be speaking a lot, you can use insert-s to stop the speech synthesis.

Fixing existing issues

For people who plan to work on fixing the existing issues (and thus emptying the suppression files, which is the eventual goal), here is a process:

  1. Pick up from the output of *.suppr a .ui file to fix, make sure to know how to reach it in the application interface to understand its semantics.
  2. Move the corresponding lines away from the .suppr file (but keep them at hand in case some false positives should be suppressed)
  3. Run make to get the uncovered list of warnings (touch the .ui file if make does not do anything).
  4. Look over the first warnings, very often there is both a warning for an orphan widget and for an orphan label, and one just needs to add a relation to fix both at the same time.
  5. Fix the issue in the .ui file (see below for the details), optionally check the result with a screen reader by installing the modified version (either the whole application, or simpler, just the single .ui file). In case of false positives, move the corresponding lines from the .suppr file to the .false file (create it if it doesn't exist yet).
  6. Run make again to check that the warning went away.
  7. Repeat from step 4 until gla11y does not emit any warning any more.
  8. Submit these changes.
  9. Restart from step 1 with another .ui file :)

Note: if you are unsure about how to fix some warning, better leave the suppression rule in the .suppr file and let somebody else to fix the issue. It is way better to leave a suppressed warning (which we will then know still needs fixing) than wiping it out wrongly, which would mean hiding an accessibility issue.

Coping with false positives

In some cases, gla11y emits warnings where there is actually no accessibility issue (e.g. because the context is obvious, or the label does not actually bring meaning, thus making the output heavier than useful, etc.). In that case, one can suppress the warnings completely by putting suppression rules to ui-a11y.false . For existing issues, the suppression rules can be taken from the .suppr file. Otherwise, one can use

gla11y -g suppr.false path/to/file.ui

to generate a suppression file for the whole .ui file, and from that file copy/paste the lines corresponding to the warning to be suppressed into ui-a11y.false .

Important: do not put a suppression rule in the .false file unless you are sure that there is nothing to fix here. If you just happen not to know how to fix it, keep the suppression rule in the .suppr file.

Explanations of gla11y warnings

'GtkLabel' 'labelfoo' does not specify what it labels

This label (or another within the same scope) may have to be associated with a widget which does not have a label yet. One should thus look for the widgets which do not have a label, and add appropriate accessibility relations.

Such orphan labels are reported even if there is no such orphan widget (but that is not made fatal), because labels being orphan is most of the time doubtful: labels are usually there for a reason, and not associating them with a widget means that some meaning is rendered visually but not through screen readers.

  • In some cases labels are used to convey independent information, e.g. in the find&replace dialog to report the number of replacements. These should not be using the LABEL role, but a STATIC role, so that screen readers know how to report them appropriately. This can be done by adding
    <accessibility>
        <role type="static"/>
    </accessibility>

in the <object class="GtkLabel">.

  • In some cases there are two labels for a widget: one before the widget, and one after the widget. For such a case we will need another "label-for-after" accessibility relation, in addition to the standard label-for. For now, the suppression rule should be kept in the .suppr file, so we remember to fix them once the new relation is available.

  • In some cases the label is only used to describe a group of options, and is thus not for one precise widget but a group of them. The label is typically the first child of a vertical GtkBox. In this case, a GtkFrame should be inserted between the upper container and the GtkBox, and the GtkLabel set as

    <child type="label">
        ... GtkLabel definition ...
    </child>

of the GtkFrame.

  • In some cases labels are really there for quite trivial reasons ( it is there only for visual coherence but does not provide any meaning). In such cases a suppression rule should be added to the .false file.

'GtkFoo' 'foobar' has no accessibility label

This widget does not have labelling. If there are orphan labels alongside, they may be potential candidates for labelling this widget, as described above about the ''does not specify what is labels'' warning. If there aren't orphan labels, perhaps another widget can be used as a label, for instance a GtkRadioButton or a GtkCheckButton. If there aren't candidates (because the context is obvious visually), depending on the widget type one can set a tooltip_text property, or a placeholder_text property, to provide a textual content that the screen reader will be able to show to the user.

'Foo' 'foobar' has no accessibility label

The warning mentioned above is only for Gtk widgets, for which gla11y knows quite well which types should have labelling, and which types do not need labelling. For application-specific widgets, gla11y does not have this knowledge, but by default it is assumed that they need labelling.

If it is known that an application-specific widget types never needs labelling, this knowledge can be added to the gla11y call with --widgets-ignored.

If it is known that an application-specific widget types always needs labelling (just like a GtkEntry does), this can also be added there with --widgets-needlabel

Otherwise, the precise widgets which need labelling should be fixed as explained in the previous section, and the precise widgets which do not need labelling should be mentioned in a suppression line in the .false file.

'GtkLabel' 'labelfoo' has label-for, but is not labelled-by by 'GtkFoo' 'foobar' line 123

label-for / labelled-by relations have to be set by pair: if we have a label-for relation, we also need the corresponding labelled-by relation. Here, one probably just needs to add to the 'foobar' widget a 'labelled-by' relation targetting 'labelfoo'.

'GtkFoo' 'foobar' has labelled-by, but is not label-for by 'GtkLabel' 'labelfoo' line 123

label-for / labelled-by relations have to be set by pair: if we have a labelled-by relation, we also need the corresponding label-for relation. Here, one probably just needs to add to the 'labelfoo' widget a 'label-for' relation targetting 'foobar'.

'GtkLabel' 'labelfoo' has description-for, but is not described-by by 'GtkFoo' 'foobar' line 123

description-for / described-by relations have to be set by pair: if we have a description-for relation, we also need the corresponding described-by relation. Here, one probably just needs to add to the 'foobar' widget a 'described-by' relation targetting 'labelfoo'.

'GtkFoo' 'foobar' has described-by, but is not description-for by 'GtkLabel' 'labelfoo' line 123

description-for / described-by relations have to be set by pair: if we have a described-by relation, we also need the corresponding description-for relation. Here, one probably just needs to add to the 'labelfoo' widget a 'description-for' relation targetting 'foobar'.

'GtkButton' 'foobutton' does not have its own label

Some buttons are designed to only embed an image (e.g. an arrow). For sight-impaired users, a label is needed to convey the information in a textual form (e.g. notably the direction of the arrow). If a visual label actually already exists, the label-for/labelled-by relation just needs to be added. If no visual label already exists, one can provide extra labelling by including a tooltip_text property in the GtkButton, for instance:

    <property name="tooltip_text" translatable="yes" context="mydialog|forward">Next page</property>

This will actually be also useful to sighted users who want to make sure of the consequence of clicking the button.

A tooltip_text is not enough for GtkCheckButton that lacks a label property, because that type of widget is supposed to be using its own label, and the tooltip is only supposed to provide more lengthy explanations. Quite often in that case, there is a visual label alongside, and one can just add the relation. If there is really no label because the context is obvious visually, the accessibility labelling can be provided explicitly with

    <child internal-child="accessible">
      <object class="AtkObject" id="checkbutton_legend-atkobject">
        <property name="AtkObject::accessible-name" translatable="yes">The label for the checkbutton</property>
      </object>
    </child>

'GtkEntry' 'fooentry' is referenced by multiple mnemonic_widget 'GtkLabel' 'labelfoo1' line 457 , 'GtkLabel' 'labelfoo2' line 782

Several labels with mnemonics have fooentry as target. This may happen when e.g. only one of these labels is visible at a time (but in that case one should make sure that either the two labels are exactly the same, or the screen reader indeed gets the proper label at the proper time) and then a suppression rule can be added to the .false file. But otherwise it is often an indication that one of these labels was actually mistargetted and there is an orphan widget that it was supposed to target instead. One then just need to fix the target of labels.

'GtkTextView' 'fooentry' has both a mnemonic 'GtkLabel' 'descriptionlabel' line 152 and labelled-by relation

fooentry has both a labelling relation and a label with mnemonic targetting it. This is very doubtful, and is usually an indication that one of these labels was actually mistargetted and there is an orphan widget that it was supposed to target instead. One then just need to fix the target of labels.

'GtkFoo' 'foofoo' has the same id as other elements 'GtkFoo' 'foobar' line 1234

foofoo and foobar have the same 'id' property, which is not allowed. The id of one of them needs to be renamed.

'GtkFoo' 'foo' visibility conflicts with paired 'GtkBar' 'bar' line 1234

'foo' is labelled by 'bar', and one of them has visibility enabled while the other has visibility disabled. Visibility should be coherent for labelling to work.