Skip to content

Add a controller-accessible Quit option to the Gameplay menu - #1255

Open
bronze-ff wants to merge 3 commits into
NotRexed:mainfrom
bronze-ff:feat/controller-quit-menu
Open

bronze-ff wants to merge 3 commits into
NotRexed:mainfrom
bronze-ff:feat/controller-quit-menu

Conversation

@bronze-ff

Copy link
Copy Markdown
Contributor

Add a Quit row to the Insert menu's Gameplay tab. The first activation shows Confirm. A second activation closes the game through the normal window-close path. B or Esc cancels the confirmation. The same action is available with Enter and mouse clicks.

This addresses the in-menu exit requested in #1203 and tracked in #1007.

Validation

  • Built from source and ran the game on CachyOS with Hyprland/Wayland, SDL3, and an RTX 5060.
  • Used a virtual USB Xbox Series controller through Linux uinput. View + Menu opened the overlay, RB selected Gameplay, and the D-pad selected Quit. Holding A left the game running with Confirm displayed. B cancelled it. Two separate A presses then closed the game with exit code 0 through the normal window-close handler.
  • Passed the three focused source regressions for menu hit testing, the rumble menu, and background input on Linux. Steam Game Mode and a physical controller still need a hardware check.

Assisted by OpenAI Codex.

bronze-ff and others added 2 commits November 9, 2026 15:58
Assisted-by: OpenAI Codex
Co-Authored-By: OpenAI Codex <codex@openai.com>
…t-menu

# Conflicts:
#	gpu/vk/vk_menu.cpp
#	host/posix/display_sdl.c
@hckrman101

Copy link
Copy Markdown
Collaborator

Ah I was also going to add this. Can we also add a 'Restart' option?

@hckrman101 hckrman101 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nice, this is a clean reuse of the existing close path. It posts WM_CLOSE to the window, which goes through rx_close_asked() and hos_window_closed_exit() just like the X button (and like Restart now, minus the relaunch). That also works on Windows with no extra change, since display.c already handles WM_CLOSE. The new Row line fits main's Row layout, the confirm state is cleared on B/Esc, on moving off the row, switching tab and closing the menu, and nothing touches the ini or presets. CI is green and it merges cleanly.

Two small nits, nothing blocking:

  • Restart now calls save() and pipeline_cache_save(true) before it posts its message. Quit goes straight to WM_CLOSE. If the normal window close already covers that, fine, but it is worth a quick look.
  • kQuitRow = kCheatsRow - 1 relies on Quit staying right before Cheats in the table. A comment or a static_assert on the row name would keep a later reorder from silently moving it.

Comment thread gpu/vk/vk_menu.cpp
if (press[7] && quit_selected) {
if (mine && !press[5]) {
if (quit_pending) {
if (const HWND window = app_window()) PostMessageA(window, WM_CLOSE, 0, 0);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Restart now does save() + pipeline_cache_save(true) before posting its message. Does the plain WM_CLOSE path already cover that, or should Quit do the same here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch, it doesn't. The plain close only runs rx_close_asked(), which stops a shader preparation still under way, and then hos_window_closed_exit() exits. Nothing forces the pipeline cache, so it is only written by the every-300-presents save in vk_replay.cpp. Settings were already safe, since set_row saves each change.

a7b27de makes Quit call save() and pipeline_cache_save(true) before WM_CLOSE, the same as Restart now. On CachyOS, mkw_vk_pipelines.bin was rewritten in the same second as the Quit exit.

Review of NotRexed#1255: the window's own close (rx_close_asked, then
hos_window_closed_exit) does not force the pipeline cache, so Quit now calls
save() and pipeline_cache_save(true) before posting WM_CLOSE, as the restart
question's Restart now does. A comment by the table says Quit and Cheats
stay its last two rows, since kQuitRow and kCheatsRow count back from its
end (rows[] is not constexpr, so a static_assert on the name cannot check it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bronze-ff

Copy link
Copy Markdown
Contributor Author

Thanks for the review! Both points are in a7b27de:

  • Saving first: Quit now does save() and pipeline_cache_save(true) before WM_CLOSE, the same as Restart now. Details are in the inline thread.
  • Row order: a static_assert on the name won't compile here, because rows[] isn't constexpr (its rows point at opts). A comment by the table now says Quit and Cheats stay its last two rows, since kQuitRow and kCheatsRow count back from its end.

Re-tested on CachyOS (RTX 5060, Hyprland) with a virtual Xbox Series controller, on a build of main a1c4bcd plus this branch. The menu tests pass (test_menu_hit, test_menu_restart, test_rumble_menu, test_input_background). In the game, View + Menu, RB and D-pad up reach Quit. Holding A shows Confirm without quitting, B cancels, and A twice exits with code 0.

About the Restart option you asked for: I'll send it as a separate PR, since CONTRIBUTING asks for one topic per pull request. It will reuse the same confirm step and the restart question's Restart now path (WM_APP + 9).

@bronze-ff

Copy link
Copy Markdown
Contributor Author

The Restart option is now #1266. It is built on this branch, and only its last commit is new.

@hckrman101 hckrman101 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks, both covered: Quit now saves the settings and forces the pipeline cache before closing, like Restart now, and the comment by the table pins the row order. LGTM.

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.

2 participants