Module: Plushie::Event

Defined in:
lib/plushie/event.rb,
lib/plushie/event/specs.rb,
lib/plushie/event/diagnostic.rb

Overview

Event types delivered to update/2.

All event types are immutable Data classes. Pattern match on them in your update method:

case event in Event::Widget[type: :click, id: "save"] model.with(saved: true) in Event::Key[type: :press, key: "s", modifiers: { command: true }] [model, Command.task(-> { save(model) }, :save_result)] end

Defined Under Namespace

Modules: Diagnostic, Specs Classes: Async, CommandError, DiagnosticMessage, Effect, Ime, Key, Modifiers, SessionClosed, SessionError, Stream, System, Timer, Widget, Window

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Attribute Details

#captured [Boolean] true if a widget consumed this event([Boolean]) ⇒ Object (readonly)

Modifier key state change events. Triggered when modifier keys (shift, ctrl, alt, command) change state. Subscribe via Subscription.on_modifiers_changed.

Examples:

Modifiers changed

in Event::Modifiers[modifiers: { shift: true }]


108
109
110
111
112
113
114
115
# File 'lib/plushie/event.rb', line 108

Key = Data.define(:type, :key, :modified_key, :physical_key,
  :location, :modifiers, :text, :repeat, :captured, :window_id) do
  def initialize(type:, key:, modified_key: nil, physical_key: nil,
    location: :standard, modifiers: {}, text: nil, repeat: false,
    captured: false, window_id: nil)
    super
  end
end

#code [String] stable diagnostic code: `session_panic`,([String]) ⇒ Object (readonly)

max_sessions_reached, session_channel_closed, writer_dead, font_cap_exceeded, renderer_panic, session_reset_in_progress, session_backpressure_overflow



380
# File 'lib/plushie/event.rb', line 380

SessionError = Data.define(:session, :code, :error)

#cursor [Array<Integer>, nil] cursor position within preedit([Array<Integer>, nil]) ⇒ Object (readonly)

IME (Input Method Editor) events for international text input. Triggered by IME composition sessions (CJK input, accent composition, etc.). Subscribe via Subscription.on_ime.

Examples:

IME commit

in Event::Ime[type: :commit, text:]

Preedit composition

in Event::Ime[type: :preedit, text:, cursor:]


133
134
135
136
137
138
# File 'lib/plushie/event.rb', line 133

Ime = Data.define(:type, :id, :scope, :text, :cursor, :captured, :window_id) do
  def initialize(type:, id: nil, scope: [], text: nil, cursor: nil,
    captured: false, window_id: nil)
    super
  end
end

#diagnostic [Object] typed diagnostic variant([Object]) ⇒ Object (readonly)

A structured diagnostic delivered through the renderer's diagnostic wire channel.

Wire shape: {type: "diagnostic", session, level, diagnostic: {kind, ...}}. The +diagnostic+ field is one of the typed variants in Diagnostic.



215
216
217
218
219
# File 'lib/plushie/event/diagnostic.rb', line 215

DiagnosticMessage = Data.define(:session, :level, :diagnostic) do
  def initialize(session:, level:, diagnostic:)
    super
  end
end

#error [String] human-readable error description([String]) ⇒ Object (readonly)

A multiplexed session encountered an error.

Emitted by the renderer when a session thread panics, hits a session-scoped cap, or otherwise fails. Only delivered when the renderer is run with --max-sessions > 1.

Examples:

in Event::SessionError[session:, code:, error:]
  logger.error("session #{session} failed (#{code}): #{error}")


380
# File 'lib/plushie/event.rb', line 380

SessionError = Data.define(:session, :code, :error)

#family [String, nil] command family name([String, nil]) ⇒ Object (readonly)

Renderer error for a command.

Emitted when the renderer cannot deliver or execute a command.

Examples:

in Event::CommandError[family:, id:, message:]
  logger.warn("command #{family} failed on #{id}: #{message}")


310
311
312
313
314
# File 'lib/plushie/event.rb', line 310

CommandError = Data.define(:reason, :id, :family, :widget_type, :message) do
  def initialize(reason:, id: nil, family: nil, widget_type: nil, message: nil)
    super
  end
end

#height [Float, nil] window height (for :resized, :opened)([Float, nil]() ⇒ Object (readonly)

Window lifecycle events (open, close, resize, move, focus, etc.). Triggered by window manager actions or user interaction with window chrome. Subscribe via Subscription.on_window_close, on_window_open, on_window_resize, etc.

Examples:

Window close requested

in Event::Window[type: :close_requested, window_id:]

Window resized

in Event::Window[type: :resized, width:, height:]

Display scale changed

in Event::Window[type: :rescaled, scale_factor:]

File drop cancelled (cursor left the window while hovering)

in Event::Window[type: :files_hovered_left, window_id:]


163
164
165
166
167
168
169
# File 'lib/plushie/event.rb', line 163

Window = Data.define(:type, :window_id, :x, :y, :width, :height,
  :scale_factor, :path) do
  def initialize(type:, window_id: nil, x: nil, y: nil,
    width: nil, height: nil, scale_factor: nil, path: nil)
    super
  end
end

#id [String, nil] target widget ID([String, nil]) ⇒ Object (readonly)

Renderer error for a command.

Emitted when the renderer cannot deliver or execute a command.

Examples:

in Event::CommandError[family:, id:, message:]
  logger.warn("command #{family} failed on #{id}: #{message}")


310
311
312
313
314
# File 'lib/plushie/event.rb', line 310

CommandError = Data.define(:reason, :id, :family, :widget_type, :message) do
  def initialize(reason:, id: nil, family: nil, widget_type: nil, message: nil)
    super
  end
