gfx/accessible_info.h
What a component IS, as opposed to what it looks like.
#include <sonore/gfx/accessible_info.h>- 1type
- 5other declarations
- Guides: The native editor
On this page
Design notes
The gap
The component tree is a purely visual object. A knob is a rectangle that draws an arc and responds to drags; nothing in it says "this is a control called Gain, currently at -6.0 dB, whose value you may change". So a producer using a screen reader gets silence, and a plugin generated by this SDK is unusable without sight.
The keyboard half of this landed first -- every control is reachable by Tab and operable by arrow keys, which was itself a total barrier -- but a control you can operate and cannot hear is still not usable.
What this file is, and what it is not
The vocabulary only: a role, a name, a value and a range. Split from accessibility.h so Component can declare accessibleInfo() without including the traversal that walks Components -- the circular include that otherwise forces the whole thing into component.h.
This file on its own is not a screen reader integration -- it is what a bridge READS. gfx/uia_win32.h is the Windows bridge and is verified against a real UI Automation client. gfx/accessibility_mac.h is the macOS bridge, onto NSAccessibility, and as of 2026-10-14 it has been COMPILED against a shim of Apple's declarations and never run: no Mac is in this loop. So on Windows a reader is known to hear a plugin built with this; on macOS it should, and tests/mac_input_selftest.cpp is what a Mac developer runs to find out.
(This paragraph said "nothing here reaches UI Automation" until the Windows bridge landed one commit later, and "macOS has none yet" until the Mac one did. A header comment that describes a limitation is a claim with an expiry date, and this one is dated deliberately.)
Operating a control, not only reading it
A reader also ACTS: VoiceOver's "increment" on a slider, "press" on a button, typing a value straight into a field. Those go to the component itself (Component::performAccessibleAction, setAccessibleValue, setAccessibleText), which answers through the same code its keys and clicks use -- a slider stepped by a reader brackets the edit exactly as an arrow key does, so the host records one gesture either way. What a control will do is part of its description (actions, valueSettable) so a bridge can list it without asking the live tree from another thread.
Why roles are a small closed set
Every platform has its own vocabulary and they do not agree. A closed enum that each bridge maps into its own platform's names is the only arrangement where adding a second platform cannot change what the first one says.
Types 1
Everything a screen reader would want about one component.
Built on demand rather than kept as state: the value of a knob is already in the knob, and a second copy updated by a callback is a second copy that can be stale at exactly the moment somebody asks.
Functions 2
- fn
inline const char* accessibleRoleName(AccessibleRole role)The role in plain lower-case English ("toggle button"), for logs and tests; "unknown" for Unknown. Not localised.gfx::accessibleRoleName · accessible_info.h:97 - fn
inline unsigned accessibleActionBit(AccessibleAction action)The action's bit, for AccessibleInfo::actions.gfx::accessibleActionBit · accessible_info.h:138
Enums 3
- enum
enum class AccessibleRoleWhat kind of thing a component is.gfx::AccessibleRole · accessible_info.h:69 - enum
enum class AccessibleAction : unsignedWhat a reader may ask a control to DO. Bits, so a description can carry the set a control offers right now.gfx::AccessibleAction · accessible_info.h:127 - enum
enum class AccessibleToggleA two-state control's state, for the platforms that read it as a number (NSAccessibility's AXCheckBox value is 0 or 1) rather than as the text.gfx::AccessibleToggle · accessible_info.h:142