diff --git a/CHANGELOG.md b/CHANGELOG.md index 28d642b7..e94e5447 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/). ### Added +- Launcher rendering mode `CODEX_LINUX_RENDERING_MODE=wayland-gpu`, which + forces native Wayland with GPU compositing enabled and skips forced renderer + accessibility by default for Wayland desktops where XWayland or software + rendering is unstable. - New opt-in Linux feature `read-aloud-mcp` that stages a standalone Rust Read Aloud MCP plugin with `doctor`, `read_aloud`, and `stop` tools. The MCP server reuses the Kokoro runner/model configuration from the Read Aloud UI feature diff --git a/README.md b/README.md index 04d83059..a52bf77b 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Optional Linux-only additions live in `linux-features/`. Use them for integratio | Atomic desktops / other Linux distros | none | `.AppImage` | Local self-build only; no bundled auto-updater | | NixOS / Nix | flake | runnable directly | `nix run github:ilysenko/codex-desktop-linux` | -Anything systemd-based should work for the optional auto-updater service (`systemd --user`). The launcher targets Wayland with `XWayland` first (better Electron popup positioning); pure Wayland sessions fall through to `--ozone-platform-hint=auto`. X11 is fully supported. +Anything systemd-based should work for the optional auto-updater service (`systemd --user`). The launcher targets Wayland with `XWayland` first (better Electron popup positioning); pure Wayland sessions fall through to `--ozone-platform-hint=auto`. X11 is fully supported. If XWayland or software rendering is unstable on a Wayland desktop, `CODEX_LINUX_RENDERING_MODE=wayland-gpu` forces native Wayland while keeping GPU compositing enabled. ## What you get @@ -528,7 +528,7 @@ make clean-state | `CODEX_CLI_PATH` error | Reopen the app to retry the automatic CLI install flow, or install manually with `npm i -g @openai/codex` / `npm i -g --prefix ~/.local @openai/codex` | | `gh auth status` works in a terminal but fails inside Codex Desktop | The app shell may be using isolated XDG paths or missing keyring DBus access. See [GitHub CLI auth in app-launched shells](docs/github-cli-auth.md) | | Electron hangs while CLI is outdated | Re-run the launcher and check `~/.cache/codex-desktop/launcher.log` plus `~/.local/state/codex-update-manager/service.log`. Best-effort CLI preflight will warn if the automatic refresh fails | -| GPU / Vulkan / Wayland errors | Under Wayland with `DISPLAY` available, the launcher uses `--ozone-platform=x11` for window-positioning compatibility. Otherwise it uses `--ozone-platform-hint=auto`. The GPU sandbox is disabled by default, while GPU compositing stays enabled | +| GPU / Vulkan / Wayland errors | Under Wayland with `DISPLAY` available, the launcher uses `--ozone-platform=x11` for window-positioning compatibility. Otherwise it uses `--ozone-platform-hint=auto`. The GPU sandbox is disabled by default, while GPU compositing stays enabled. On desktops where XWayland or software rendering hangs, such as some COSMIC/NVIDIA sessions, try `CODEX_LINUX_RENDERING_MODE=wayland-gpu ./codex-app/start.sh` | | Window flickering | Try `CODEX_ELECTRON_DISABLE_GPU_COMPOSITING=1 ./codex-app/start.sh` to use the legacy compositing workaround. If flickering persists, try `./codex-app/start.sh --disable-gpu` to fully disable GPU acceleration | | Sandbox errors | The launcher already sets `--no-sandbox` | | Stale install / cached DMG | `make build-app-fresh` removes the existing install dir and cached DMG, then re-downloads | diff --git a/launcher/start.sh.template b/launcher/start.sh.template index b366da43..8061e792 100644 --- a/launcher/start.sh.template +++ b/launcher/start.sh.template @@ -218,12 +218,13 @@ Default launch keeps Electron GPU enabled and lets Electron choose the platform. Extra flags are passed directly to Electron. Environment: - CODEX_LINUX_RENDERING_MODE=auto|default|wslg - Auto-detect WSLg, keep generic Linux defaults, or force the WSLg profile + CODEX_LINUX_RENDERING_MODE=auto|default|wslg|wayland-gpu + Auto-detect WSLg, keep generic Linux defaults, force the WSLg profile, + or force native Wayland with GPU compositing enabled CODEX_ELECTRON_DISABLE_GPU_COMPOSITING=0|1 Set to 1 to add --disable-gpu-compositing for flicker workarounds CODEX_FORCE_RENDERER_ACCESSIBILITY=auto|0|1 - Override --force-renderer-accessibility; auto skips it under WSLg + Override --force-renderer-accessibility; auto skips it under WSLg and wayland-gpu CODEX_MULTI_LAUNCH=1 Treat normal launches like --new-instance CODEX_MULTI_LAUNCH_PORT_RANGE=START-END Port allocation range for --new-instance (default: CODEX_WEBVIEW_PORT through +4) @@ -1735,7 +1736,7 @@ is_wslg_session() { normalize_linux_rendering_mode() { case "${CODEX_LINUX_RENDERING_MODE:-auto}" in - auto|default|wslg) + auto|default|wslg|wayland-gpu) echo "${CODEX_LINUX_RENDERING_MODE:-auto}" ;; *) @@ -1761,7 +1762,11 @@ falsey_env_value() { scan_electron_rendering_arg() { case "$1" in - --ozone-platform|--ozone-platform=*|--ozone-platform-hint|--ozone-platform-hint=*) + --ozone-platform=*) + ELECTRON_OZONE_SWITCH_IN_ARGS=1 + ELECTRON_OZONE_PLATFORM_ARG="${1#--ozone-platform=}" + ;; + --ozone-platform|--ozone-platform-hint|--ozone-platform-hint=*) ELECTRON_OZONE_SWITCH_IN_ARGS=1 ;; --use-gl|--use-gl=*|--use-angle|--use-angle=*) @@ -1797,6 +1802,13 @@ apply_electron_rendering_profile() { default) return 0 ;; + wayland-gpu) + if [ "$ELECTRON_PLATFORM_EXPLICIT" -eq 0 ] && [ "$ELECTRON_OZONE_SWITCH_IN_ARGS" -eq 0 ]; then + ELECTRON_OZONE_PLATFORM="wayland" + ELECTRON_OZONE_HINT="" + fi + return 0 + ;; esac [ "$ELECTRON_RENDERING_MODE" = "wslg" ] || return 0 @@ -1831,7 +1843,20 @@ should_disable_gpu_compositing() { return 1 } +effective_electron_ozone_platform() { + if [ -n "$ELECTRON_OZONE_PLATFORM" ]; then + echo "$ELECTRON_OZONE_PLATFORM" + return 0 + fi + + if [ -n "$ELECTRON_OZONE_PLATFORM_ARG" ]; then + echo "$ELECTRON_OZONE_PLATFORM_ARG" + fi +} + should_force_renderer_accessibility() { + local effective_platform + if [ -n "${CODEX_FORCE_RENDERER_ACCESSIBILITY:-}" ]; then if truthy_env_value "$CODEX_FORCE_RENDERER_ACCESSIBILITY"; then return 0 @@ -1847,7 +1872,18 @@ should_force_renderer_accessibility() { esac fi - [ "$ELECTRON_RENDERING_MODE" != "wslg" ] + case "$ELECTRON_RENDERING_MODE" in + wslg) + return 1 + ;; + wayland-gpu) + effective_platform="$(effective_electron_ozone_platform)" + [ "$effective_platform" = "wayland" ] && return 1 + return 0 + ;; + esac + + return 0 } set_electron_defaults() { @@ -1858,6 +1894,7 @@ set_electron_defaults() { ELECTRON_WSLG_DETECTED=0 ELECTRON_PLATFORM_EXPLICIT=0 ELECTRON_OZONE_SWITCH_IN_ARGS=0 + ELECTRON_OZONE_PLATFORM_ARG="" ELECTRON_GL_SWITCH_PROVIDED=0 ELECTRON_GL_SWITCH_ADDED=0 ELECTRON_GPU_DISABLE_SWITCH_IN_ARGS=0 diff --git a/tests/scripts_smoke.sh b/tests/scripts_smoke.sh index f8672e79..2a39c063 100755 --- a/tests/scripts_smoke.sh +++ b/tests/scripts_smoke.sh @@ -2088,6 +2088,27 @@ PY [[ "$output" == *"electron=<--ozone-platform=x11>"* ]] || fail "pass-through ozone platform must reach Electron: $output" [[ "$output" != *"<--ozone-platform-hint=auto>"* ]] || fail "launcher must not add ozone hint when pass-through supplies an ozone platform: $output" + output="$(env -i PATH="$PATH" HOME="$HOME" CODEX_LINUX_RENDERING_MODE=wayland-gpu "$launcher_probe" probe)" + [[ "$output" == *"mode=wayland-gpu"* && "$output" == *"ozone_platform=wayland"* && "$output" == *"gpu=1"* ]] || fail "wayland-gpu profile must force native Wayland with GPU enabled: $output" + [[ "$output" == *"comp=0"* && "$output" != *"<--disable-gpu-compositing>"* ]] || fail "wayland-gpu profile must keep GPU compositing enabled: $output" + [[ "$output" == *"<--ozone-platform=wayland>"* && "$output" == *"<--enable-features=WaylandWindowDecorations>"* ]] || fail "wayland-gpu profile must add Wayland launch args: $output" + [[ "$output" == *"renderer_accessibility=0"* && "$output" != *"<--force-renderer-accessibility>"* ]] || fail "wayland-gpu profile must skip renderer accessibility by default: $output" + + output="$(env -i PATH="$PATH" HOME="$HOME" CODEX_LINUX_RENDERING_MODE=wayland-gpu CODEX_FORCE_RENDERER_ACCESSIBILITY=1 "$launcher_probe" probe)" + [[ "$output" == *"renderer_accessibility=1"* && "$output" == *"<--force-renderer-accessibility>"* ]] || fail "CODEX_FORCE_RENDERER_ACCESSIBILITY=1 must force renderer accessibility under wayland-gpu: $output" + + output="$(env -i PATH="$PATH" HOME="$HOME" CODEX_LINUX_RENDERING_MODE=wayland-gpu "$launcher_probe" probe --x11)" + [[ "$output" == *"mode=wayland-gpu"* && "$output" == *"ozone_platform=x11"* ]] || fail "explicit --x11 must override the wayland-gpu platform: $output" + [[ "$output" == *"renderer_accessibility=1"* && "$output" == *"<--force-renderer-accessibility>"* ]] || fail "wayland-gpu with explicit --x11 must keep X11 renderer accessibility default: $output" + + output="$(env -i PATH="$PATH" HOME="$HOME" CODEX_LINUX_RENDERING_MODE=wayland-gpu "$launcher_probe" probe --safe-mode)" + [[ "$output" == *"mode=wayland-gpu"* && "$output" == *"ozone_platform=x11"* && "$output" == *"gpu=0"* ]] || fail "safe-mode must override wayland-gpu to X11 software rendering: $output" + [[ "$output" == *"renderer_accessibility=1"* && "$output" == *"<--force-renderer-accessibility>"* ]] || fail "wayland-gpu with safe-mode must keep X11 renderer accessibility default: $output" + + output="$(env -i PATH="$PATH" HOME="$HOME" CODEX_LINUX_RENDERING_MODE=wayland-gpu "$launcher_probe" probe -- --ozone-platform=x11)" + [[ "$output" == *"electron=<--ozone-platform=x11>"* && "$output" != *"<--ozone-platform-hint=auto>"* ]] || fail "pass-through X11 platform must override wayland-gpu hinting: $output" + [[ "$output" == *"renderer_accessibility=1"* && "$output" == *"<--force-renderer-accessibility>"* ]] || fail "wayland-gpu with pass-through X11 platform must keep X11 renderer accessibility default: $output" + output="$(env -i PATH="$PATH" HOME="$HOME" CODEX_LINUX_RENDERING_MODE=wslg "$launcher_probe" probe)" [[ "$output" == *"mode=wslg"* && "$output" == *"comp=0"* && "$output" == *"gl_added=1"* ]] || fail "forced WSLg profile must keep GPU compositing enabled and add ANGLE: $output" [[ "$output" == *"<--ozone-platform=x11>"* && "$output" == *"electron=<--use-gl=angle>"* ]] || fail "forced WSLg profile must use X11 and ANGLE by default: $output" @@ -2142,6 +2163,7 @@ PY assert_contains "$REPO_DIR/launcher/start.sh.template" '--app-id="$CODEX_LINUX_APP_ID"' assert_contains "$REPO_DIR/scripts/lib/process-detection.sh" "CODEX_APP_ID" assert_contains "$REPO_DIR/launcher/start.sh.template" 'ELECTRON_OZONE_HINT="auto"' + assert_contains "$REPO_DIR/launcher/start.sh.template" "CODEX_LINUX_RENDERING_MODE=auto|default|wslg|wayland-gpu" assert_contains "$REPO_DIR/launcher/start.sh.template" '--ozone-platform-hint="$ELECTRON_OZONE_HINT"' assert_contains "$REPO_DIR/launcher/start.sh.template" "--disable-gpu-sandbox" assert_contains "$REPO_DIR/launcher/start.sh.template" "--force-renderer-accessibility"