Wayland Implementation for JUCE

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 input Done!
  • Fractional scaling
  • Multi-display setups haven’t been tested Works, 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!

14 Likes

An excellent bit of work - I look forward to putting this through some tests in the next week. Will send feedback on github.

Well done and thanks for sharing it with us!

1 Like

This looks great!

If you added multi-touch input then lots of people using JUCE on embedded systems would be very interested in this fork. Some of the more popular embedded platforms only support multi-touch and OpenGL (ES) when using Wayland directly, rather than via XWayland.

The JUCE team has been thinking about Wayland support. We’re shortly going to start some work to add OpenGL ES support to our current Linux backend, with the view that this would also be useful for eventual Wayland support on those embedded platforms.

3 Likes

@t0m - will you be reviewing @timothyschoen’s patch to see about its viability for integration in future JUCE develop work? Would be good to have a clear view of what it would take to mainline it. I’ll be digging into it (because I also have a Wayland branch, albeit in worse shape by far) and testing it for my Linux systems this week.

I would also be happy to assist anyone with an interest in adding multi-touch support to JUCE, and can help with any immediate testing that might be required.

We don’t have any immediate plans to add Wayland support to JUCE, but having Wayland multi-touch and OpenGL ES working (particularly on embedded systems) may be enough to change those plans. We’re going to start work on the latter shortly, so it’s multi-touch that’s the other important piece.

Thanks for the info. FWIW, I’ve workbenched embedded JUCE in a product prototype and it seems very promising. I predict we will see hardware designed for running JUCE plugins, fulfilling many a DSP hackers dream, in the near future … not just projects like FundamentalFrequencys’ LMN3-DAW, which is awesome, but pretty close to that in terms of architecture, albeit maybe designed with a JUCE plugin “app store” front end …

JUCE is already in a lot of hardware, and trusted enough to be in some flagship products :slightly_smiling_face:

Maybe you can tell us about some of the more interesting examples? Possibly in a new thread?

I’m afraid that is already right on the limit of what I’m able to disclose.

It is well known that the modern Akai MPC line is built using JUCE, for instance.
There are also several JUCE based plugins running embedded on MOD hardware, although they have to use a separate LV2 implementation because JUCE doesn’t support Control Ports.

@t0m I wonder why you are linking GLES and Wayland? rendering and windowing are not necessarily related I’d think (you could run GLES without any windowing or even in a browser using webgl).

1 Like

Making progress with touch!

7 Likes

It’s a little counterintuitive, but you cannot use OpenGL (or equivalent) when using XWayland on some of the more popular embedded platforms, and they have stopped supporting X11 directly.

I probably wouldn’t use a windowing context for an embedded device anyway. just grab a dedicated framebuffer :wink:

I think with the move to drop the X11 backend in GNOME this just became a whole lot more relevant. I’ll see about trying this out on my machine.

You can always run xwayland, but it doesn’t work perfectly and we’ve seen regular issues from users.