Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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 |
Expand Down
49 changes: 43 additions & 6 deletions launcher/start.sh.template
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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}"
;;
*)
Expand All @@ -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=*)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -1847,7 +1872,18 @@ should_force_renderer_accessibility() {
esac
fi

[ "$ELECTRON_RENDERING_MODE" != "wslg" ]
case "$ELECTRON_RENDERING_MODE" in
wslg)
return 1
Comment on lines +1875 to +1877
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Gate renderer accessibility on platform, not requested mode

When CODEX_LINUX_RENDERING_MODE=wayland-gpu is set, should_force_renderer_accessibility() now always disables --force-renderer-accessibility even if launch args later force X11 (for example --x11, --safe-mode, or passthrough --ozone-platform=x11). That regresses prior behavior for those X11 launches and can break accessibility-dependent tooling in exactly the troubleshooting path users are likely to take after exporting the new mode globally. The check should use the effective platform (or explicit X11 overrides) rather than only the requested rendering profile.

Useful? React with 👍 / 👎.

;;
wayland-gpu)
effective_platform="$(effective_electron_ozone_platform)"
[ "$effective_platform" = "wayland" ] && return 1
return 0
;;
esac

return 0
}

set_electron_defaults() {
Expand All @@ -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
Expand Down
22 changes: 22 additions & 0 deletions tests/scripts_smoke.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down
Loading