termwright_protocol/roles.rs
1//! Closed vocabularies. Unknown members are rejected, never passed through.
2
3use serde::{Deserialize, Serialize};
4
5/// A semantic role. ARIA-aligned and closed: unknown roles fail validation.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
7#[serde(rename_all = "lowercase")]
8pub enum Role {
9 /// The application as a whole.
10 Application,
11 /// A grouping container with no stronger meaning.
12 Region,
13 /// A dialog, modal or not.
14 Dialog,
15 /// An urgent message.
16 Alert,
17 /// A non-urgent status message.
18 Status,
19 /// A collection of items.
20 List,
21 /// One entry in a list.
22 #[serde(rename = "listitem")]
23 ListItem,
24 /// A menu of commands.
25 Menu,
26 /// One command in a menu.
27 #[serde(rename = "menuitem")]
28 MenuItem,
29 /// An activatable control.
30 Button,
31 /// A two- or three-state toggle.
32 Checkbox,
33 /// One option in a mutually exclusive set.
34 Radio,
35 /// One tab in a tab strip.
36 Tab,
37 /// An editable text field.
38 Textbox,
39 /// A section heading.
40 Heading,
41 /// Static text.
42 Text,
43 /// Progress towards completion.
44 #[serde(rename = "progressbar")]
45 ProgressBar,
46 /// A visual divider.
47 Separator,
48 /// A scroll position indicator.
49 Scrollbar,
50 /// A grid of rows and cells.
51 Table,
52 /// One row of a table.
53 Row,
54 /// One cell of a table row.
55 Cell,
56 /// No more specific role applies.
57 Generic,
58}
59
60/// Every role, in the order the reference implementation declares them.
61pub const SEMANTIC_ROLES: [&str; 23] = [
62 "application",
63 "region",
64 "dialog",
65 "alert",
66 "status",
67 "list",
68 "listitem",
69 "menu",
70 "menuitem",
71 "button",
72 "checkbox",
73 "radio",
74 "tab",
75 "textbox",
76 "heading",
77 "text",
78 "progressbar",
79 "separator",
80 "scrollbar",
81 "table",
82 "row",
83 "cell",
84 "generic",
85];
86
87/// A descriptive capability hint: a diagnostic, never a callback endpoint.
88#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
89#[serde(rename_all = "camelCase")]
90pub enum Action {
91 /// The node can take focus.
92 Focus,
93 /// The node can be activated (pressed, chosen).
94 Activate,
95 /// The node's checked state can be flipped.
96 Toggle,
97 /// The node's value can be replaced.
98 SetValue,
99 /// The node's viewport can be scrolled.
100 Scroll,
101 /// The node can be selected within its set.
102 Select,
103 /// The node can be expanded or collapsed.
104 Expand,
105}
106
107/// Every action.
108pub const SEMANTIC_ACTIONS: [&str; 7] = [
109 "focus", "activate", "toggle", "setValue", "scroll", "select", "expand",
110];
111
112/// Something the adapter tells the driver it can provide.
113#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
114#[serde(rename_all = "kebab-case")]
115pub enum Capability {
116 /// Publishes a node tree.
117 Tree,
118 /// Publishes authoritative intended layout geometry for every applicable node.
119 IntendedGeometry,
120 /// Publishes authoritative clipped geometry for every applicable node.
121 ClippedGeometry,
122 /// Publishes state flags.
123 States,
124 /// Publishes authoritative focus state.
125 FocusState,
126 /// Publishes action hints.
127 Actions,
128 /// Publishes physical input recipes.
129 ActionRecipes,
130 /// Publishes offset-to-cell mappings.
131 TextRanges,
132 /// Emits a render-commit marker per revision.
133 RenderRevisions,
134 /// Can forward application log records over the channel.
135 Logs,
136 /// Publishes a complete exact fresh-pointer ownership grid.
137 PointerHitGrid,
138}
139
140/// Every adapter capability.
141pub const ADAPTER_CAPABILITIES: [&str; 11] = [
142 "tree",
143 "intended-geometry",
144 "clipped-geometry",
145 "states",
146 "focus-state",
147 "actions",
148 "action-recipes",
149 "text-ranges",
150 "render-revisions",
151 "logs",
152 "pointer-hit-grid",
153];
154
155/// Whether `role` is one of the roles.
156pub fn valid_role(role: &str) -> bool {
157 SEMANTIC_ROLES.contains(&role)
158}
159
160/// Whether `action` is one of the actions.
161pub fn valid_action(action: &str) -> bool {
162 SEMANTIC_ACTIONS.contains(&action)
163}
164
165/// Whether `capability` is one of the capabilities.
166pub fn valid_capability(capability: &str) -> bool {
167 ADAPTER_CAPABILITIES.contains(&capability)
168}