end

#id [String, nil] widget ID that has IME focus([String, nil]) ⇒ Object (readonly)

IME (Input Method Editor) events for international text input. Triggered by IME composition sessions (CJK input, accent composition, etc.). Subscribe via Subscription.on_ime.

Examples:

IME commit

in Event::Ime[type: :commit, text:]

Preedit composition

in Event::Ime[type: :preedit, text:, cursor:]


133
134
135
136
137
138
# File 'lib/plushie/event.rb', line 133

Ime = Data.define(:type, :id, :scope, :text, :cursor, :captured, :window_id) do
  def initialize(type:, id: nil, scope: [], text: nil, cursor: nil,
    captured: false, window_id: nil)
    super
  end
end

#id [String] widget ID that produced the event([String]) ⇒ Object (readonly)

All widget interaction events.

Covers standard widget events (:click, :input, :submit, etc.), unified pointer events (:press, :release, :move, :scroll, :enter, :exit, :double_click, :resize), generic element events (:focused, :blurred, :drag, :drag_end, :key_press, :key_release), pane events (:pane_resized, :pane_dragged, :pane_clicked), animation events (:transition_complete), and subscription pointer events.

The +value+ field carries the event payload. For single-value events (input text, slider position, toggle state) it holds the scalar. For multi-field events (pointer coordinates, pane operations, key data) it holds a symbol-keyed Hash.

No-payload events (click, open, close) always have +value: nil+. Pattern-match without binding +value+ for these:

in Event::Widget[type: :click, id: "save"]

The +scope+ array lists ancestor container IDs from immediate parent to outermost. The window_id is appended as the last element (outermost ancestor). Use Event.target to reconstruct the forward-order path (window_id is stripped).

Examples:

Click

in Event::Widget[type: :click, id: "save"]

Input with value

in Event::Widget[type: :input, id: "search", value:]

Pointer press

in Event::Widget[type: :press, id: "canvas", value: {x:, y:, button: :left}]

Enter (cursor hover or touch enter)

in Event::Widget[type: :enter, id: "hover_zone"]

Resize (sensor)

in Event::Widget[type: :resize, id: "content", value: {width:, height:}]

Pane resized

in Event::Widget[type: :pane_resized, id: "editor", value: {ratio:}]


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/plushie/event.rb', line 62

Widget = Data.define(:type, :id, :value, :window_id, :scope) do
  def initialize(type:, id:, value: nil, window_id: nil, scope: [])
    super
  end

  # Category predicates for event type families.

  # Pointer events (press, release, move, scroll, enter, exit, double_click).
  def pointer? = Specs::POINTER_TYPES.include?(type)

  # Widget-scoped keyboard events (key_press, key_release).
  def keyboard? = Specs::KEYBOARD_TYPES.include?(type)

  # Pane grid events (pane_resized, pane_dragged, pane_clicked, pane_focus_cycle).
  def pane? = Specs::PANE_TYPES.include?(type)

  # Focus lifecycle events (focused, blurred).
  def focus? = Specs::FOCUS_TYPES.include?(type)

  # Drag events (drag, drag_end).
  def drag? = Specs::DRAG_TYPES.include?(type)

  # Look up the spec for this event's type.
  # @return [Hash, nil]
  def spec = Specs.for(type)
end

#key [Symbol, String] logical key name (:escape, :enter, "a", "s", etc.)([Symbol, String](: escape, :enter, "a", "s", etc.)) ⇒ Object (readonly)

Keyboard events delivered when keys are pressed or released. Triggered by keyboard input while the window has focus. Subscribe via Subscription.on_key_press or Subscription.on_key_release.

Examples:

Key press with modifier

in Event::Key[type: :press, key: "s", modifiers: { command: true }]

Any key release

in Event::Key[type: :release, key:]


108
109
110
111
112
113
114
115
# File 'lib/plushie/event.rb', line 108

Key = Data.define(:type, :key, :modified_key, :physical_key,
  :location, :modifiers, :text, :repeat, :captured, :window_id) do
  def initialize(type:, key:, modified_key: nil, physical_key: nil,
    location: :standard, modifiers: {}, text: nil, repeat: false,
    captured: false, window_id: nil)
    super
  end
end

#level [Symbol] :info, :warn, or :error([Symbol], : warn) ⇒ Object (readonly)

A structured diagnostic delivered through the renderer's diagnostic wire channel.

Wire shape: {type: "diagnostic", session, level, diagnostic: {kind, ...}}. The +diagnostic+ field is one of the typed variants in Plushie::Event::Diagnostic.



215
216
217
218
219
# File 'lib/plushie/event/diagnostic.rb', line 215

DiagnosticMessage = Data.define(:session, :level, :diagnostic) do
  def initialize(session:, level:, diagnostic:)
    super
  end
end

#location [Symbol] key location (:standard, :left, :right, :numpad)([Symbol](: standard, :left, :right, :numpad)) ⇒ Object (readonly)

Keyboard events delivered when keys are pressed or released. Triggered by keyboard input while the window has focus. Subscribe via Subscription.on_key_press or Subscription.on_key_release.

Examples:

Key press with modifier

in Event::Key[type: :press, key: "s", modifiers: { command: true }]

Any key release

in Event::Key[type: :release, key:]


108
109
110
111
112
113
114
115
# File 'lib/plushie/event.rb', line 108

Key = Data.define(:type, :key, :modified_key, :physical_key,
  :location, :modifiers, :text, :repeat, :captured, :window_id) do
  def initialize(type:, key:, modified_key: nil, physical_key: nil,
    location: :standard, modifiers: {}, text: nil, repeat: false,
    captured: false, window_id: nil)
    super
  end
