Skip to content

Linux window host: hand-rolled X11 + wgpu/Vulkan (PlatformLinux) - #1550

Merged
larsbrubaker merged 2 commits into
MatterHackers:mainfrom
cope413:linux-x11-host
Aug 25, 2026
Merged

Linux window host: hand-rolled X11 + wgpu/Vulkan (PlatformLinux)#1550
larsbrubaker merged 2 commits into
MatterHackers:mainfrom
cope413:linux-x11-host

Conversation

@cope413

@cope413 cope413 commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

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 to PlatformMac'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 against Xlib.h with a C probe (VerifyLayouts() + unit test).
  • X11SystemWindowIPlatformWindow port of MacSystemWindow: poll-based event loop that doubles as the idle pump, paint/present, resize (synchronous paint during a WM drag burst), close routing (HandlePlatformCloseRequest verbatim), screenshots, AGG_SMOKE_* contract, cursors, _NET_WM_NAME / _NET_WM_STATE (pre-map, per EWMH). Input: Y flip pixelHeight - y (matches WinformsEventSink and AutomationRunner's inverse), OutOfViewMouseCapture backed by XGrabPointer with state-mask reconciliation, keyboard via XLookupString with autorepeat detection, modifier tracking, focus filtering on mode and detail (focus-follows-mouse safe).
  • X11WebGpuLayer — port of MacWebGpuLayer over WindowSurfaceRequest.ForXlibWindow.
  • WebGpuX11WindowProvider, LinuxInformationProvider (OSType.X11, Xft.dpi scale).
  • 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 — real CLIPBOARD selection 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 in PasteFromClipboard).

WebGpuRenderWindowSurfaceRequest.ForXlibWindow(display, window, …) and an OperatingSystem.IsLinux() branch in CreateRawSurface using WGPUSurfaceSourceXlibWindow.

WiringAggContext.ProviderSettings is three-way (Linux names the agg_platform_linux providers); AGG_WINDOW_PROVIDER=x11 short name.

TestsAgg.Tests gains WindowsBuild/MacBuild/LinuxBuild selectors (Linux is the fallback leg; -p:WindowsBuild=true forces 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 fixes agg/agg.csprojagg/Agg.csproj casing — Agg.Tests had never built on a case-sensitive filesystem.

Verification

  • Linux, forced-mac and forced-Windows legs all build with 0 errors.
  • 408/408 Agg.UI tests (incl. the automation suite driving real input) pass under Xvfb + lavapipe.
  • Smokes under Xvfb: AGG_SMOKE ok with [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-overwrite deprecated in zenity 4; native Wayland; vulkan golden-image baseline.

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.
Copilot AI lite review requested due to automatic review settings August 25, 2026 18:48

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 / WebGpuRenderDevice to support Linux/X11 surface creation via (Display*, XID) using WGPUSurfaceSourceXlibWindow.
  • 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.Tests multi-OS build selection + fix Agg.csproj casing 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>
@larsbrubaker
larsbrubaker merged commit d66bc43 into MatterHackers:main Aug 25, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants