Skip to content

feat(menu): a Display tab for the screen, HDR and overlay rows - #2178

Draft
pmwork-personal wants to merge 13 commits into
NotRexed:mainfrom
pmwork-personal:feat/menu-display-tab
Draft

pmwork-personal wants to merge 13 commits into
NotRexed:mainfrom
pmwork-personal:feat/menu-display-tab

Conversation

@pmwork-personal

@pmwork-personal pmwork-personal commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

The Graphics tab holds both how the picture is made and how it reaches the screen. This gives the screen's rows a tab of
their own, so Graphics is about the picture's quality and cost alone. It is step 2 of the menu organization in #2177
(sections on the Graphics tab), and needs it first.

What changed

  • A Display tab, second in the strip:
  • Graphics keeps the Quality preset, Resolution and upscaling, Frame generation and latency, Detail, and GPU and memory.
  • Moves only: every row's definition is unchanged apart from its tab, so options files carry over and feat: the Insert menu in 13 languages, with Game language and Menu la… #1864's tables
    (keyed by the English text) still find every row. New strings: "Display", "Overlays".
  • The tab strip fits the window. The menu is scaled by the window's height alone, so the strip is as wide in points
    everywhere: six tabs at Large were wider than a 16:10 screen (on the Steam Deck's 1280x800 the Q and E keys fell past
    its edges) and a 4:3 one (already true there with five). New tab_strip_fit: where the titles and their gaps are wider
    than the room between the safe margins and the tab keys, the gaps narrow first, down to 16 points, then the titles
    shrink in proportion; where they fit, nothing changes (every 16:9 screen at Small and Medium, the Deck at Medium).
  • enum MenuTab: TAB_DISPLAY = 1, the tabs after it one up; the Motion and Controls pages follow TAB_COUNT as before.
    scrolled_to starts every slot at -1 (the Controls page's was left at 0 since the Audio tab), with a static_assert so
    the list grows with the slots.
  • The restart line shows on Display too (Ultrawide takes a restart).
  • Main's tuning bar (feat(menu): add compact TV-style tuning bar for live setting tweaks #2378) names a row's tab from the same list (tab_titles, now global): it says Display for these rows.
  • The control socket (feat(control): drive a running game over a local socket, with a CLI #926): bridge_fill's tab names have display in its place, so option_get and option_set tell the
    moved rows' tab as display (they were graphics or gameplay). A script that looks for those rows by tab needs the new
    name; by key (fps_counter, vsync, ...) nothing changes.
  • readme.md: the Display tab's rows under Display in the option table; the sections sentence and the restart note name
    it; the tab list names all six (it still said four, Graphics, Gameplay, Controls and Debug).
  • Tests: test_vsync_row.py finds V-Sync on Display; test_menu_sections.py checks Display's sections and that it is the
    strip's second tab (the shape row by its value, so it holds whether it is named Ultrawide or Aspect ratio); new
    test_tab_strip_fit.py runs the fit over 16:9, 16:10, the Deck, 4:3 and a narrow window at each menu size.

With #2119 (the Aspect ratio row, was Ultrawide): the two touch the same row and its readme line. Whichever lands second
takes the other's: the row reads Aspect ratio, with #2119's help, on Display ▸ Screen. Checked with a merge of the two
branches: those two places conflict, nothing else.

Testing

Not tested: a pad and the mouse in a window (the tab keys and clicks are unchanged code), AMD and Intel, Linux, a real
Steam Deck (its size was tested, not the device).

Screenshots

The Display tab and Graphics after it, 1920x1080, Medium:

Display tab: Screen, HDR and Overlays

Graphics tab: Quality preset, Resolution and upscaling, Frame generation and latency

The strip fitted at Large on the Steam Deck's 1280x800 (the gaps narrower) and on 1440x1080 (the titles a little smaller too):

Display tab at Large, 1280x800

Display tab at Large, 1440x1080

Preview, not this PR: the Display tab with #2119 merged in as well (a local merge of the two branches), the shape row
as Aspect ratio at its new default:

Display tab with #2119: Aspect ratio, Monitor's shape

All from headless runs of builds of this branch (HOS_HEADLESS=1, RX_VK_SHOT_MENU=1, the keys from
RX_VK_MENU_SCRIPT), RTX 5090, built with HOOKSHOT_VERSION=v2.2.0-rc.1 for a release's build label.

🤖 Generated with Claude Code

pmwork-personal and others added 2 commits November 10, 2026 23:46
The Graphics tab is one list of 24 settings, with the window, HDR, upscaling,
frame generation and GPU options mixed together, and more are on their way in
open PRs. Its rows now sit under section titles, heading rows like the Debug
tab's Developer: the Quality preset first, then Resolution and upscaling,
Frame generation and latency, Screen, HDR, Detail, and GPU and memory last.

Moves only: every row's definition is unchanged, so saved options and saved
keys carry over. The menu already draws heading rows on any tab and the keys,
the pad and the mouse step over them, so no drawing or input code changes.

- readme.md: a sentence on the sections; the option table in the new order.
- tests/test_upscaler_rows.py: the order list follows the picture's path
  (output, upscaler, render size, sharpening, then the frame rows, then the
  window).
- tests/test_menu_sections.py (new): the Graphics sections and the rows they
  hold, and on every tab no section that row_shown could leave empty.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Graphics tab held both how the picture is made and how it reaches the
screen. The rows about the screen now have a tab of their own, second in the
strip: Display, with the Screen and HDR sections from Graphics (Fullscreen,
V-Sync, Window scaling filter, Ultrawide, Ultrawide menus; HDR and its paper
white and peak brightness) and a new Overlays section with the FPS counter
and Menu size from Gameplay. Graphics keeps the Quality preset, Resolution
and upscaling, Frame generation and latency, Detail, and GPU and memory.

Moves only: every row's definition is unchanged apart from its tab, so saved
options keep working.

The tab strip fits the window: the menu is scaled by the window's height
alone, so six tabs at Large were wider than a 16:10 screen (the Steam Deck's
1280x800 put the Q and E keys past its edges) and a 4:3 one (already so with
five). tab_strip_fit narrows the gaps between the titles first, down to 16
points, then shrinks the titles; where they fit, nothing changes.

- enum MenuTab: TAB_DISPLAY = 1, the tabs after it one up; the Motion and
  Controls pages follow TAB_COUNT as before. scrolled_to starts every slot at
  -1 (the Controls page's slot was left at 0 since the Audio tab), with a
  static_assert to keep the list as long as the slots.
- The restart line shows on Display too (Ultrawide takes a restart).
- readme.md: the Display tab's rows under Display in the option table; the
  sections sentence and the restart note name the tab.
- tests: test_vsync_row.py finds V-Sync on Display; test_menu_sections.py
  checks Display's sections and that it is the strip's second tab (the shape
  row by its value); test_tab_strip_fit.py (new) runs the fit over 16:9,
  16:10, the Deck, 4:3 and a narrow window at each menu size.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pmwork-personal and others added 10 commits November 11, 2026 11:00
# Conflicts:
#	gpu/vk/vk_menu.cpp
#	readme.md
# Conflicts:
#	gpu/vk/vk_menu.cpp
#	readme.md
NotRexed#926's bridge_fill names each MenuTab by its place in a list, and the list
had no name for TAB_DISPLAY: the static_assert stopped the build. "display"
in its place, so option_get/option_set tell the FPS counter's and the
screen rows' tab as display.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	gpu/vk/vk_menu.cpp
#	tests/test_upscaler_rows.py
# Conflicts:
#	tests/test_menu_sections.py
# Conflicts:
#	gpu/vk/vk_menu.cpp
#	tests/test_menu_sections.py
…2119, NotRexed#2197, NotRexed#2481, NotRexed#2496)

NotRexed#2177 landed (squashed), so this takes main's sections as they shipped and
keeps this PR's change on top: the Screen, HDR and Overlays rows on the
Display tab. Main's newer rows go with them, word for word: NotRexed#2119's Aspect
ratio and Ultrawide menus text and NotRexed#2481's HDR tone mapper (last in Display's
HDR). Every one of main's 88 rows keeps main's definition; the only changes
are the moved rows' tab and the Overlays heading. draw_options keeps main's
Save my pipeline list line (NotRexed#2447) with the restart line on Display too. The
readme takes main's Menu shortcut text (NotRexed#2197) with six tabs, NotRexed#2177's VRAM
budget line, and main's HDR tone mapper and Field of view lines.
test_menu_sections.py pins Aspect ratio by name and HDR tone mapper in
Display's HDR; test_scene_tonemap_pass.py (NotRexed#2481) finds the tone mapper row on Display.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pmwork-personal added a commit to pmwork-personal/Hookshot-pr that referenced this pull request Nov 11, 2026
NotRexed#2197, NotRexed#2481, NotRexed#2496) into feat/menu-game-tab

Takes NotRexed#2178 as merged with main (cf90c14f) and keeps this PR's change on
top: the Game tab first, where the menu opens. Main's new Gameplay row,
Field of view, goes with the Game rows at the table's top, word for word,
after Game speed. Every one of main's 88 rows keeps main's definition; the
only changes are the moved rows' tab (Display) and the Overlays heading.
The readme takes main's Menu shortcut text (NotRexed#2197) with this PR's tab
sentence, and Field of view among Game's rows. The tab enum, the strip's
titles and the control bridge's names follow the same Game-first order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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