Force game windows fullscreen: off by default (#276)

A game whose resolution differs from the screen's (DiRT 3 at 1280x720)
fights --force-windows-fullscreen: every forced resize makes it rebuild
its swapchain, and the picture flickers between its own size and the
screen's - often from the first menu, before the player can reach the
game's resolution setting. It also drove the Xwayland dma-buf leak fixed
separately.

The switch stays in Settings > Games and the session drawer, now off
unless turned on; its hint says when to turn it on (a game coming back
small or in a corner after switching apps, e.g. FlatOut) and when to
leave it off (flicker). Users who already set it keep their choice. The
session script's fallback when the app passes nothing is off as well.

Co-authored-by: The412Banner <[email protected]>
This commit is contained in:
The412BannerandThe412Banner authored and GitHub committed 2026-10-05 12:44:45 -04:00
1 parent 0607bb0b3a
commit 9f46c7a50b
4 files changed
+13 -9

No files matched your search

@@ -152,7 +152,7 @@ class MainActivity : ComponentActivity() {
private var showPhantomGate by mutableStateOf(false)
private var directAudio by mutableStateOf(false)
private var clientDirectAudio by mutableStateOf(false)
private var forceFullscreen by mutableStateOf(true)
private var forceFullscreen by mutableStateOf(false)
private var stretch16x9 by mutableStateOf(false)
private var launcherFullscreen by mutableStateOf(true)
private var animationsEnabled by mutableStateOf(true)
@@ -168,9 +168,12 @@ object SessionPrefs {
* Steam only: gamescope makes every game window the size of the screen. A game that resizes
* its own window when it loses focus (FlatOut) otherwise comes back smaller, drawn in a
* corner; a game that sets its own resolution and never looks at its window again (Quake 3)
* instead draws small in the bottom-left of the stretched one. On unless turned off.
* instead draws small in the bottom-left of the stretched one. A game whose resolution differs
* from the screen's (DiRT 3 at 1280x720) fights it: it rebuilds its swapchain on every forced
* resize and the picture flickers between its own size and the screen's, often from the first
* menu, before the player can reach its resolution setting. Off unless turned on.
*/
fun forceFullscreen(context: Context): Boolean = prefs(context).getBoolean("forceFullscreen", true)
fun forceFullscreen(context: Context): Boolean = prefs(context).getBoolean("forceFullscreen", false)
fun setForceFullscreen(context: Context, on: Boolean) {
prefs(context).edit().putBoolean("forceFullscreen", on).apply()
+2 -2
View File
@@ -1039,8 +1039,8 @@
<string name="display_frame_rate">Frame rate</string>
<string name="display_window_compatibility">Game window compatibility</string>
<string name="display_force_fullscreen">Force game windows fullscreen</string>
<string name="display_force_fullscreen_hint">Keeps games fullscreen after focus changes. Turn off if a game draws small. Applies live during a session.</string>
<string name="display_force_fullscreen_live">Keeps games fullscreen after focus changes. Applies live.</string>
<string name="display_force_fullscreen_hint">Makes every game window the size of the screen. Turn on if a game comes back small or in a corner after switching apps; leave off if a game flickers between sizes. Applies live during a session.</string>
<string name="display_force_fullscreen_live">Turn on if a game comes back small after switching; off if it flickers. Applies live.</string>
<string name="display_look_filter">%1$s Sets scaling to %2$s.</string>
<string name="display_match_screen">Match screen (%1$d×%2$d)</string>
<string name="mode_tab_steam">Steam</string>
@@ -179,9 +179,10 @@ if [ -z "${BL_INSIDE:-}" ]; then
[ "$mode" = steam ] && args+=(--default-touch-mode 4)
# A game that resizes its own window when it loses focus (the Steam menu opening over it) comes
# back smaller, and gamescope draws a window that is not flagged fullscreen at its own size in
# the top-left corner. Forcing every window to the output's size keeps it filling the screen.
# BL_GAMESCOPE_FORCE_FULLSCREEN=0 turns it off.
[ "$mode" = steam ] && [ "${BL_GAMESCOPE_FORCE_FULLSCREEN:-1}" = 1 ] && args+=(--force-windows-fullscreen)
# the top-left corner. Forcing every window to the output's size keeps it filling the screen,
# but a game running at a resolution other than the screen's fights it and flickers, so it is
# off unless the app asks for it: BL_GAMESCOPE_FORCE_FULLSCREEN=1 turns it on.
[ "$mode" = steam ] && [ "${BL_GAMESCOPE_FORCE_FULLSCREEN:-0}" = 1 ] && args+=(--force-windows-fullscreen)
# 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)
@@ -445,7 +446,7 @@ case $mode in
# the root window, which it watches. What gamescope was started with is where this begins.
# Not on the desktop (BL_DESKTOP): no gamescope there, and the loop would outlive the client.
[ -z "${BL_DESKTOP:-}" ] && (
last=${BL_GAMESCOPE_FORCE_FULLSCREEN:-1}
last=${BL_GAMESCOPE_FORCE_FULLSCREEN:-0}
while :; do
nap 1
want=