fix: keep the game running behind the Steam menu and QAM, as on a Steam Deck

This commit is contained in:
xXJsonDeruloXx committed 2026-10-01 14:31:30 -04:00
1 parent 11d997dc65
commit 0a58a7faee
3 files changed
+79

No files matched your search

+7
View File
@@ -39,5 +39,12 @@ library list, before anything is published.
then focus is handed over again. `GAMESCOPE_RESTORE_FOCUS_WINDOW` on the root window asks for the
same restore from outside (the session script's resume watcher).
- `0113-steam-overlay-keeps-game-keyboard-focus.patch` - this app: the Steam client opens the Quick
Access Menu and Steam menu over a game with `STEAM_INPUT_FOCUS` 1, which moves X keyboard focus to
its overlay; wine then deactivates the game and a fullscreen game minimizes itself, freezing
behind the menu instead of running on as on a Steam Deck. Steam's own overlay taking input now
keeps keyboard focus on the game, as mode 2 does; its input comes from the controller through
Steam Input, not the X keyboard.
Sixteen more of Armada's patches are DRM/lease/HDR-on-KMS work for a native display, which this
app's Wayland-hosted gamescope never reaches, or need a newer gamescope than the runtime has.
@@ -0,0 +1,70 @@
From: DroidDeck
Subject: [PATCH] steamcompmgr: keep the game's keyboard focus under Steam's overlay
The Steam client opens its Quick Access Menu and Steam menu over a game by setting
STEAM_OVERLAY 1 and STEAM_INPUT_FOCUS 1 on its window. Mode 1 moves X keyboard focus to the
overlay, so the game's window gets FocusOut: wine moves the foreground to the desktop, a fullscreen
game deactivates and minimizes itself (WM_CHANGE_STATE IconicState), and it stops rendering behind
the menu - frozen, all threads asleep, until the menu closes (Alan Wake's American Nightmare,
Proton Experimental ARM64). On a Steam Deck the game runs on behind the menu.
Mode 2 already means "input to the overlay, keyboard focus stays on the focus window". Treat
Steam's own overlay taking input in mode 1 the same way at the three places mode 2 is honoured.
The overlay's input does not need X keyboard focus: the controller drives it through Steam Input.
Measured by rewriting the property to 2 by hand: the game kept running behind the menu and the
controller still moved only the menu.
diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp
index 372a82c..f870974 100644
--- a/src/steamcompmgr.cpp
+++ b/src/steamcompmgr.cpp
@@ -1321,6 +1321,22 @@ window_is_steam( steamcompmgr_win_t *w )
return w && ( w->isSteamLegacyBigPicture || w->appID == 769 );
}
+// Whether keyboard focus stays on the focus window while this window has input focus.
+// STEAM_INPUT_FOCUS 2 asks for that. The Steam client also opens its Quick Access Menu and Steam
+// menu over a game with 1, which moves X keyboard focus to the overlay: wine then deactivates the
+// game, a fullscreen game minimizes itself, and it froze behind the menu instead of running on as
+// on a Steam Deck. The overlay's own input does not need X keyboard focus (the controller drives
+// it through Steam Input), so Steam's overlay keeps the game's keyboard focus too.
+static bool
+window_keeps_game_keyboard_focus( steamcompmgr_win_t *w )
+{
+ if ( !w )
+ return false;
+ if ( w->inputFocusMode == 2 )
+ return true;
+ return w->inputFocusMode == 1 && w->isOverlay && window_is_steam( w );
+}
+
static bool
window_is_vr_scene_app( steamcompmgr_win_t *w )
{
@@ -4728,7 +4744,7 @@ void xwayland_ctx_t::DetermineAndApplyFocus( const std::vector< steamcompmgr_win
if ( gamescope::VirtualConnectorIsSingleOutput() )
{
- if ( inputFocus && inputFocus->inputFocusMode == 2 )
+ if ( window_keeps_game_keyboard_focus( inputFocus ) )
keyboardFocusWin = ctx->focus.focusWindow;
}
else
@@ -5340,7 +5356,7 @@ determine_and_apply_focus( global_focus_t *pFocus )
pFocus->inputFocusMode = pFocus->inputFocusWindow->inputFocusMode;
if ( gamescope::VirtualConnectorIsSingleOutput() &&
- pFocus->inputFocusMode == 2 )
+ window_keeps_game_keyboard_focus( pFocus->inputFocusWindow ) )
{
pFocus->keyboardFocusWindow = pFocus->overrideWindow
? pFocus->overrideWindow
@@ -6485,7 +6501,7 @@ handle_wl_surface_id(xwayland_ctx_t *ctx, steamcompmgr_win_t *w, uint32_t surfac
steamcompmgr_win_t *keyboardFocusWindow = pCurrentFocus->inputFocusWindow;
if ( gamescope::VirtualConnectorIsSingleOutput() &&
- keyboardFocusWindow && keyboardFocusWindow->inputFocusMode == 2 )
+ window_keeps_game_keyboard_focus( keyboardFocusWindow ) )
keyboardFocusWindow = pCurrentFocus->focusWindow;
if ( w == keyboardFocusWindow )
@@ -172,6 +172,8 @@ if [ -z "${BL_INSIDE:-}" ]; then
# HDR10: the app opened its compositor's colour-management gate for this session (BL_HDR=1);
# gamescope then offers HDR to its clients through the same wp_color_manager_v1 it binds on ours.
[ "${BL_HDR:-0}" = 1 ] && args+=(--hdr-enabled)
# Extra gamescope arguments for an experiment (--debug-focus, say), from Download/droiddeck-env.
[ -n "${BL_GAMESCOPE_ARGS:-}" ] && read -r -a _bl_extra <<<"$BL_GAMESCOPE_ARGS" && args+=("${_bl_extra[@]}")
# Deck mode's performance overlay (Quick Access Menu → Performance → Overlay Level) is drawn by
# mangoapp, which gamescope starts beside the client; the client sets the level by rewriting
# MANGOHUD_CONFIGFILE. The apk stages Valve's aarch64 build (tools/mangoapp) - without it the menu