Skip to content

pcsx2-qt: Add buddies and tabstops#13388

Merged
F0bes merged 1 commit intoPCSX2:masterfrom
TheTechnician27:screen-reader
Oct 21, 2025
Merged

pcsx2-qt: Add buddies and tabstops#13388
F0bes merged 1 commit intoPCSX2:masterfrom
TheTechnician27:screen-reader

Conversation

@TheTechnician27
Copy link
Copy Markdown
Contributor

Description of Changes

Adds buddies and tabstops to interactive elements in the Qt UI for accessibility, polish, and consistency.

Rationale behind Changes

Buddies

Buddies are a property in Qt which associate a label with an interactive element. For example, if I have a UI looking like label1: [spinbox1], Qt will associate spinbox1 with label1 when label1 is given spinbox1 as its buddy. This is transparent for most users, but for users with a screen reader, this means you can actually tell what an interactive element does. It's a win for accessibility with minimal maintenance overhead and arguably better self-documentation.

Currently, for example, focusing a spinbox will just say that you've focused a spinbox without saying what it's supposed to be for – rendering much of our UI totally unusable. With a buddy, it will read out the label on top of the element type. As an example, with buddies, the OSD scale option will read approximately as "OSD Scale: Spin Box 100", but without, it will only read "Spin Box 100". There is no way to focus the labels either, so it's unlikely they can be read out without buddies.

These are easy to follow in the raw XML, and the Qt Widgets Designer has an easy interface for them under Edit > Edit Buddies.

image image

Tabstops

Tabstops are another property of Qt which allows an explicit ordering of elements when tabbing through a widget (i.e. focusing on one element then pressing Tab). Without them, the tab order is subject to the physical ordering of the elements in XML, which 1) does not inherently correspond to the row/column order displayed and 2) is highly chaotic and unrealistic to maintain, especially when a file is run through the Qt Widgets Designer.

Currently, tab orders in almost every menu are complete nonsense (see e.g. the global controller settings, various settings menus, etc.), which is a problem for both accessibility and polish.

These are trivial to understand in the raw XML, because they're represented as one singular list, and the Qt Widgets Designer has an easy interface for them under Edit > Edit Tab Order.

image image

I chose the Graphics Display widget at random. Here is the current tab ordering without tabstops:

image

Suggested Testing Steps

  • Make sure on each page with interactive elements that tabbing through is consistent and sensible.
  • Make sure when using a screen reader that interactive elements with a label are read out.

Did you use AI to help find, test, or implement this issue or feature?

No.

Comment thread pcsx2-qt/Settings/DEV9SettingsWidget.ui Outdated
@kamfretoz
Copy link
Copy Markdown
Contributor

There seems to be a gap between Show FPS and Show FPS on the check boxes of the OSD Settings.

image

@TheTechnician27
Copy link
Copy Markdown
Contributor Author

There seems to be a gap between Show FPS and Show FPS on the check boxes of the OSD Settings.

image

This is a screenshot of current master. I know what causes this and what fixes it, and a very easy fix was in a larger WiP PR that I decided to subdivide into this, #13367, and at least one or two more future PRs. I can fix it in this PR if people want that (it's just an issue of row number in the Qt XML), but it was left in this state intentionally to segregate buddies and tabstops from other UI changes that I intend to make in upcoming PRs.

Copy link
Copy Markdown
Contributor

@TheLastRar TheLastRar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default tab is now correct in Ethernet settings panel

Copy link
Copy Markdown
Contributor

@TheLastRar TheLastRar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the Graphics panel, the tab menu is the last thing you can tab to
This is unchanged from master, but I wonder if that can be resolved.

In the Audio panel, Standard Volume is tabbed to after FF volume, this should be the other way around (as is the case in Master).

In the HDD settings, I can't easily tab into the HDD section.
On Master, I can't tab into to the DHCP section easily (but can to the HDD section), so Idk what's going on, maybe Qt is having issues here.

Not everything was tested.
Aside from above, what I did test had improved tabbing order.

@TheTechnician27
Copy link
Copy Markdown
Contributor Author

TheTechnician27 commented Oct 19, 2025

In the Graphics panel, the tab menu is the last thing you can tab to This is unchanged from master, but I wonder if that can be resolved.

I looked into this one, but I think that would have to be done dynamically in the code rather than statically in the .ui files. I could be wrong, but I think the XML files are totally blind to those tabs.

In the Audio panel, Standard Volume is tabbed to after FF volume, this should be the other way around (as is the case in Master).

image image

I can actually reproduce this one, and I'm realizing the bug never showed up on my end because the GitHub artifact is treating these UI elements as "volume" and "resetVolume" rather than the new "standardVolume" and "resetStandardVolume" from #13316. I will push a fix shortly. I have now fixed this by rebasing and conforming the buddy and tabstops to the new IDs.

In the HDD settings, I can't easily tab into the HDD section. On Master, I can't tab into to the DHCP section easily (but can to the HDD section), so Idk what's going on, maybe Qt is having issues here.

