Event Flow
ZREV Event Batches
The engine emits events as ZREV binary batches containing one or more event records.Event Record Types
| Record Kind | Description | Fields |
|---|---|---|
| Key | Keyboard input | keyCode, mods, text |
| Mouse | Mouse events | x, y, mouseKind, buttons, wheelX, wheelY |
| Resize | Terminal size change | cols, rows |
| Tick | Animation frame timer | deltaNs |
Event Parsing
Location:packages/core/src/events.ts
- No reads past buffer end
- No unbounded allocations from untrusted sizes
- Explicit structured errors (no exceptions)
Key Events
Key Event Structure
Key Codes
Defined inpackages/core/src/keybindings/keyCodes.ts:
| Key | Code | Notes |
|---|---|---|
ZR_KEY_ESCAPE | 1 | |
ZR_KEY_ENTER | 2 | |
ZR_KEY_TAB | 3 | |
ZR_KEY_BACKSPACE | 4 | |
ZR_KEY_UP | 20 | Arrow keys |
ZR_KEY_DOWN | 21 | |
ZR_KEY_LEFT | 22 | |
ZR_KEY_RIGHT | 23 | |
ZR_KEY_F1 … ZR_KEY_F12 | 100-111 | Function keys |
Modifier Bitmask
Keybinding Matching
Applications register keybindings viaapp.keys():
- Parse keybinding string into
ParsedKey(code + mods) - Build trie from keybindings for efficient lookup
- On key event, match
(keyCode, mods)against trie - Support multi-key chords (e.g.,
"ctrl+k ctrl+s")
packages/core/src/keybindings/index.ts
Mouse Events
Mouse Event Structure
Mouse Kind Values
| Kind | Value | Description |
|---|---|---|
move | 1 | Mouse moved without button pressed |
drag | 2 | Mouse moved with button pressed |
down | 3 | Button pressed |
up | 4 | Button released |
wheel | 5 | Scroll wheel moved |
Hit Testing
Mouse events are routed to widgets via hit testing:- Find deepest widget at
(x, y)that is focusable - Check bounding box containment
- Respect clipping bounds
- Return widget instance ID
packages/core/src/layout/hitTest.ts
Mouse Action Routing
Mouse events generate widget actions:| Mouse Event | Widget Capability | Action |
|---|---|---|
down on Button | pressable | press |
down on Input | focusable | Focus change |
wheel in scroll region | scrollable | scroll |
down on Table row | rowPressable | rowPress |
packages/core/src/app/widgetRenderer.ts
Wheel Event Routing
Mouse wheel events route to the nearest scrollable ancestor.Scroll Target Detection
- Hit test at wheel event
(x, y) - Walk up ancestor chain from hit widget
- Find first ancestor with
overflow: "scroll" - Apply scroll delta to that widget
packages/core/src/runtime/router/wheel.ts
Event Routing to Widgets
Widgets receive events via action system:Action Types
| Action | Emitted By | Trigger |
|---|---|---|
press | Button, Checkbox | Mouse down or Enter key |
input | Input | Text input |
select | Select, Dropdown | Item chosen |
toggle | Checkbox, Switch | State toggled |
change | Input, Select | Value changed |
activate | List item | Enter or click |
scroll | ScrollView | Wheel event |
rowPress | Table | Row clicked |
Action Event Structure
Input Widget Editing
Input widgets handle text editing directly in the event system.Input State
Edit Events
Key events are translated to edit operations:| Key | Modifier | Operation |
|---|---|---|
| Printable char | None | Insert at cursor |
| Backspace | None | Delete before cursor |
| Delete | None | Delete after cursor |
| Left | None | Move cursor left |
| Right | None | Move cursor right |
| Home | None | Move to start |
| End | None | Move to end |
| Left/Right | Shift | Extend selection |
| Ctrl+A | None | Select all |
packages/core/src/runtime/inputEditor.ts
Undo Stack
Input widgets maintain undo/redo stacks:- Ctrl+Z: Undo
- Ctrl+Y / Ctrl+Shift+Z: Redo
Resize Events
Terminal resize events trigger full re-layout:- Update viewport dimensions
- Trigger full layout pass
- Re-render entire tree
Tick Events
Animation frame events for declarative animations:useTransition()— declarative state transitionsuseSpring()— physics-based animationsuseSequence()— animation sequences
fpsCap (default: 30 FPS)
Event Caps
Event batches have configurable size limits:- Engine enforces cap when building ZREV batches
- Events exceeding cap are dropped (with warning)
- Prevents unbounded memory allocation
Focus Management
Focus state determines which widget receives keyboard events.Focus Traversal
Tab: Move focus forwardShift+Tab: Move focus backward Algorithm:
- Collect all focusable widgets in depth-first order
- Find current focused widget
- Move to next/previous in list (wrapping at edges)
packages/core/src/runtime/focus.ts
Focus Events
Widgets are notified of focus changes:Related Documentation
- ZREV Protocol — Binary event format
- Mouse Support Guide — Mouse interaction patterns
- Keybindings Reference — Keybinding API
- Input Widgets — Input widget editing