Skip to main content

azul_core/
a11y.rs

1//! Accessibility types for screen reader support.
2//!
3//! Key types:
4//! - [`AccessibilityInfo`] — full accessibility metadata for a UI element
5//! - [`SmallAriaInfo`] — lightweight alternative for common cases (label + role + description)
6//! - [`AccessibilityRole`] — element purpose (button, link, checkbox, etc.)
7//! - [`AccessibilityState`] — dynamic state (focused, checked, expanded, etc.)
8//! - [`AccessibilityAction`] — actions performable on an element (click, scroll, etc.)
9//!
10//! These types are consumed by `layout/src/managers/a11y.rs` and mapped to
11//! platform accessibility backends in `dll/src/desktop/shell2/`.
12
13use azul_css::{
14    AzString, OptionF32, OptionString,
15    props::basic::length::FloatValue,
16};
17use crate::{
18    dom::OptionDomNodeId,
19    geom::LogicalPosition,
20    window::OptionVirtualKeyCodeCombo,
21};
22
23/// Holds information about a UI element for accessibility purposes (e.g., screen readers).
24/// This is a wrapper for platform-specific accessibility APIs like MSAA.
25#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
26#[repr(C)]
27pub struct AccessibilityInfo {
28    /// Get the "name" of the `IAccessible`, for example the
29    /// name of a button, checkbox or menu item. Try to use unique names
30    /// for each item in a dialog so that voice dictation software doesn't
31    /// have to deal with extra ambiguity.
32    pub accessibility_name: OptionString,
33    /// Get the "value" of the `IAccessible`, for example a number in a slider,
34    /// a URL for a link, the text a user entered in a field.
35    pub accessibility_value: OptionString,
36    /// Optional text description providing additional context about the element.
37    /// Maps to `aria-description` / accesskit's `set_description()`.
38    pub description: OptionString,
39    /// Optional keyboard accelerator.
40    pub accelerator: OptionVirtualKeyCodeCombo,
41    /// Optional "default action" description. Only used when there is at least
42    /// one `ComponentEventFilter::DefaultAction` callback present on this node.
43    pub default_action: OptionString,
44    /// Possible on/off states, such as focused, focusable, selected, selectable,
45    /// visible, protected (for passwords), checked, etc.
46    pub states: AccessibilityStateVec,
47    /// A list of actions the user can perform on this element.
48    /// Maps to accesskit's Action enum.
49    pub supported_actions: AccessibilityActionVec,
50    /// ID of another node that labels this one (for `aria-labelledby`).
51    pub labelled_by: OptionDomNodeId,
52    /// ID of another node that describes this one (for `aria-describedby`).
53    pub described_by: OptionDomNodeId,
54    /// Get an enumerated value representing what this IAccessible is used for,
55    /// for example is it a link, static text, editable text, a checkbox, or a table cell, etc.
56    pub role: AccessibilityRole,
57    /// For live regions that update automatically (e.g., chat messages, timers).
58    /// Maps to accesskit's `Live` property.
59    pub is_live_region: bool,
60}
61
62/// Actions that can be performed on an accessible element.
63/// This is a simplified version of accesskit::Action to avoid direct dependency in core.
64#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
65#[repr(C, u8)]
66pub enum AccessibilityAction {
67    /// The default action for the element (usually a click).
68    Default,
69    /// Set focus to this element.
70    Focus,
71    /// Remove focus from this element.
72    Blur,
73    /// Collapse an expandable element (e.g., tree node, accordion).
74    Collapse,
75    /// Expand a collapsible element (e.g., tree node, accordion).
76    Expand,
77    /// Scroll this element into view.
78    ScrollIntoView,
79    /// Increment a numeric value (e.g., slider, spinner).
80    Increment,
81    /// Decrement a numeric value (e.g., slider, spinner).
82    Decrement,
83    /// Show a context menu.
84    ShowContextMenu,
85    /// Hide a tooltip.
86    HideTooltip,
87    /// Show a tooltip.
88    ShowTooltip,
89    /// Scroll up.
90    ScrollUp,
91    /// Scroll down.
92    ScrollDown,
93    /// Scroll left.
94    ScrollLeft,
95    /// Scroll right.
96    ScrollRight,
97    /// Replace selected text with new text.
98    ReplaceSelectedText(AzString),
99    /// Scroll to a specific point.
100    ScrollToPoint(LogicalPosition),
101    /// Set scroll offset.
102    SetScrollOffset(LogicalPosition),
103    /// Set text selection.
104    SetTextSelection(TextSelectionStartEnd),
105    /// Set sequential focus navigation starting point.
106    SetSequentialFocusNavigationStartingPoint,
107    /// Set the value of a control.
108    SetValue(AzString),
109    /// Set numeric value of a control.
110    SetNumericValue(FloatValue),
111    /// Custom action with ID.
112    CustomAction(i32),
113}
114
115#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
116#[repr(C)]
117pub struct TextSelectionStartEnd {
118    pub selection_start: usize,
119    pub selection_end: usize,
120}
121
122impl_vec!(AccessibilityAction, AccessibilityActionVec, AccessibilityActionVecDestructor, AccessibilityActionVecDestructorType, AccessibilityActionVecSlice, OptionAccessibilityAction);
123impl_vec_debug!(AccessibilityAction, AccessibilityActionVec);
124impl_vec_clone!(
125    AccessibilityAction,
126    AccessibilityActionVec,
127    AccessibilityActionVecDestructor
128);
129impl_vec_partialeq!(AccessibilityAction, AccessibilityActionVec);
130impl_vec_eq!(AccessibilityAction, AccessibilityActionVec);
131impl_vec_partialord!(AccessibilityAction, AccessibilityActionVec);
132impl_vec_ord!(AccessibilityAction, AccessibilityActionVec);
133impl_vec_hash!(AccessibilityAction, AccessibilityActionVec);
134
135impl_option![
136    AccessibilityAction,
137    OptionAccessibilityAction,
138    copy = false,
139    [Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
140];
141
142impl_option!(
143    AccessibilityInfo,
144    OptionAccessibilityInfo,
145    copy = false,
146    [Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
147);
148
149/// Defines the element's purpose for accessibility APIs, informing assistive technologies
150/// like screen readers about the function of a UI element. Each variant corresponds to a
151/// standard control type or UI structure.
152///
153/// For more details, see the [MSDN Role Constants page](https://docs.microsoft.com/en-us/windows/winauto/object-roles).
154#[repr(C)]
155#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
156pub enum AccessibilityRole {
157    /// Represents the title or caption bar of a window.
158    /// - **Purpose**: To identify the title bar containing the window title and system commands.
159    /// - **When to use**: This role is typically inserted by the operating system for standard
160    ///   windows.
161    /// - **Example**: The bar at the top of an application window displaying its name and the
162    ///   minimize, maximize, and close buttons.
163    TitleBar,
164
165    /// Represents a menu bar at the top of a window.
166    /// - **Purpose**: To contain a set of top-level menus for an application.
167    /// - **When to use**: For the main menu bar of an application, such as one containing "File,"
168    ///   "Edit," and "View."
169    /// - **Example**: The "File", "Edit", "View" menu bar at the top of a text editor.
170    MenuBar,
171
172    /// Represents a vertical or horizontal scroll bar.
173    /// - **Purpose**: To enable scrolling through content that is larger than the visible area.
174    /// - **When to use**: For any scrollable region of content.
175    /// - **Example**: The bar on the side of a web page that allows the user to scroll up and
176    ///   down.
177    ScrollBar,
178
179    /// Represents a handle or grip used for moving or resizing.
180    /// - **Purpose**: To provide a user interface element for manipulating another element's size
181    ///   or position.
182    /// - **When to use**: For handles that allow resizing of windows, panes, or other objects.
183    /// - **Example**: The small textured area in the bottom-right corner of a window that can be
184    ///   dragged to resize it.
185    Grip,
186
187    /// Represents a system sound indicating an event.
188    /// - **Purpose**: To associate a sound with a UI event, providing an auditory cue.
189    /// - **When to use**: When a sound is the primary representation of an event.
190    /// - **Example**: A system notification sound that plays when a new message arrives.
191    Sound,
192
193    /// Represents the system's mouse pointer or other pointing device.
194    /// - **Purpose**: To indicate the screen position of the user's pointing device.
195    /// - **When to use**: This role is managed by the operating system.
196    /// - **Example**: The arrow that moves on the screen as you move the mouse.
197    Cursor,
198
199    /// Represents the text insertion point indicator.
200    /// - **Purpose**: To show the current text entry or editing position.
201    /// - **When to use**: This role is typically managed by the operating system for text input
202    ///   fields.
203    /// - **Example**: The blinking vertical line in a text box that shows where the next character
204    ///   will be typed.
205    Caret,
206
207    /// Represents an alert or notification.
208    /// - **Purpose**: To convey an important, non-modal message to the user.
209    /// - **When to use**: For non-intrusive notifications that do not require immediate user
210    ///   interaction.
211    /// - **Example**: A small, temporary "toast" notification that appears to confirm an action,
212    ///   like "Email sent."
213    Alert,
214
215    /// Represents a window frame.
216    /// - **Purpose**: To serve as the container for other objects like a title bar and client
217    ///   area.
218    /// - **When to use**: This is a fundamental role, typically managed by the windowing system.
219    /// - **Example**: The main window of any application, which contains all other UI elements.
220    Window,
221
222    /// Represents a window's client area, where the main content is displayed.
223    /// - **Purpose**: To define the primary content area of a window.
224    /// - **When to use**: For the main content region of a window. It's often the default role for
225    ///   a custom control container.
226    /// - **Example**: The area of a web browser where the web page content is rendered.
227    Client,
228
229    /// Represents a pop-up menu.
230    /// - **Purpose**: To display a list of `MenuItem` objects that appears when a user performs an
231    ///   action.
232    /// - **When to use**: For context menus (right-click menus) or drop-down menus.
233    /// - **Example**: The menu that appears when you right-click on a file in a file explorer.
234    MenuPopup,
235
236    /// Represents an individual item within a menu.
237    /// - **Purpose**: To represent a single command, option, or separator within a menu.
238    /// - **When to use**: For individual options inside a `MenuBar` or `MenuPopup`.
239    /// - **Example**: The "Save" option within the "File" menu.
240    MenuItem,
241
242    /// Represents a small pop-up window that provides information.
243    /// - **Purpose**: To offer brief, contextual help or information about a UI element.
244    /// - **When to use**: For informational pop-ups that appear on mouse hover.
245    /// - **Example**: The small box of text that appears when you hover over a button in a
246    ///   toolbar.
247    Tooltip,
248
249    /// Represents the main window of an application.
250    /// - **Purpose**: To identify the top-level window of an application.
251    /// - **When to use**: For the primary window that represents the application itself.
252    /// - **Example**: The main window of a calculator or notepad application.
253    Application,
254
255    /// Represents a document window within an application.
256    /// - **Purpose**: To represent a contained document, typically in a Multiple Document
257    ///   Interface (MDI) application.
258    /// - **When to use**: For individual document windows inside a larger application shell.
259    /// - **Example**: In a photo editor that allows multiple images to be open in separate
260    ///   windows, each image window would be a `Document`.
261    Document,
262
263    /// Represents a pane or a distinct section of a window.
264    /// - **Purpose**: To divide a window into visually and functionally distinct areas.
265    /// - **When to use**: For sub-regions of a window, like a navigation pane, preview pane, or
266    ///   sidebar.
267    /// - **Example**: The preview pane in an email client that shows the content of the selected
268    ///   email.
269    Pane,
270
271    /// Represents a graphical chart or graph.
272    /// - **Purpose**: To display data visually in a chart format.
273    /// - **When to use**: For any type of chart, such as a bar chart, line chart, or pie chart.
274    /// - **Example**: A bar chart displaying monthly sales figures.
275    Chart,
276
277    /// Represents a dialog box or message box.
278    /// - **Purpose**: To create a secondary window that requires user interaction before returning
279    ///   to the main application.
280    /// - **When to use**: For modal or non-modal windows that prompt the user for information or a
281    ///   response.
282    /// - **Example**: The "Open File" or "Print" dialog in most applications.
283    Dialog,
284
285    /// Represents a window's border.
286    /// - **Purpose**: To identify the border of a window, which is often used for resizing.
287    /// - **When to use**: This role is typically managed by the windowing system.
288    /// - **Example**: The decorative and functional frame around a window.
289    Border,
290
291    /// Represents a group of related controls.
292    /// - **Purpose**: To logically group other objects that share a common purpose.
293    /// - **When to use**: For grouping controls like a set of radio buttons or a fieldset with a
294    ///   legend.
295    /// - **Example**: A "Settings" group box in a dialog that contains several related checkboxes.
296    Grouping,
297
298    /// Represents a visual separator.
299    /// - **Purpose**: To visually divide a space or a group of controls.
300    /// - **When to use**: For visual separators in menus, toolbars, or between panes.
301    /// - **Example**: The horizontal line in a menu that separates groups of related menu items.
302    Separator,
303
304    /// Represents a toolbar containing a group of controls.
305    /// - **Purpose**: To group controls, typically buttons, for quick access to frequently used
306    ///   functions.
307    /// - **When to use**: For a bar of buttons or other controls, usually at the top of a window
308    ///   or pane.
309    /// - **Example**: The toolbar at the top of a word processor with buttons for "Bold,"
310    ///   "Italic," and "Underline."
311    Toolbar,
312
313    /// Represents a status bar for displaying information.
314    /// - **Purpose**: To display status information about the current state of the application.
315    /// - **When to use**: For a bar, typically at the bottom of a window, that displays messages.
316    /// - **Example**: The bar at the bottom of a web browser that shows the loading status of a
317    ///   page.
318    StatusBar,
319
320    /// Represents a data table.
321    /// - **Purpose**: To present data in a two-dimensional grid of rows and columns.
322    /// - **When to use**: For grid-like data presentation.
323    /// - **Example**: A spreadsheet or a table of data in a database application.
324    Table,
325
326    /// Represents a column header in a table.
327    /// - **Purpose**: To provide a label for a column of data.
328    /// - **When to use**: For the headers of columns in a `Table`.
329    /// - **Example**: The header row in a spreadsheet with labels like "Name," "Date," and
330    ///   "Amount."
331    ColumnHeader,
332
333    /// Represents a row header in a table.
334    /// - **Purpose**: To provide a label for a row of data.
335    /// - **When to use**: For the headers of rows in a `Table`.
336    /// - **Example**: The numbered rows on the left side of a spreadsheet.
337    RowHeader,
338
339    /// Represents a full column of cells in a table.
340    /// - **Purpose**: To represent an entire column as a single accessible object.
341    /// - **When to use**: When it is useful to interact with a column as a whole.
342    /// - **Example**: The "Amount" column in a financial data table.
343    Column,
344
345    /// Represents a full row of cells in a table.
346    /// - **Purpose**: To represent an entire row as a single accessible object.
347    /// - **When to use**: When it is useful to interact with a row as a whole.
348    /// - **Example**: A row representing a single customer's information in a customer list.
349    Row,
350
351    /// Represents a single cell within a table.
352    /// - **Purpose**: To represent a single data point or control within a `Table`.
353    /// - **When to use**: For individual cells in a grid or table.
354    /// - **Example**: A single cell in a spreadsheet containing a specific value.
355    Cell,
356
357    /// Represents a hyperlink to a resource.
358    /// - **Purpose**: To provide a navigational link to another document or location.
359    /// - **When to use**: For text or images that, when clicked, navigate to another resource.
360    /// - **Example**: A clickable link on a web page.
361    Link,
362
363    /// Represents a help balloon or pop-up.
364    /// - **Purpose**: To provide more detailed help information than a standard tooltip.
365    /// - **When to use**: For a pop-up that offers extended help text, often initiated by a help
366    ///   button.
367    /// - **Example**: A pop-up balloon with a paragraph of help text that appears when a user
368    ///   clicks a help icon.
369    HelpBalloon,
370
371    /// Represents an animated, character-like graphic object.
372    /// - **Purpose**: To provide an animated agent for user assistance or entertainment.
373    /// - **When to use**: For animated characters or avatars that provide help or guidance.
374    /// - **Example**: An animated paperclip that offers tips in a word processor (e.g.,
375    ///   Microsoft's Clippy).
376    Character,
377
378    /// Represents a list of items.
379    /// - **Purpose**: To contain a set of `ListItem` objects.
380    /// - **When to use**: For list boxes or similar controls that present a list of selectable
381    ///   items.
382    /// - **Example**: The list of files in a file selection dialog.
383    List,
384
385    /// Represents an individual item within a list.
386    /// - **Purpose**: To represent a single, selectable item within a `List`.
387    /// - **When to use**: For each individual item in a list box or combo box.
388    /// - **Example**: A single file name in a list of files.
389    ListItem,
390
391    /// Represents an outline or tree structure.
392    /// - **Purpose**: To display a hierarchical view of data.
393    /// - **When to use**: For tree-view controls that show nested items.
394    /// - **Example**: A file explorer's folder tree view.
395    Outline,
396
397    /// Represents an individual item within an outline or tree.
398    /// - **Purpose**: To represent a single node (which can be a leaf or a branch) in an
399    ///   `Outline`.
400    /// - **When to use**: For each node in a tree view.
401    /// - **Example**: A single folder in a file explorer's tree view.
402    OutlineItem,
403
404    /// Represents a single tab in a tabbed interface.
405    /// - **Purpose**: To provide a control for switching between different `PropertyPage` views.
406    /// - **When to use**: For the individual tabs that the user can click to switch pages.
407    /// - **Example**: The "General" and "Security" tabs in a file properties dialog.
408    PageTab,
409
410    /// Represents the content of a page in a property sheet.
411    /// - **Purpose**: To serve as a container for the controls displayed when a `PageTab` is
412    ///   selected.
413    /// - **When to use**: For the content area associated with a specific tab.
414    /// - **Example**: The set of options displayed when the "Security" tab is active.
415    PropertyPage,
416
417    /// Represents a visual indicator, like a slider thumb.
418    /// - **Purpose**: To visually indicate the current value or position of another control.
419    /// - **When to use**: For a sub-element that indicates status, like the thumb of a scrollbar.
420    /// - **Example**: The draggable thumb of a scrollbar that indicates the current scroll
421    ///   position.
422    Indicator,
423
424    /// Represents a picture or graphical image.
425    /// - **Purpose**: To display a non-interactive image.
426    /// - **When to use**: For images and icons that are purely decorative or informational.
427    /// - **Example**: A company logo displayed in an application's "About" dialog.
428    Graphic,
429
430    /// Represents read-only text.
431    /// - **Purpose**: To provide a non-editable text label for another control or for displaying
432    ///   information.
433    /// - **When to use**: For text that the user cannot edit.
434    /// - **Example**: The label "Username:" next to a text input field.
435    StaticText,
436
437    /// Represents editable text or a text area.
438    /// - **Purpose**: To allow for user text input or selection.
439    /// - **When to use**: For text input fields where the user can type.
440    /// - **Example**: A text box for entering a username or password.
441    Text,
442
443    /// Represents a standard push button.
444    /// - **Purpose**: To initiate an immediate action.
445    /// - **When to use**: For standard buttons that perform an action when clicked.
446    /// - **Example**: An "OK" or "Cancel" button in a dialog.
447    PushButton,
448
449    /// Represents a check box control.
450    /// - **Purpose**: To allow the user to make a binary choice (checked or unchecked).
451    /// - **When to use**: For options that can be toggled on or off independently.
452    /// - **Example**: A "Remember me" checkbox on a login form.
453    CheckButton,
454
455    /// Represents a radio button.
456    /// - **Purpose**: To allow the user to select one option from a mutually exclusive group.
457    /// - **When to use**: For a choice where only one option from a `Grouping` can be selected.
458    /// - **Example**: "Male" and "Female" radio buttons for selecting gender.
459    RadioButton,
460
461    /// Represents a combination of a text field and a drop-down list.
462    /// - **Purpose**: To allow the user to either type a value or select one from a list.
463    /// - **When to use**: For controls that offer a list of suggestions but also allow custom
464    ///   input.
465    /// - **Example**: A font selector that allows you to type a font name or choose one from a
466    ///   list.
467    ComboBox,
468
469    /// Represents a drop-down list box.
470    /// - **Purpose**: To allow the user to select an item from a non-editable list that drops
471    ///   down.
472    /// - **When to use**: For selecting a single item from a predefined list of options.
473    /// - **Example**: A country selection drop-down menu.
474    DropList,
475
476    /// Represents a progress bar.
477    /// - **Purpose**: To indicate the progress of a lengthy operation.
478    /// - **When to use**: To provide feedback for tasks like file downloads or installations.
479    /// - **Example**: The bar that fills up to show the progress of a file copy operation.
480    ProgressBar,
481
482    /// Represents a dial or knob.
483    /// - **Purpose**: To allow selecting a value from a continuous or discrete range, often
484    ///   circularly.
485    /// - **When to use**: For controls that resemble real-world dials, like a volume knob.
486    /// - **Example**: A volume control knob in a media player application.
487    Dial,
488
489    /// Represents a control for entering a keyboard shortcut.
490    /// - **Purpose**: To capture a key combination from the user.
491    /// - **When to use**: In settings where users can define their own keyboard shortcuts.
492    /// - **Example**: A text field in a settings dialog where a user can press a key combination
493    ///   to assign it to a command.
494    HotkeyField,
495
496    /// Represents a slider for selecting a value within a range.
497    /// - **Purpose**: To allow the user to adjust a setting along a continuous or discrete range.
498    /// - **When to use**: For adjusting values like volume, brightness, or zoom level.
499    /// - **Example**: A slider to control the volume of a video.
500    Slider,
501
502    /// Represents a spin button (up/down arrows) for incrementing or decrementing a value.
503    /// - **Purpose**: To provide fine-tuned adjustment of a value, typically numeric.
504    /// - **When to use**: For controls that allow stepping through a range of values.
505    /// - **Example**: The up and down arrows next to a number input for setting the font size.
506    SpinButton,
507
508    /// Represents a diagram or flowchart.
509    /// - **Purpose**: To represent data or relationships in a schematic form.
510    /// - **When to use**: For visual representations of structures that are not charts, like a
511    ///   database schema diagram.
512    /// - **Example**: A flowchart illustrating a business process.
513    Diagram,
514
515    /// Represents an animation control.
516    /// - **Purpose**: To display a sequence of images or indicate an ongoing process.
517    /// - **When to use**: For animations that show that an operation is in progress.
518    /// - **Example**: The animation that plays while files are being copied.
519    Animation,
520
521    /// Represents a mathematical equation.
522    /// - **Purpose**: To display a mathematical formula in the correct format.
523    /// - **When to use**: For displaying mathematical equations.
524    /// - **Example**: A rendered mathematical equation in a scientific document editor.
525    Equation,
526
527    /// Represents a button that drops down a list of items.
528    /// - **Purpose**: To combine a default action button with a list of alternative actions.
529    /// - **When to use**: For buttons that have a primary action and a secondary list of options.
530    /// - **Example**: A "Send" button with a dropdown arrow that reveals "Send and Archive."
531    ButtonDropdown,
532
533    /// Represents a button that drops down a full menu.
534    /// - **Purpose**: To provide a button that opens a menu of choices rather than performing a
535    ///   single action.
536    /// - **When to use**: When a button's primary purpose is to reveal a menu.
537    /// - **Example**: A "Tools" button that opens a menu with various tool options.
538    ButtonMenu,
539
540    /// Represents a button that drops down a grid for selection.
541    /// - **Purpose**: To allow selection from a two-dimensional grid of options.
542    /// - **When to use**: For buttons that open a grid-based selection UI.
543    /// - **Example**: A color picker button that opens a grid of color swatches.
544    ButtonDropdownGrid,
545
546    /// Represents blank space between other objects.
547    /// - **Purpose**: To represent significant empty areas in a UI that are part of the layout.
548    /// - **When to use**: Sparingly, to signify that a large area is intentionally blank.
549    /// - **Example**: A large empty panel in a complex layout might use this role.
550    Whitespace,
551
552    /// Represents the container for a set of tabs.
553    /// - **Purpose**: To group a set of `PageTab` elements.
554    /// - **When to use**: To act as the parent container for a row or column of tabs.
555    /// - **Example**: The entire row of tabs at the top of a properties dialog.
556    PageTabList,
557
558    /// Represents a clock control.
559    /// - **Purpose**: To display the current time.
560    /// - **When to use**: For any UI element that displays time.
561    /// - **Example**: The clock in the system tray of the operating system.
562    Clock,
563
564    /// Represents a button with two parts: a default action and a dropdown.
565    /// - **Purpose**: To combine a frequently used action with a set of related, less-used
566    ///   actions.
567    /// - **When to use**: When a button has a default action and other related actions available
568    ///   in a dropdown.
569    /// - **Example**: A "Save" split button where the primary part saves, and the dropdown offers
570    ///   "Save As."
571    SplitButton,
572
573    /// Represents a control for entering an IP address.
574    /// - **Purpose**: To provide a specialized input field for IP addresses, often with formatting
575    ///   and validation.
576    /// - **When to use**: For dedicated IP address input fields.
577    /// - **Example**: A network configuration dialog with a field for entering a static IP
578    ///   address.
579    IpAddress,
580
581    /// Represents an element with no specific role.
582    /// - **Purpose**: To indicate an element that has no semantic meaning for accessibility.
583    /// - **When to use**: Should be used sparingly for purely decorative elements that should be
584    ///   ignored by assistive technologies.
585    /// - **Example**: A decorative graphical flourish that has no function or information to
586    ///   convey.
587    Nothing,
588
589    /// Unknown or unspecified role.
590    /// - **Purpose**: Default fallback when no specific role is assigned.
591    /// - **When to use**: As a default value or when role information is unavailable.
592    Unknown,
593}
594
595impl_option!(
596    AccessibilityRole,
597    OptionAccessibilityRole,
598    [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
599);
600
601/// Defines the current state of an element for accessibility APIs (e.g., focused, checked).
602/// These states provide dynamic information to assistive technologies about the element's
603/// condition.
604///
605/// See the [MSDN State Constants page](https://docs.microsoft.com/en-us/windows/win32/winauto/object-state-constants) for more details.
606#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
607#[repr(C)]
608pub enum AccessibilityState {
609    /// The element is unavailable and cannot be interacted with.
610    /// - **Purpose**: To indicate that a control is disabled or grayed out.
611    /// - **When to use**: For disabled buttons, non-interactive menu items, or any control that is
612    ///   temporarily non-functional.
613    /// - **Example**: A "Save" button that is disabled until the user makes changes to a document.
614    Unavailable,
615
616    /// The element is selected.
617    /// - **Purpose**: To indicate that an item is currently chosen or highlighted. This is
618    ///   distinct from having focus.
619    /// - **When to use**: For selected items in a list, highlighted text, or the currently active
620    ///   tab in a tab list.
621    /// - **Example**: A file highlighted in a file explorer, or multiple selected emails in an
622    ///   inbox.
623    Selected,
624
625    /// The element has the keyboard focus.
626    /// - **Purpose**: To identify the single element that will receive keyboard input.
627    /// - **When to use**: For the control that is currently active and ready to be manipulated by
628    ///   the keyboard.
629    /// - **Example**: A text box with a blinking cursor, or a button with a dotted outline around
630    ///   it.
631    Focused,
632
633    /// The element is checked, toggled, or in an "on" state.
634    /// - **Purpose**: To represent checked checkboxes, selected radio buttons, and active toggles.
635    /// - **Example**: A checked "I agree" checkbox, a selected "Yes" radio button.
636    CheckedTrue,
637    /// The element is unchecked, untoggled, or in an "off" state.
638    /// - **Purpose**: To explicitly represent an unchecked checkbox or unselected radio button.
639    /// - **Example**: An unchecked checkbox that the user has not yet ticked.
640    CheckedFalse,
641
642    /// The element's content cannot be edited by the user.
643    /// - **Purpose**: To indicate that the element's value can be viewed and copied, but not
644    ///   modified.
645    /// - **When to use**: For display-only text fields or documents.
646    /// - **Example**: A text box displaying a license agreement that the user can scroll through
647    ///   but cannot edit.
648    Readonly,
649
650    /// The element is the default action in a dialog or form.
651    /// - **Purpose**: To identify the button that will be activated if the user presses the Enter
652    ///   key.
653    /// - **When to use**: For the primary confirmation button in a dialog.
654    /// - **Example**: The "OK" button in a dialog box, which often has a thicker or colored
655    ///   border.
656    Default,
657
658    /// The element is expanded, showing its child items.
659    /// - **Purpose**: To indicate that a collapsible element is currently open and its contents
660    ///   are visible.
661    /// - **When to use**: For tree view nodes, combo boxes with their lists open, or expanded
662    ///   accordion panels.
663    /// - **Example**: A folder in a file explorer's tree view that has been clicked to show its
664    ///   subfolders.
665    Expanded,
666
667    /// The element is collapsed, hiding its child items.
668    /// - **Purpose**: To indicate that a collapsible element is closed and its contents are
669    ///   hidden.
670    /// - **When to use**: The counterpart to `Expanded` for any collapsible UI element.
671    /// - **Example**: A closed folder in a file explorer's tree view, hiding its contents.
672    Collapsed,
673
674    /// The element is busy and cannot respond to user interaction.
675    /// - **Purpose**: To indicate that the element or application is performing an operation and
676    ///   is temporarily unresponsive.
677    /// - **When to use**: When an application is loading, processing data, or otherwise occupied.
678    /// - **Example**: A window that is grayed out and shows a spinning cursor while saving a large
679    ///   file.
680    Busy,
681
682    /// The element is not currently visible on the screen.
683    /// - **Purpose**: To indicate that an element exists but is currently scrolled out of the
684    ///   visible area.
685    /// - **When to use**: For items in a long list or a large document that are not within the
686    ///   current viewport.
687    /// - **Example**: A list item in a long dropdown that you would have to scroll down to see.
688    Offscreen,
689
690    /// The element can accept keyboard focus.
691    /// - **Purpose**: To indicate that the user can navigate to this element using the keyboard
692    ///   (e.g., with the Tab key).
693    /// - **When to use**: On all interactive elements like buttons, links, and input fields,
694    ///   whether they currently have focus or not.
695    /// - **Example**: A button that can receive focus, even if it is not the currently focused
696    ///   element.
697    Focusable,
698
699    /// The element is a container whose children can be selected.
700    /// - **Purpose**: To indicate that the element contains items that can be chosen.
701    /// - **When to use**: On container controls like list boxes, tree views, or text spans where
702    ///   text can be highlighted.
703    /// - **Example**: A list box control is `Selectable`, while its individual list items have the
704    ///   `Selected` state when chosen.
705    Selectable,
706
707    /// The element is a hyperlink.
708    /// - **Purpose**: To identify an object that navigates to another resource or location when
709    ///   activated.
710    /// - **When to use**: On any object that functions as a hyperlink.
711    /// - **Example**: Text or an image that, when clicked, opens a web page.
712    Linked,
713
714    /// The element is a hyperlink that has been visited.
715    /// - **Purpose**: To indicate that a hyperlink has already been followed by the user.
716    /// - **When to use**: On a `Linked` object that the user has previously activated.
717    /// - **Example**: A hyperlink on a web page that has changed color to show it has been
718    ///   visited.
719    Traversed,
720
721    /// The element allows multiple of its children to be selected at once.
722    /// - **Purpose**: To indicate that a container control supports multi-selection.
723    /// - **When to use**: On container controls like list boxes or file explorers that support
724    ///   multiple selections (e.g., with Ctrl-click).
725    /// - **Example**: A file list that allows the user to select several files at once for a copy
726    ///   operation.
727    Multiselectable,
728
729    /// The element contains protected content that should not be read aloud.
730    /// - **Purpose**: To prevent assistive technologies from speaking the content of a sensitive
731    ///   field.
732    /// - **When to use**: Primarily for password input fields.
733    /// - **Example**: A password text box where typed characters are masked with asterisks or
734    ///   dots.
735    Protected,
736}
737
738impl_option!(
739    AccessibilityState,
740    OptionAccessibilityState,
741    [Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash]
742);
743
744impl_vec!(AccessibilityState, AccessibilityStateVec, AccessibilityStateVecDestructor, AccessibilityStateVecDestructorType, AccessibilityStateVecSlice, OptionAccessibilityState);
745impl_vec_clone!(
746    AccessibilityState,
747    AccessibilityStateVec,
748    AccessibilityStateVecDestructor
749);
750impl_vec_debug!(AccessibilityState, AccessibilityStateVec);
751impl_vec_partialeq!(AccessibilityState, AccessibilityStateVec);
752impl_vec_partialord!(AccessibilityState, AccessibilityStateVec);
753impl_vec_eq!(AccessibilityState, AccessibilityStateVec);
754impl_vec_ord!(AccessibilityState, AccessibilityStateVec);
755impl_vec_hash!(AccessibilityState, AccessibilityStateVec);
756
757/// Compact accessibility information for common use cases.
758///
759/// This is a lighter-weight alternative to `AccessibilityInfo` for cases where
760/// only basic accessibility properties are needed. Developers must explicitly
761/// pass `None` if they choose not to provide accessibility information.
762#[derive(Debug, Clone, PartialEq, Eq, Hash)]
763#[repr(C)]
764pub struct SmallAriaInfo {
765    /// Accessible label/name
766    pub label: OptionString,
767    /// Element's role (button, link, etc.)
768    pub role: OptionAccessibilityRole,
769    /// Additional description
770    pub description: OptionString,
771}
772
773impl_option!(
774    SmallAriaInfo,
775    OptionSmallAriaInfo,
776    copy = false,
777    [Debug, Clone, PartialEq, Eq, Hash]
778);
779
780impl SmallAriaInfo {
781    pub fn label<S: Into<AzString>>(text: S) -> Self {
782        Self {
783            label: OptionString::Some(text.into()),
784            role: OptionAccessibilityRole::None,
785            description: OptionString::None,
786        }
787    }
788
789    pub fn with_role(mut self, role: AccessibilityRole) -> Self {
790        self.role = OptionAccessibilityRole::Some(role);
791        self
792    }
793
794    pub fn with_description<S: Into<AzString>>(mut self, desc: S) -> Self {
795        self.description = OptionString::Some(desc.into());
796        self
797    }
798
799    /// Convert to full `AccessibilityInfo`
800    pub fn to_full_info(&self) -> AccessibilityInfo {
801        AccessibilityInfo {
802            accessibility_name: self.label.clone(),
803            accessibility_value: OptionString::None,
804            description: self.description.clone(),
805            role: match self.role {
806                OptionAccessibilityRole::Some(r) => r,
807                OptionAccessibilityRole::None => AccessibilityRole::Unknown,
808            },
809            states: Vec::new().into(),
810            accelerator: OptionVirtualKeyCodeCombo::None,
811            default_action: OptionString::None,
812            supported_actions: Vec::new().into(),
813            is_live_region: false,
814            labelled_by: OptionDomNodeId::None,
815            described_by: OptionDomNodeId::None,
816        }
817    }
818}
819
820/// Accessibility information for a `<progress>` indicator.
821///
822/// Mirrors HTML's `<progress value max>` plus an `indeterminate` flag for
823/// progress bars whose end is unknown. Maps to `AccessibilityRole::ProgressBar`.
824#[derive(Debug, Clone, PartialEq)]
825#[repr(C)]
826pub struct ProgressAriaInfo {
827    /// Accessible label describing the task being measured.
828    pub label: OptionString,
829    /// Current progress value. `None` for indeterminate progress.
830    pub current_value: OptionF32,
831    /// Maximum value the progress bar can reach. `None` falls back to `1.0`.
832    pub max: OptionF32,
833    /// `true` for spinners / progress with no known endpoint. Overrides `current_value`.
834    pub indeterminate: bool,
835    /// Optional extended description (`aria-describedby` equivalent).
836    pub description: OptionString,
837}
838
839impl_option!(
840    ProgressAriaInfo,
841    OptionProgressAriaInfo,
842    copy = false,
843    [Debug, Clone, PartialEq]
844);
845
846impl ProgressAriaInfo {
847    /// Creates a `ProgressAriaInfo` with only an accessible label.
848    pub fn create(label: AzString) -> Self {
849        Self {
850            label: OptionString::Some(label),
851            current_value: OptionF32::None,
852            max: OptionF32::None,
853            indeterminate: false,
854            description: OptionString::None,
855        }
856    }
857
858    /// Returns a copy with the given current value.
859    pub fn with_current_value(mut self, value: f32) -> Self {
860        self.current_value = OptionF32::Some(value);
861        self
862    }
863
864    /// Returns a copy with the given maximum value.
865    pub fn with_max(mut self, max: f32) -> Self {
866        self.max = OptionF32::Some(max);
867        self
868    }
869
870    /// Returns a copy with the indeterminate flag set.
871    pub fn with_indeterminate(mut self, indeterminate: bool) -> Self {
872        self.indeterminate = indeterminate;
873        self
874    }
875
876    /// Returns a copy with the given description.
877    pub fn with_description(mut self, desc: AzString) -> Self {
878        self.description = OptionString::Some(desc);
879        self
880    }
881
882    /// Convert to full `AccessibilityInfo` so the value can be installed on a node.
883    pub fn to_full_info(&self) -> AccessibilityInfo {
884        let value_string = if self.indeterminate {
885            OptionString::None
886        } else {
887            match self.current_value {
888                OptionF32::Some(v) => OptionString::Some(format!("{}", v).into()),
889                OptionF32::None => OptionString::None,
890            }
891        };
892        AccessibilityInfo {
893            accessibility_name: self.label.clone(),
894            accessibility_value: value_string,
895            description: self.description.clone(),
896            role: AccessibilityRole::ProgressBar,
897            states: Vec::new().into(),
898            accelerator: OptionVirtualKeyCodeCombo::None,
899            default_action: OptionString::None,
900            supported_actions: Vec::new().into(),
901            is_live_region: false,
902            labelled_by: OptionDomNodeId::None,
903            described_by: OptionDomNodeId::None,
904        }
905    }
906}
907
908/// Accessibility information for a `<meter>` gauge.
909///
910/// Unlike `<progress>`, `<meter>` always carries a known `value`/`min`/`max`
911/// triple, so those fields are required at construction time. Maps to
912/// `AccessibilityRole::Indicator`.
913#[derive(Debug, Clone, PartialEq)]
914#[repr(C)]
915pub struct MeterAriaInfo {
916    /// Accessible label describing what the meter measures.
917    pub label: OptionString,
918    /// Current value of the meter (within `[min, max]`).
919    pub current_value: f32,
920    /// Lower bound of the measurement range.
921    pub min: f32,
922    /// Upper bound of the measurement range.
923    pub max: f32,
924    /// Optional "low" threshold (values below this are considered low).
925    pub low: OptionF32,
926    /// Optional "high" threshold (values above this are considered high).
927    pub high: OptionF32,
928    /// Optional optimum value within the range.
929    pub optimum: OptionF32,
930    /// Optional extended description.
931    pub description: OptionString,
932}
933
934impl_option!(
935    MeterAriaInfo,
936    OptionMeterAriaInfo,
937    copy = false,
938    [Debug, Clone, PartialEq]
939);
940
941impl MeterAriaInfo {
942    /// Creates a `MeterAriaInfo` with the required label and value/range triple.
943    pub fn create(label: AzString, current_value: f32, min: f32, max: f32) -> Self {
944        Self {
945            label: OptionString::Some(label),
946            current_value,
947            min,
948            max,
949            low: OptionF32::None,
950            high: OptionF32::None,
951            optimum: OptionF32::None,
952            description: OptionString::None,
953        }
954    }
955
956    /// Returns a copy with the given low threshold.
957    pub fn with_low(mut self, low: f32) -> Self {
958        self.low = OptionF32::Some(low);
959        self
960    }
961
962    /// Returns a copy with the given high threshold.
963    pub fn with_high(mut self, high: f32) -> Self {
964        self.high = OptionF32::Some(high);
965        self
966    }
967
968    /// Returns a copy with the given optimum value.
969    pub fn with_optimum(mut self, optimum: f32) -> Self {
970        self.optimum = OptionF32::Some(optimum);
971        self
972    }
973
974    /// Returns a copy with the given description.
975    pub fn with_description(mut self, desc: AzString) -> Self {
976        self.description = OptionString::Some(desc);
977        self
978    }
979
980    /// Convert to full `AccessibilityInfo` so the value can be installed on a node.
981    pub fn to_full_info(&self) -> AccessibilityInfo {
982        AccessibilityInfo {
983            accessibility_name: self.label.clone(),
984            accessibility_value: OptionString::Some(format!("{}", self.current_value).into()),
985            description: self.description.clone(),
986            role: AccessibilityRole::Indicator,
987            states: Vec::new().into(),
988            accelerator: OptionVirtualKeyCodeCombo::None,
989            default_action: OptionString::None,
990            supported_actions: Vec::new().into(),
991            is_live_region: false,
992            labelled_by: OptionDomNodeId::None,
993            described_by: OptionDomNodeId::None,
994        }
995    }
996}
997
998/// Accessibility information for a `<dialog>` element.
999///
1000/// Captures the modal/non-modal distinction and a reference to a separate
1001/// node that describes the dialog (`aria-describedby`). The `role` defaults
1002/// to `AccessibilityRole::Dialog` but can be overridden (e.g., for alert
1003/// dialogs).
1004#[derive(Debug, Clone, PartialEq)]
1005#[repr(C)]
1006pub struct DialogAriaInfo {
1007    /// Accessible label / title for the dialog.
1008    pub label: OptionString,
1009    /// Optional ID of another node that describes the dialog content.
1010    pub described_by: OptionString,
1011    /// Optional inline description.
1012    pub description: OptionString,
1013    /// Role for the dialog. Defaults to `Dialog`; use `Alert` for urgent dialogs.
1014    pub role: AccessibilityRole,
1015    /// `true` if the dialog is modal (focus trapped, background inert).
1016    pub modal: bool,
1017}
1018
1019impl_option!(
1020    DialogAriaInfo,
1021    OptionDialogAriaInfo,
1022    copy = false,
1023    [Debug, Clone, PartialEq]
1024);
1025
1026impl DialogAriaInfo {
1027    /// Creates a `DialogAriaInfo` with the given accessible label. Defaults
1028    /// to a non-modal dialog with role `Dialog`.
1029    pub fn create(label: AzString) -> Self {
1030        Self {
1031            label: OptionString::Some(label),
1032            modal: false,
1033            described_by: OptionString::None,
1034            role: AccessibilityRole::Dialog,
1035            description: OptionString::None,
1036        }
1037    }
1038
1039    /// Returns a copy with the given modality flag.
1040    pub fn with_modal(mut self, modal: bool) -> Self {
1041        self.modal = modal;
1042        self
1043    }
1044
1045    /// Returns a copy with `aria-describedby` pointing at the given node ID.
1046    pub fn with_described_by(mut self, described_by: AzString) -> Self {
1047        self.described_by = OptionString::Some(described_by);
1048        self
1049    }
1050
1051    /// Returns a copy with the given role (defaults to `Dialog`).
1052    pub fn with_role(mut self, role: AccessibilityRole) -> Self {
1053        self.role = role;
1054        self
1055    }
1056
1057    /// Returns a copy with the given inline description.
1058    pub fn with_description(mut self, desc: AzString) -> Self {
1059        self.description = OptionString::Some(desc);
1060        self
1061    }
1062
1063    /// Convert to full `AccessibilityInfo` so the value can be installed on a node.
1064    pub fn to_full_info(&self) -> AccessibilityInfo {
1065        AccessibilityInfo {
1066            accessibility_name: self.label.clone(),
1067            accessibility_value: OptionString::None,
1068            description: self.description.clone(),
1069            role: self.role,
1070            states: Vec::new().into(),
1071            accelerator: OptionVirtualKeyCodeCombo::None,
1072            default_action: OptionString::None,
1073            supported_actions: Vec::new().into(),
1074            is_live_region: false,
1075            labelled_by: OptionDomNodeId::None,
1076            described_by: OptionDomNodeId::None,
1077        }
1078    }
1079}