end

#message [String, nil] human-readable error text([String, nil]) ⇒ Object (readonly)

Renderer error for a command.

Emitted when the renderer cannot deliver or execute a command.

Examples:

in Event::CommandError[family:, id:, message:]
  logger.warn("command #{family} failed on #{id}: #{message}")


310
311
312
313
314
# File 'lib/plushie/event.rb', line 310

CommandError = Data.define(:reason, :id, :family, :widget_type, :message) do
  def initialize(reason:, id: nil, family: nil, widget_type: nil, message: nil)
    super
  end
end

#modified_key [Symbol, String, nil] key with modifiers applied([Symbol, String, nil]) ⇒ Object (readonly)

Keyboard events delivered when keys are pressed or released. Triggered by keyboard input while the window has focus. Subscribe via Subscription.on_key_press or Subscription.on_key_release.

Examples:

Key press with modifier

in Event::Key[type: :press, key: "s", modifiers: { command: true }]

Any key release

in Event::Key[type: :release, key:]


108
109
110
111
112
113
114
115
# File 'lib/plushie/event.rb', line 108

Key = Data.define(:type, :key, :modified_key, :physical_key,
  :location, :modifiers, :text, :repeat, :captured, :window_id) do
  def initialize(type:, key:, modified_key: nil, physical_key: nil,
    location: :standard, modifiers: {}, text: nil, repeat: false,
    captured: false, window_id: nil)
    super
  end
end

#modifiers [Hash] active modifier state ({shift: true, command: false, ...})([Hash]({shift: true, command: false, ...})) ⇒ Object (readonly)

Keyboard events delivered when keys are pressed or released. Triggered by keyboard input while the window has focus. Subscribe via Subscription.on_key_press or Subscription.on_key_release.

Examples:

Key press with modifier

in Event::Key[type: :press, key: "s", modifiers: { command: true }]

Any key release

in Event::Key[type: :release, key:]


108
109
110
111
112
113
114
115
# File 'lib/plushie/event.rb', line 108

Key = Data.define(:type, :key, :modified_key, :physical_key,
  :location, :modifiers, :text, :repeat, :captured, :window_id) do
  def initialize(type:, key:, modified_key: nil, physical_key: nil,
    location: :standard, modifiers: {}, text: nil, repeat: false,
    captured: false, window_id: nil)
    super
  end
end

#modifiers [Hash] current modifier state ({shift: true, control: false, alt: false, command: false})([Hash]({shift: true, control: false, alt: false, command: false})) ⇒ Object (readonly)

Modifier key state change events. Triggered when modifier keys (shift, ctrl, alt, command) change state. Subscribe via Subscription.on_modifiers_changed.

Examples:

Modifiers changed

in Event::Modifiers[modifiers: { shift: true }]


181
182
183
184
185
# File 'lib/plushie/event.rb', line 181

Modifiers = Data.define(:modifiers, :captured, :window_id) do
  def initialize(modifiers:, captured: false, window_id: nil)
    super
  end
end

#path [String, nil] file path (for :file_dropped, :file_hovered)([String, nil]() ⇒ Object (readonly)

Window lifecycle events (open, close, resize, move, focus, etc.). Triggered by window manager actions or user interaction with window chrome. Subscribe via Subscription.on_window_close, on_window_open, on_window_resize, etc.

Examples:

Window close requested

in Event::Window[type: :close_requested, window_id:]

Window resized

in Event::Window[type: :resized, width:, height:]

Display scale changed

in Event::Window[type: :rescaled, scale_factor:]

File drop cancelled (cursor left the window while hovering)

in Event::Window[type: :files_hovered_left, window_id:]


163
164
165
166
167
168
169
# File 'lib/plushie/event.rb', line 163

Window = Data.define(:type, :window_id, :x, :y, :width, :height,
  :scale_factor, :path) do
  def initialize(type:, window_id: nil, x: nil, y: nil,
    width: nil, height: nil, scale_factor: nil, path: nil)
    super
  end
end

#physical_key [Symbol, String, nil] hardware scan code name([Symbol, String, nil]) ⇒ Object (readonly)

Keyboard events delivered when keys are pressed or released. Triggered by keyboard input while the window has focus. Subscribe via Subscription.on_key_press or Subscription.on_key_release.

Examples:

Key press with modifier

in Event::Key[type: :press, key: "s", modifiers: { command: true }]

Any key release

in Event::Key[type: :release, key:]


108
109
110
111
112
113
114
115
# File 'lib/plushie/event.rb', line 108

Key = Data.define(:type, :key, :modified_key, :physical_key,
  :location, :modifiers, :text, :repeat, :captured, :window_id) do
  def initialize(type:, key:, modified_key: nil, physical_key: nil,
    location: :standard, modifiers: {}, text: nil, repeat: false,
    captured: false, window_id: nil)
    super
  end
end

#reason [String] close reason from the renderer([String]) ⇒ Object (readonly)

A multiplexed session was closed by the renderer.

Emitted after a Reset completes and the session thread exits.



388
# File 'lib/plushie/event.rb', line 388

SessionClosed = Data.define(:session, :reason)

#reason [String] machine-readable error reason([String]) ⇒ Object (readonly)

Renderer error for a command.

Emitted when the renderer cannot deliver or execute a command.

Examples:

in Event::CommandError[family:, id:, message:]
  logger.warn("command #{family} failed on #{id}: #{message}")


310
311
312
313
314
# File 'lib/plushie/event.rb', line 310

CommandError = Data.define(:reason, :id, :family, :widget_type, :message) do
  def initialize(reason:, id: nil, family: nil, widget_type: nil, message: nil)
    super
  end
