[WIP] Add Wayland backend
What does the pull request do?
Add a Wayland backend for Linux. This PR is based on the previous one with significant bug fixes and easier maintenance .
In order to test this PR, locally building NWayland NuGet packages is required:
git clone --recursive https://github.com/affederaffe/NWayland next to the Avalonia directory
├── Avalonia │ ├── samples │ ├── src │ ├── ... ├── NWayland │ ├── src │ ├── ...
Navigate to ./NWayland/src/NWayland.Scanner and dotnet run to generate the bindings.
Then dotnet build -c Release the ./NWayland/src/NWayland and ./NWayland/src/NWayland.Protocols.Plasma projects, which creates the required NuGet packages.
These steps won't be necessary once NWayland is released officially on NuGet.
TODOs:
- Better CSD integration
- IME
What is the current behavior?
XWayland is used in order to run Avalonia apps on Wayland systems.
What is the updated/expected behavior with this PR?
Use Wayland instead of X11 on compatible systems.
How was the solution implemented (if it's not obvious)?
Checklist
- [ ] Added unit tests (if possible)?
- [ ] Added XML documentation to any related classes?
- [ ] Consider submitting a PR to https://github.com/AvaloniaUI/Documentation with user documentation
Breaking changes
None
Obsoletions / Deprecations
None
Fixed issues
Fixes #1243 Fixes #2338
Thank you so much for your work! I hope this gets merged into 11!
@affederaffe Do you think this can be still merged for the 11 update?
There are still some minor bugs to be fixed before merging and since Avalonia 11 seems to be moving closer and closer to RCs (feature freeze), I don't think we'll see this merged before 11.0. 11.x seems to be possible though, see the prior discussion
There are still some minor bugs to be fixed before merging and since Avalonia 11 seems to be moving closer and closer to RCs (feature freeze), I don't think we'll see this merged before 11.0. 11.x seems to be possible though, see the prior discussion
11.1.
11.0 rc is coming in a matter of days and the team wont have time to test or review this in that time.
11.1 is likely to be very very soon after 11.0 however.
@affederaffe seems like there's an error building NWayland.Protocols.Plasma
CSC : error CS7027: Error signing output with public key from file '/NWayland/src/sign.snk' -- Could not find file '/NWayland/src/sign.snk'. [/NWayland/src/NWayland.Protocols.Plasma/NWayland.Protocols.Plasma.csproj::TargetFramework=netstandard2.0] CSC : error CS8102: Public signing was specified and requires a public key, but no public key was specified. [/NWayland/src/NWayland.Protocols.Plasma/NWayland.Protocols.Plasma.csproj::TargetFramework=netstandard2.0]
Please git pull in NWayland and try again, see https://github.com/affederaffe/NWayland/commit/c032e578c282a1d53dfed510c3fa3149a456b0be.
Seems like I forgot to push those changes
seems like NWayland needs to be published first so that the unit tests would work again
Anything happening at the moment?
There are at least 2 blockers from my side:
- general support for CSD in the base framework (stealing pixels from ClientSize isn't a good idea)
- merge changes to NWayland and make it to be properly packaged
There are at least 2 blockers from my side:
- general support for CSD in the base framework (stealing pixels from ClientSize isn't a good idea)
- merge changes to NWayland and make it to be properly packaged
I think CSD deserves its own tracker issue.
I took a closer look at the code, and I've noticed that this is still missing a NativeControlHost and access to platform handles.
This raises some issues:
- Wayland uses some global objects (
wl_compositor,wl_subcompositor,wl_display). Should we expose Avalonia's instances directly? - A
wl_surfaceis generally not enough to get anything done—you also need the surface role (xdg_toplevel,xdg_popup,wl_subsurface) to do certain things. How do we expose bothwl_surfaceand<surface role>? - Is
NativeControlHostgoing to usewl_subsurfaceorxdg_toplevel?
@jgcodes2020 does wayland even support windows/control embedding?
@jgcodes2020
I've noticed that this is still missing a NativeControlHost
- Wayland doesn't support cross-client control embedding
- It's not really possible to share a single connection between two toolkits (in some event handlers it's not clear which of the subscribers has ownership over the object created by libwayland-client and it's not possible to tell if there are subscriptions from another toolkit
The recommended (from the official #wayland IRC channel) way to embed widgets from other toolkits is to "write your own nested wayland compositor" and ask said toolkit to use it instead of the system one.
Then you need to create a toplevel window in such toolkit and then find that window in your nested compositor (or maybe spawn a separate compositor per embedded control).
Then you are required to pass input events and receive rendered frames via completely compatible and similar DMA-BUF or EGLStreams APIs depending on the current graphics hardware.
There is also no defined way to integrate TAB-navigation for input focus since the embedded control would think that it's a normal toplevel window, so you'll probably need to patch said third-party toolkit to provide one too.
Such nested compositor would be so rigorously and intuitively obvious to even the most casual software developer, that we leave the implementation to ones who want to use the wonderful, secure, and powerful Wayland protocol for any non-helloworld applications, they'll surely be able to do it an hour or two.
@jgcodes2020 does wayland even support windows/control embedding? @maxkatz6 @kekekeks
Qt uses xdg_foreign to do this.
The issue now of course is getting an xdg_foreign string handle represented by an IntPtr.
Adding onto my previous comment, some frameworks (e.g. SDL, GTK, VLC) support rendering to existing wl_surfaces. So it would go something like (in pseudocode):
wl_surface* surface = gui_get_child_surface(window);
gui2_set_render_surface(surface);
@jgcodes2020 What a peculiar link you've posted here. It indeed describes a protocol that allows apps to exchange surface handles. However an attentive reader (in case said reader has read the protocol at all) would notice that it only works with xdg_toplevel surfaces to establish dialog parent relationships and has nothing to do with control embedding. It was introduced to provide system file dialogs for containerized apps by the means of xdg-portal.
@jgcodes2020 Just to clarify: this sarcastic tone isn't pointed at you but at wayland poor design decisions. It's really hard to do anything useful when protocol authors are actively trying to prevent you from that using made up reasons as excuses.
some frameworks (e.g. SDL, GTK, VLC) support rendering to existing wl_surfaces
I don't think there is a way to make GTK to use a pre-existing wl_display connection. It also would be really hard to integrate event loops, given that Avalonia uses WPF's dispatcher model with rather strict guarantees about callback execution ordering.
We'll need to think about SDL/VLC integration, since those probably expect being non-primary toolkits in the app.
It's not really possible to share a single connection between two toolkits (in some event handlers it's not clear which of the subscribers has ownership over the object created by libwayland-client and it's not possible to tell if there are subscriptions from another toolkit
When it comes to "ownership" of a Wayland object there is wl_proxy_set_tag but it's just a tag that exists per-object. The event handler thing is still definitely an issue I think.
Adding on to some of my previous comments here: providing access to all Wayland singletons used by Avalonia (wl_display, wl_compositor, etc.) plus wl_surface handles is necessary for embedding, as the wl_subsurface has to be created on the same connection as the parent.
There are at least 2 blockers from my side:
- general support for CSD in the base framework (stealing pixels from ClientSize isn't a good idea)
- merge changes to NWayland and make it to be properly packaged
Still the same issues left?
We'll need to think about SDL/VLC integration, since those probably expect being non-primary toolkits in the app.
Going to assume that this is wayland related - I'm using the unofficial avalonia vlc with overlay on Avalonia. Overlay/compositing/alpha works fine but when I exit the app the whole screen freezes and spits
gnome-shell[1685]: Window manager warning: Buggy client sent a _NET_ACTIVE_WINDOW message with a timestamp of 0 for 0xa0016f
mpp[35290]: mpp_info: mpp version: unknown mpp version for missing VCS info
gnome-shell[1685]: Window manager warning: Invalid WM_TRANSIENT_FOR window 0xa00169 specified for 0xa0016f.
Looking at the Avalonia Window source code and Ryujinx, I'm wondering if Avalonia needs to expose better Window close methods for native components but other than that, the hack from the unofficial VLC with an Avalonia window on top of the VLC component works like a charm.
As I see it window embedding isn't really a problem anymore, at least on the video-player side. phonon-vlc seems to be able to integrate vlc and mpv can also be used with an GL context iirc. SDL seems also be possible now: https://wiki.libsdl.org/SDL3/README/wayland#importing-external-surfaces-into-sdl-windows
Any update on this PR?
There's still some work to do:
- Client Side Decorations: Probably needs support in Avalonia.Base Window itself, as pointed out, stealing client side pixels isn't a good idea
- Touch support: currently just crashes when receiving a touch
- IME support: currently in progress
- NWayland NuGet package (submopdules are tolerable for my own development, but this approach won't work for master)
- For a smooth transition, 3rd-party-support, most important video players: needs to use the library directly without window embedding, see libMpv (for example, mpvqt and libVlc. Embedding support is just not feasible as stated above
- (optional) survive compositor crashes There's probably some more, those are just the things from the top of my head.
- [x] All contributors have signed the CLA.
is this dead?
The plan is to figure something about CSD support in core avalonia and continue.
Alternatively we could release it without CSD for usage with embedded systems, wayland seems to be ready enough for those.
There are just too many unresolved issues, until I have the time and motivation to address those this PR continues to be WIP and thus unmergable from my perspective. If everything goes well I'll probably have some time in September to work on some of these issues.
The plan is to figure something about CSD support in core avalonia and continue.
Alternatively we could release it without CSD for usage with embedded systems, wayland seems to be ready enough for those.
My understanding is that only GNOME requires CSD, and most other DEs are happy with SSD.
If that's true, then it might make more sense to just default back to X11 for GNOME, and use Wayland on everything else?