Skip to content

feat(windows): expose a localized switch type and ScrollPattern - #816

Open
sena-nana wants to merge 1 commit into
AccessKit:mainfrom
sena-nana:windows-switch-localized-type-and-scroll-pattern
Open

sena-nana wants to merge 1 commit into
AccessKit:mainfrom
sena-nana:windows-switch-localized-type-and-scroll-pattern

Conversation

@sena-nana

@sena-nana sena-nana commented Oct 7, 2026 •

Copy link
Copy Markdown

Summary

This pull request was implemented by an AI agent (Agent).

Role::Switch stays a UI Automation Button because classic UI Automation has no Switch control type. The localized control type is switch, so a screen reader can announce a switch instead of only a button. ScrollPattern is implemented from existing scroll offsets and directional actions so assistive technology can scroll the container, not only ScrollIntoView.

Localized control type

role_description remains the localization hook (aria-roledescription). When a node sets it, that string is still the localized control type. The Windows adapter has no string catalog of its own. For Role::Switch with no role_description, the localized control type is the English token switch, the same string this adapter already returns as the ARIA role. A toolkit that has a translated name can set role_description. This change does not invent a translated control type or a new UIA control type.

ScrollPattern

The shared schema already has scroll_x / scroll_y (with min and max), Action::ScrollUp, ScrollDown, ScrollLeft, and ScrollRight with ActionData::ScrollUnit, and Action::SetScrollOffset. No parallel event protocol was added.

  • Scroll percent is (current - min) / (max - min) * 100, or UIA_ScrollPatternNoScroll when that axis has no range.
  • View size treats the node's own bounds as the viewport and scroll_*_max - scroll_*_min as the hidden remainder: 100 * viewport / (viewport + range). There is no separate viewport field in the schema. If the bounds or the range are missing, the view size is reported as 100 rather than inventing a content size.
  • IScrollProvider::Scroll maps ScrollAmount onto the existing directional actions. Small amounts use ScrollUnit::Item and large amounts use ScrollUnit::Page. Increment moves toward a larger scroll offset.
  • SetScrollPercent maps to Action::SetScrollOffset when that action is supported. UIA_ScrollPatternNoScroll (-1) leaves that axis unchanged. If the node does not support SetScrollOffset, the call returns UIA_E_NOTSUPPORTED.

The pattern is exposed when an axis has a positive scroll range or a directional scroll action. That includes Role::ScrollView and other roles that carry the same fields, such as a list. Action::ScrollIntoView by itself still only enables ScrollItemPattern.

Verification

cargo test -p accesskit_windows -- --test-threads=1: 19 passed, 0 failed, including window tests tests::simple::has_native_uia, navigation, focus, and tests::subclassed::has_native_uia, double_instantiate.

cargo clippy -p accesskit_windows --all-targets -- -D warnings: no warnings.

NVDA 2026.1.1, eSpeak NG 1.52.0, spoken lines: Speaking ['Night mode', 'toggle button', 'not pressed']; Speaking ['Inbox offset 40']; Speaking ['Inbox offset 100']. UIA control type remained Button (50000). Localized control type was switch. Scroll(NoAmount, SmallIncrement) moved vertical percent 0 to 20 (offset 40). SetScrollPercent(NoScroll, 50) set offset 100 and vertical percent 50.

Narrator speech history: AccessKitSwitchScroll 区域, Night mode, switch, 关闭 and Inbox offset 0. Narrator used the localized control type switch. NVDA and Narrator were quit afterward.

If this implementation style does not match project requirements, maintainers can ask for changes and the author will update the pull request, or they can close the pull request directly. Either outcome is fine.

Classic UI Automation has no Switch control type, and the Windows adapter did not implement IScrollProvider for the scroll fields the schema already defines.

Co-authored-by: Cursor <cursoragent@cursor.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant