# xwayland-satellite, rootless Xwayland for compositors that will not write one

> xwayland-satellite gives rootless Xwayland integration to any Wayland compositor that implements xdg_wm_base and viewporter, so a compositor can run X11 applications without writing an X11 window manager itself. It is a Rust program that acts as both a Wayland client and a Wayland compositor, and it can be launched by hand, by a systemd user unit, or by the host compositor itself.

**Supreeeme/xwayland-satellite** — Xwayland outside your Wayland

- Repository: https://github.com/Supreeeme/xwayland-satellite
- Stars: 1,156 · Forks: 107
- Language: Rust
- License: MPL-2.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/supreeeme-xwayland-satellite

## Why a compositor would want this

xwayland-satellite grants rootless Xwayland integration to any Wayland compositor implementing xdg_wm_base and viewporter, and the README is clear about who it is for, compositors that understandably do not want to go through implementing support for rootless Xwayland themselves. The motivation section explains the cost from the compositor's point of view. Supporting rootless XWayland involves writing an X11 window manager and dealing with all those quirks. The X11 windowing model also does not map cleanly onto Wayland, since there is no absolute positioning support in Wayland, so a compositor would have to do things differently specifically for X11 windows. And the author adds that X11 is just poorly documented in his experience. That last point is the one that decides the project, because an X11 window manager is a large body of undocumented behaviour that every compositor would otherwise have to absorb on its own.

## Dependencies, build flags and two optional features

The dependency list is short and concrete. At runtime you need Xwayland 23.1 or newer, xcb and xcb-util-cursor, and to build it you need cargo and clang, with git optional. The build itself is the standard cargo invocation.

```bash
# dev build
cargo build
# release build
cargo build --release
```

There are two optional features, enabled with the -F flag on the cargo build command. The systemd feature makes the program send a state change notification once Xwayland has been initialised, which lets other services depend on satellite's startup, and the README notes the feature can be enabled without systemd installed even though it then does nothing. The fontconfig feature uses fontconfig to load Open Sans at run time rather than compiling it into the binary, which makes the font and fontconfig run time dependencies of the build.

## It starts after the compositor and before any X client

The running section states the ordering constraint plainly, because xwayland-satellite is a Wayland client in addition to being a Wayland compositor, so it has to launch after your compositor launches but obviously before any X11 applications. Run by hand, you start the binary or use cargo run, with or without --release. You can specify which X display to use, for example :12, and you have to set the same DISPLAY environment variable for any X11 clients. The README gives the reason, that setting the display lets you choose which instance of satellite the X11 client communicates with, which is useful for debugging crashes or bypassing automatically started instances. The RUST_LOG environment variable can be set to debug for more logging. For a user of a compositor that already handles Xwayland, none of this applies, since the compositor integration path takes over.

## A systemd user unit, or the compositor takes over

For the manual systemd path there is an example service file at resources/xwayland-satellite.service, and the README says to replace the ExecStart line with the proper location before using it. The file can go in a systemd user unit directory, either $XDG_CONFIG_HOME/systemd/user or /etc/systemd/user, and it is launched and enabled with systemctl --user enable --now xwayland-satellite. It starts when graphical-session.target is reached, which is likely after the compositor if that supports systemd. The README also says you do not need the unit at all if the compositor already integrates xwayland-satellite. That integration path is the more interesting one. Satellite supports passing through the -listenfd Xwayland argument, which lets a compositor integrate satellite and by extension Xwayland, and do things like on demand activation, with the requirement that a display number is passed as the first argument followed by -listenfd. Niri's implementation is linked as a reference. The trade is that if satellite is integrated into the compositor, updating either satellite or the compositor's satellite settings requires restarting the compositor, unless you launch satellite with a display and matching DISPLAY variables for the applications you want to test.

## The protocols a host compositor must implement

The protocol requirements are listed in two tiers, and the distinction is between what satellite cannot work without and what it will use if it is there. The host compositor must implement the core interfaces such as wl_output, wl_surface and wl_compositor, the xdg_shell set of xdg_wm_base, xdg_surface, xdg_popup and xdg_toplevel, and wp_viewporter, which is used for scaling. Satellite can optionally take advantage of Linux dmabuf, XDG activation, XDG decoration, XDG foreign, pointer constraints, primary selection, tablet input and fractional scale. The xdg_wm_base requirement is what the opening description refers to when it says the compositor must implement xdg_wm_base and viewporter, and the optional tier is a list of conveniences rather than prerequisites. For a compositor author this list is the actual interface contract, and it is short enough to audit against an implementation.

