make non-native application accessible to screen readers for the visually impaired

Viewed 545

I create applications, that are divorced from any native framework. All rendering happens in OpenGL, with a context provided by GLFW, all in C, with no framework to rely on supplying compatibility. As such, standard screen readers like NVDA have no chance of picking up information ( excluding OCR ) and my applications are an accessibility black hole. How can I provide an interface for screen readers to cling unto? I presume this is a per OS thing... How would that be possible on Windows, Linux, BSD or even android? In the *NIX world, I presume this would be Desktop environment dependent... I'm finding a lot of information on this, with a framework as a starting point, but have a hard time finding resources on how to do it from scratch.

I'm fully aware this is far beyond the capability of a sole developer and know, that writing programs by ignoring native interfaces is a common accessibility hole, which you are advised to avoid.

However, I have a tough time finding resources and jump-in points to explore this topic. Can someone point me in the right direction?

TL;DR: How to provide screen-reader compatibility from scratch. Not in detail - but conceptually.

1 Answers

As you have already well identified, your app is an accessibility blackhole because you are using a rendering engine. It's basicly the same for OpenGL, SDL, or <canvas> on the web, or any library rendering something without specific accessibility support.

WE can talk about several possibilities:

  1. Become an accessibility server. Under windows, it means doing the necessary so that your app provide accessible components on demand from UIA / IAccessible2 interface.
  2. Use a well known GUI toolkits having accessibility support and their provieded accessibility API to make your app.
  3. Directly talk to screen readers via their respective API in order to make them say something and/or show something on a connected braille display.
  4. Do specific screen reader scripting

However, it doesnt stops there. Supporting screen readers isn't sufficient to make your app really accessible. You must also think about many other things.

1. Accessibility server, UIA, IAccessible2

This option is of course the best, because users of assistive technologies in general (not only screen readers) will feel right at home with a perfectly accessible app if you do your job correctly. However, it's also by far the hardest since you have to reinvent everything. You must decompose your interface into components, tell which category of component each of them are (more commonly called roles), make callback to fetch values and descriptions, etc.

IF you are making web development, compare that with if you had to use ARIA everywhere because there's no defaults, no titles, no paragraphs, no input fields, no buttons, etc. That's an huge job ! But if you do it really well, your app will be well accessible.

You may get code and ideas on how to do it by looking at open source GUI toolkits or browsers which all do it.

Of course, the API to use are different for each OS. UIA and IAccessible2 are for windows, but MacOS and several linux desktops also have OS-specific accessibility API that are based on the same root principles.

Note about terminology: the accessibility server or provider is your app or the GUI toolkit you are using, while the accessibility client or consumer is the scren reader (or others assistive tools).

2. Use a GUI toolkit with good accessibility support

By chance, you aren't obliged to reinvent the wheel, of course ! Many people did the job of point 1 above and it resulted in libraries commonly called GUI toolkits.

Some of them are known to generally produce well accessible apps, while others are known to produce totally inaccessible apps. QT, WXWidgets and Java SWT are three of them with quite good accessibility support. So you can quite a lot simplify the job by simply using one of them and their associated accessibility API. You will be saved from talking more or less directly to the OS with UIA/IAccessible2 and similar API on other platforms.

Be careful though, it isn't as easy as it seems: all components provided by GUI toolkits aren't necessarily all accessible under all platforms. Some components may be accessible out of the box, some other need configuration and/or a few specific code on your side, and some are unaccessible no matter what. Some are accessible under windows but not under MacOS or vice-versa. For example, GTK is the first choice for linux under GNOME for making accessible apps, but GTK under windows give quite poor results. Another example: wxWidgets's DataView control is known to be good under MacOS, but it is emulated under windows and therefore much less accessible. In case of doubt, the best is to test yourself under all combinations of OS and screen readers you intent to support.

Sadly, for a game, using a GUI toolkit is perhaps not a viable option, even if there exist OpenGL components capable of displaying a 3D scene. Here come the third possibility.

3. Talk directly to screen readers

Several screen readers provide an API to make them speak, adjust some settings and/or show something on braille display. If you can't, or don't want to use a GUI toolkit, this might be a solution. Jaws come with an API called FSAPI, NVDA with NVDA controller client. Apple also alow to control several aspects of VoiceOver programatically.

There are still several disadvantages, though:

  • You are specificly targetting some screen readers. People using another one, or another assistive tool than a screen reader (a screen magnifier for example), are all out of luc. Or you may multiply support for a big forest of different API for different products on different platforms.
  • All of these screen reader specific API support different things that may not be supported by others. There is no standards at all here.

Thinking about WCAG and how it would be transposed to desktop apps, in fact you are bypassing most best practices, which all recommand first above anything else to use well known standard component, and only customize when really necessary. So this third possibility should ideally be used if, and only if, using a good GUI toolkit isn't possible, or if the accessibility of the used GUI toolkit isn't sufficient.

I'm the autohr of UniversalSpeech, a small library trying to unify direct talking with several screen readers. You may have a look at it if you are interested.

4. Screen reader scripting

If your app isn't accessible alone, you may distribute screen reader specific scripts to users. These scripts can be instructed to fetch information to give to the user, add additional keyboard shortcuts and several other things. Jaws has its own scripting language, while NVDA scripts are developed with Python. AS far as I know, there's also scripting capabilities with VoiceOver under MacOS.

I gave you this fourth point for your information, but since you are starting from a completely inaccessible app, I wouldn't advise you to go that way. In order for scripts to be able to do useful things, you must have a working accessible base. A script can help fixing small accessibility issues, but it's nearly impossible to turn a completly inaccessible app into an accessible one just with a script. Additionally, you must distribute these scripts separately from your app, and users have to install them. It may be a difficulty for some people, depending on your target audience.

Beyond screen reader support

Screen reader support isn't everything. This is beyond your question, so I won't enter into details, but you shouldn't forget about the following points if you really want to make an accessible app which isn't only accessible but also comfortable to use for a screen reader user. This isn't at all an exhaustive list of additional things to watch out.

  • Keyboard navigation: most blind and many visually impaired aren't comfortable with the mouse and/or a touch screen. You must provide a full and consist way of using your app only with a keyboard, or, on mobile, only by standard touch gestures supported by the screen reader. Navigation should be as simple as possible, and should as much as you can conform to user preferences and general OS conventions (i.e. functions of tab, space, enter, etc.). This in turn implies to have a good structure of components.
  • Gamepad, motion sensors and other inputs: unless it's absolutely mandatory because it's your core concept, don't force the use of them and always allow a keyboard fallback
  • Visual appearance: as much as you can, you should use the settings/preferences defined at OS level for disposition, colors, contrasts, fonts, text size, dark mode, high contrast mode, etc. rather than using your own
  • Audio: don't output anything if the user can't reasonably expect any, make sure the volume can be changed at any time very easily, and if possible if it isn't against your core concept, always allow it to be paused, resumed, stopped and muted. Same reflection can apply to other outputs like vibration which you should always be able to disable.
Related