end

#repeat [Boolean] true if this is a key-repeat event([Boolean]) ⇒ Object (readonly)

Keyboard events delivered when keys are pressed or released. Triggered by keyboard input while the window has focus. Subscribe via Subscription.on_key_press or Subscription.on_key_release.

Examples:

Key press with modifier

in Event::Key[type: :press, key: "s", modifiers: { command: true }]

Any key release

in Event::Key[type: :release, key:]


108
109
110
111
112
113
114
115
# File 'lib/plushie/event.rb', line 108

Key = Data.define(:type, :key, :modified_key, :physical_key,
  :location, :modifiers, :text, :repeat, :captured, :window_id) do
  def initialize(type:, key:, modified_key: nil, physical_key: nil,
    location: :standard, modifiers: {}, text: nil, repeat: false,
    captured: false, window_id: nil)
    super
  end
end

#result [Object] return value of the async lambda([Object]) ⇒ Object (readonly)

Async command result events. Triggered when a Command.async lambda completes execution.

Examples:

Async result

in Event::Async[tag: :fetch_data, result:]


352
# File 'lib/plushie/event.rb', line 352

Async = Data.define(:tag, :result)

#scale_factor [Float, nil] display scale factor (for :rescaled)([Float, nil]() ⇒ Object (readonly)

Window lifecycle events (open, close, resize, move, focus, etc.). Triggered by window manager actions or user interaction with window chrome. Subscribe via Subscription.on_window_close, on_window_open, on_window_resize, etc.

Examples:

Window close requested

in Event::Window[type: :close_requested, window_id:]

Window resized

in Event::Window[type: :resized, width:, height:]

Display scale changed

in Event::Window[type: :rescaled, scale_factor:]

File drop cancelled (cursor left the window while hovering)

in Event::Window[type: :files_hovered_left, window_id:]


163
164
165
166
167
168
169
# File 'lib/plushie/event.rb', line 163

Window = Data.define(:type, :window_id, :x, :y, :width, :height,
  :scale_factor, :path) do
  def initialize(type:, window_id: nil, x: nil, y: nil,
    width: nil, height: nil, scale_factor: nil, path: nil)
    super
  end
end

#scope [Array<String>] reversed ancestor scope chain([Array<String>]) ⇒ Object (readonly)

IME (Input Method Editor) events for international text input. Triggered by IME composition sessions (CJK input, accent composition, etc.). Subscribe via Subscription.on_ime.

Examples:

IME commit

in Event::Ime[type: :commit, text:]

Preedit composition

in Event::Ime[type: :preedit, text:, cursor:]


133
134
135
136
137
138
# File 'lib/plushie/event.rb', line 133

Ime = Data.define(:type, :id, :scope, :text, :cursor, :captured, :window_id) do
  def initialize(type:, id: nil, scope: [], text: nil, cursor: nil,
    captured: false, window_id: nil)
    super
  end
end

#scope [Array<String>] reversed ancestor scope chain (immediate parent first, window_id last)([Array<String>](immediate parent first, window_id last)) ⇒ Object (readonly)

All widget interaction events.

Covers standard widget events (:click, :input, :submit, etc.), unified pointer events (:press, :release, :move, :scroll, :enter, :exit, :double_click, :resize), generic element events (:focused, :blurred, :drag, :drag_end, :key_press, :key_release), pane events (:pane_resized, :pane_dragged, :pane_clicked), animation events (:transition_complete), and subscription pointer events.

The +value+ field carries the event payload. For single-value events (input text, slider position, toggle state) it holds the scalar. For multi-field events (pointer coordinates, pane operations, key data) it holds a symbol-keyed Hash.

No-payload events (click, open, close) always have +value: nil+. Pattern-match without binding +value+ for these:

in Event::Widget[type: :click, id: "save"]

The +scope+ array lists ancestor container IDs from immediate parent to outermost. The window_id is appended as the last element (outermost ancestor). Use Event.target to reconstruct the forward-order path (window_id is stripped).

Examples:

Click

in Event::Widget[type: :click, id: "save"]

Input with value

in Event::Widget[type: :input, id: "search", value:]

Pointer press

in Event::Widget[type: :press, id: "canvas", value: {x:, y:, button: :left}]

Enter (cursor hover or touch enter)

in Event::Widget[type: :enter, id: "hover_zone"]

Resize (sensor)

in Event::Widget[type: :resize, id: "content", value: {width:, height:}]

Pane resized

in Event::Widget[type: :pane_resized, id: "editor", value: {ratio:}]


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/plushie/event.rb', line 62

Widget = Data.define(:type, :id, :value, :window_id, :scope) do
  def initialize(type:, id:, value: nil, window_id: nil, scope: [])
    super
  end

  # Category predicates for event type families.

  # Pointer events (press, release, move, scroll, enter, exit, double_click).
  def pointer? = Specs::POINTER_TYPES.include?(type)

  # Widget-scoped keyboard events (key_press, key_release).
  def keyboard? = Specs::KEYBOARD_TYPES.include?(type)

  # Pane grid events (pane_resized, pane_dragged, pane_clicked, pane_focus_cycle).
  def pane? = Specs::PANE_TYPES.include?(type)

  # Focus lifecycle events (focused, blurred).
  def focus? = Specs::FOCUS_TYPES.include?(type)

  # Drag events (drag, drag_end).
  def drag? = Specs::DRAG_TYPES.include?(type)

  # Look up the spec for this event's type.
  # @return [Hash, nil]
  def spec = Specs.for(type)
end

#session [String] session the diagnostic is attributable to.([String]) ⇒ Object (readonly)

