Ranvier.View.WebCore.Sdl 0.1.0-rc.1

This is a prerelease version of Ranvier.View.WebCore.Sdl.
dotnet add package Ranvier.View.WebCore.Sdl --version 0.1.0-rc.1
                    
NuGet\Install-Package Ranvier.View.WebCore.Sdl -Version 0.1.0-rc.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Ranvier.View.WebCore.Sdl" Version="0.1.0-rc.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Ranvier.View.WebCore.Sdl" Version="0.1.0-rc.1" />
                    
Directory.Packages.props
<PackageReference Include="Ranvier.View.WebCore.Sdl" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Ranvier.View.WebCore.Sdl --version 0.1.0-rc.1
                    
#r "nuget: Ranvier.View.WebCore.Sdl, 0.1.0-rc.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Ranvier.View.WebCore.Sdl@0.1.0-rc.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Ranvier.View.WebCore.Sdl&version=0.1.0-rc.1&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Ranvier.View.WebCore.Sdl&version=0.1.0-rc.1&prerelease
                    
Install as a Cake Tool

Ranvier.View.WebCore.Sdl

Shows a Ranvier.View.WebCore page in an SDL3 window, through ppy.SDL3-CS. The window paints the page when it asks for a frame. It forwards mouse, wheel, keyboard, input method and focus events to the page. It also sets the page's cursor and moves its text/plain clipboard data through SDL.

Install

dotnet add package Ranvier.View.WebCore.Sdl --version 0.1.0-rc.1

Use Ranvier.View.WebCore.Sdl.Traced for a traced build. Backend, shared contracts, canonical interop, SDL3 and the five-RID native aggregate are transitive dependencies.

For Windows x64 shared GPU presentation, add the matching GPU runtime and suppress the aggregate's Slim win-x64 assets in the application project:

<ItemGroup>
  <PackageReference Include="Ranvier.WebCore.Native.win-x64" Version="[0.1.1-rc.2]" ExcludeAssets="all" />
  <PackageReference Include="Ranvier.WebCore.Native.Gpu.win-x64" Version="[0.1.1-rc.2]" />
</ItemGroup>

Select the direct3d11 renderer through Window.create's renderer argument. The other four native RID dependencies remain available; the explicit exclusion prevents conflicting Windows native payloads.

On Windows, a native GPU runtime with the presentation-d3d11 capability uses shared D3D11 textures with SDL's direct3d11 renderer at display scale 1. Other renderers, unsupported devices and other display scales use CPU painting. An explicit renderer = "software" keeps CPU presentation. GPU frames are released after SDL submits its drawing, including readback, and before renderer teardown.

The accessibility-uia capability attaches the page's Windows UI Automation tree to the SDL window. It detaches before page or window disposal. The bridge uses native COM and also works in a NativeAOT app.

Linux input methods

SDL forwards composition and committed text to the focused page. For an X11 application that needs IBus surrounding text, an optional patched SDL build selects SDL's direct IBus context when SDL_RANVIER_IBUS=1 is set before the first SDL window is created. Query window.ImeSurroundingAvailable to determine whether surrounding text is currently available. It is false when the context is unavailable or cleared, including while a password field is focused. If direct IBus cannot initialize, X11 falls back to XIM; that fallback does not provide this extension.

The optional Ranvier.View.WebCore.Sdl.Ibus package and its SDL build are currently private qualification artifacts, not published packages. The SDL build and packaging instructions describe the pinned source, prerequisites, explicit linux-x64 publish target, and current limitations. Wayland text-input-v3 and XIM do not use this direct-IBus extension; single-file publish and other architectures have not been qualified for the optional package.

Platform support

Experimental, on Windows x64, Windows ARM64, Linux x64 and macOS arm64 (macOS 26), like the backend. WebCore's run loop and SDL's event pump share the process main thread on macOS, with the same Window.Step implementation.

macOS CI passed 770 tests, with 16 ignored and no failures. Those tests cover a hidden window, paint readback and SDL input; the visible sample smoke also passed (480x320 backing pixels, scale 1, painted content and clipboard). RANVIER_SMOKE=1 closes the sample automatically. Retina scale 2 and a real IME still need manual verification; the clipboard bridge supports text/plain only.

