Repository navigation
Wayland protocol support - #21448
Wayland protocol support#21448
Conversation
d90d0b8 to
5bcdf3c
Compare
5bcdf3c to
eada92b
Compare
There was a problem hiding this comment.
Pull request overview
Adds an experimental Wayland backend to Avalonia, including worker-thread protocol plumbing, UI-thread window/popup implementations, input/IME/clipboard integrations, and Wayland-specific rendering backends (EGL WSI and optional dmabuf). It also extends the cross-thread proxy source generator and the OpenGL/EGL interop layer needed to support the new platform.
Changes:
- Introduces
Avalonia.Waylandproject with window/popup surfaces, worker/persistent/transient object model, reconnection-oriented architecture, and protocol bindings usage via NWayland. - Implements Wayland input (pointer/touch/keyboard), drag-and-drop/clipboard, and zwp_text_input_v3 IME plumbing.
- Extends Avalonia.OpenGL EGL/GL interop to support swap-interval, EGLImage, and dmabuf-related EGL extensions used by the Wayland renderer.
Reviewed changes
Copilot reviewed 95 out of 95 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/tools/DevGenerators/CrossThreadProxyGenerator.cs | Enhances proxy generation (diagnostics, proxy boundary checks, signature adjustments). |
| src/Avalonia.Wayland/XkbContext.cs | Adds xkb_context wrapper. |
| src/Avalonia.Wayland/XkbComposeTable.cs | Adds compose table wrapper (locale-based). |
| src/Avalonia.Wayland/XkbComposeState.cs | Adds compose state wrapper for dead-key/compose sequences. |
| src/Avalonia.Wayland/XkbCommonKeymap.cs | Adds keymap/state wrapper for key resolution/modifiers. |
| src/Avalonia.Wayland/WindowImplBase.Pointer.cs | Wires pointer/touch events into Avalonia raw input. |
| src/Avalonia.Wayland/WindowImplBase.Keyboard.cs | Wires keyboard events and key repeat handling. |
| src/Avalonia.Wayland/WindowImplBase.DragDrop.cs | Adds UI-thread DnD event dispatch + feedback routing. |
| src/Avalonia.Wayland/WindowImplBase.cs | Adds shared base for Wayland toplevel/popup implementations. |
| src/Avalonia.Wayland/WindowImpl.TextInput.cs | Adds UI-thread text input broker (compose gating + IME v3). |
| src/Avalonia.Wayland/WindowImpl.Sink.cs | Adds toplevel sink for configure/close + chrome gesture routing. |
| src/Avalonia.Wayland/WaylandTopLevelFactory.cs | Provides IWindowingPlatform implementation for Wayland. |
| src/Avalonia.Wayland/WaylandTextUtils.cs | Adds UTF-8 byte offset ↔ UTF-16 index conversion helpers. |
| src/Avalonia.Wayland/WaylandSurfaceCreateResult.cs | Adds UI-thread surface creation result bundle. |
| src/Avalonia.Wayland/WaylandPlatform.cs | Platform initialization, service registration, options, UseWayland(). |
| src/Avalonia.Wayland/WaylandCursorFactory.cs | Adds cursor factory + cursor impl stubs. |
| src/Avalonia.Wayland/WaylandConversionExtensions.cs | Adds Avalonia↔Wayland type conversions (popup positioner). |
| src/Avalonia.Wayland/TextInputOptionsConverter.cs | Maps Avalonia text input options to zwp_text_input_v3 hints/purpose. |
| src/Avalonia.Wayland/Server/WaylandWorkerClient.cs | Adds UI-thread-safe worker façade and surface creation APIs. |
| src/Avalonia.Wayland/Server/WaylandWorker.RenderTimer.cs | Adds render-loop wakeup logic + starvation fallback ticking. |
| src/Avalonia.Wayland/Server/WaylandPlatformGraphics.cs | Adds Wayland platform graphics abstraction + ready-state feature. |
| src/Avalonia.Wayland/Server/WaylandMarshallers.cs | Adds marshaller(s) for generated cross-thread proxies. |
| src/Avalonia.Wayland/Server/WaylandDispatchPriority.cs | Defines UI↔worker dispatch priority enum. |
| src/Avalonia.Wayland/Server/Transient/XdgToplevelExport.cs | Implements xdg-foreign export with UI-thread façade. |
| src/Avalonia.Wayland/Server/Transient/WaylandInputDispatcher.Keyboard.cs | Implements keyboard dispatch incl. keymap/compose handling. |
| src/Avalonia.Wayland/Server/Transient/WaylandGlobals.cs | Binds globals, manages versions, initializes graphics + input dispatcher. |
| src/Avalonia.Wayland/Server/Transient/WaylandCursorManager.cs | Loads cursor theme and creates cursor surfaces/buffers. |
| src/Avalonia.Wayland/Server/Transient/Rendering/WaylandFramebuffer.cs | Software framebuffer surface using shm pools and per-frame commits. |
| src/Avalonia.Wayland/Server/Transient/Rendering/WaylandEglWsiSurface.cs | EGL WSI surface wrapping wl_egl_window + swap-driven commit. |
| src/Avalonia.Wayland/Server/Transient/Rendering/WaylandEglWsiPlatformGraphics.cs | EGL display creation for EGL_PLATFORM_WAYLAND_KHR. |
| src/Avalonia.Wayland/Server/Transient/Rendering/WaylandEglDmaBufPlatformGraphics.cs | Optional dmabuf/GBM-based EGL backend + format negotiation. |
| src/Avalonia.Wayland/Server/Transient/Rendering/WaylandEglDisplay.cs | Extends EglDisplay with GBM/DRM/dmabuf metadata. |
| src/Avalonia.Wayland/Server/Transient/Rendering/WaylandDmabufFeedback.cs | Collects dmabuf feedback tranches + format table parsing. |
| src/Avalonia.Wayland/Server/Transient/IWaylandTextInputV3Events.cs | Defines worker→UI IME callback interface for proxy generation. |
| src/Avalonia.Wayland/Server/Transient/Clipboard/WaylandOfferCookie.cs | Adds offer cookie for reconnect-safe/worker-thread-only operations. |
| src/Avalonia.Wayland/Server/Transient/Clipboard/WaylandDataSource.cs | Wraps wl_data_source and dispatches send/cancel events. |
| src/Avalonia.Wayland/Server/Transient/Clipboard/WaylandDataOffer.cs | Wraps wl_data_offer, MIME collection, accept/receive APIs. |
| src/Avalonia.Wayland/Server/ServerSignaler.cs | Adds coalescing signal mechanism for worker callbacks. |
| src/Avalonia.Wayland/Server/Persistent/XdgPopupPositionerParams.cs | Immutable UI→worker popup positioner parameters record. |
| src/Avalonia.Wayland/Server/Persistent/XdgPopupConfigureBatch.cs | Worker-side popup configure accumulator. |
| src/Avalonia.Wayland/Server/Persistent/XdgConfigureBatch.cs | Worker-side toplevel configure batch + state parsing. |
| src/Avalonia.Wayland/Server/Persistent/WaylandInputEventCookie.cs | Adds per-input cookie for seat/serial + reconnect-safe posting. |
| src/Avalonia.Wayland/Server/Persistent/IWXdgTopLevel.cs | Defines UI→worker proxy interfaces for xdg surfaces/toplevels/popups. |
| src/Avalonia.Wayland/Server/Persistent/IWSurfaceEventSink.cs | Defines worker→UI sink interfaces (input/configure/close/popup). |
| src/Avalonia.Wayland/Server/Persistent/IWSurface.cs | Defines UI→worker proxy interface for generic surface ops + text input. |
| src/Avalonia.Wayland/Server/Persistent/IPersistentObject.cs | Defines persistent wayland object lifecycle interface. |
| src/Avalonia.Wayland/Server/Persistent/DecorationMode.cs | Defines decoration mode enum decoupled from binding types. |
| src/Avalonia.Wayland/Server/Interop/XkbCommonNativeMethods.cs | Adds libxkbcommon P/Invokes and constants. |
| src/Avalonia.Wayland/Server/Interop/WaylandEglNativeMethods.cs | Adds wl_egl_window interop P/Invokes. |
| src/Avalonia.Wayland/Server/Interop/WaylandConnection.cs | Adds connection wrapper + poll/flush/read dispatch loop. |
| src/Avalonia.Wayland/Server/Interop/WakeupFd.cs | Adds wakeup pipe abstraction for worker polling. |
| src/Avalonia.Wayland/Server/Interop/UnsafeNativeMethods.cs | Adds libc + cursor-theme P/Invokes and constants. |
| src/Avalonia.Wayland/Server/Interop/Pipe2Stream.cs | Wraps pipe2 fd into PipeStream for async IO. |
| src/Avalonia.Wayland/Server/Interop/DrmGbmUnsafeNativeMethods.cs | Adds GBM/DRM P/Invokes and dmabuf-related constants. |
| src/Avalonia.Wayland/Screens/WaylandOutputSnapshot.cs | Adds immutable output snapshots for UI-side screen model. |
| src/Avalonia.Wayland/Screens/SnapshotScreensImpl.cs | Implements UI-thread screen impl driven by worker snapshots. |
| src/Avalonia.Wayland/Screens/IWaylandOutputsSink.cs | Defines worker→UI outputs sink interface for proxy generation. |
| src/Avalonia.Wayland/README.md | Documents Wayland backend architecture, threading, protocol rules. |
| src/Avalonia.Wayland/PopupImpl.Sink.cs | Adds popup sink (configure/done + worker proxy wiring). |
| src/Avalonia.Wayland/PopupImpl.cs | Implements xdg_popup UI-side logic and positioner integration. |
| src/Avalonia.Wayland/IWaylandXdgTopLevelExport.cs | Defines UI-thread interface for xdg-foreign export handle. |
| src/Avalonia.Wayland/Clipboard/WaylandOutgoingTransfer.cs | Implements outgoing clipboard/DnD source bridging UI↔worker. |
| src/Avalonia.Wayland/Clipboard/WaylandMimeMapper.cs | Maps Avalonia formats to Wayland MIME types and back. |
| src/Avalonia.Wayland/Clipboard/WaylandDragSource.cs | Implements IPlatformDragSource using Wayland DnD. |
| src/Avalonia.Wayland/Clipboard/WaylandDataTransfer.cs | Implements incoming data transfer from wl_data_offer (sync/async). |
| src/Avalonia.Wayland/Clipboard/WaylandClipboardImpl.cs | Implements owned clipboard via Wayland worker interactions. |
| src/Avalonia.Wayland/AvaloniaWaylandException.cs | Adds Wayland-specific exception types. |
| src/Avalonia.Wayland/Avalonia.Wayland.csproj | Adds new Wayland project + NWayland reference and shared includes. |
| src/Avalonia.OpenGL/GlInterface.cs | Adds GL_OES_EGL_image entry point binding. |
| src/Avalonia.OpenGL/GlConsts.cs | Enables required GL constants for image/FBO plumbing. |
| src/Avalonia.OpenGL/Egl/EglInterface.cs | Adds eglSwapInterval and EGLImage + dmabuf extension entry points. |
| src/Avalonia.OpenGL/Egl/EglImage.cs | Adds EGLImage wrapper with proper destruction. |
| src/Avalonia.OpenGL/Egl/EglGlPlatformSurfaceBase.cs | Adds beforeSwap hook and adjusts overridable visibility. |
| src/Avalonia.OpenGL/Egl/EglGlPlatformSurface.cs | Updates SkipWaits override visibility to match base change. |
| src/Avalonia.OpenGL/Egl/EglGlPlatformImageSurfaceBase.cs | Adds EGLImage-backed image surface render target base. |
| src/Avalonia.OpenGL/Egl/EglDisplay.cs | Fixes dispose enumeration safety by iterating on a snapshot list. |
| src/Avalonia.OpenGL/Egl/EglConsts.cs | Adds EGL constants for images, dmabuf import, and GBM platform. |
| src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj | Adds InternalsVisibleTo for Avalonia.Wayland. |
| src/Avalonia.Dialogs/Avalonia.Dialogs.csproj | Adds InternalsVisibleTo for Avalonia.Wayland. |
| src/Avalonia.Controls/Avalonia.Controls.csproj | Adds InternalsVisibleTo for Avalonia.Wayland. |
| src/Avalonia.Base/Avalonia.Base.csproj | Adds InternalsVisibleTo for Avalonia.Wayland. |
| samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj | References Avalonia.Wayland for sample usage. |
| Avalonia.slnx | Adds Avalonia.Wayland project to solution structure. |
| Avalonia.Desktop.slnf | Adds Avalonia.Wayland + associated test projects to filter. |
| api/Avalonia.nupkg.xml | Suppresses API diff for EGL BeginDraw signature change. |
| .github/copilot-instructions.md | Adds guidance to consult Wayland README when reviewing Wayland code. |
|
You can test this PR using the following package version. |
|
We discussed that elsewhere, but desktop GL versions aren't working correctly with the latest Nvidia drivers (595.71.05) with EGL. I'm leaving a comment here so we don't forget. For now, specifying |
| @@ -104,6 +104,9 @@ public partial IntPtr CreateContext(IntPtr display, IntPtr config, | |||
| [GetProcAddress("eglSwapBuffers")] | |||
| public partial void SwapBuffers(IntPtr display, IntPtr surface); | |||
There was a problem hiding this comment.
This predates this PR, but eglSwapBuffers returns a bool. We're saved by the ABI again :)
|
You can test this PR using the following package version. |
|
You can test this PR using the following package version. |
|
You can test this PR using the following package version. |
|
You can test this PR using the following package version. |
28f3661 to
ec421e6
Compare
|
You can test this PR using the following package version. |
|
You can test this PR using the following package version. |
| ## Special considerations | ||
|
|
||
| Unlike other platforms where the OS provided window server is considered to be stable, with Wayland it's EXPECTED for | ||
| compositor to crash and restart during normal usage. This means that applications need to be able to handle this situation |
There was a problem hiding this comment.
Is this actually accurate? From my understanding, most Wayland compositors don't even support crash recovery out-of-the-box (or if they do, it's a pretty new feature), and compositors that do support some form of crash recovery try to handle this my making it as "invisible" as possible to the application (e.g. a separate layer that holds buffers so they don't get released/destroyed if the compositor crashes. (I just googled to check again, and at least Gnome doesn't seem to have any crash recovery or compositor restart capability at all.)
Maybe special-purpose embedded Wayland compositors handle things differently somehow, but from everything I've seen/heard/read/experienced, applications (or toolkits in this case) shouldn't need to concern themselves with compositor crashes.
Missing (planned) features:
Known issues:
framecallbacks and don't need to tracksuspendedfor a windowTODO:
For technical notes refer for README.md.
Please, do not manually bump the branch to master, this branch is not authoritative and contains manually picked parts of one with unfinished integration test suite and various garbage changes that I need for backend development.