Yeah, basically what's happening here is that in other panels like the Graphics settings, we have separate Qt .ui files for each tab (e.g. display, advanced). The DEV9 panel is the one case where we don't; the two tabs are in the same file. Qt has odd behavior where the tab ordering doesn't properly account for whether you have tabs (it's just a static, linear list), and so if your tabs "go into" the other tab, they more or less disappear into a black hole.

The options here were to 1) map the tabstops to header, then tab 1, then tab 2, then HDD footer knowing this is the "correct" mapping or 2) assume a most likely case of a user staying on the first tab and map an "incorrect" order of header, then tab 1, then HDD footer, then tab 2. (A nuclear option 3 is to turn them into separate .ui files like we do in Graphics and Debug.)

@TheTechnician27 TheTechnician27 force-pushed the screen-reader branch 2 times, most recently from 3065043 to d083a7a Compare October 19, 2025 21:23
@TheLastRar
Copy link
Copy Markdown
Contributor

In the Graphics panel, the tab menu is the last thing you can tab to This is unchanged from master, but I wonder if that can be resolved.

I looked into this one, but I think that would have to be done dynamically in the code rather than statically in the .ui files. I could be wrong, but I think the XML files are totally blind to those tabs.

Okay, that might be tricky, as is if fine for now.

I can actually reproduce this one, and I'm realizing the bug never showed up on my end because the GitHub artifact is treating these UI elements as "volume" and "resetVolume" rather than the new "standardVolume" and "resetStandardVolume" from #13316. I will push a fix shortly. I have now fixed this by rebasing and conforming the buddy and tabstops to the new IDs.

Can confirm, this is fixed.

The options here were to 1) map the tabstops to header, then tab 1, then tab 2, then HDD footer knowing this is the "correct" mapping or 2) assume a most likely case of a user staying on the first tab and map an "incorrect" order of header, then tab 1, then HDD footer, then tab 2. (A nuclear option 3 is to turn them into separate .ui files like we do in Graphics and Debug.)

Okay so it's a Qt issue then
I suspect option 2 might be more user friendly, but would be wrong if Qt ever fixes the issue.
The nuclear option is best but probably out of scope here.

Comment thread pcsx2-qt/Settings/AudioExpansionSettingsDialog.ui
Comment thread pcsx2-qt/Settings/ControllerLEDSettingsDialog.ui Outdated
Comment thread pcsx2-qt/Settings/MemoryCardConvertDialog.ui
Comment thread pcsx2-qt/Settings/MemoryCardCreateDialog.ui
Comment thread pcsx2-qt/Settings/USBBindingWidget_DrivingForce.ui
Comment thread pcsx2-qt/SetupWizardDialog.ui
Comment thread pcsx2-qt/Tools/InputRecording/InputRecordingViewer.ui
Comment thread pcsx2-qt/Tools/InputRecording/NewInputRecordingDlg.ui
Comment thread pcsx2-qt/Debugger/Docking/LayoutEditorDialog.ui Outdated
Comment thread pcsx2-qt/Settings/ControllerMouseSettingsDialog.ui
Comment thread pcsx2-qt/Debugger/AnalysisOptionsDialog.ui Outdated
@F0bes F0bes merged commit 51bc6c1 into PCSX2:master Oct 21, 2025
12 checks passed
@TheTechnician27 TheTechnician27 deleted the screen-reader branch October 21, 2025 23:54
Hancock33 added a commit to Hancock33/batocera.piboy that referenced this pull request Oct 26, 2025
------------------------------------------------------------------------------------------
dolphin-emu.mk 06b4c89c518e16c6aa19c2c52a2d96f6e056eb50 # Version: Commits on Oct 22, 2025
------------------------------------------------------------------------------------------
Merge pull request #14024 from cobalt2727/patch-5

DolphinQt: explicitly include QAction for building with older QT6 libs,

