Skip to content

fix(linux): work around WebKitGTK white screen on AppImage + Wayland - #28

Merged
kipavy merged 2 commits into
VoltiusApp:devfrom
ezhkov-ph:fix/linux-appimage-wayland
Jul 19, 2026
Merged

fix(linux): work around WebKitGTK white screen on AppImage + Wayland#28
kipavy merged 2 commits into
VoltiusApp:devfrom
ezhkov-ph:fix/linux-appimage-wayland

Conversation

@ezhkov-ph

Copy link
Copy Markdown
Contributor

Problem

On some Linux setups (confirmed on CachyOS with an NVIDIA GPU under Wayland), launching the AppImage shows a blank/white window unless the user manually sets LD_PRELOAD=/usr/lib/libwayland-client.so before running it. Users also reported noticeably janky/non-smooth rendering compared to the Windows build, even once the white screen was worked around.

This is not a bug in Voltius's own code — there was no Linux-specific webview setup at all prior to this PR. It's a well-known WebKitGTK/AppImage packaging interaction that other Tauri apps (e.g. Yaak) have hit and worked around the same way.

Root causes (two independent issues)

  1. Bundled libwayland-client.so shadows the system one. linuxdeploy (used by the Tauri bundler) packages the build machine's libwayland-client.so.0 (Ubuntu 24.04 in our CI) into the AppImage as a WebKit dependency. On a host with a newer Wayland stack (Arch/CachyOS/Fedora), the bundled copy wins the library search order and EGL display creation fails (Could not create default EGL display: EGL_BAD_PARAMETER) — resulting in either a white window, or a silent fallback to Xwayland (which would also explain the reported jank, since it's no longer compositing natively).

  2. WebKitGTK's DMA-BUF renderer. WebKitGTK >= 2.42 composites through DMA-BUF by default, which is broken on many NVIDIA-proprietary-driver + Wayland combinations (and some Mesa/compositor combos). The ecosystem-standard fix is the WEBKIT_DISABLE_DMABUF_RENDERER=1 environment variable, which falls back to the older (still GPU-accelerated) EGL path.

Fix

Added src-tauri/src/linux_gfx.rs, wired in as the very first thing run() does (before Tauri/WebKit touch anything):

  • Sets WEBKIT_DISABLE_DMABUF_RENDERER=1 when running from an AppImage or when an NVIDIA driver is detected (/proc/driver/nvidia or /sys/module/nvidia) — unless the user already set the variable themselves.
  • When running from an AppImage on a Wayland session (WAYLAND_DISPLAY set) with no user-supplied LD_PRELOAD, re-execs the process once (/proc/self/exe) with the system's libwayland-client preloaded, picked from a list of standard Debian/Fedora/Arch paths. The candidate is validated by parsing its ELF header (class + machine) so a mismatched-arch library is never preloaded. A guard env var (VOLTIUS_WAYLAND_PRELOAD_ATTEMPTED) prevents re-exec loops if the preload doesn't help.
  • Everything here is opt-outable via VOLTIUS_NO_LINUX_GFX_WORKAROUNDS=1, and none of it compiles on non-Linux targets (#[cfg(target_os = "linux")]), so Windows/macOS/Android builds are untouched.

Verification

  • Built the AppImage locally (Docker, Ubuntu 24.04 container matching CI) and confirmed both workarounds are compiled in and fire correctly:
    • Smoke-tested under Xvfb in the container (no Wayland there, so only the DMA-BUF env var applies) — app starts cleanly.
    • Had the actual reporting user test the AppImage on their CachyOS + NVIDIA + Wayland machine: previously required manual LD_PRELOAD; with this fix, launches directly to a working, non-blank window. Log output confirmed the re-exec path engaged with the correct system library path (/usr/lib64/libwayland-client.so.0 on their machine).
  • cargo fmt --all --check passes; added unit tests for the ELF-header validation logic (rejects non-ELF files, wrong architecture/class, missing files; picks the first valid candidate from a list).

Test plan

  • cargo fmt --all --check / cargo build --release (via Docker, Ubuntu 24.04)
  • AppImage smoke-tested under Xvfb
  • AppImage tested end-to-end on CachyOS (Wayland + NVIDIA) — white screen gone, no more manual LD_PRELOAD needed
  • Would appreciate a spot-check on a non-NVIDIA Wayland setup (e.g. AMD/Mesa) and on X11, to confirm no regressions there — the DMA-BUF variable is harmless on X11 (WebKit ignores it) but hasn't been explicitly tested

linuxdeploy bundles the build machine's libwayland-client.so into the
AppImage, which shadows the host's newer copy on Wayland (Arch/CachyOS)
and breaks EGL init (EGL_BAD_PARAMETER) -> blank/white window, or a
silent fallback to Xwayland that also explains the jank vs. Windows.
Separately, WebKitGTK's DMA-BUF compositor is broken on many
NVIDIA+Wayland setups.

Confirmed root cause and fix by building the AppImage and reproducing
on a real CachyOS/NVIDIA/Wayland machine, where the prior workaround
was manually setting LD_PRELOAD before launch.

linux_gfx::apply_startup_workarounds() runs first thing in run() and,
unless the user already set the relevant env var: sets
WEBKIT_DISABLE_DMABUF_RENDERER=1 under AppImage or NVIDIA, and under
AppImage+Wayland re-execs once via /proc/self/exe with the system
libwayland-client preloaded (ELF-arch-checked, loop-guarded). Opt-out
via VOLTIUS_NO_LINUX_GFX_WORKAROUNDS=1.
@ezhkov-ph
ezhkov-ph force-pushed the fix/linux-appimage-wayland branch from 67e9306 to 8d870d9 Compare July 14, 2026 20:13
@kipavy
kipavy changed the base branch from main to dev July 19, 2026 18:48
@kipavy
kipavy merged commit 88607cc into VoltiusApp:dev Jul 19, 2026
2 checks passed
@kipavy

kipavy commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Thanks a lot for this, Alex — really thorough work. The two-root-cause breakdown (bundled libwayland + DMABUF renderer) and the ELF-validated preload are exactly the right way to handle it, and the doc comments made review easy.

I checked it out, built it in our CI image, and confirmed it compiles clean with the unit tests, fmt, and clippy all green. I pushed one tiny follow-up to your branch (map_or(true, …)is_none_or) so clippy's -D warnings gate stays happy — hope you don't mind. Merged and shipping. 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants