cvkg-render-native
Desktop windowing and rendering backend for the CVKG UI framework. Uses winit for window and event handling, accesskit for accessibility tree integration, and cvkg-render-gpu for GPU-accelerated drawing.
Purpose
This crate bridges CVKG's virtual DOM and rendering abstractions to native desktop platforms. It owns the event loop, window lifecycle, input translation, accessibility tree synchronization, asset loading from the local filesystem, audio playback via rodio, and the frame rendering pipeline that connects cvkg-vdom diffs to cvkg-render-gpu draw calls.
It is not a general-purpose windowing library. It exists solely to serve as the native target backend for CVKG applications.
Boundaries
In scope:
- Winit event loop and window creation/management
- Keyboard, mouse, IME, focus, and file-drop event translation to CVKG events
- AccessKit accessibility tree integration and per-window adapter management
- GPU renderer lifecycle: initialization, resize, frame begin/end, draw-call forwarding
- Local filesystem asset loading with lock-free
ArcSwapcache - Audio playback via rodio (spatialized sound cues)
- Visual haptic feedback fallback
- Multi-monitor DPI awareness and safe-area inset computation
- Visual regression testing infrastructure (golden-image comparison)
Out of scope:
- Web or mobile targets (those have their own render backends)
- Widget toolkit implementation (CVKG widgets live in
cvkg-vdomandcvkg-core) - GPU backend implementation (lives in
cvkg-render-gpu) - Shader authoring or 3D scene graph (handled by the GPU renderer)
- Accessibility tree content (generated by
cvkg-vdom; this crate only synchronizes it)
Dependency graph
graph LR
subgraph External
W[winit 0.30]
A[accesskit 0.24]
AW[accesskit_winit 0.33]
AU[accesskit_unix 0.21<br/>cfg linux]
AR[arc-swap 1.9]
AB[arboard 3.4.0]
IM[image 0.25]
LC[libc 0.2]
LG[log 0.4]
PL[pollster 0.4.0]
RD[rodio 0.21]
TK[tokio 1.0<br/>sync,rt,macros,rt-multi-thread]
end
subgraph Internal
CC[cvkg-core 0.2.15]
CG[cvkg-render-gpu 0.2.15]
CV[cvkg-vdom 0.2.15]
CT[cvkg-themes 0.2.15]
RT[cvkg-runic-text 0.2.15]
end
RN[cvkg-render-native]
RN --> W
RN --> A
RN --> AW
RN --> AU
RN --> AR
RN --> AB
RN --> IM
RN --> LC
RN --> LG
RN --> PL
RN --> RD
RN --> TK
RN --> CC
RN --> CG
RN --> CV
RN --> CT
RN --> RT
Public API overview
Re-exports (crate root)
| Name | Source module | Description |
|---|---|---|
RodioAudioEngine |
audio |
Cross-platform audio engine using rodio. Implements cvkg_core::AudioEngine. |
VisualHapticEngine |
audio |
Fallback haptic engine that records impact timestamps for visual micro-animation. Implements cvkg_core::HapticEngine. |
NativeAssetManager |
asset_manager |
Filesystem-backed asset cache with lock-free reads via ArcSwap. Implements cvkg_core::AssetManager. |
WindowState |
window |
Enum: Normal, Minimized, Fullscreen, SplitView, Occluded, Hidden. |
WindowStateDetector |
window |
Tracks window lifecycle state from winit events; exposes should_render() and control_flow(). |
ResizeHitTest |
window |
Hit-tests cursor position against rounded-corner resize regions. |
SafeAreaInsets |
window |
Platform safe-area insets (menu bar, notch, Dock). Zero in fullscreen. |
Module: audio
RodioAudioEngine— opens the default audio output stream; plays named sound cues ("nav_tick","success_chime","warning_tone") or raw PCM buffers.new()returnsNoneif audio hardware is unavailable.VisualHapticEngine— recordsInstantof last haptic impact per intensity level. Used as cross-platform fallback.
Module: asset_manager
NativeAssetManager—load_image(url)reads from the local filesystem path given byurl. UsesArcSwap::rcu()for lock-free cache insertion. Spawns a background thread per unique URL on cache miss.preload_image(url)triggers the same background load without reading the result.
Module: window
WindowState— six-state enum for render-loop decisions.WindowStateDetector— updates state fromWindowEventorWindowqueries.should_render()returnsfalseforOccluded,Minimized,Hidden.control_flow()returnsControlFlow::PollorControlFlow::Wait.ResizeHitTest—new(window_size, corner_radius, expansion)thenhit_test(pos, corner_radius)for corner resize detection.SafeAreaInsets—zero()andfor_window_state(state). Returnstop: 24.0on macOS in non-fullscreen;0.0elsewhere.NativeWindowWrapper— implementscvkg_core::Window. Delegatesclose(),set_title(),set_size(),set_visible(),bring_to_front()to the event loop proxy.WindowManager— owns all active windows, maintains awindow_stackfor Z-order, maps between winitWindowIdand CVKGCoreWindowId.create_window()builds a winit window, AccessKit adapter, VDom, andWindowData.WindowData— per-window state: cursor position, velocity, frame history, drag state, focus manager, AccessKit adapter, VDom.WindowType— enum:Document,Panel,Popover,Dialog,Tooltip.WindowCapabilityMatrix—for_current_platform()returns supported window types and capabilities per OS.MonitorConfig— name, position, size, scale factor, refresh rate.MultiMonitorManager—new(monitors),current_monitor(),update_window_position(),scale_dimensions(),requires_dpi_adaptation().
Module: main_loop
AppEvent— custom event enum:AccessibilityAction,CloseWindow,SetTitle,SetSize,SetVisible,BringToFront,AccessibilityInitialTreeRequested. ImplementsFrom<accesskit_winit::Event>.App<V: View>— implementsApplicationHandler<AppEvent>. Owns theWindowManager,GpuRenderer,NativeAssetManager, audio/haptic engines, frame budget tracker. Onresumed(): detects accessibility preferences, detects system theme, initializes audio, creates the main window, forges the GPU renderer, and pre-warms a text cache. Onwindow_event(): runs VDom diff, synchronizes AccessKit tree, and renders the frame.
Module: events
convert_keyboard_event(event, modifiers)— mapsPhysicalKey::Codeto CVKGKeyDown/KeyUp. ReturnsNonefor non-physical keys.convert_ime_event(event)— mapsIme::Committo CVKGIme.convert_mouse_event(state, position, button)— maps press/release toPointerDown/PointerUp.load_icon()— searches CWD and executable directory foricon.png, decodes viaimage, and constructs a winitIcon.
Module: contracts
RenderingMode— enum:Native,Custom,Hybrid.TranslationContract— maps CVKG widget type to platform type name, rendering mode, and native accessibility flag.TranslationContractRegistry— pre-populated withButton,TextInput,Canvas,TreeViewcontracts.find(cvkg_type)for lookup.SyncDirection— enum:CvkgToNative,NativeToCvkg,Bidirectional.StateSyncContract— per-widget sync direction and debounce configuration.StateSyncRegistry— pre-populated withButton,TextInput,Slider,Checkboxcontracts.WidgetVirtualizationConfig—buffer_size,recycle_handles,max_active_handles. Default: 5, true, 100.SemanticRoleMapping— mapsaccesskit::Roleto macOS AXRole, Windows UIA ControlType, and Linux ATK Role strings.SemanticRoleRegistry— pre-populated withButton,TextInput,CheckBox,Slider,Labelmappings.
Module: regression
VisualRegressionTracker—new(reference_dir, pixel_tolerance, max_mismatched_percentage).verify_frame(test_name, captured_png)compares against a golden PNG. If no reference exists, writes the captured frame as the new reference and returnstrue. Comparison is per-pixel RGBA with absolute tolerance and a mismatched-pixel percentage threshold.
Module: renderer
GPU_FRAME_PTR— thread-local raw pointer to the lockedGpuRenderer. Set only whileMutexGuardis live on the call stack.NativeRenderer— implementscvkg_core::Rendererandcvkg_core::ElapsedTime. Forwards all draw calls tocvkg_render_gpu::GpuRenderervia the thread-local fast path or mutex fallback.NativeRenderer::run(view, prewarm_assets)— creates a winit event loop, constructs anApp, and runs the application. Entry point for standalone native CVKG apps.NativeRenderer::run_with_background(view, image_name, image_path)— convenience wrapper that loads an image from disk and passes it as a pre-warm asset.
Usage example
use View;
use NativeRenderer;
;
Use cases
- Standalone CVKG desktop applications — use
NativeRenderer::run()orrun_with_background()as the application entry point. - Multi-window apps — use
WindowManagerdirectly to create, close, and reorder windows. - Accessibility-enabled UIs — AccessKit adapters are created per window; semantic role mappings drive screen reader behavior.
- Asset-heavy applications —
NativeAssetManagerprovides lock-free background loading withArcSwapcache. - Visual regression testing —
VisualRegressionTrackercaptures frames and compares against golden references for CI pipelines. - Multi-monitor DPI-aware layouts —
MultiMonitorManagertracks monitor changes and scale factors for correct logical-to-physical coordinate conversion.
Edge cases and limitations
- Audio is best-effort.
RodioAudioEngine::new()returnsNoneif the audio device is unavailable. No error is propagated to the caller. - Asset loading is filesystem-only.
NativeAssetManagertreatsurlas a local file path. HTTP, HTTPS, and other URL schemes are not supported. - Spatial audio is a fallback.
play_spatial()ignores the position parameter and delegates toplay_sound(). No positional attenuation is applied. - macOS-only safe-area insets.
SafeAreaInsets::for_window_state()returnstop: 24.0only on macOS in non-fullscreen. All other platforms return zero insets. - Portal rendering is not implemented.
enter_portal()andexit_portal()log a warning and return without action. - GPU_FRAME_PTR safety. The thread-local pointer is only valid while the
MutexGuardis alive on the same thread's call stack. Do not store or send it across threads. - Single-threaded by design.
Appmust run on the main thread.winitevent loops are platform-main-thread-bound. Audio engine isSend + Syncbut only used from the main thread. - Linux accessibility requires AT-SPI.
accesskit_unixis only linked ontarget_os = "linux". Without it, accessibility tree updates are silently skipped. - Icon search is heuristic.
load_icon()searches a fixed set of candidate paths relative to CWD and the executable. Custom icon paths must be handled externally. - Visual regression: recording mode. If a golden reference does not exist,
verify_frame()writes the captured image and returnstrue. First run always passes. - Window close is asynchronous.
NativeWindowWrapper::close()sends an event to the event loop proxy. The window is not destroyed synchronously.
Build flags, features, and env vars
This crate has no optional Cargo features. All dependencies are always compiled.
Platform-conditional dependencies:
accesskit_unixis only linked ontarget_os = "linux".
Notable dependency constraints:
arboard = "=3.4.0"— pinned to exact version 3.4.0.imageenables thejpegfeature.tokiouses onlysync,rt,macros,rt-multi-threadfeatures (nonet,time,io-util, etc.).accesskit_unixis compiled withdefault-features = false.
Environment variables: The crate itself does not read environment variables. However, the GPU renderer it depends on (cvkg-render-gpu) reads:
WGPU_ADAPTER_NAME— case-insensitive substring match to force a specific GPU adapter.WGPU_BACKEND— force a specific wgpu backend (e.g.vulkan,metal).RUST_LOG— controls log output; set tocvkg_render_gpu=debugfor renderer diagnostics.
Build requirements:
- Rust 2024 edition (
rustc>= 1.85). winit 0.30requires a working display server on Linux (X11 or Wayland).rodio 0.21requires a working audio output device (gracefully degrades toNoneif unavailable).