The subsequent four-platform CI run passed 773 tests per platform, with 16 existing ignored and no failures, plus the visible sample and both NativeAOT apps. Windows ARM64 ran on a real ARM runner; Linux used Ubuntu 24.04 with Xvfb.

open Ranvier
open Ranvier.View
open Ranvier.View.Dom
open Ranvier.View.WebCore.Sdl

Window.run ("Counter", 480, 320) (fun host ->
    let graph = new Graph ()
    let container = host.Document.createElement "div"
    host.Document.body.appendChild container |> ignore

    Mounting.mount graph None (fun errors -> raise (AggregateException errors)) container None (fun context ->
        Program.run (Component.render counter 0) context.Backend))

Window.run returns when the window closes. An app that owns its loop calls Window.create and then Step each turn instead. Step waits for window events until the next timer is due, dispatches them, cycles the host and presents a frame when one is wanted:

use window = Window.create ("Counter", 480, 320)
// mount into window.Host.Document
while window.Step () do
    () // the app's own work

The window's size is in the platform's window units. The page's CSS pixels follow the display's scale, so a 480 by 320 window shows 480 by 320 CSS pixels on any display. NativeHandle is the platform's window (an HWND on Windows), for an accessibility bridge.

All calls go on the thread that created the window. That thread is the host's thread, and the main thread on macOS.

examples/Ranvier.NativeCounter is a complete app, published with NativeAOT.

NativeAOT

Publish the smoke app and counter on the target OS:

dotnet publish tests/Ranvier.View.WebCore.AotSmoke -c Release -r win-x64 -o artifacts/native-aot/smoke
dotnet publish examples/Ranvier.NativeCounter -c Release -r win-x64 -o artifacts/native-aot/counter

Use -r osx-arm64 on macOS 26. Windows needs the .NET 10 SDK, Visual Studio C++ Build Tools (the Desktop development with C++ workload) and a Windows SDK; macOS needs the .NET 10 SDK and Xcode command-line tools. Run the published smoke executable directly; it verifies mount, paint, native click and repaint. Run the published counter with RANVIER_SMOKE=1 for its bounded visible-window check. Keep all native libraries and WebKit.resources from the publish folder beside the executable. The app is native; the WebCore libraries and resources remain separate files.

Size-oriented publishing

For a smaller NativeAOT executable, opt in to the .NET SDK's size optimization at publish time:

dotnet publish examples/Ranvier.NativeCounter -c Release -r win-x64 -p:OptimizationPreference=Size -o artifacts/native-aot/counter-size

Apply the same property to your own application's project and target RID. The default publish remains unchanged; size optimization can trade execution speed for a smaller executable, so measure your own workload.

In a matched Windows x64 Release comparison using public Ranvier.Dom alpha.55, View source 5435298 and the private ABI 62 GPU native runtime 590e299, the Counter executable changed from 6,450,176 to 5,701,120 bytes (−11.61%). The backend smoke executable changed from 6,181,376 to 5,463,040 bytes (−11.62%). Both profiles passed the same Counter and 30-check smoke runs with NativeAOT warnings treated as errors. The 89,778,897-byte WebCore native payload was identical in both profiles; the Counter runtime files excluding symbols and XML documentation therefore fell from 99,350,737 to 98,601,681 bytes (−0.75%). These are measurements of one private Windows GPU cohort, not a size guarantee for other runtimes, applications or platforms.

Both apps published and ran on Windows x64 locally and in Windows and macOS arm64 CI. The counter opened a visible 480x320 window, with scale 1, matching backing dimensions, painted content and a successful text/plain clipboard round-trip on each platform. Retina scale 2 and a real IME remain manual checks. NativeAOT still reports FSharp.Core/view reflection, trimming and generic-recursion warnings; the exercised app paths pass, and broader AOT coverage remains work to do.

Windows presentation and accessibility acceptance

The visible smoke reads SDL's actual backbuffer. RANVIER_SMOKE_GPU=1 requires at least one shared D3D11 frame; RANVIER_SMOKE_UIA=1 requires an attached UI Automation tree. Build the independent OS client with python tools/native-window-probe.py, then set RANVIER_UIA_PROBE to the absolute path of artifacts/native-window/UiAutomationProbe.exe. The smoke keeps pumping the owner thread while the client finds the counter button, invokes it, observes its new accessible name and closes the window. It verifies that the retained UIA element becomes unavailable after teardown.

