WSLg Wayland and XWayland Compatibility: Choose the Display Path on Evidence
Separate native Wayland and X11-through-XWayland failures in WSLg by inspecting sockets, toolkit backends, environment, and app diagnostics.
A Linux GUI application can open a window in WSLg without using the display protocol you expected. WSLg provides a Wayland compositor and X server integration; an application may speak Wayland directly, speak X11 through XWayland, or use a toolkit backend selected at runtime. A blank window, missing decoration, rendering difference, or “cannot open display” error should therefore be mapped to the actual client protocol before changing WSL configuration.
This guide focuses on protocol selection and compatibility. It is not a general installation guide for GUI applications. The objective is to determine which endpoint the application uses, prove that endpoint is available, and compare a minimal client with the failing application. Do not launch a second compositor or manually replace display variables until you know which WSLg socket and server the process was intended to use.
Know the display components
Wayland clients connect to a compositor using a Unix-domain socket named through WAYLAND_DISPLAY, commonly relative to XDG_RUNTIME_DIR or another projected WSLg path. The compositor manages surfaces and coordinates the remoting of Linux application windows to Windows. X11 clients use DISPLAY and the X11 protocol. WSLg includes an X server path so applications that are not native Wayland clients can still display.
XWayland is the compatibility server that lets X11 clients run in a Wayland session. It is not a requirement that every app use XWayland; modern toolkits can have native Wayland support while retaining an X11 backend. Browser, Electron, GTK, Qt, SDL, and Java applications may choose backends differently by release and packaging. An environment override can change that choice and make a previously working application fail.
The Windows desktop is reached through WSLg’s remoting architecture. It is not the same as exporting an X11 display to a separate X server installed on Windows, and it is not a full Linux desktop session by default. The WSLg repository explains its Weston compositor, X server, projected sockets, and RDP integration. Keep that architecture distinct from the graphics driver path: a client may have a functioning display socket but software rendering or a broken GPU driver.
Capture the environment from the failing process context
Start from the same shell, Start Menu entry, desktop file, service, or container that launches the failing app. Capture the variables:
printf 'DISPLAY=%s\nWAYLAND_DISPLAY=%s\nXDG_RUNTIME_DIR=%s\n' \
"$DISPLAY" "$WAYLAND_DISPLAY" "$XDG_RUNTIME_DIR"
env | grep -E '^(GDK_BACKEND|QT_QPA_PLATFORM|SDL_VIDEODRIVER|MOZ_ENABLE_WAYLAND)='
case ${WAYLAND_DISPLAY:-} in
/*) test -S "$WAYLAND_DISPLAY" && echo "Wayland socket present" ;;
*) test -n "${XDG_RUNTIME_DIR:-}" &&
test -S "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" && echo "Wayland socket present" ;;
esac
find /mnt/wslg -maxdepth 3 -type s -print 2>/dev/null
The environment variable list only shows inherited settings; absence of an override does not prove which protocol a toolkit selected. A GUI app launched from a shell can inherit a different environment from its Start Menu launcher. A container can lack projected sockets even when the parent distro has them. Capture the environment at the app process boundary, not only in an unrelated interactive terminal.
Do not assume both DISPLAY and WAYLAND_DISPLAY must be set for every working app. A native Wayland application needs a reachable Wayland socket; an X11 client needs an X endpoint. Some frameworks probe multiple backends. The relevant question is whether the selected client path matches an available server, not whether every variable has a nonempty value.
Test each protocol independently
Use small diagnostic applications from the same distro and launch context. An X11 utility such as xdpyinfo can test X server reachability. A Wayland utility such as wayland-info can query compositor globals when installed. Their package names and availability vary by distribution. If one test cannot connect, preserve its exact error and verify the corresponding socket and permissions before changing toolkit settings.
For a test application that logs backend selection, enable its documented verbose logging. Toolkit-specific flags vary; do not export a permanent GDK_BACKEND or QT_QPA_PLATFORM value copied from another app. If comparing backends, set the override only for a single process and record the result:
env GDK_BACKEND=wayland application
env GDK_BACKEND=x11 application
This example applies only to applications built with GTK and a version that supports those backend names. It is not a universal WSL setting. For Qt, SDL, browsers, and Electron, consult that application’s current documentation for backend selection.
If the app renders on X11 but fails on Wayland, inspect native Wayland support, toolkit version, and protocol assumptions such as older X11-only extensions. If it works on Wayland but not X11, inspect XWayland availability and X-specific behavior. If both test apps work but the product fails, investigate its sandboxing, application dependencies, GPU selection, and launch environment.
Distinguish protocol failure from graphics failure
A successful connection to a display server proves only that a protocol endpoint answers. It does not prove that OpenGL, Vulkan, hardware acceleration, input, scaling, or a particular rendering extension works. Test basic window creation first, then add one rendering capability at a time. Use the app’s own diagnostic output and appropriate tools such as glxinfo only when the app actually uses OpenGL through X11.
If a window opens but is blank or corrupt, capture the WSLg and application logs, renderer string, WSL version, Windows graphics driver version, and chosen backend. Compare a low-complexity client with the product. Avoid setting LIBGL_ALWAYS_SOFTWARE globally as a first response: it changes rendering for other applications and may conceal a GPU-path problem without explaining it.
WSLg’s X and Wayland servers are part of its system distribution and are managed by WSL. Do not install another server into that read-only distribution. If you intentionally use a separate server, treat it as a different architecture and document the network/socket path, authentication, and support boundaries.
Control common environment mistakes
Look for stale DISPLAY or WAYLAND_DISPLAY exports in shell startup files, IDE launch settings, container manifests, and systemd service definitions. An old X server address can survive a Windows update in a dotfile and route every new app away from WSLg. Do not erase the variables globally; compare them with a clean shell first and remove only the stale override.
Check that XDG_RUNTIME_DIR refers to a runtime directory appropriate to the launching user and that any Wayland socket is accessible to that process. A service running as another UID can inherit a path that exists but is not usable. Containers need explicit socket access and compatible UID or group arrangements. Validate mount visibility and permissions inside the container rather than assuming host-distro paths are shared.
A per-process launch test is safer than editing global profiles:
env -u DISPLAY -u WAYLAND_DISPLAY application
Use this only as a controlled experiment and only if the application or launcher sets the intended variables itself. It is not a repair command. If the application then fails, that establishes the variables were necessary in that context.
Check versions and update boundaries
WSLg is distributed with WSL in inbox and Microsoft Store servicing channels, and its version can differ from the Linux distro and Windows build. Capture wsl.exe –version, Windows build, distro release, and relevant toolkit package versions. When the problem appeared after an update, compare the last known-good and current client/server versions rather than updating every component at once.
The supported GUI experience is associated with WSL 2. A WSL 1 distro does not run inside the WSL 2 managed VM that hosts WSLg’s GUI integration. Confirm distro version with wsl.exe –list –verbose before investigating display sockets. If only one distro is affected, compare its configuration and app packages with a known-good distro instead of reinstalling WSL globally.
Interpret input, scaling, and window behavior separately
Display protocol selection does not explain every GUI symptom. Keyboard layout, input methods, fractional scaling, clipboard selection, and window management can involve different toolkit and compositor interfaces. An X11 client that appears as a first-class Windows window still passes through XWayland and WSLg’s window integration. Compare a simple client and the target app at the same scale factor before attributing clipped text or missing shortcuts to a rendering driver.
When an app’s window opens but keyboard input is absent, verify that focus reaches the Linux window and test a minimal client using the same protocol. If only text input or non-Latin input fails, capture the toolkit, input method, locale, and display backend. Do not globally change keyboard layout or scaling to repair one app until the protocol and input method path have been isolated.
Acceptance checks
For each supported application, record whether it uses Wayland or X11/XWayland, its launch path, environment variables, toolkit version, renderer, and WSLg version. Test a minimal client on the same protocol, start the application from both its normal launcher and a clean terminal when both paths matter, and verify window creation, keyboard input, resize, and basic rendering.
A reproducible report includes the exact app command, protocol endpoint, relevant logs, WSL version, distro, Windows build, and whether a minimal client succeeds. This separates an absent socket, a toolkit backend issue, a container boundary, and a graphics failure. Changing all of those layers at once destroys the evidence needed to choose a durable fix.
Related:
- Fixing WSLg Graphics Rendering and Display Issues
- Debugging WSLg Audio: PulseAudio Playback, Microphone Capture, and Routing
Sources: