Search guides and the APICtrl K
  1. API reference
  2. Native GUI

gfx/accessibility.h

Walking the tree a screen reader would want to see.

#include <sonore/gfx/accessibility.h>
On this page

Design notes

The vocabulary -- roles, names, values, ranges -- is in accessible_info.h, which Component includes so it can declare accessibleInfo(). This is the traversal, which needs Components and so cannot live there.

Everything here is testable against a component tree with no window at all. That is the reason for the split: the platform bridges are the part that cannot be tested on this machine, and they should be a mechanical mapping from this rather than a second source of truth about what a knob is called.

One table, every platform

What each role is called on each platform lives in ONE table below, read by both bridges: uia_win32.h for UI Automation's control type, and accessibility_mac.h for NSAccessibility's role, subrole and how the value is read. Two switch statements in two files are two answers to "what is a combo box", and the second platform would drift from the first without anything noticing; one row per role is a thing a test can walk.

The rest of what the macOS bridge decides -- which change to announce, which element survives a rebuild, where a rectangle is on a y-up screen -- is here too, in detail, because it is arithmetic and bookkeeping that runs on any machine. The bridge that cannot be run here is left holding only the calls into AppKit.

Types 2

One role, on every platform.

The UIA numbers are UIA_*ControlTypeId from UIAutomationClient.h -- stable ABI, written out so this header needs no Windows header, and checked against the real constants by static_assert in uia_win32.h. The AX strings are the values of Apple's kAX*Role / kAX*Subrole constants (AXRoleConstants.h), which is what NSAccessibilityButtonRole and the rest ARE: NSStrings that compare by value.

One entry in the flattened tree a bridge walks.

Flattened rather than nested, because every bridge needs both -- a linear order for "next element" and a parent link for hierarchy -- and computing one from the other twice is how the two end up disagreeing.

Functions 3

Enums 1

↑↓ to move↵ to openEvery public name in the headers, and every guide