Over the last week, I’ve been working on a Wayland implementation for JUCE that eliminates the need to run through XWayland. Several major distros are dropping X11 support soon. Fedora has done it already, and Ubuntu will be following in October. JUCE still works on these platforms thanks to the XWayland compatibility layer, but it’s not without its problems:
- Window resizing is always a bit glitchy, but it becomes really bad on GNOME if you also have an openGL context attached to your window, or if you need to do substantial rendering work.
- Windows without native titlebars cannot be dragged off-screen, or make use of tiling features
As demonstrated in this video, the resizing glitches affects my app quite badly, and I don’t think JUCE is to blame for that. GNOME with XWayland handles this poorly. This motivated me to try to quickly put together a Wayland backend for JUCE. I didn’t expect to get very far because of the inherent limitations of Wayland, but I managed to get most things working well enough!
What works:
- Rendering with JUCE and openGL (using wayland-egl)
- VBlank timing
- Host managed window moving and resizing (and window tiling)
- Almost all ComponentPeer flags:
- windowHasTitleBar
- windowIsTemporary
- windowHasMinimiseButton/windowHasMaximiseButton/windowHasCloseButton
- windowIsSemiTransparent
- windowIgnoresMouseClicks/windowIgnoresKeyPresses
- Window positioning (for windows with a parent, more on this later)
- Minimise/maximise
- Screen scaling support (but not fractional yet)
- Keyboard input
- Mouse input (with better trackpad support than JUCE+X11 has)
- Setting mouse cursor
- Clipboard
- File/text drag and drop
- Monitor information
- Loads dynamically at runtime, no hard dependencies
- Automatic X11 fallback:
- If WAYLAND_DISPLAY is not set
- If Wayland or libdecor could not be loaded
- If JUCE_XWAYLAND environment variable is set
- If we’re loaded as a plugin
- Tested on KDE/GNOME/elementary/Weston
Not implemented but doable:
Touch inputDone!- Fractional scaling
Multi-display setups haven’t been testedWorks, but not if they have different scaling factors
What doesn’t work yet:
- System tray icons (should be using dbus)
- Setting application icons at runtime (should be provided in .desktop file)
- XEmbedComponent and web browser component
- Working with real screen coordinates (we simulate screen coordinates)
Keep in mind, this implementation is brand new, so there’s almost certainly more edge cases I’ve missed. It also has a dependency on libdecor to be able to draw native titlebars, if it’s not installed, it will fall back to XWayland.
The biggest difference between JUCE on Wayland compared to other platforms, is the way window positioning works. Wayland doesn’t allow controlling the position of top-level windows by design. You can however position a child window relative to a parent window.
If we simulate a screen coordinate space by pretending that each top-level window is at {0, 0}, we can position dialogs in that faked screen space, so they will appear in the correct position relative to their parent window. Retrieving the screen mouse position will return the position in the coordinate space of the window that the mouse is currently over. This sounds complicated, but in practice this will work fine for most JUCE apps.
The only big difference on your app’s side is gonna be choosing whether windows are top level, or child windows. Currently, if you set windowIsTemporary without setting windowHasTitlebar, your window will become a positionable child window, attached to the last top-level window that had focus. The same applies to z-index: child windows can be ordered relative to other child windows with the same parent.
Right now, audio plugins will always use X11 because right now, that’s what plugin hosts expect. I believe there is work done on getting LV2 plugins to work under Wayland.
Perhaps this will be useful for other JUCE apps that ship on Linux. It would be cool to see optional Wayland support merged into JUCE someday, but I guess it’s hard to justify that when it will always inherently behave differently from JUCE on any other platform. Also, feel free to send PRs if you see any improvements that can be made!