An empty string for process-scoped diagnostics (font load failures, renderer startup / panic, writer-dead, anything that affects the whole renderer rather than a single session). Non-empty for session-scoped diagnostics (widget panics, view errors, tree validation warnings, anything produced inside a session's update / apply pipeline).



215
216
217
218
219
# File 'lib/plushie/event/diagnostic.rb', line 215

DiagnosticMessage = Data.define(:session, :level, :diagnostic) do
  def initialize(session:, level:, diagnostic:)
    super
  end
end

#session [String] the session ID that errored([String]) ⇒ Object (readonly)

A multiplexed session encountered an error.

Emitted by the renderer when a session thread panics, hits a session-scoped cap, or otherwise fails. Only delivered when the renderer is run with --max-sessions > 1.

Examples:

in Event::SessionError[session:, code:, error:]
  logger.error("session #{session} failed (#{code}): #{error}")


380
# File 'lib/plushie/event.rb', line 380

SessionError = Data.define(:session, :code, :error)

#session [String] the session ID that was closed([String]) ⇒ Object (readonly)

A multiplexed session was closed by the renderer.

Emitted after a Reset completes and the session thread exits.



388
# File 'lib/plushie/event.rb', line 388

SessionClosed = Data.define(:session, :reason)

#tag [Symbol, nil] subscription tag (for :animation_frame)([Symbol, nil]() ⇒ Object (readonly)

System events for theme changes, animation frames, and other runtime signals. Triggered by OS-level changes or renderer lifecycle events. Subscribe via Subscription.on_theme_change or on_animation_frame.

Examples:

Theme changed

in Event::System[type: :theme_changed, value: theme]

Animation frame

in Event::System[type: :animation_frame, value: delta_ms]


328
329
330
331
332
# File 'lib/plushie/event.rb', line 328

System = Data.define(:type, :tag, :value) do
  def initialize(type:, tag: nil, value: nil)
    super
  end
end

#tag [Symbol] the tag specified in Command.async([Symbol]) ⇒ Object (readonly)

Async command result events. Triggered when a Command.async lambda completes execution.

Examples:

Async result

in Event::Async[tag: :fetch_data, result:]


352
# File 'lib/plushie/event.rb', line 352

Async = Data.define(:tag, :result)

#tag [Symbol] the tag specified in Command.stream([Symbol]) ⇒ Object (readonly)

Stream command chunk events. Triggered for each value emitted by a Command.stream source.

Examples:

Stream chunk

in Event::Stream[tag: :download, value:]


362
# File 'lib/plushie/event.rb', line 362

Stream = Data.define(:tag, :value)

#tag [Symbol] the tag specified in Subscription.every([Symbol]) ⇒ Object (readonly)

Timer events from interval subscriptions. Triggered periodically by Subscription.every at the specified interval.

Examples:

Timer tick

in Event::Timer[tag: :tick, timestamp:]


342
# File 'lib/plushie/event.rb', line 342

Timer = Data.define(:tag, :timestamp)

#text [String, nil] composed or committed text([String, nil]) ⇒ Object (readonly)

IME (Input Method Editor) events for international text input. Triggered by IME composition sessions (CJK input, accent composition, etc.). Subscribe via Subscription.on_ime.

Examples:

IME commit

in Event::Ime[type: :commit, text:]

Preedit composition

in Event::Ime[type: :preedit, text:, cursor:]


133
134
135
136
137
138
# File 'lib/plushie/event.rb', line 133

Ime = Data.define(:type, :id, :scope, :text, :cursor, :captured, :window_id) do
  def initialize(type:, id: nil, scope: [], text: nil, cursor: nil,
    captured: false, window_id: nil)
    super
  end
end

#text [String, nil] text produced by the key event (nil for non-printable keys)([String, nil](nil) ⇒ Object (readonly)

Keyboard events delivered when keys are pressed or released. Triggered by keyboard input while the window has focus. Subscribe via Subscription.on_key_press or Subscription.on_key_release.

Examples:

Key press with modifier

in Event::Key[type: :press, key: "s", modifiers: { command: true }]

Any key release

in Event::Key[type: :release, key:]


108
109
110
111
112
113
114
115
# File 'lib/plushie/event.rb', line 108

Key = Data.define(:type, :key, :modified_key, :physical_key,
  :location, :modifiers, :text, :repeat, :captured, :window_id) do
  def initialize(type:, key:, modified_key: nil, physical_key: nil,
    location: :standard, modifiers: {}, text: nil, repeat: false,
    captured: false, window_id: nil)
    super
  end
end

#timestamp [Integer] monotonic timestamp in milliseconds([Integer]) ⇒ Object (readonly)

Timer events from interval subscriptions. Triggered periodically by Subscription.every at the specified interval.

Examples:

Timer tick

in Event::Timer[tag: :tick, timestamp:]


342
# File 'lib/plushie/event.rb', line 342

Timer = Data.define(:tag, :timestamp)

#type [Symbol] :opened, :close_requested, :closed,([Symbol], : close_requested, : closed) ⇒ Object (readonly)

:resized, :rescaled, :moved, :focused, :unfocused, :file_dropped, :file_hovered, :files_hovered_left



163
164
165
166
167
168
169
# File 'lib/plushie/event.rb', line 163

Window = Data.define(:type, :window_id, :x, :y, :width, :height,
  :scale_factor, :path) do
  def initialize(type:, window_id: nil, x: nil, y: nil,
    width: nil, height: nil, scale_factor: nil, path: nil)
    super
  end
end

#type [Symbol] :opened, :preedit, :commit, :closed([Symbol], : preedit, : commit, : closed) ⇒ Object (readonly)

IME (Input Method Editor) events for international text input. Triggered by IME composition sessions (CJK input, accent composition, etc.). Subscribe via Subscription.on_ime.

Examples:

IME commit

in Event::Ime[type: :commit, text:]

Preedit composition

in Event::Ime[type: :preedit, text:, cursor:]


133
134
135
136
137
138
# File 'lib/plushie/event.rb', line 133

Ime = Data.define(:type, :id, :scope, :text, :cursor, :captured, :window_id) do
  def initialize(type:, id: nil, scope: [], text: nil, cursor: nil,
    captured: false, window_id: nil)
    super
  end
end

#type [Symbol] :press or :release([Symbol]) ⇒ Object (readonly)

Keyboard events delivered when keys are pressed or released. Triggered by keyboard input while the window has focus. Subscribe via Subscription.on_key_press or Subscription.on_key_release.

Examples:

Key press with modifier

in Event::Key[type: :press, key: "s", modifiers: { command: true }]

Any key release

in Event::Key[type: :release, key:]


108
109
110
111
112
113
114
115
# File 'lib/plushie/event.rb', line 108

Key = Data.define(:type, :key, :modified_key, :physical_key,
  :location, :modifiers, :text, :repeat, :captured, :window_id) do
  def initialize(type:, key:, modified_key: nil, physical_key: nil,
    location: :standard, modifiers: {}, text: nil, repeat: false,
    captured: false, window_id: nil)
    super
  end
end

#type [Symbol] :theme_changed, :animation_frame([Symbol], : animation_frame) ⇒ Object (readonly)

System events for theme changes, animation frames, and other runtime signals. Triggered by OS-level changes or renderer lifecycle events. Subscribe via Subscription.on_theme_change or on_animation_frame.

Examples:

Theme changed

in Event::System[type: :theme_changed, value: theme]

Animation frame

in Event::System[type: :animation_frame, value: delta_ms]


328
329
330
331
332
# File 'lib/plushie/event.rb', line 328

System = Data.define(:type, :tag, :value) do
  def initialize(type:, tag: nil, value: nil)
    super
  end
end

#type [Symbol] event kind([Symbol]) ⇒ Object (readonly)

All widget interaction events.

Covers standard widget events (:click, :input, :submit, etc.), unified pointer events (:press, :release, :move, :scroll, :enter, :exit, :double_click, :resize), generic element events (:focused, :blurred, :drag, :drag_end, :key_press, :key_release), pane events (:pane_resized, :pane_dragged, :pane_clicked), animation events (:transition_complete), and subscription pointer events.

The +value+ field carries the event payload. For single-value events (input text, slider position, toggle state) it holds the scalar. For multi-field events (pointer coordinates, pane operations, key data) it holds a symbol-keyed Hash.

No-payload events (click, open, close) always have +value: nil+. Pattern-match without binding +value+ for these:

in Event::Widget[type: :click, id: "save"]

The +scope+ array lists ancestor container IDs from immediate parent to outermost. The window_id is appended as the last element (outermost ancestor). Use Event.target to reconstruct the forward-order path (window_id is stripped).

Examples:

Click

in Event::Widget[type: :click, id: "save"]

Input with value

in Event::Widget[type: :input, id: "search", value:]

Pointer press

in Event::Widget[type: :press, id: "canvas", value: {x:, y:, button: :left}]

Enter (cursor hover or touch enter)

in Event::Widget[type: :enter, id: "hover_zone"]

Resize (sensor)

in Event::Widget[type: :resize, id: "content", value: {width:, height:}]

Pane resized

in Event::Widget[type: :pane_resized, id: "editor", value: {ratio:}]


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/plushie/event.rb', line 62

Widget = Data.define(:type, :id, :value, :window_id, :scope) do
  def initialize(type:, id:, value: nil, window_id: nil, scope: [])
    super
  end

  # Category predicates for event type families.

  # Pointer events (press, release, move, scroll, enter, exit, double_click).
  def pointer? = Specs::POINTER_TYPES.include?(type)

  # Widget-scoped keyboard events (key_press, key_release).
  def keyboard? = Specs::KEYBOARD_TYPES.include?(type)

  # Pane grid events (pane_resized, pane_dragged, pane_clicked, pane_focus_cycle).
  def pane? = Specs::PANE_TYPES.include?(type)

  # Focus lifecycle events (focused, blurred).
  def focus? = Specs::FOCUS_TYPES.include?(type)

  # Drag events (drag, drag_end).
  def drag? = Specs::DRAG_TYPES.include?(type)

  # Look up the spec for this event's type.
  # @return [Hash, nil]
  def spec = Specs.for(type)
end

#value [Object, nil] event payload (scalar or symbol-keyed Hash)([Object, nil](scalar) ⇒ Object (readonly)

All widget interaction events.

Covers standard widget events (:click, :input, :submit, etc.), unified pointer events (:press, :release, :move, :scroll, :enter, :exit, :double_click, :resize), generic element events (:focused, :blurred, :drag, :drag_end, :key_press, :key_release), pane events (:pane_resized, :pane_dragged, :pane_clicked), animation events (:transition_complete), and subscription pointer events.

The +value+ field carries the event payload. For single-value events (input text, slider position, toggle state) it holds the scalar. For multi-field events (pointer coordinates, pane operations, key data) it holds a symbol-keyed Hash.

No-payload events (click, open, close) always have +value: nil+. Pattern-match without binding +value+ for these:

in Event::Widget[type: :click, id: "save"]

The +scope+ array lists ancestor container IDs from immediate parent to outermost. The window_id is appended as the last element (outermost ancestor). Use Event.target to reconstruct the forward-order path (window_id is stripped).

Examples:

Click

in Event::Widget[type: :click, id: "save"]

Input with value

in Event::Widget[type: :input, id: "search", value:]

Pointer press

in Event::Widget[type: :press, id: "canvas", value: {x:, y:, button: :left}]

Enter (cursor hover or touch enter)

in Event::Widget[type: :enter, id: "hover_zone"]

Resize (sensor)

in Event::Widget[type: :resize, id: "content", value: {width:, height:}]

Pane resized

in Event::Widget[type: :pane_resized, id: "editor", value: {ratio:}]


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/plushie/event.rb', line 62

Widget = Data.define(:type, :id, :value, :window_id, :scope) do
  def initialize(type:, id:, value: nil, window_id: nil, scope: [])
    super
  end

  # Category predicates for event type families.

  # Pointer events (press, release, move, scroll, enter, exit, double_click).
  def pointer? = Specs::POINTER_TYPES.include?(type)

  # Widget-scoped keyboard events (key_press, key_release).
  def keyboard? = Specs::KEYBOARD_TYPES.include?(type)

  # Pane grid events (pane_resized, pane_dragged, pane_clicked, pane_focus_cycle).
  def pane? = Specs::PANE_TYPES.include?(type)

  # Focus lifecycle events (focused, blurred).
  def focus? = Specs::FOCUS_TYPES.include?(type)

  # Drag events (drag, drag_end).
  def drag? = Specs::DRAG_TYPES.include?(type)

  # Look up the spec for this event's type.
  # @return [Hash, nil]
  def spec = Specs.for(type)
end

#value [Object, nil] event payload (theme name for :theme_changed, delta ms for :animation_frame)([Object, nil](theme name) ⇒ Object (readonly)

System events for theme changes, animation frames, and other runtime signals. Triggered by OS-level changes or renderer lifecycle events. Subscribe via Subscription.on_theme_change or on_animation_frame.

Examples:

Theme changed

in Event::System[type: :theme_changed, value: theme]

Animation frame

in Event::System[type: :animation_frame, value: delta_ms]


328
329
330
331
332
# File 'lib/plushie/event.rb', line 328

System = Data.define(:type, :tag, :value) do
  def initialize(type:, tag: nil, value: nil)
    super
  end
end

#value [Object] the emitted chunk value([Object]) ⇒ Object (readonly)

Stream command chunk events. Triggered for each value emitted by a Command.stream source.

Examples:

Stream chunk

in Event::Stream[tag: :download, value:]


362
# File 'lib/plushie/event.rb', line 362

Stream = Data.define(:tag, :value)

#widget_type [String, nil] widget type name([String, nil]) ⇒ Object (readonly)

Renderer error for a command.

Emitted when the renderer cannot deliver or execute a command.

Examples:

in Event::CommandError[family:, id:, message:]
  logger.warn("command #{family} failed on #{id}: #{message}")


310
311
312
313
314
# File 'lib/plushie/event.rb', line 310

CommandError = Data.define(:reason, :id, :family, :widget_type, :message) do
  def initialize(reason:, id: nil, family: nil, widget_type: nil, message: nil)
    super
  end
end

#width [Float, nil] window width (for :resized, :opened)([Float, nil]() ⇒ Object (readonly)

Window lifecycle events (open, close, resize, move, focus, etc.). Triggered by window manager actions or user interaction with window chrome. Subscribe via Subscription.on_window_close, on_window_open, on_window_resize, etc.

Examples:

Window close requested

in Event::Window[type: :close_requested, window_id:]

Window resized

in Event::Window[type: :resized, width:, height:]

Display scale changed

in Event::Window[type: :rescaled, scale_factor:]

File drop cancelled (cursor left the window while hovering)

in Event::Window[type: :files_hovered_left, window_id:]


163
164
165
166
167
168
169
# File 'lib/plushie/event.rb', line 163

Window = Data.define(:type, :window_id, :x, :y, :width, :height,
  :scale_factor, :path) do
  def initialize(type:, window_id: nil, x: nil, y: nil,
    width: nil, height: nil, scale_factor: nil, path: nil)
    super
  end
end

#window_id [String, nil] ID of the affected window([String, nil]) ⇒ Object (readonly)

Window lifecycle events (open, close, resize, move, focus, etc.). Triggered by window manager actions or user interaction with window chrome. Subscribe via Subscription.on_window_close, on_window_open, on_window_resize, etc.

Examples:

Window close requested

in Event::Window[type: :close_requested, window_id:]

Window resized

in Event::Window[type: :resized, width:, height:]

Display scale changed

in Event::Window[type: :rescaled, scale_factor:]

File drop cancelled (cursor left the window while hovering)

in Event::Window[type: :files_hovered_left, window_id:]


163
164
165
166
167
168
169
# File 'lib/plushie/event.rb', line 163

Window = Data.define(:type, :window_id, :x, :y, :width, :height,
  :scale_factor, :path) do
  def initialize(type:, window_id: nil, x: nil, y: nil,
    width: nil, height: nil, scale_factor: nil, path: nil)
    super
  end
end

#window_id [String, nil] window that produced the event([String, nil]) ⇒ Object (readonly)

All widget interaction events.

Covers standard widget events (:click, :input, :submit, etc.), unified pointer events (:press, :release, :move, :scroll, :enter, :exit, :double_click, :resize), generic element events (:focused, :blurred, :drag, :drag_end, :key_press, :key_release), pane events (:pane_resized, :pane_dragged, :pane_clicked), animation events (:transition_complete), and subscription pointer events.

The +value+ field carries the event payload. For single-value events (input text, slider position, toggle state) it holds the scalar. For multi-field events (pointer coordinates, pane operations, key data) it holds a symbol-keyed Hash.

No-payload events (click, open, close) always have +value: nil+. Pattern-match without binding +value+ for these:

in Event::Widget[type: :click, id: "save"]

The +scope+ array lists ancestor container IDs from immediate parent to outermost. The window_id is appended as the last element (outermost ancestor). Use Event.target to reconstruct the forward-order path (window_id is stripped).

Examples:

Click

in Event::Widget[type: :click, id: "save"]

Input with value

in Event::Widget[type: :input, id: "search", value:]

Pointer press

in Event::Widget[type: :press, id: "canvas", value: {x:, y:, button: :left}]

Enter (cursor hover or touch enter)

in Event::Widget[type: :enter, id: "hover_zone"]

Resize (sensor)

in Event::Widget[type: :resize, id: "content", value: {width:, height:}]

Pane resized

in Event::Widget[type: :pane_resized, id: "editor", value: {ratio:}]


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/plushie/event.rb', line 62

Widget = Data.define(:type, :id, :value, :window_id, :scope) do
  def initialize(type:, id:, value: nil, window_id: nil, scope: [])
    super
  end

  # Category predicates for event type families.

  # Pointer events (press, release, move, scroll, enter, exit, double_click).
  def pointer? = Specs::POINTER_TYPES.include?(type)

  # Widget-scoped keyboard events (key_press, key_release).
  def keyboard? = Specs::KEYBOARD_TYPES.include?(type)

  # Pane grid events (pane_resized, pane_dragged, pane_clicked, pane_focus_cycle).
  def pane? = Specs::PANE_TYPES.include?(type)

  # Focus lifecycle events (focused, blurred).
  def focus? = Specs::FOCUS_TYPES.include?(type)

  # Drag events (drag, drag_end).
  def drag? = Specs::DRAG_TYPES.include?(type)

  # Look up the spec for this event's type.
  # @return [Hash, nil]
  def spec = Specs.for(type)
end

#window_id [String, nil] window that was focused when the event fired([String, nil]) ⇒ Object (readonly)

Modifier key state change events. Triggered when modifier keys (shift, ctrl, alt, command) change state. Subscribe via Subscription.on_modifiers_changed.

Examples:

Modifiers changed

in Event::Modifiers[modifiers: { shift: true }]


108
109
110
111
112
113
114
115
# File 'lib/plushie/event.rb', line 108

Key = Data.define(:type, :key, :modified_key, :physical_key,
  :location, :modifiers, :text, :repeat, :captured, :window_id) do
  def initialize(type:, key:, modified_key: nil, physical_key: nil,
    location: :standard, modifiers: {}, text: nil, repeat: false,
    captured: false, window_id: nil)
    super
  end
end

#x [Float, nil] window x position (for :moved)([Float, nil]() ⇒ Object (readonly)

Window lifecycle events (open, close, resize, move, focus, etc.). Triggered by window manager actions or user interaction with window chrome. Subscribe via Subscription.on_window_close, on_window_open, on_window_resize, etc.

Examples:

Window close requested

in Event::Window[type: :close_requested, window_id:]

Window resized

in Event::Window[type: :resized, width:, height:]

Display scale changed

in Event::Window[type: :rescaled, scale_factor:]

File drop cancelled (cursor left the window while hovering)

in Event::Window[type: :files_hovered_left, window_id:]


163
164
165
166
167
168
169
# File 'lib/plushie/event.rb', line 163

Window = Data.define(:type, :window_id, :x, :y, :width, :height,
  :scale_factor, :path) do
  def initialize(type:, window_id: nil, x: nil, y: nil,
    width: nil, height: nil, scale_factor: nil, path: nil)
    super
  end
end

#y [Float, nil] window y position (for :moved)([Float, nil]() ⇒ Object (readonly)

Window lifecycle events (open, close, resize, move, focus, etc.). Triggered by window manager actions or user interaction with window chrome. Subscribe via Subscription.on_window_close, on_window_open, on_window_resize, etc.

Examples:

Window close requested

in Event::Window[type: :close_requested, window_id:]

Window resized

in Event::Window[type: :resized, width:, height:]

Display scale changed

in Event::Window[type: :rescaled, scale_factor:]

File drop cancelled (cursor left the window while hovering)

in Event::Window[type: :files_hovered_left, window_id:]


163
164
165
166
167
168
169
# File 'lib/plushie/event.rb', line 163

Window = Data.define(:type, :window_id, :x, :y, :width, :height,
  :scale_factor, :path) do
  def initialize(type:, window_id: nil, x: nil, y: nil,
    width: nil, height: nil, scale_factor: nil, path: nil)
    super
  end
end

Class Method Details

.strip_window_scope(scope, window_id) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Remove window_id from the end of a scope array.



408
409
410
411
# File 'lib/plushie/event.rb', line 408

def self.strip_window_scope(scope, window_id)
  return scope if window_id.nil? || scope.empty?
  (scope.last == window_id) ? scope[0...-1] : scope
end

.target(event) ⇒ Object

Reconstruct the full scoped path as a forward-order string. Strips the window_id from scope (it appears at the end of the scope list but is not part of the container path).

Event.target(widget_event) # => "sidebar/form/save"



396
397
398
399
400
401
402
403
404
# File 'lib/plushie/event.rb', line 396

def self.target(event)
  scope = event.respond_to?(:scope) ? event.scope : []
  window_id = event.respond_to?(:window_id) ? event.window_id : nil

  scope = strip_window_scope(scope, window_id)

  return event.id if scope.empty?
  (scope.reverse + [event.id]).join("/")
end