Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
uia_mapping.hpp
Go to the documentation of this file.
1#pragma once
2
3// Windows UIA mapping for Pulp AccessRole.
4//
5// Pure-constant header — no UIAutomationCore.h dependency — so the same
6// mapping compiles on every platform and can be unit-tested offline.
7// The Windows accessibility provider (accessibility_win.cpp) consumes
8// these constants to populate IRawElementProviderSimple properties.
9//
10// UIA control type and pattern IDs are stable across Windows versions
11// (documented in UIAutomationCore.h). They're written here as named
12// constants so every call site becomes grep-able.
13
14#include <pulp/view/view.hpp>
15
16#include <array>
17#include <cstdint>
18
19namespace pulp::view::uia {
20
21// ── UIA Control Type IDs (subset Pulp exposes) ───────────────────────
22// Full list in <UIAutomationCore.h>. We map the roles that Pulp declares
23// today; additional roles (tree, table, text, menu) land as widgets need
24// them.
25inline constexpr int32_t kControlTypeButton = 50000;
26inline constexpr int32_t kControlTypeCheckBox = 50002;
27inline constexpr int32_t kControlTypeComboBox = 50003;
28inline constexpr int32_t kControlTypeEdit = 50004;
29inline constexpr int32_t kControlTypeHyperlink = 50005;
30inline constexpr int32_t kControlTypeImage = 50006;
31inline constexpr int32_t kControlTypeListItem = 50007;
32inline constexpr int32_t kControlTypeList = 50008;
33inline constexpr int32_t kControlTypeMenu = 50009;
34inline constexpr int32_t kControlTypeMenuItem = 50011;
35inline constexpr int32_t kControlTypeProgressBar = 50012;
36inline constexpr int32_t kControlTypeRadioButton = 50013;
37inline constexpr int32_t kControlTypeScrollBar = 50014;
38inline constexpr int32_t kControlTypeSlider = 50015;
39inline constexpr int32_t kControlTypeTab = 50018;
40inline constexpr int32_t kControlTypeTabItem = 50019;
41inline constexpr int32_t kControlTypeText = 50020;
42// UIA_CustomControlTypeId is 50025. It was written as 50033 here, which is
43// UIA_PaneControlTypeId — every unroled fragment claimed to be a Pane.
44inline constexpr int32_t kControlTypeCustom = 50025;
45inline constexpr int32_t kControlTypeGroup = 50026;
46inline constexpr int32_t kControlTypeDataItem = 50029;
47inline constexpr int32_t kControlTypeWindow = 50032;
48inline constexpr int32_t kControlTypeTable = 50036;
49
50// ── UIA Pattern IDs the provider may advertise per role ──────────────
51//
52// ONLY the patterns PulpFragmentProvider actually implements are listed here.
53// The provider's GetPatternProvider (platform/win/accessibility_win.cpp)
54// returns exactly two interfaces — IRangeValueProvider and IValueProvider — so
55// those are the only two IDs that exist. Invoke / Toggle / Text were advertised
56// here with no IInvokeProvider, IToggleProvider or ITextProvider anywhere in
57// the codebase: Narrator would query the pattern, get a null interface, and
58// the control would go dead. An advertised pattern is a promise; do not list
59// one here until the provider can serve it.
60inline constexpr int32_t kPatternValue = 10002;
61inline constexpr int32_t kPatternRangeValue = 10003;
62
65constexpr int32_t role_to_control_type(View::AccessRole role) {
66 switch (role) {
68 // A UIA CheckBox is the control type that carries the Toggle pattern.
69 // `toggle` used to map to Button, which advertised Toggle on a control
70 // type that has no toggle state — Narrator announced "button" and then
71 // read a checked state the type does not define.
86 // UIA has no Row control type; a table row is a DataItem, and cells are
87 // ListItems under it (the DataGrid/Table pattern convention).
96 // UIA has no Heading control type; Text + a HeadingLevel property is
97 // the convention. HeadingLevel is not populated yet.
101 }
102 return kControlTypeCustom;
103}
104
113 std::array<int32_t, 4> ids{};
114 int count = 0;
115};
116
118 PatternSet s{};
119 switch (role) {
122 // Both: RangeValue reports min/max/value; Value reports the
123 // widget's display string ("-6.0 dB").
124 s.ids[s.count++] = kPatternRangeValue;
125 s.ids[s.count++] = kPatternValue;
126 break;
129 // Read-only gauge: RangeValue only (get_IsReadOnly = TRUE).
130 s.ids[s.count++] = kPatternRangeValue;
131 break;
134 // Value carries the text content / selected item. ITextProvider
135 // (caret, ranges, attributes) is NOT implemented, so the Text
136 // pattern is not advertised.
137 s.ids[s.count++] = kPatternValue;
138 break;
139 // Every remaining role's defining pattern (Invoke for button/link/
140 // menu_item, Toggle for toggle/checkbox, SelectionItem for radio/tab/
141 // list_item, ExpandCollapse for the combo box's dropdown, Grid/Table
142 // for table) is NOT implemented by PulpFragmentProvider. They advertise
143 // NO pattern — the role name is correct, the interactions are the
144 // follow-up. Roles are named exhaustively (no default:) so a new role
145 // cannot silently inherit "no patterns".
166 break;
167 }
168 return s;
169}
170
175 const PatternSet pats = patterns_for_role(role);
176 for (int i = 0; i < pats.count; ++i) {
177 if (pats.ids[i] == kPatternRangeValue) return true;
178 }
179 return false;
180}
181
187 const PatternSet pats = patterns_for_role(role);
188 for (int i = 0; i < pats.count; ++i) {
189 if (pats.ids[i] == kPatternValue) return true;
190 }
191 return false;
192}
193
194// ── Source-gated pattern availability ────────────────────────────────
195//
196// A role says what a pattern COULD be served; the View says whether it can
197// actually serve it. Both must be true. Advertising RangeValue on a
198// progress bar with no AccessibilityValueInterface made get_Value /
199// get_Minimum / get_Maximum all return 0.0 — Narrator announced 0 at any
200// progress, and min == max == 0 is a degenerate range that divides by zero in
201// any client computing (v - min) / (max - min).
202//
203// Pure predicates so the offline test can assert them: accessibility_win.cpp
204// (Windows-only TU, never compiled on the required macOS gate) does nothing but
205// call these.
206
210 bool has_value_interface) {
211 return role_supports_range_value(role) && has_value_interface;
212}
213
216constexpr bool exposes_value(View::AccessRole role,
217 bool has_value_interface,
218 bool has_text_interface,
219 bool has_value_string) {
220 return role_supports_value(role) &&
221 (has_value_interface || has_text_interface || has_value_string);
222}
223
230constexpr bool is_read_only(View::AccessRole role,
231 bool has_value_interface,
232 bool has_editable_text_interface) {
233 const bool writable_value =
234 has_value_interface && role_supports_value(role);
235 return !(writable_value || has_editable_text_interface);
236}
237
238// ── Per-widget fragment runtime IDs ───────────────────────────────────
239//
240// Every UIA fragment must return a process-stable runtime ID so clients
241// can compare element identity across calls. The first element of a
242// runtime ID array is conventionally UiaAppendRuntimeId (3) for
243// provider-supplied fragments; the remainder is a provider-chosen
244// unique key. We derive the key from the fragment's depth-first index
245// in the View tree, which is stable for the lifetime of the tree the
246// provider was built against (the provider is rebuilt on structural
247// change, which also raises StructureChanged so clients re-query).
248//
249// UiaAppendRuntimeId is documented as the integer constant 3; named
250// here so the COM TU and the offline test share one definition without
251// pulling in UIAutomationCore.h.
252inline constexpr int32_t kUiaAppendRuntimeId = 3;
253
258struct RuntimeId {
259 std::array<int32_t, 2> ids{};
260 static constexpr int count = 2;
261};
262
263constexpr RuntimeId runtime_id_for_index(int index) {
264 RuntimeId rid{};
265 rid.ids[0] = kUiaAppendRuntimeId;
266 rid.ids[1] = 1 + index;
267 return rid;
268}
269
274constexpr double normalized_value_fraction(double current,
275 double lo,
276 double hi) {
277 if (!(hi > lo)) return 0.0;
278 if (current <= lo) return 0.0;
279 if (current >= hi) return 1.0;
280 return (current - lo) / (hi - lo);
281}
282
283} // namespace pulp::view::uia
AccessRole
Screen-reader role.
Definition view.hpp:988
@ list
Definition view.hpp:991
@ slider
Definition view.hpp:989
@ list_item
Definition view.hpp:991
@ link
Definition view.hpp:990
@ none
Definition view.hpp:989
@ toggle
Definition view.hpp:989
@ meter
Definition view.hpp:989
@ image
Definition view.hpp:989
@ menu_item
Definition view.hpp:992
@ cell
Definition view.hpp:991
@ menu
Definition view.hpp:992
@ dialog
Definition view.hpp:992
@ checkbox
Definition view.hpp:990
@ radio
Definition view.hpp:990
@ tab_list
Definition view.hpp:991
@ table
Definition view.hpp:991
@ scroll_bar
Definition view.hpp:992
@ button
Definition view.hpp:990
@ label
Definition view.hpp:989
@ group
Definition view.hpp:989
@ tab
Definition view.hpp:991
@ text_field
Definition view.hpp:990
@ progress_bar
Definition view.hpp:992
@ row
Definition view.hpp:991
@ heading
Definition view.hpp:992
@ combo_box
Definition view.hpp:990
Definition uia_mapping.hpp:19
constexpr int32_t kControlTypeRadioButton
Definition uia_mapping.hpp:36
constexpr int32_t kControlTypeSlider
Definition uia_mapping.hpp:38
constexpr RuntimeId runtime_id_for_index(int index)
Definition uia_mapping.hpp:263
constexpr int32_t kControlTypeMenu
Definition uia_mapping.hpp:33
constexpr int32_t kControlTypeCheckBox
Definition uia_mapping.hpp:26
constexpr int32_t kControlTypeListItem
Definition uia_mapping.hpp:31
constexpr int32_t kPatternRangeValue
Definition uia_mapping.hpp:61
constexpr int32_t kControlTypeProgressBar
Definition uia_mapping.hpp:35
constexpr int32_t kControlTypeGroup
Definition uia_mapping.hpp:45
constexpr int32_t kControlTypeCustom
Definition uia_mapping.hpp:44
constexpr int32_t kControlTypeEdit
Definition uia_mapping.hpp:28
constexpr int32_t kPatternValue
Definition uia_mapping.hpp:60
constexpr int32_t kControlTypeTable
Definition uia_mapping.hpp:48
constexpr bool role_supports_range_value(View::AccessRole role)
True if a role's pattern set advertises the RangeValue pattern, i.e.
Definition uia_mapping.hpp:174
constexpr int32_t role_to_control_type(View::AccessRole role)
Map a Pulp AccessRole to the best-fit UIA control type.
Definition uia_mapping.hpp:65
constexpr int32_t kControlTypeText
Definition uia_mapping.hpp:41
constexpr int32_t kControlTypeDataItem
Definition uia_mapping.hpp:46
constexpr int32_t kControlTypeButton
Definition uia_mapping.hpp:25
constexpr int32_t kControlTypeComboBox
Definition uia_mapping.hpp:27
constexpr int32_t kControlTypeTab
Definition uia_mapping.hpp:39
constexpr int32_t kControlTypeMenuItem
Definition uia_mapping.hpp:34
constexpr PatternSet patterns_for_role(View::AccessRole role)
Definition uia_mapping.hpp:117
constexpr int32_t kUiaAppendRuntimeId
Definition uia_mapping.hpp:252
constexpr bool exposes_value(View::AccessRole role, bool has_value_interface, bool has_text_interface, bool has_value_string)
IValueProvider::get_Value needs SOME string: a value interface's display string, a text interface's c...
Definition uia_mapping.hpp:216
constexpr int32_t kControlTypeImage
Definition uia_mapping.hpp:30
constexpr bool is_read_only(View::AccessRole role, bool has_value_interface, bool has_editable_text_interface)
IsReadOnly must mean exactly "SetValue will fail".
Definition uia_mapping.hpp:230
constexpr int32_t kControlTypeList
Definition uia_mapping.hpp:32
constexpr int32_t kControlTypeHyperlink
Definition uia_mapping.hpp:29
constexpr bool role_supports_value(View::AccessRole role)
True if a role advertises the Value pattern (IValueProvider).
Definition uia_mapping.hpp:186
constexpr int32_t kControlTypeWindow
Definition uia_mapping.hpp:47
constexpr int32_t kControlTypeScrollBar
Definition uia_mapping.hpp:37
constexpr bool exposes_range_value(View::AccessRole role, bool has_value_interface)
IRangeValueProvider needs numeric min/max/current — i.e.
Definition uia_mapping.hpp:209
constexpr double normalized_value_fraction(double current, double lo, double hi)
Clamp a raw value into [lo, hi] then map to the [0, 1] fraction UIA's Value pattern reports for a ran...
Definition uia_mapping.hpp:274
constexpr int32_t kControlTypeTabItem
Definition uia_mapping.hpp:40
@ s
Definition input_events.hpp:41
@ i
Definition input_events.hpp:40
Pattern IDs the provider should advertise for a given role.
Definition uia_mapping.hpp:112
std::array< int32_t, 4 > ids
Definition uia_mapping.hpp:113
int count
Definition uia_mapping.hpp:114
Build the two-element runtime-id key for the fragment at index (its depth-first position among access...
Definition uia_mapping.hpp:258
static constexpr int count
Definition uia_mapping.hpp:260
std::array< int32_t, 2 > ids
Definition uia_mapping.hpp:259