## Java windows, HiDPI and the Xsettings conflict

The troubleshooting section names two problems that anyone running X11 applications under Wayland will hit. The first is Java, where some applications present themselves as a blank screen by default with satellite, and the fix is to set the environment variable _JAVA_AWT_WM_NONREPARENTING=1 before launching the application. The README is explicit that satellite cannot do this automatically, and suggests configuring Java instead by adding set _JAVA_AWT_WM_NONREPARENTING=1 to /etc/profile.d/jre.sh. The second is scaling. For most GTK and Qt applications satellite scales them properly on its own, but in a mixed DPI monitor setup it chooses the smallest monitor's DPI, which means text can be small on the others, and applications such as Wine ones may also end up with small text, which is application dependent and points at the Arch Wiki on HiDPI. On top of that, satellite acts as an Xsettings manager for the scaling settings but steps aside for other Xsettings managers, and xsettingsd is the tool the README suggests for setting them by hand.

## The Rust workspace behind the satellite

The project is a Rust workspace on edition 2024 with a minimum rust version of 1.85, and the Cargo.toml denies all clippy lints at the workspace level. The workspace has three members beyond the main crate, macros, testwl and wl_drm, and the main package pulls in wayland-client 0.31.11, wayland-server 0.31.10, wayland-protocols 0.32.9 and wayland-scanner 0.31.7, with rustix 1.1.2 and the xcb crate at 1.7.0 with the composite, randr and res features enabled. On top of the protocol layer there is smithay-client-toolkit 0.20.0, bitflags, the hecs entity component system, num_enum, tiny-skia with ab_glyph and fontdue for rendering, and pretty_env_logger with syslog for output, and the crate embeds OpenSans-Regular.ttf at the root of the repository, which is exactly what the fontconfig feature exists to avoid. The licence is MPL-2.0, the file is named xwayland-satellite.man, and there is an ARCHITECTURE.md alongside a flake.nix and a flake.lock for Nix based builds.

## Conclusion

xwayland-satellite fits a compositor author who wants X11 application support without taking on an X11 window manager, and it fits a user of a compositor that has not implemented rootless Xwayland and wants it today. It does not fit a compositor that already ships its own Xwayland integration and has no reason to run a second layer, and it does not fit a user with a mixed DPI multi monitor setup who needs text scaled per screen, since the documentation says satellite picks the smallest monitor's DPI. Verify three things before you build: that your compositor implements the required protocols, namely xdg_shell and wp_viewporter alongside the core interfaces, that you have Xwayland 23.1 or newer with xcb and xcb-util-cursor present, and how the compositors you care about behave with the scaling and the Java window manager hint described in the troubleshooting section.

## FAQ

### What does xwayland-satellite do?

It grants rootless Xwayland integration to any Wayland compositor implementing xdg_wm_base and viewporter, so a compositor can support X11 applications without writing an X11 window manager itself. The README notes that X11's windowing model does not map cleanly onto Wayland and that X11 is poorly documented.

### What does xwayland-satellite need to build and run?

At runtime it needs Xwayland 23.1 or newer, xcb and xcb-util-cursor, and to build it you need cargo and clang, with git optional. The build is cargo build, or cargo build --release, and the systemd and fontconfig features are enabled with the -F flag.

### When should xwayland-satellite be started?

It is a Wayland client as well as a Wayland compositor, so it must launch after the compositor and before any X11 applications. You can run it by hand, enable the supplied systemd user unit with systemctl --user enable --now xwayland-satellite, or let the compositor integrate it by passing through the -listenfd Xwayland argument.

### Why do some Java applications show a blank screen with xwayland-satellite?

Some Java applications present a blank screen by default with satellite. The fix is to set the environment variable _JAVA_AWT_WM_NONREPARENTING=1 before launching the application, and satellite cannot do this automatically, so the README suggests adding set _JAVA_AWT_WM_NONREPARENTING=1 to /etc/profile.d/jre.sh instead.

## Sources

- [Issues](https://github.com/Supreeeme/xwayland-satellite/issues)
- [License: MPL-2.0](https://github.com/Supreeeme/xwayland-satellite/blob/main/LICENSE)
- [README](https://github.com/Supreeeme/xwayland-satellite/blob/main/README.md)
- [Releases](https://github.com/Supreeeme/xwayland-satellite/releases)
- [Supreeeme/xwayland-satellite on GitHub](https://github.com/Supreeeme/xwayland-satellite)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/supreeeme-xwayland-satellite
