Skip to content

Wayland protocol support - #21448

Merged
kekekeks merged 3 commits into
masterfrom
feature/wayland-pr-branch
Jun 17, 2026
Merged

kekekeks merged 3 commits into
masterfrom
feature/wayland-pr-branch

Conversation

@kekekeks

@kekekeks kekekeks commented May 28, 2026 •

Copy link
Copy Markdown
Member

Missing (planned) features:

  • A11Y
  • Global app menu (KDE-only feature)
  • Window icons (KDE-only feature)
  • Blur-behind (KDE-only feature)
  • Native embedding (will be a separate package that will work with X11/offscreen/whatever too, out of scope of the backend, backend-level embedding deemed impossible to implement properly for any of the considered complex 3rd party UI kits)
  • Integration test suite (will arrive as a separate PR later)
  • UsePlatformDetect() integration (backend is currently considered experimental and needs to be manually enabled via UseWayland())

Known issues:

  • min/max size doesn't take frame into account (need AdjustWindowRectEx-esque API for CSD)
  • need to verify across multiple compositors that we can rely on frame callbacks and don't need to track suspended for a window
  • Client area extension feature is underdeveloped, area gets extended to the full surface including shadows (not really a backend problem, need to fix on Avalonia.Controls side)

TODO:

  • more testing for IME, in particular need to verify that we are grouping operations correctly

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.

@MrJul MrJul added this to the 12.1 milestone May 28, 2026
@kekekeks
kekekeks force-pushed the feature/wayland-pr-branch branch from d90d0b8 to 5bcdf3c Compare May 28, 2026 14:17
@kekekeks
kekekeks force-pushed the feature/wayland-pr-branch branch from 5bcdf3c to eada92b Compare June 8, 2026 08:45
@kekekeks
kekekeks requested a review from Copilot June 8, 2026 08:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.Wayland project 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.

@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.1.999-cibuild0066157-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@MrJul

MrJul commented Jun 9, 2026

Copy link
Copy Markdown
Member

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 GlProfiles = [new GlVersion(GlProfileType.OpenGLES, 3, 2)] works.

Comment thread src/Avalonia.Wayland/WaylandPlatform.cs Resolved
Comment thread src/Avalonia.OpenGL/Egl/EglImage.cs Resolved
@@ -104,6 +104,9 @@ public partial IntPtr CreateContext(IntPtr display, IntPtr config,
[GetProcAddress("eglSwapBuffers")]
public partial void SwapBuffers(IntPtr display, IntPtr surface);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This predates this PR, but eglSwapBuffers returns a bool. We're saved by the ABI again :)

Comment thread src/Avalonia.Wayland/README.md Resolved
@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.1.999-cibuild0066445-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.1.999-cibuild0066447-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.1.999-cibuild0066458-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.1.999-cibuild0066460-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

MrJul
MrJul previously approved these changes Jun 16, 2026

@MrJul MrJul left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

MrJul
MrJul previously approved these changes Jun 16, 2026
@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.1.999-cibuild0066532-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.1.999-cibuild0066547-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@kekekeks
kekekeks merged commit 12cefeb into master Jun 17, 2026
11 checks passed
@kekekeks
kekekeks deleted the feature/wayland-pr-branch branch June 17, 2026 05:28
## 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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants