Skip to content

Let a button be exposed as a page tab - #348

Open
rezabakhshilaktasaraei wants to merge 4 commits into
desktop-app:masterfrom
rezabakhshilaktasaraei:button-page-tab
Open

Let a button be exposed as a page tab#348
rezabakhshilaktasaraei wants to merge 4 commits into
desktop-app:masterfrom
rezabakhshilaktasaraei:button-page-tab

Conversation

@rezabakhshilaktasaraei

@rezabakhshilaktasaraei rezabakhshilaktasaraei commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

A strip of real tab buttons (the forum topic tabs) is named tabs in the UI, so a screen reader should call its items tabs as well. setIsPageTab gives a button the PageTab role, next to the existing setIsListItem, and the accessible container's selection interface accepts those items alongside list items.

The second commit fixes the focus forwarding order that a painted tab strip (Ui::DiscreteSlider in tdesktop) runs into: such a container holds real keyboard focus itself while the browse position moves between its virtual children, so forwarding container focus to the selected item would announce the current tab when the screen reader asked for a merely browsed one. A child reporting focus now wins, with the selection forwarding kept as the fallback. Containers of real widget children are unaffected - a focused child there means the container itself does not have focus.

The last commit adds Ui::ContextMenuPosition, choosing where a context menu opens: at the mouse cursor for a mouse-invoked one, on the control (or on a painted element inside it) for a keyboard-invoked one - the cursor may sit nowhere near the control then, and the position Qt puts into the keyboard event is synthesized from the input method rect, which plain controls leave empty. The tab strips in tdesktop adopt it with one line each.

No bridge-side changes needed: on Windows the Selection / SelectionItem patterns are granted by the selection interface, not the role, so a PageTabList container works the same way a List does.

Used by telegramdesktop/tdesktop#31110 for the topic tabs strip, and verified there with NVDA on Windows 10: the strip announces as a tab control, the items as tabs, with browsing, activation and the selected state unchanged.

Also used by telegramdesktop/tdesktop#31097 for the painted sliders (search result tabs, stickers box tabs and so on), which exposes them as tabs through the same selection interface.

The third commit moves the selection state and selection events of SideBarButton from the list item role to the tab role, for telegramdesktop/tdesktop#31176, which turns the folders sidebar - the only user of that widget - into tabs as well. Testing showed locked (premium) folders read fine as tabs that open the Premium box instead of becoming current, so no strip stays a list anymore.

A strip of real tab buttons (the forum topic tabs) is named tabs in the
UI, so a screen reader should call its items tabs as well. setIsPageTab
gives a button the PageTab role, and the selection interface of the
container accepts those items alongside list items - the Windows bridge
grants the Selection patterns by the interface, not the role, so a
PageTabList container keeps working the same way a List does.
A container with painted children holds real keyboard focus itself
while the browse position moves between them, so forwarding container
focus to the selected item would announce the current item when the
screen reader asked for a merely browsed one. A child reporting focus
now wins; the selection forwarding stays as the fallback.
The selected state and the selection events of SideBarButton were
gated on the list item role, so switching the folders sidebar to tabs
silenced them. The sidebar is the only user of this widget and it is
tabs now, so the gate simply follows the role along.
A menu asked for from the keyboard opens at the mouse cursor at every
call site, which may sit nowhere near the control or outside the
window altogether - and the position Qt puts into the keyboard event
is synthesized from the input method rect, which plain controls leave
empty. The helper anchors a keyboard-invoked menu on the control (or
on a painted element inside it) and keeps the cursor position for a
mouse-invoked one, so call sites can adopt the policy with one line.
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