Linux window host: hand-rolled X11 + wgpu/Vulkan (PlatformLinux) - #1550
Merged
Conversation
PlatformLinux mirrors PlatformMac: Xlib P/Invoke layer, X11SystemWindow (event loop, paint/present, resize, close, input with Y flip and pointer capture), X11WebGpuLayer over WindowSurfaceRequest.ForXlibWindow, LinuxInformationProvider, LinuxFileDialogProvider (zenity/kdialog, non-blocking), LinuxClipboard + X11Selection (real CLIPBOARD owner and requestor with INCR receive). AggContext provider settings become three-way; Agg.Tests gains Windows/Mac/Linux build legs and 145 Linux-only tests. Also fixes the agg/Agg.csproj reference casing that kept Agg.Tests from building on case-sensitive filesystems.
There was a problem hiding this comment.
Pull request overview
Adds a new Linux/X11 window-host layer (PlatformLinux) and wires WebGPU surface creation to support Xlib windows at runtime, bringing Linux on-screen rendering/input/clipboard/file dialogs to parity with the existing Windows (WinForms) and macOS (AppKit) hosts.
Changes:
- Extend
WindowSurfaceRequest/WebGpuRenderDeviceto support Linux/X11 surface creation via(Display*, XID)usingWGPUSurfaceSourceXlibWindow. - Introduce
PlatformLinux(X11 host, X11 constants, Linux OS info, clipboard, file dialogs, window provider) and update provider selection/wiring. - Add Linux-specific unit tests and update
Agg.Testsmulti-OS build selection + fixAgg.csprojcasing for case-sensitive filesystems.
Reviewed changes
Copilot reviewed 25 out of 26 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| WebGpuRender/WindowSurfaceRequest.cs | Adds X11-aware surface request factory and stores the XID separately from the display handle. |
| WebGpuRender/WebGpuRenderDevice.cs | Creates wgpu surfaces for Linux/X11 using WGPUSurfaceSourceXlibWindow and improves validation/errors. |
| Tests/Agg.Tests/Agg.WebGpuRender/WindowSurfaceRequestTests.cs | Verifies X11 request field mapping and rejects invalid display/window values. |
| Tests/Agg.Tests/Agg.UI/X11WheelTests.cs | Tests X11 wheel button-to-delta mapping behavior. |
| Tests/Agg.Tests/Agg.UI/X11SystemWindowCloseRoutingTests.cs | Validates close routing logic for X11 host behavior (single-window shell vs dialogs). |
| Tests/Agg.Tests/Agg.UI/X11ResizePaintTests.cs | Tests resize-burst “paint synchronously” decision logic. |
| Tests/Agg.Tests/Agg.UI/X11ModifierStateTests.cs | Tests modifier translation/state correction and focus-loss modifier release behavior. |
| Tests/Agg.Tests/Agg.UI/X11KeyTranslationTests.cs | Tests keysym-to-Keys translation and modifier composition for X11. |
| Tests/Agg.Tests/Agg.UI/X11EventLayoutTests.cs | Verifies Xlib ABI struct layouts and headless-safe Linux information provider behavior. |
| Tests/Agg.Tests/Agg.UI/X11DragOutsideViewTests.cs | Tests out-of-view mouse capture filtering, coordinate transforms, and click counting logic. |
| Tests/Agg.Tests/Agg.UI/LinuxFileDialogProviderTests.cs | Tests zenity/kdialog argument building, output parsing, and failure-vs-cancel classification. |
| Tests/Agg.Tests/Agg.UI/LinuxClipboardTests.cs | Tests X11 selection encoding/decoding helpers and LinuxClipboard headless fallback semantics. |
| Tests/Agg.Tests/Agg.Tests.csproj | Adds Mac/Linux build selectors, conditional platform references, and Linux-specific test includes/removals. |
| PlatformLinux/PlatformLinux.csproj | Introduces the Linux platform project (net10.0, no NuGet deps) with required project references. |
| PlatformLinux/linux/X11WebGpuLayer.cs | Implements the X11 WebGPU swapchain owner + compat GL context, device loss recovery, resize, screenshots. |
| PlatformLinux/linux/X11Constants.cs | Defines required X11 protocol/constants (events, masks, keysyms, cursor shapes, EWMH values). |
| PlatformLinux/linux/WebGpuX11WindowProvider.cs | Provides ISystemWindowProvider implementation for X11-backed system windows. |
| PlatformLinux/linux/LinuxInformationProvider.cs | Implements Linux/X11 OS info provider (desktop size, scale, physical memory) with headless behavior. |
| PlatformLinux/linux/LinuxFileDialogProvider.cs | Implements zenity/kdialog-based file dialogs and reveal-in-folder integration. |
| PlatformLinux/linux/LinuxClipboard.cs | Implements X11 CLIPBOARD selection-backed clipboard with headless and off-thread read behavior. |
| Gui/SystemWindow/SystemWindow.cs | Adds AGG_WINDOW_PROVIDER=x11 short-name resolution and updates messaging accordingly. |
| agg/Platform/AggContext.cs | Wires Linux provider defaults for OS info, dialogs, and system windows based on IsLinux(). |
| agg-sharp.sln | Adds the new PlatformLinux project to the solution. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+15
to
+17
| <LinuxBuild Condition="'$(LinuxBuild)' == ''">$([MSBuild]::IsOSPlatform('Linux'))</LinuxBuild> | ||
| <LinuxBuild Condition="'$(WindowsBuild)' == 'true' or '$(MacBuild)' == 'true'">false</LinuxBuild> | ||
| <LinuxBuild Condition="'$(WindowsBuild)' != 'true' and '$(MacBuild)' != 'true'">true</LinuxBuild> |
Comment on lines
+78
to
+82
| public class LinuxFileDialogProvider : IFileDialogProvider | ||
| { | ||
| /// <summary>Which helper this machine has. Probed once - PATH does not change under a running app.</summary> | ||
| private static readonly Lazy<DialogTool> InstalledTool = new Lazy<DialogTool>(ProbeForTool); | ||
|
|
Comment on lines
+231
to
+235
| /// <returns> | ||
| /// True if a dialog was launched. False only when neither helper is installed - which is reported | ||
| /// once to stderr and never thrown, because a missing optional package must not take the | ||
| /// application down over a menu item. | ||
| /// </returns> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Linux window host: hand-rolled X11 + wgpu/Vulkan (PlatformLinux)
Resolves the port doc's open "O7b" decision: the Linux host is hand-rolled X11 via P/Invoke (
libX11.so.6), structurally parallel toPlatformMac's AppKit P/Invoke host. No SDL/GLFW/GTK dependency. Wayland runs via XWayland.What's here
PlatformLinux/(new,agg_platform_linux, plain net10.0, zero PackageReferences)Xlib.cs— P/Invoke layer; every struct layout verified againstXlib.hwith a C probe (VerifyLayouts()+ unit test).X11SystemWindow—IPlatformWindowport ofMacSystemWindow: poll-based event loop that doubles as the idle pump, paint/present, resize (synchronous paint during a WM drag burst), close routing (HandlePlatformCloseRequestverbatim), screenshots,AGG_SMOKE_*contract, cursors,_NET_WM_NAME/_NET_WM_STATE(pre-map, per EWMH). Input: Y flippixelHeight - y(matchesWinformsEventSinkandAutomationRunner's inverse),OutOfViewMouseCapturebacked byXGrabPointerwith state-mask reconciliation, keyboard viaXLookupStringwith autorepeat detection, modifier tracking, focus filtering onmodeanddetail(focus-follows-mouse safe).X11WebGpuLayer— port ofMacWebGpuLayeroverWindowSurfaceRequest.ForXlibWindow.WebGpuX11WindowProvider,LinuxInformationProvider(OSType.X11,Xft.dpiscale).LinuxFileDialogProvider— zenity → kdialog, argv-only, non-blocking (pool thread +UiThread.RunOnIdle), cancel = no callback (Mac parity), GLib stderr noise filtered from error classification.LinuxClipboard+X11Selection— realCLIPBOARDselection owner/requestor:TARGETS/UTF8_STRING/STRING/TEXT/text/html, INCR receive with per-chunk timeout and abandoned-transfer purge, TARGETS cache, input events deferred during a conversion and replayed (fixes lost keystrokes inPasteFromClipboard).WebGpuRender —
WindowSurfaceRequest.ForXlibWindow(display, window, …)and anOperatingSystem.IsLinux()branch inCreateRawSurfaceusingWGPUSurfaceSourceXlibWindow.Wiring —
AggContext.ProviderSettingsis three-way (Linux names theagg_platform_linuxproviders);AGG_WINDOW_PROVIDER=x11short name.Tests —
Agg.TestsgainsWindowsBuild/MacBuild/LinuxBuildselectors (Linux is the fallback leg;-p:WindowsBuild=trueforces the other two false), references PlatformMac only on mac and PlatformLinux only on Linux, and adds 145 Linux-only tests (X11*Tests,Linux*Tests,WindowSurfaceRequestTests) mirroring the Mac test set. Also fixesagg/agg.csproj→agg/Agg.csprojcasing —Agg.Testshad never built on a case-sensitive filesystem.Verification
Agg.UItests (incl. the automation suite driving real input) pass under Xvfb + lavapipe.AGG_SMOKE okwith[Vulkan llvmpipe]; xdotool input round-trips (click y,a, Shift+Tab, wheel, double-click); xclip clipboard both directions incl. an 8 MB INCR paste; keystrokes sent during a blocked paste arrive afterwards in order.Known follow-ups (out of scope)
No XIM/XIC (dead keys/compose/CJK); INCR sending; no modal scrim under the external dialog; zenity
--confirm-overwritedeprecated in zenity 4; native Wayland;vulkangolden-image baseline.