plushie/event
Event types for the plushie wire protocol.
Events are delivered to the app’s update function from the Rust
binary via the bridge actor. Pattern match on specific constructors
and use _ -> for unhandled events.
Widget events carry an id (the widget’s local ID after scope
splitting) and a scope (list of ancestor container IDs, nearest
first). For example, a button “save” inside container “form” produces
WidgetClick(id: "save", scope: ["form"]).
Fields typed as Dynamic carry wire-originated values whose shape
varies by context. Use gleam/dynamic/decode to extract typed data.
These appear in catch-all events, pane identifiers, async results,
and effect responses.
Types
Platform effect result from file dialogs, clipboard, notifications.
EffectOk(data): success; data shape depends on the effect kind (e.g., file dialogs return a map with"path"or"paths"keys)EffectCancelled: user dismissed the dialogEffectError(reason): operation failed (timeout, permission, etc.)
Use gleam/dynamic/decode to extract typed values from the Dynamic.
pub type EffectResult {
EffectOk(dynamic.Dynamic)
EffectCancelled
EffectError(dynamic.Dynamic)
}
Constructors
-
EffectOk(dynamic.Dynamic)The effect succeeded. Data shape depends on the effect kind.
-
EffectCancelledThe user dismissed a dialog without making a selection.
-
EffectError(dynamic.Dynamic)The effect failed (timeout, permission denied, etc.).
All events from the plushie runtime.
pub type Event {
WidgetClick(id: String, scope: List(String))
WidgetInput(id: String, scope: List(String), value: String)
WidgetSubmit(id: String, scope: List(String), value: String)
WidgetToggle(id: String, scope: List(String), value: Bool)
WidgetSelect(id: String, scope: List(String), value: String)
WidgetSlide(id: String, scope: List(String), value: Float)
WidgetSlideRelease(
id: String,
scope: List(String),
value: Float,
)
WidgetPaste(id: String, scope: List(String), value: String)
WidgetScroll(id: String, scope: List(String), data: ScrollData)
WidgetOpen(id: String, scope: List(String))
WidgetClose(id: String, scope: List(String))
WidgetOptionHovered(
id: String,
scope: List(String),
value: String,
)
WidgetSort(id: String, scope: List(String), value: String)
WidgetKeyBinding(
id: String,
scope: List(String),
value: String,
)
WidgetEvent(
kind: String,
id: String,
scope: List(String),
value: dynamic.Dynamic,
data: dynamic.Dynamic,
)
KeyPress(
key: String,
modified_key: String,
modifiers: Modifiers,
physical_key: option.Option(String),
location: KeyLocation,
text: option.Option(String),
repeat: Bool,
captured: Bool,
)
KeyRelease(
key: String,
modified_key: String,
modifiers: Modifiers,
physical_key: option.Option(String),
location: KeyLocation,
text: option.Option(String),
captured: Bool,
)
WindowOpened(
window_id: String,
width: Float,
height: Float,
position_x: option.Option(Float),
position_y: option.Option(Float),
scale_factor: Float,
)
WindowClosed(window_id: String)
WindowCloseRequested(window_id: String)
WindowResized(window_id: String, width: Float, height: Float)
WindowMoved(window_id: String, x: Float, y: Float)
WindowFocused(window_id: String)
WindowUnfocused(window_id: String)
WindowRescaled(window_id: String, scale_factor: Float)
WindowFileHovered(window_id: String, path: String)
WindowFileDropped(window_id: String, path: String)
WindowFilesHoveredLeft(window_id: String)
MouseMoved(x: Float, y: Float, captured: Bool)
MouseEntered(captured: Bool)
MouseLeft(captured: Bool)
MouseButtonPressed(button: MouseButton, captured: Bool)
MouseButtonReleased(button: MouseButton, captured: Bool)
MouseWheelScrolled(
delta_x: Float,
delta_y: Float,
unit: ScrollUnit,
captured: Bool,
)
TouchPressed(
finger_id: Int,
x: Float,
y: Float,
captured: Bool,
)
TouchMoved(finger_id: Int, x: Float, y: Float, captured: Bool)
TouchLifted(finger_id: Int, x: Float, y: Float, captured: Bool)
TouchLost(finger_id: Int, x: Float, y: Float, captured: Bool)
ImeOpened(captured: Bool)
ImePreedit(
text: String,
cursor: option.Option(#(Int, Int)),
captured: Bool,
)
ImeCommit(text: String, captured: Bool)
ImeClosed(captured: Bool)
ModifiersChanged(modifiers: Modifiers, captured: Bool)
SensorResize(
id: String,
scope: List(String),
width: Float,
height: Float,
)
MouseAreaRightPress(id: String, scope: List(String))
MouseAreaRightRelease(id: String, scope: List(String))
MouseAreaMiddlePress(id: String, scope: List(String))
MouseAreaMiddleRelease(id: String, scope: List(String))
MouseAreaDoubleClick(id: String, scope: List(String))
MouseAreaEnter(id: String, scope: List(String))
MouseAreaExit(id: String, scope: List(String))
MouseAreaMove(
id: String,
scope: List(String),
x: Float,
y: Float,
)
MouseAreaScroll(
id: String,
scope: List(String),
delta_x: Float,
delta_y: Float,
)
CanvasPress(
id: String,
scope: List(String),
x: Float,
y: Float,
button: String,
)
CanvasRelease(
id: String,
scope: List(String),
x: Float,
y: Float,
button: String,
)
CanvasMove(id: String, scope: List(String), x: Float, y: Float)
CanvasScroll(
id: String,
scope: List(String),
x: Float,
y: Float,
delta_x: Float,
delta_y: Float,
)
CanvasShapeEnter(
id: String,
scope: List(String),
shape_id: String,
x: Float,
y: Float,
captured: Bool,
)
CanvasShapeLeave(
id: String,
scope: List(String),
shape_id: String,
captured: Bool,
)
CanvasShapeClick(
id: String,
scope: List(String),
shape_id: String,
x: Float,
y: Float,
button: String,
captured: Bool,
)
CanvasShapeDrag(
id: String,
scope: List(String),
shape_id: String,
x: Float,
y: Float,
delta_x: Float,
delta_y: Float,
captured: Bool,
)
CanvasShapeDragEnd(
id: String,
scope: List(String),
shape_id: String,
x: Float,
y: Float,
captured: Bool,
)
CanvasShapeFocused(
id: String,
scope: List(String),
shape_id: String,
captured: Bool,
)
PaneResized(
id: String,
scope: List(String),
split: dynamic.Dynamic,
ratio: Float,
)
PaneDragged(
id: String,
scope: List(String),
pane: dynamic.Dynamic,
target: dynamic.Dynamic,
action: String,
region: option.Option(String),
edge: option.Option(String),
)
PaneClicked(
id: String,
scope: List(String),
pane: dynamic.Dynamic,
)
PaneFocusCycle(
id: String,
scope: List(String),
pane: dynamic.Dynamic,
)
SystemInfo(tag: String, data: dynamic.Dynamic)
SystemTheme(tag: String, theme: String)
ThemeChanged(theme: String)
AnimationFrame(timestamp: Int)
AllWindowsClosed
ImageList(tag: String, handles: List(String))
TreeHash(tag: String, hash: String)
FocusedWidget(tag: String, widget_id: option.Option(String))
TimerTick(tag: String, timestamp: Int)
AsyncResult(
tag: String,
result: Result(dynamic.Dynamic, dynamic.Dynamic),
)
StreamValue(tag: String, value: dynamic.Dynamic)
Announce(text: String)
DuplicateNodeIds(details: dynamic.Dynamic)
EffectResponse(request_id: String, result: EffectResult)
}
Constructors
-
WidgetClick(id: String, scope: List(String))A widget was clicked. Fired by buttons and other clickable widgets.
-
WidgetInput(id: String, scope: List(String), value: String)Text was entered into a text_input or text_editor widget.
-
WidgetSubmit(id: String, scope: List(String), value: String)A text input was submitted (e.g. user pressed Enter).
-
WidgetToggle(id: String, scope: List(String), value: Bool)A toggler or checkbox widget changed state.
-
WidgetSelect(id: String, scope: List(String), value: String)An option was selected in a pick_list or combo_box widget.
-
WidgetSlide(id: String, scope: List(String), value: Float)A slider value changed during dragging.
-
WidgetSlideRelease(id: String, scope: List(String), value: Float)A slider was released at its final value.
-
WidgetPaste(id: String, scope: List(String), value: String)Text was pasted into a text input or text editor.
-
WidgetScroll(id: String, scope: List(String), data: ScrollData)A scrollable widget’s viewport changed position.
-
WidgetOpen(id: String, scope: List(String))A collapsible or expandable widget was opened (e.g. combo_box dropdown, disclosure).
-
WidgetClose(id: String, scope: List(String))A collapsible or expandable widget was closed.
-
WidgetOptionHovered( id: String, scope: List(String), value: String, )An option in a pick_list or combo_box was hovered.
-
WidgetSort(id: String, scope: List(String), value: String)A sortable column header was clicked. The value is the column key.
-
WidgetKeyBinding(id: String, scope: List(String), value: String)A registered key binding was triggered on a widget.
-
WidgetEvent( kind: String, id: String, scope: List(String), value: dynamic.Dynamic, data: dynamic.Dynamic, )Catch-all for uncommon or future widget event types not covered by the typed constructors above.
-
KeyPress( key: String, modified_key: String, modifiers: Modifiers, physical_key: option.Option(String), location: KeyLocation, text: option.Option(String), repeat: Bool, captured: Bool, )A key was pressed. Includes modifier state, physical key info, and whether the event was already captured by a subscription.
Arguments
- modified_key
-
The key value after applying modifier transforms. For example, Shift+a produces modified_key “A”. Falls back to the unmodified key when no transform applies.
- captured
-
Whether a subscription already consumed this event. Apps can check this to skip captured events and avoid double-processing.
-
KeyRelease( key: String, modified_key: String, modifiers: Modifiers, physical_key: option.Option(String), location: KeyLocation, text: option.Option(String), captured: Bool, )A key was released.
Arguments
- modified_key
-
The key value after applying modifier transforms.
- captured
-
Whether a subscription already consumed this event.
-
WindowOpened( window_id: String, width: Float, height: Float, position_x: option.Option(Float), position_y: option.Option(Float), scale_factor: Float, )A window finished opening. Includes initial size, position, and DPI scale factor.
-
WindowClosed(window_id: String)A window was closed and destroyed.
-
WindowCloseRequested(window_id: String)The user requested to close a window (e.g. clicked the X button). The app can handle this to show a confirmation dialog or ignore it.
-
WindowResized(window_id: String, width: Float, height: Float)A window was resized to new dimensions in logical pixels.
-
WindowMoved(window_id: String, x: Float, y: Float)A window was moved to a new screen position in logical pixels.
-
WindowFocused(window_id: String)A window gained keyboard/input focus.
-
WindowUnfocused(window_id: String)A window lost keyboard/input focus.
-
WindowRescaled(window_id: String, scale_factor: Float)A window’s DPI scale factor changed (e.g. moved between monitors).
-
WindowFileHovered(window_id: String, path: String)A file is being dragged over a window (not yet dropped).
-
WindowFileDropped(window_id: String, path: String)A file was dropped onto a window.
-
WindowFilesHoveredLeft(window_id: String)A previously hovered file drag left the window without dropping.
-
MouseMoved(x: Float, y: Float, captured: Bool)The mouse cursor moved to a new position.
-
MouseEntered(captured: Bool)The mouse cursor entered the application window.
-
MouseLeft(captured: Bool)The mouse cursor left the application window.
-
MouseButtonPressed(button: MouseButton, captured: Bool)A mouse button was pressed.
-
MouseButtonReleased(button: MouseButton, captured: Bool)A mouse button was released.
-
MouseWheelScrolled( delta_x: Float, delta_y: Float, unit: ScrollUnit, captured: Bool, )The mouse wheel was scrolled. Unit indicates whether deltas are in lines (wheel notches) or pixels (trackpad).
-
TouchPressed(finger_id: Int, x: Float, y: Float, captured: Bool)A finger touched the screen.
-
TouchMoved(finger_id: Int, x: Float, y: Float, captured: Bool)A finger moved on the screen.
-
TouchLifted(finger_id: Int, x: Float, y: Float, captured: Bool)A finger was lifted from the screen.
-
TouchLost(finger_id: Int, x: Float, y: Float, captured: Bool)Touch tracking was interrupted by the OS.
-
ImeOpened(captured: Bool)The IME composition session started.
-
ImePreedit( text: String, cursor: option.Option(#(Int, Int)), captured: Bool, )The IME is composing text. The cursor tuple is the selection range within the preedit string (byte offsets).
-
ImeCommit(text: String, captured: Bool)The IME committed final text to the input.
-
ImeClosed(captured: Bool)The IME composition session ended.
-
ModifiersChanged(modifiers: Modifiers, captured: Bool)The set of held modifier keys changed (Shift, Ctrl, Alt, etc.). Useful for updating UI hints without waiting for a key event.
-
SensorResize( id: String, scope: List(String), width: Float, height: Float, )A sensor widget detected that its rendered dimensions changed. Useful for responsive layouts that need to know actual size.
-
MouseAreaRightPress(id: String, scope: List(String))Right mouse button pressed inside a mouse_area widget.
-
MouseAreaRightRelease(id: String, scope: List(String))Right mouse button released inside a mouse_area widget.
-
MouseAreaMiddlePress(id: String, scope: List(String))Middle mouse button pressed inside a mouse_area widget.
-
MouseAreaMiddleRelease(id: String, scope: List(String))Middle mouse button released inside a mouse_area widget.
-
MouseAreaDoubleClick(id: String, scope: List(String))Double-click detected inside a mouse_area widget.
-
MouseAreaEnter(id: String, scope: List(String))Mouse cursor entered a mouse_area widget’s bounds.
-
MouseAreaExit(id: String, scope: List(String))Mouse cursor exited a mouse_area widget’s bounds.
-
MouseAreaMove( id: String, scope: List(String), x: Float, y: Float, )Mouse cursor moved within a mouse_area widget. Coordinates are in the widget’s local space.
-
MouseAreaScroll( id: String, scope: List(String), delta_x: Float, delta_y: Float, )Mouse wheel scrolled inside a mouse_area widget.
-
CanvasPress( id: String, scope: List(String), x: Float, y: Float, button: String, )A mouse button was pressed on a canvas widget.
-
CanvasRelease( id: String, scope: List(String), x: Float, y: Float, button: String, )A mouse button was released on a canvas widget.
-
CanvasMove(id: String, scope: List(String), x: Float, y: Float)The mouse cursor moved within a canvas widget.
-
CanvasScroll( id: String, scope: List(String), x: Float, y: Float, delta_x: Float, delta_y: Float, )The mouse wheel was scrolled within a canvas widget.
-
CanvasShapeEnter( id: String, scope: List(String), shape_id: String, x: Float, y: Float, captured: Bool, )Mouse entered an interactive canvas shape’s bounds.
-
CanvasShapeLeave( id: String, scope: List(String), shape_id: String, captured: Bool, )Mouse left an interactive canvas shape’s bounds.
-
CanvasShapeClick( id: String, scope: List(String), shape_id: String, x: Float, y: Float, button: String, captured: Bool, )An interactive canvas shape was clicked.
-
CanvasShapeDrag( id: String, scope: List(String), shape_id: String, x: Float, y: Float, delta_x: Float, delta_y: Float, captured: Bool, )An interactive canvas shape is being dragged.
-
CanvasShapeDragEnd( id: String, scope: List(String), shape_id: String, x: Float, y: Float, captured: Bool, )Drag ended on an interactive canvas shape.
-
CanvasShapeFocused( id: String, scope: List(String), shape_id: String, captured: Bool, )An interactive canvas shape received keyboard focus.
-
PaneResized( id: String, scope: List(String), split: dynamic.Dynamic, ratio: Float, )A pane_grid split divider was resized. The ratio is the new split position (0.0 to 1.0).
-
PaneDragged( id: String, scope: List(String), pane: dynamic.Dynamic, target: dynamic.Dynamic, action: String, region: option.Option(String), edge: option.Option(String), )A pane was dragged in a pane_grid. The action is “picked”, “dropped”, or “canceled”. Region and edge describe the drop target.
-
PaneClicked( id: String, scope: List(String), pane: dynamic.Dynamic, )A pane was clicked in a pane_grid, making it the active pane.
-
PaneFocusCycle( id: String, scope: List(String), pane: dynamic.Dynamic, )Focus cycled to the next pane in a pane_grid (e.g. via Tab).
-
SystemInfo(tag: String, data: dynamic.Dynamic)Response to a GetSystemInfo query. The data Dynamic contains a map with keys like “system_name”, “cpu_brand”, “memory_total”, etc.
-
SystemTheme(tag: String, theme: String)Response to a GetSystemTheme query. The theme is “light”, “dark”, or “none”.
-
ThemeChanged(theme: String)The OS theme preference changed at runtime.
-
AnimationFrame(timestamp: Int)An animation frame tick with a monotonic timestamp in milliseconds. Only fires when on_animation_frame is subscribed.
-
AllWindowsClosedAll windows have been closed. Typically used to trigger app exit.
-
ImageList(tag: String, handles: List(String))Response to a ListImages query with all registered image handles.
-
TreeHash(tag: String, hash: String)Response to a TreeHashQuery with the SHA-256 hash of the current renderer tree state.
-
FocusedWidget(tag: String, widget_id: option.Option(String))Response to a FindFocused query. The widget_id is None if no widget currently has focus.
-
TimerTick(tag: String, timestamp: Int)A timer subscription fired. The tag identifies which subscription, and timestamp is monotonic milliseconds.
-
AsyncResult( tag: String, result: Result(dynamic.Dynamic, dynamic.Dynamic), )Result from an Async command. Ok on success, Error on failure. The tag matches the tag passed to the originating Async command.
-
StreamValue(tag: String, value: dynamic.Dynamic)An intermediate value emitted by a Stream command. The tag matches the tag passed to the originating Stream command.
-
Announce(text: String)Request the system screen reader to announce the given text.
-
DuplicateNodeIds(details: dynamic.Dynamic)Emitted when the tree contains duplicate node IDs after normalization. The details Dynamic contains a list of the offending IDs. Usually indicates a bug in the view function.
-
EffectResponse(request_id: String, result: EffectResult)Response to a platform Effect command (file dialog, clipboard, notification). The request_id correlates with the originating Effect command’s id field.
Key location on the keyboard.
pub type KeyLocation {
Standard
LeftSide
RightSide
Numpad
}
Constructors
-
StandardDefault key position (main keyboard area).
-
LeftSideLeft-side modifier key (e.g. left Shift, left Ctrl).
-
RightSideRight-side modifier key (e.g. right Shift, right Ctrl).
-
NumpadKey on the numeric keypad.
Keyboard modifier state. Fields match the Rust binary’s modifier
report. logo is the Super/Windows key; command is the macOS
Command key. Both are sent by the binary – on macOS they typically
track together.
pub type Modifiers {
Modifiers(
shift: Bool,
ctrl: Bool,
alt: Bool,
logo: Bool,
command: Bool,
)
}
Constructors
-
Modifiers( shift: Bool, ctrl: Bool, alt: Bool, logo: Bool, command: Bool, )
Mouse button identifier.
pub type MouseButton {
LeftButton
RightButton
MiddleButton
BackButton
ForwardButton
OtherButton(String)
}
Constructors
-
LeftButtonPrimary mouse button (usually left).
-
RightButtonSecondary mouse button (usually right).
-
MiddleButtonMiddle mouse button (scroll wheel click).
-
BackButtonBrowser/mouse back button.
-
ForwardButtonBrowser/mouse forward button.
-
OtherButton(String)Any other mouse button, identified by name.
Widget scroll viewport data. All measurements in logical pixels.
absolute_x/y: current scroll offset from content originrelative_x/y: fractional position (0.0 = start, 1.0 = end)bounds_width/height: visible viewport dimensionscontent_width/height: total scrollable content dimensions
pub type ScrollData {
ScrollData(
absolute_x: Float,
absolute_y: Float,
relative_x: Float,
relative_y: Float,
bounds_width: Float,
bounds_height: Float,
content_width: Float,
content_height: Float,
)
}
Constructors
-
ScrollData( absolute_x: Float, absolute_y: Float, relative_x: Float, relative_y: Float, bounds_width: Float, bounds_height: Float, content_width: Float, content_height: Float, )
Scroll measurement unit.
pub type ScrollUnit {
Line
Pixel
}
Constructors
-
LineScroll delta measured in lines (e.g. mouse wheel notches).
-
PixelScroll delta measured in pixels (e.g. trackpad smooth scrolling).