Local JIT and NativeAOT checks passed with a private Windows x64 GPU host/WebCore build: the SDL backbuffer was 480x320 at scale 1, shared frames were presented, and the independent tree/action/teardown checks and clipboard round-trip passed. The persisted presenter also passed software-renderer and scale-2 CPU fallback checks, then resumed shared presentation at scale 1. These checks precede the coordinated package release.

Corrected preview.7 native CI packages from run 40729363033 also passed normal/traced package-only CPU consumers under JIT and NativeAOT. Each counter run verified the 480x320 actual backbuffer, clipboard and independent UIA discovery, bounds, Invoke, reactive name updates and provider disconnection. Native and resource payload hashes matched the packages, including the corrected nested icon paths. The same eight normal/traced Smoke/Counter JIT/NativeAOT runs also pass with native packages from official NuGet, matching the clean preview.7 release source. View libraries are locally packed in these runs. The package acceptance workflow checks fully published normal/traced CPU and GPU consumers.

Full source CI passed all four platform jobs with 781 backend tests, 12 existing ignored, 15 NativeAOT smoke checks and both visible counter runs each. Windows x64 verifies the independent external UIA client; Windows ARM64 verifies UIA attachment/smoke without that client.

The manual CI webcore-gpu lane takes an exact gpu_runtime_version, public NuGet v3 gpu_runtime_source and gpu_runtime_package (default Ranvier.WebCore.Native.Gpu.win-x64). It verifies the package's GPU flavor, RID, version, clean source revision and file hashes before staging it. Managed interop uses that same version. Both JIT and NativeAOT must pass the strict shared-frame, actual-backbuffer and independent UIA checks, and a failing enabled GPU lane fails the aggregate CI result. An empty version disables the lane; CPU CI does not count as GPU verification. Run 40784192253 passed all 18 jobs with public GPU preview.7: JIT and NativeAOT each presented two shared frames at 480x320/scale 1 and passed clipboard and independent UIA tree/action/teardown checks.

Final fully public acceptance passed all four normal/traced Slim/GPU jobs. Both apps ran under JIT and NativeAOT in each job: all eight visible Counter runs passed clipboard/backbuffer and independent UIA checks. Each GPU Counter recorded two shared frames; Slim Counters recorded zero. NativeAOT stdout/stderr logs are preserved as artifacts. Every selected native/resource file matches its public package manifest (24 Slim or 26 GPU).

Optional Linux accessibility

An optional libRanvierWebCoreAtspi.so sidecar mirrors the native rv_ax_* tree through the desktop AT-SPI bus. It uses the existing host loop and stays outside the renderer library. Place the matching module beside the app or on its native library search path. The provider discovers AT_SPI_BUS_ADDRESS or org.a11y.Bus on the session bus; Window.AccessibilityAttached is false when the module or desktop service is unavailable.

The Window owns the provider lease through the Host's cleanup installations. Direct Host disposal and Window disposal release it before destroying the native page. SDL movement and display-scale changes update its geometry. X11 exposes physical screen positions; Wayland reports screen coordinates unsupported while window coordinates remain available. All operations run on the host owner thread. This integration does not replace Windows UI Automation.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0-rc.1 45 11/4/2026
0.1.0-alpha.48 46 11/4/2026
0.1.0-alpha.47 41 11/3/2026
0.1.0-alpha.46 51 11/3/2026
0.1.0-alpha.45 60 11/3/2026
0.1.0-alpha.44 60 11/1/2026
0.1.0-alpha.39 59 11/1/2026
0.1.0-alpha.8 63 10/31/2026
0.1.0-alpha.7 56 10/31/2026
0.1.0-alpha.6 58 10/31/2026
0.1.0-alpha.5 57 10/30/2026
0.1.0-alpha.4 60 10/30/2026
0.1.0-alpha.3 58 10/29/2026
0.1.0-alpha.2 58 10/29/2026
0.1.0-alpha.1 69 10/29/2026

Experimental. The API may change.