Skip to main content

Crate noesis_runtime

Crate noesis_runtime 

Source
Expand description

Safe Rust bindings to the Noesis GUI native SDK, a XAML-based UI engine, wrapped here by a hand-written C ABI over opaque, reference-counted handles.

The crate is renderer-agnostic: it builds UI trees, drives input, and ticks the layout/animation engine, but leaves drawing to you through the render_device::RenderDevice trait. A ready-made Bevy/wgpu integration lives in the sibling crate noesis_bevy.

§Getting started

The lifecycle is process-wide: call init exactly once at startup and shutdown once at exit, after every Noesis handle has been dropped. In between, a typical session looks like:

  1. Install an asset source with xaml_provider::set_xaml_provider (plus optional font and texture providers).
  2. Build a UI root: view::FrameworkElement::load from a URI, or view::FrameworkElement::parse from an in-memory XAML string.
  3. Wrap it in a view::View with view::View::create, then feed it the surface size, input events, and per-frame time updates.
  4. Render the view through your render_device::RenderDevice.

For a quick import of the types most code reaches for, glob the prelude.

§Setup

Set NOESIS_SDK_DIR to the extracted Noesis Native SDK 3.2.13 root (the directory containing Include/ and Bin/). See README.md.

§Thread affinity

Noesis objects are thread-affine: the engine expects every method on a given object (and on the view::View that owns it) to be called from the one thread that drives that view. The owning handle types in this crate (geometries, brushes, transforms, commands, bindings, the RAII registration guards, etc.) therefore implement Send but deliberately not Sync:

  • Send is sound. Noesis::BaseRefCounted::mRefCount is an AtomicInteger, so the -1 release performed by Drop is safe on any thread. Ownership of a handle may be moved to whichever thread owns the Noesis view, after which all calls happen on that thread.
  • Sync is unsound. Many &self methods call into Noesis (FFI reads, and some lazily mutate engine state, e.g. resource-dictionary or collection getters). Sharing a &handle across threads would let two threads invoke those concurrently on a thread-affine engine, which races.

Callers must invoke Noesis methods only from the view’s thread. SAFETY comments on the individual unsafe impl Send blocks point back here rather than restating this contract. (The render-device trait is the exception: a user render_device::RenderDevice impl must be Send + Sync because Noesis may call its trampolines from a dedicated render thread. That bound is on the trait, not on these owning handles.)

Modules§

