Added better support for kubuntu and fixed some issues with telemetry.

This commit is contained in:
2026-09-09 22:35:13 +02:00
parent 6e6219107e
commit 290d1a5383
8 changed files with 587 additions and 65 deletions

View File

@@ -428,10 +428,41 @@ def _bundled_gamescope_is_usable() -> bool:
return os.access(path, os.X_OK)
def _select_wayland_gamescope(executable: str) -> tuple[str, bool, bool]:
def _is_kde_session(environment: Mapping[str, str]) -> bool:
"""Recognize Plasma sessions without relying on an Ubuntu flavor name."""
if environment.get("KDE_FULL_SESSION", "").strip().casefold() in {
"1",
"true",
"yes",
}:
return True
if environment.get("KDE_SESSION_VERSION", "").strip():
return True
for key in ("XDG_CURRENT_DESKTOP", "XDG_SESSION_DESKTOP", "DESKTOP_SESSION"):
tokens = re.split(
r"[^a-z0-9]+",
environment.get(key, "").strip().casefold(),
)
if "kde" in tokens or any(token.startswith("plasma") for token in tokens):
return True
return False
def _select_wayland_gamescope(
executable: str,
*,
environment: Mapping[str, str] | None = None,
) -> tuple[str, bool, bool]:
"""Choose a direct-safe Gamescope or request the stable composed path."""
version = _read_gamescope_version(executable)
env = os.environ if environment is None else environment
if _is_kde_session(env):
# This is reached only when Plasma has no usable XWayland display. Keep
# native Wayland fully composed because newer Gamescope builds still have
# KWin-specific presentation failures outside our backing-surface fixes.
return executable, True, False
if version is not None and version >= WAYLAND_BACKING_FIX_VERSION:
return executable, False, False
if version == BUNDLED_GAMESCOPE_VERSION and _bundled_gamescope_is_usable():
@@ -458,9 +489,15 @@ def _wayland_socket_available(environment: Mapping[str, str]) -> bool:
def _select_host_backend(environment: Mapping[str, str]) -> str:
"""Prefer Wayland's retained-buffer resize path when it is usable."""
"""Choose the host backend with a Plasma-safe XWayland fallback."""
if _wayland_socket_available(environment):
# Gamescope's native Wayland backend still has KWin-specific presentation,
# fullscreen, and fractional-scaling failures. Plasma normally exposes an
# XWayland display, so keep the resizable host window on the mature SDL/X11
# path while leaving non-Plasma Wayland sessions on direct presentation.
if _is_kde_session(environment) and environment.get("DISPLAY", "").strip():
return "sdl"
return "wayland"
return "sdl"
@@ -629,6 +666,13 @@ def run_gamescope(command: Sequence[str], width: int, height: int) -> int:
diagnostics = WindowDiagnosticRecorder("gamescope_host")
environment = os.environ.copy()
backend = _select_host_backend(environment)
kde_session = _is_kde_session(environment)
kde_wayland_xwayland_fallback = (
backend == "sdl"
and kde_session
and bool(environment.get("WAYLAND_DISPLAY", "").strip())
and bool(environment.get("DISPLAY", "").strip())
)
selected_command = list(map(str, command))
force_composition = backend == "sdl"
using_bundled_gamescope = False
@@ -637,7 +681,10 @@ def run_gamescope(command: Sequence[str], width: int, height: int) -> int:
selected_command[0],
force_composition,
using_bundled_gamescope,
) = _select_wayland_gamescope(selected_command[0])
) = _select_wayland_gamescope(
selected_command[0],
environment=environment,
)
mapper = _open_host_x11() if backend == "sdl" else None
diagnostics.record(
"runtime_configured",
@@ -647,6 +694,22 @@ def run_gamescope(command: Sequence[str], width: int, height: int) -> int:
display_available=bool(environment.get("DISPLAY")),
wayland_display_available=bool(environment.get("WAYLAND_DISPLAY")),
host_x11_monitor_available=mapper is not None,
kde_session=kde_session,
kde_wayland_compatibility_mode=(
kde_wayland_xwayland_fallback
or (backend == "wayland" and kde_session and force_composition)
),
kde_wayland_xwayland_fallback=kde_wayland_xwayland_fallback,
backend_reason=(
"kde_wayland_xwayland_compatibility"
if kde_wayland_xwayland_fallback
else "wayland_socket"
if backend == "wayland"
else "x11_or_unavailable_wayland"
),
presentation_mode=(
f"{backend}_{'composed' if force_composition else 'direct'}"
),
canvas_width=width,
canvas_height=height,
)
@@ -740,6 +803,14 @@ def run_gamescope(command: Sequence[str], width: int, height: int) -> int:
diagnostics.close(process_started=False, backend=backend)
raise GamescopeRuntimeError(f"could not start Gamescope: {exc}") from exc
if kde_wayland_xwayland_fallback:
print(
"KDE Wayland compatibility mode active: Gamescope is using its "
"SDL host window through XWayland to avoid KWin presentation, "
"fullscreen, and fractional-scaling failures.",
file=sys.stderr,
flush=True,
)
if backend == "wayland" and not force_composition:
message = (
"Gamescope resize optimization active: native Wayland direct "
@@ -751,6 +822,13 @@ def run_gamescope(command: Sequence[str], width: int, height: int) -> int:
"decoration-input, and login-window visibility fixes are active."
)
print(message, file=sys.stderr, flush=True)
elif backend == "wayland" and kde_session:
print(
"KDE Wayland compatibility mode active: Gamescope is using its "
"composed native fallback because no XWayland display is available.",
file=sys.stderr,
flush=True,
)
elif backend == "wayland":
print(
"Warning: this Gamescope build lacks safe direct Wayland letterbox "