Framework surface
Cerneala owns the load-bearing layers: compiled authoring and bindings, retained state, bounded cross-thread marshaling, layout and input, motion, dirty scheduling, cached drawing, native hosting, and diagnostics. Controls are the visible part, not the entire damn framework.
.crn additional files compile into partial windows and controls with named elements, event hooks, resources, aspects, templates, logical conditions, and typed OneWay/TwoWay data bindings. Behavior stays in matching C#.
UiProperty<T> carries defaults, validation, coercion, precedence, inheritance, and invalidation metadata. Generated paths, Binding<T>, and observable values connect model changes without runtime reflection in the hot path.
Aspect rules cascade through defaults, states, and variants while named resources supply brushes, fonts, tokens, values, and templates. Reactive conditions update styling without rebuilding the tree.
Window, Button, RepeatButton, TextBox, ListBox, ScrollViewer, ComboBox, TabControl, Slider, and the supporting content/items primitives share templates, focus, selection, commands, and text infrastructure.
Measure and arrange run through Grid, StackPanel, Canvas, scrolling, and virtualized stacks, with layout boundaries, rounding, and incremental parent escalation built into the frame scheduler.
Pointer, keyboard, and text feed hit testing, capture, focus, commands, navigation, and tunneled/bubbled events. Touch, stylus, manipulation, and drag surfaces remain platform-gated prototypes; a semantics tree exists while native accessibility adapters remain later work.
Tweens, springs, decay, keyframes, layout transitions, presence, and gesture motion share the host clock. Hooks sample around layout and render, with reduced-motion policy in the same system.
A root-owned MPSC Relay drains bounded FIFO snapshots before retained work. Off-thread binding, command, resource, collection, and theme notifications coalesce onto the UI thread; deduplicated phase queues and idle checks stay allocation-conscious.
UiHost, MonoGame integration, and the native Windows runtime drive the same abstract command stream. Frame stats, traces, cache dumps, screenshots, and platform probes expose what happened.
Frame pipeline
A host frame first drains one bounded Relay snapshot, can settle existing scheduled work before input, dispatches that input, then runs a second retained pass only when the tree becomes dirty. State settles before layout, caches refresh independently, and drawing submits the committed command stream.
Cross-thread posts, invocations, and async continuations drain as a bounded FIFO snapshot on the root UI thread.
Pointer, keyboard, and text dispatch through hit testing, capture, focus, commands, navigation, and routed events.
Inherited values drain, command state refreshes, aspects run, then inherited propagation drains again before layout.
Only pending work is ordered. Redundant propagated entries are skipped, and parents escalate only when desired size changes.
Required entries write final bounds in deterministic visual order; propagated-only work can clear without redundant layout.
Dirty elements refresh retained caches. Unchanged entries and the shared visual-order index stay reusable.
Input routes and hit-test data refresh as their own phase after render work, ready for the next dispatch.
The host commits root commands, then draw submits them to IDrawingBackend; MonoGame consumes the stream.
Markup + code-behind
A .crn additional file declares the retained window, named elements, and event hooks. Its matching .crn.cs partial class receives typed names and handler wiring at build time.
.crn file to the incremental generator.
Runtime diagnostics
Cerneala exposes frame snapshots, invalidation traces, dirty-tree dumps, routed event routes, render cache diagnostics, layout captures, input targets, motion traces, and platform/resource probes.
Use the diagnostic layer to see what changed, which caches were reused, why layout ran, how input routed, and what services the runtime can actually reach.
Get started
Cerneala UI is under active development. Read the docs, browse the source, or drop a retained-mode panel into your next MonoGame project.