animation
Code-built animation & timing: construct Storyboards, the common animation classes (DoubleAnimation / ColorAnimation / ThicknessAnimation / PointAnimation), their key-frame variants, and the easing-function family from Rust, then run them off the View clock.
binding
Data-binding bridge: drive XAML from Rust-owned data.
brushes
Code-built brushes and effects: construct Brush / Effect objects from Rust and paint elements with them without authoring XAML.
classes
Register Rust-backed XAML classes.
collection_view
ICollectionView current-item navigation.
commands
ICommand from Rust: let XAML Command="{Binding ...}" invoke Rust logic.
converters
Rust value converters for data binding.
diagnostics
Diagnostics: error / assert handlers and memory-usage queries.
drawing
Immediate-mode drawing via DrawingContext.
element_tree
Code-side element-tree construction: build and mutate panel trees and Grid row/column definitions from Rust.
events
Subscribe Rust callbacks to Noesis routed events.
font_provider
Rust-side FontProvider trait + set_font_provider registration. Mirrors crate::xaml_provider: a boxed trait object is handed to the C++ RustFontProvider subclass via a vtable of trampolines; the returned Registered guard owns both the boxed impl and the C++ provider handle.
formatted_text
Code-built FormattedText measurement / layout: measure a string in a given font without authoring XAML or building a TextBlock.
geometry
Code-built geometry object model. Construct Geometry objects from Rust without authoring XAML: StreamGeometry, PathGeometry (figures + segments), the primitive Ellipse/Rectangle/Line geometries, CombinedGeometry, and GeometryGroup.
gui
Thin wrappers around the top-level Noesis::GUI::* helpers that don’t fit into the provider / view / render-device modules.
imaging
Code-built ImageSource / BitmapSource family: construct CroppedBitmap, TextureSource, BitmapImage, and DynamicTextureSource objects from Rust without authoring XAML.
input
Input: keyboard/focus enums, input gestures and bindings, and the FocusManager / KeyboardNavigation static surfaces.
integration
System integration callbacks from NsGui/IntegrationAPI.h (namespace Noesis::GUI). These are process-global host hooks (not per-view) that let the host react to engine requests: update the OS cursor, show or hide the on-screen keyboard, open a URL, play a sound, and set the default culture.
markup
Register Rust-backed XAML MarkupExtensions: Rust callbacks XAML can invoke as {myns:Foo positional_arg}.
mesh
Code-built MeshData + Mesh element for immediate-mode drawing.
multi_binding
MultiBinding + IMultiValueConverter from Rust.
name_scope
Standalone NameScope: the freestanding XAML namescope object, distinct from the per-FrameworkElement RegisterName/UnregisterName path (which routes through whatever scope already hosts the element).
plain_vm
Plain (non-DependencyObject) view models for data binding.
prelude
Curated re-exports of the items most code reaches for. Glob-import it (use noesis_runtime::prelude::*;) to pull in the core view/element handles, the brush/transform/geometry traits and their common concrete types, data-binding and collection types, the custom-control and markup-extension surface, the provider traits, the lifecycle free functions, and the most-used enums.
reflection
Runtime registration of “other reflected entities”: custom enums, custom routed events on Rust-backed types, factory/metadata introspection, and the reflection TypeConverter string→value path.
render_device
Implement a custom GPU backend for Noesis by writing a Rust Noesis::RenderDevice.
resources
ResourceDictionary access + application resources.
shapes
Build Rectangle, Ellipse, and Line shapes from Rust and set their drawing properties without authoring XAML.
styles
Style from code + template assignment.
svg
SVG parsing and geometry queries, all CPU-side and headless. No GPU RenderDevice or render pass is needed, so you can use these in tests, tooling, or hit-testing without standing up a renderer.
text_inlines
Code-built TextBlock inline content: construct the Inline element family (Run, Span, Bold, Italic, Underline, Hyperlink, LineBreak, InlineUIContainer) from Rust and assemble them into a TextBlock’s (or a Span’s) InlineCollection.
texture_provider
Supply image pixels to Noesis from Rust. Implement TextureProvider to resolve Image.Source / ImageBrush.ImageSource URIs into RGBA8 textures, then register it with set_texture_provider (or one of the scheme/assembly-scoped variants). Your boxed impl is handed to a C++ RustTextureProvider subclass through a vtable of trampolines, and the returned Registered guard owns both the boxed impl and the C++ handle.
transforms
Build Transform objects from Rust and apply them as an element’s RenderTransform.
typography
Typography & text properties: the FontFamily wrapper, the TextElement attached font properties (size / family / foreground / weight / style / stretch), a representative subset of the OpenType Typography attached properties, and the IME CompositionUnderline list on a TextBox.
view
Safe wrappers around the Noesis FrameworkElement, IView, and IRenderer opaque pointers.
xaml
XAML loading variants.
xaml_provider
Teach Noesis where to find your XAML. Implement the XamlProvider trait, then call set_xaml_provider (or one of the scheme/assembly-scoped variants) to install it. Your boxed impl is handed to a C++ RustXamlProvider subclass through a vtable of trampolines, and the returned Registered guard owns both the boxed impl and the C++ provider handle.

Functions§

disable_hot_reload
Disable the Hot Reload feature before init. Hot Reload is on by default in Debug/Profile SDK builds and costs a little extra memory; disabling it is purely an optimization. No-op once init has run, and a no-op on a Release dylib where the feature is compiled out.
disable_inspector
Disable all remote Inspector connections before init. The Inspector is enabled by default in Debug/Profile SDK builds (it opens a socket and waits for the remote tool); call this to keep it off. No-op after init / on a Release dylib where the Inspector is compiled out.
disable_socket_init
Skip the Inspector’s socket initialization (e.g. WSAStartup on Windows) before init. Use this only when the host process has already initialized sockets itself, to avoid a double init. No-op after init / on a Release dylib.
init
Initialize Noesis subsystems. Call exactly once per process; Noesis does not support re-init after shutdown.
is_inspector_connected
Returns whether a remote Inspector is currently connected.
set_license
Optional. Apply Indie license credentials before init to suppress the trial watermark. Pass empty strings (or skip the call) to run in trial mode.
shutdown
Shut Noesis down. Call once at process exit, after all Noesis-owned objects have been released.
update_inspector
Keep the Inspector connection alive. crate::view::View updates call this internally, so it is only needed when the Inspector connects before any view exists. No-op on a Release dylib.
version
Returns the Noesis runtime build version (e.g. "3.2.13").