Fission 0.12.0 adds a retained, backend-neutral camera and a declarative
infinite canvas without creating a second rendering or state system. It also
completes the input work those widgets require: multiple pointer identities,
pinch and magnification, cancellation, detailed scrolling, browser editing
shortcuts, context menus, and reliable WebGPU presentation at real application
sizes.
This is a minor release because it adds major public capabilities and changes
the public pointer and scoped-action contracts.
InteractiveViewer pans and uniformly scales one normal Fission widget
subtree. The camera may be runtime-owned or controlled by application state,
and its behavior is expressed with backend-neutral policies for boundaries,
clipping, axes, minimum and maximum scale, wheel behavior, and inertia.
let viewer: Widget = InteractiveViewer {
id: Some(WidgetId::explicit("floor-plan")),
child: Image::asset("floor-plan.png").into(),
min_scale: 0.25,
max_scale: 8.0,
zoom_policy: ViewportZoomPolicy::WheelWithModifier,
..Default::default()
}
.into();
Mouse, touch, stylus, modifier-wheel, macOS magnification, and browser pinch
feed the same core controller. A draggable child wins an ordinary one-pointer
drag, while a second contact promotes the nearest viewer to a captured
two-pointer pan and zoom without a camera jump when one contact is released.
Callbacks preserve their bound action payload. Reducers read the live camera,
focal points, pan delta, scale factor, input family, modifiers, and lifecycle
from ctx.input.viewport_interaction().
InfiniteCanvas stays declarative
InfiniteCanvas builds on InteractiveViewer instead of introducing an
imperative scene authority. Applications continue to own committed nodes,
edges, selection, and optional controlled camera state.
The initial widget includes:
stable node and edge identities with negative and positive world coordinates;
straight and cubic edges, retained labels, grids, and stable z-order;
single, toggle, and marquee selection;
node movement, eight constant-screen-size resize handles, and symmetric grid snapping;
precise transformed hit testing and transformed accessibility bounds; and
visible-world batching for grid and edge paths.
The new interactive-canvas example demonstrates both widgets with responsive
desktop and compact layouts. The public widgets are available through the
normal desktop, android, ios, mobile, and web features. Static site,
SSR, and Terminal-only builds intentionally do not expose them.
Complete pointer facts across shells
Fission no longer collapses every touch contact into one synthetic mouse
pointer. PointerEvent now retains PointerId and PointerKind, explicit
cancellation, line-versus-pixel scroll mode, scroll lifecycle, and
multiplicative magnification. Native and Web test control use the same detailed
events, which makes multi-contact behavior deterministic to test.
This is a source change for code that directly constructs or exhaustively
matches PointerEvent.
Web behaves like a Fission application
Web applications now receive platform-correct secondary clicks and Fission-owned
keyboard editing, selection, copy, cut, paste, and context menus. Browser
defaults remain suppressed by default. An application can selectively delegate
keyboard, pointer, touch, wheel, context-menu, or clipboard behavior with a
composed BrowserDefaults value:
WebApp::<AppState, _>::new(App)
.with_browser_defaults(
BrowserDefaults::CONTEXT_MENU | BrowserDefaults::WHEEL,
);
The release also fixes the blank or transparent WebGPU output seen at larger
window sizes. Fission validates WebGPU work before presentation, configures the
browser canvas surface correctly, sizes the forked Vello buffers from the real
frame workload, and mirrors framework diagnostics into the browser console.
Authoring-tree and scoped-action contracts
Widget::kind() and Widget::visit() provide read-only, depth-first access to
the authoring tree for integrations that need to discover widget structure.
Scoped handlers now return an explicit ScopedActionResolution: handle the
action locally, or forward an envelope once through normal dispatch. Fission
rejects ambiguous multiple forwards and prevents a forwarded action from
recursively re-entering the handler that forwarded it.
Migration
Update the framework and CLI:
fission = { version = "0.12.0", default-features = false, features = ["desktop"] }
cargo install cargo-fission --version 0.12.0 --locked
Then make these source updates where applicable:
Add pointer_id and kind to direct Down, Move, and Up constructors.
Handle PointerEvent::Cancel and PointerEvent::Magnify, and add scroll
delta_mode and phase.
Return ScopedActionResolution::Handled from existing scoped handlers, or
Forward(envelope) when dispatch should continue.
Use ctx.input.viewport_interaction() and
ctx.input.canvas_interaction() for runtime event facts while keeping stable
application context in the bound action.
Browser autocorrect, autofill, and soft-keyboard replacement/deletion still
need full hidden-textarea value and selection synchronization. Hardware keyboard
shortcuts, clipboard operations, context menus, and composition commits are
implemented; the remaining work is tracked in
issue #168.