noesis_runtime 0.12.1

Rust bindings for the Noesis GUI Native SDK: load XAML UI, drive the view and renderer, and write custom controls in Rust. Renderer-agnostic; Bevy integration lives in noesis_bevy.
Documentation
# Changelog

All notable changes to this crate are documented here. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/). While the crate is
pre-1.0, any `0.x` release may contain breaking changes.

## [Unreleased]

## [0.12.1] - 2026-07-05

### Added

- `FrameworkElement::set_clip_points(points)` clips any element to a closed
  polygon (`[x, y]` pairs in the element's own space) by assigning a filled
  `StreamGeometry` as its `UIElement::Clip`; an empty slice clears the clip and
  a degenerate 1–2 point polygon is rejected. The clip counterpart of
  `set_path_points`, working on any element rather than only a `Path`.

## [0.12.0] - 2026-07-02

### Added

- `ResourceDictionary::set_source(uri)` loads a dictionary's XAML by URI with
  `{StaticResource}` resolving against every scope already reachable from it.
  Join an installed parent's merged dictionaries first and a chain composes
  leaf by leaf: the open-coded `gui::install_app_resources_chain`, for callers
  that also layer code-built entries into the same parent.
- `binding::clear_binding(element, dp_name)` removes a binding wired by
  `set_binding` (`BindingOperations::ClearBinding`); the DP reverts to
  default/local-value precedence. Reports success when no binding was present,
  so removal-driven teardown needs no bound-ness tracking.

### Changed

- **Breaking:** the integration callbacks — `set_cursor_callback`,
  `set_software_keyboard_callback`, `set_open_url_callback`, and
  `set_play_audio_callback` — now require `Fn` closures instead of `FnMut`.
  Noesis can invoke these re-entrantly, so `&mut` access to captured state was
  unsound.
- **Breaking:** the diagnostics handlers — `set_error_handler`,
  `set_assert_handler`, and `set_thread_error_handler` — now require `Fn`
  closures instead of `FnMut`, for the same re-entrancy reason.
- **Breaking:** `get_font_family` now returns `FontFamilyRef<'a>` borrowing the
  `FrameworkElement` it was read from, so the reference can no longer outlive
  the element that owns it.
- **Breaking:** `EventTrigger::source_name` now returns `None` for an unset
  (empty) name instead of `Some("")`.
- The typography enum accessors (font weight/style/stretch, capitals, numeral
  style, fraction, variants, and the composition-underline line style) return
  `None` when the underlying discriminant is unknown, rather than silently
  substituting a default value.
- `Style::builder` now panics if `target_type` is unknown to the reflection
  registry or contains an interior NUL byte — previously it swallowed the error
  and returned an inert builder whose setters all silently failed. Use
  `Style::new` + `set_target_type` for the fallible form.
- Added the gamepad `Key` variants (`GamepadLeft` through `GamepadContext4`,
  ordinals 175–190) so directional-focus and accept/cancel input can be sent
  through `View::key_down` / `key_up`.
- Event-argument classification behind `EventArgs::wheel_delta` is now keyed on
  the arg-kind discriminant reported by the C++ side rather than inferred from
  position/button sentinels, so plain mouse events (moves, enter/leave) no
  longer misreport as zero-delta wheel events.

### Fixed

- Provider registration guards (font, texture, and XAML `Registered`) now clear
  the Noesis slot on drop only when their id still matches the active
  registration, so dropping a stale guard can no longer tear down a newer
  provider for the same scope. Each guard frees exactly its own boxed impl.
- Diagnostics handler guards track a per-registration id: installing a second
  handler leaves the older guard logically dead, and dropping it no longer
  clobbers the newer handler's slot. Each guard restores Noesis's default on
  drop and frees exactly its own closure.
- Event, collection-view current-changed, and lifecycle/data-object
  subscriptions now donate their boxed handler to the C++ side with a free
  trampoline. Dropping a subscription from inside its own callback is safe
  (destruction is deferred until the callback returns) and the previous
  double-free / leak on the Rust side is gone.
- Creating a reflected class instance no longer leaks a reference: the C++ shim
  handed out an object that had been `AddReference`'d twice but released once.
  The freezable make-trampoline path now adopts its `+1` correctly rather than
  taking an extra reference.
- `FontFamilyRef` borrows are tied to the source element's lifetime (see above),
  closing a use-after-free when the element was dropped while the ref was live.
- C++ shim: `noesis_collection_view_source_get_view` now documents that it
  synthesizes a `CollectionView` over the source list for a standalone
  (unhosted) `CollectionViewSource`, matching the implementation. Added
  `static_assert`s pinning the 16 gamepad `Key` ordinals against the SDK enum,
  and switched string-property FFI casts from `i8` to `c_char` for targets
  where `c_char` is `u8` (e.g. aarch64 Linux).

## [0.11.0] - 2026-06-29

### Added

- `ObservableCollection::move_item(old, new)` performs a true positional move on
  the underlying Noesis collection, raising a single `CollectionChanged.Move`
  rather than a Remove+Add. A reorder keeps `ICollectionView` currency (selection)
  and scroll position instead of resetting them.
- `ObservableCollection::insert_object` inserts a reflected object at an index for
  entity-keyed list inserts, without a clear-and-rebuild.
- `u64` reflected values: `PlainType::U64` / `PlainValue::U64`, `ItemValue::U64`,
  `PropType::UInt64`, and `Instance::{set_u64, get_u64}` plus the plain-VM
  `set_u64` / `get_u64` / `as_u64`. Stamp a `u64` (e.g. a host `Entity`'s bits) on
  a reflected row or view-model object as a stable key.
- `FrameworkElement::data_context_u64` and `EventArgs::source_data_context_u64`
  read a `u64` back off an element's (or a routed event source's) `DataContext`,
  resolving an event to the row it originated from with no side channel.
- `subscribe_selection_changed` (with `SelectionChangedHandler` and the RAII
  `SelectionChangedSubscription`) subscribes to `Selector::SelectionChanged`, so a
  control's selection surfaces through `ICollectionView` currency.

## [0.10.0] - 2026-06-29

### Changed

- **Breaking:** command parameters now reach handlers as a decodable
  `CommandParameterValue` instead of a raw `Option<NonNull<c_void>>`. The
  `CommandHandler` and `CommandBindingHandler` trait methods (and their blanket
  `Fn` impls), along with the `execute` / `can_execute` methods on
  `RoutedCommand`, `RoutedUICommand`, and `BorrowedCommand`, now take
  `CommandParameterValue`. The old `CommandParameter` type alias is removed.

### Added

- `CommandParameterValue` decodes the boxed command parameter from XAML (e.g.
  `CommandParameter="42"`): `as_bool`, `as_i32`, `as_f64`, and `as_str` return
  `None` on a type mismatch, plus `is_none` / `raw` for the no-parameter and
  raw-pointer cases. Construct one with `CommandParameterValue::new` to supply a
  parameter when invoking a command yourself.
- Typed `ItemsSource` items: `push_i32`, `push_f64`, `push_bool`, and
  `push_object` add values without boxing them yourself, and `CurrentItem` reads
  them back with `as_i32`, `as_f64`, `as_bool`, and `as_string`.
- `FrameworkElement::remove_input_binding` tears down an input binding added with
  the `add_to` counterpart.
- `View::predict_focus_name` names the element that focus navigation would move
  to in a given direction, when you only need its name.
- `View::solid_brush_color` reads back the RGBA of a named element's
  `SolidColorBrush`.
- `InlineCollection::clear` empties a `TextBlock`'s inlines so they can be
  repopulated without rebuilding the host element.
- `Shape::as_element` views a built shape as an owning `FrameworkElement`.
- `ResourceDictionary::add_brush` inserts a typed brush under a key.
- Windows (`x86_64-pc-windows-msvc`) builds. The build script links `Noesis.lib`
  from the SDK's `Lib/` directory, which the Windows package keeps separate from
  the `Noesis.dll` in `Bin/`, and stages the DLL next to the test and example
  binaries so `cargo test` runs without a `PATH` change.

## [0.9.0]

First public release. The API covers loading XAML, driving the View and
Renderer, implementing a `RenderDevice` against your own GPU, and writing
Rust-backed custom controls and markup extensions. The surface is considered
near-final ahead of a 1.0 that commits to stability.

[Unreleased]: https://github.com/dead-money/noesis_runtime/compare/v0.12.1...HEAD
[0.12.1]: https://github.com/dead-money/noesis_runtime/compare/v0.12.0...v0.12.1
[0.12.0]: https://github.com/dead-money/noesis_runtime/compare/v0.11.0...v0.12.0
[0.11.0]: https://github.com/dead-money/noesis_runtime/compare/v0.10.0...v0.11.0
[0.10.0]: https://github.com/dead-money/noesis_runtime/compare/v0.9.0...v0.10.0
[0.9.0]: https://github.com/dead-money/noesis_runtime/releases/tag/v0.9.0