-----------------------------------------------------------------------------------
eden.mk 05c721bb41c490dcb7e0396052e57590100229ef # Version: Commits on Oct 22, 2025
-----------------------------------------------------------------------------------
[compat] fix libusb when disabled error (solaris, fbsd, etc) (#2649)

----------------------------------------------------
pcsx2.mk v2.5.241 # Version: Commits on Oct 21, 2025
----------------------------------------------------
- [pcsx2-qt: Add buddies and tabstops](PCSX2/pcsx2#13388)

-------------------------------------------------------------------------------------
ppsspp.mk 28790c19af7ddfa822c4152a3cae4a7fb6c06bc7 # Version: Commits on Oct 22, 2025
-------------------------------------------------------------------------------------
Merge pull request #20912 from hrydgard/ios-portrait-support

iOS portrait mode support,

------------------------------------------------------------------------------------
rpcs3.mk 311e7a99923b6e274279d7db6a879e21f3044039 # Version: Commits on Oct 22, 2025
------------------------------------------------------------------------------------
vk: Make best-effort attempt to utilize the low-latency pool,

-----------------------------------------------------
ryujinx.mk 1.3.183 # Version: Commits on Oct 22, 2025
-----------------------------------------------------
Canary-1.3.183

--------------------------------------------------------------------------------------
tsugaru.mk 2af2c703674aca86d2fc905f066391e06cb1f786 # Version: Commits on Oct 21, 2025
--------------------------------------------------------------------------------------
This time I think I really fixed it.,

-------------------------------------------------
vice.mk r45798 # Version: Commits on Oct 21, 2025
-------------------------------------------------
added glob support

git-svn-id: https://svn.code.sf.net/p/vice-emu/code/trunk@45798 379a1393-f5fb-40a0-bcee-ef074d9b53f7,

-------------------------------------------------------------------------------------
ikemen.mk 09115aa8c67650e38f357b3997fe98715237f90a # Version: Commits on Oct 22, 2025
-------------------------------------------------------------------------------------
Merge pull request #2828 from ikemen-engine/feat2

feat: prefer runtime defaultConfig.ini, fallback to embedded,

---------------------------------------------------------------
ruffle.mk nightly-2025-10-22 # Version: Commits on Oct 22, 2025
---------------------------------------------------------------
## What's Changed

* build(deps-dev): bump @types/firefox-webext-browser from 120.0.5 to 143.0.0 in /web by @dependabot[bot] in ruffle-rs/ruffle#21975

* build(deps-dev): bump the npm-minor group across 1 directory with 6 updates by @dependabot[bot] in ruffle-rs/ruffle#21984

* build(deps): bump the cargo-minor group across 1 directory with 8 updates by @dependabot[bot] in ruffle-rs/ruffle#21987

**Full Changelog**: ruffle-rs/ruffle@nightly-2025-10-21...nightly-2025-10-22,

------------------------------------------------------------------------------------
box64.mk 1cd7edf172fe24c914590fd19f1d6b477927ae66 # Version: Commits on Oct 22, 2025
------------------------------------------------------------------------------------
[LA64_DYNAREC] Add more ops. (#3091)

For steam.

1E/1F  PUSH/POP DS

AC/AD  REP LODSB/LODSD

66.A1/A3  MOV EAX,0d, MOV 0d, EAX

Co-authored-by: phorcys <phorcys02@126.com>,

-------------------------------------------------------------------------------------------
jazz2-native.mk bd5ed517ed34219bd7741146df605b7863b6a14f # Version: Commits on Oct 22, 2025
-------------------------------------------------------------------------------------------
Big endian, removed debug messages,

---------------------------------------------------------------------------------------
mangohud.mk 5399bf1a184ce41ff55125e4a24b978392025d24 # Version: Commits on Oct 16, 2025
---------------------------------------------------------------------------------------
FEX: Update FEX stats semantics.

FEX updated some [guarantees](FEX-Emu/FEX#4984)

to enforce 16-byte size alignment of the thread stats, and introduced a

new variable for declaring the size of the struct.

This codifies the guarantee that the fex struct will stay 16-byte

aligned sizes, so we get ARM's single-copy atomicity guarantees, and if

FEX decides to add new members to the struct then things won't suddenly

break.

FEX can't guarantee that the API isn't going to break, but it is going

to attempt only adding values to the end as new values get added, so it

is less likely.

A minor change to the `atomic_copy_thread_stats` function as well to

ensure we're taking avantage of that single-copy atomicity.,

------------------------------------------------------
cbindgen.mk v0.29.2 # Version: Commits on Oct 21, 2025
------------------------------------------------------
Explicitly request serde's std features to avoid issues with newer toml versions.

Update serde while at it. Fixes #1114,

----------------------------------------------------------------------------------------
retroarch.mk d43a6410c6aa810ac779d4c1f2f155d202619367 # Version: Commits on Oct 22, 2025
----------------------------------------------------------------------------------------
Use app-specific storage for Google Play versions of the Android app (#18321),

----------------------------------------------------------------------------------------
doomretro.mk a04efb6efefaa9415b45c27830aaa6bf46a1914d # Version: Commits on Oct 22, 2025
----------------------------------------------------------------------------------------
Fix STEP2 texture, etc.

Also check for TEKWALL1 again.,

-----------------------------------------------------------------------------------
tr1x.mk ccc35f7c60de956564d7dd4173f26f0d39173e34 # Version: Commits on Oct 22, 2025
-----------------------------------------------------------------------------------
option/passport: add mode selection to play any level,

-----------------------------------------------------------------------------------
tr2x.mk ccc35f7c60de956564d7dd4173f26f0d39173e34 # Version: Commits on Oct 22, 2025
-----------------------------------------------------------------------------------
option/passport: add mode selection to play any level,

----------------------------------------------------------------------------------------------
libretro-ppsspp.mk 28790c19af7ddfa822c4152a3cae4a7fb6c06bc7 # Version: Commits on Oct 22, 2025
----------------------------------------------------------------------------------------------
Merge pull request #20912 from hrydgard/ios-portrait-support

iOS portrait mode support,
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants