Skip to content

State, commands and events

State is one plain object: windows, workspaces, outputs, focus with history, per-layer stacking, config. A command expresses intent. Events record what actually happened, which can differ: focus may be redirected to a modal, or a duplicate id rejected. Effects (render, focus) are values for the effectful shell.

import { createState, update, reduce, replay, derive, COMMANDS } from "@johnhenry/window-algebra";
let state = createState({ workspaces: ["main", "dev"] });
const out = update(state, { type: "window/create", id: "editor" });
// out.events → [{ type: "window/created", id: "editor" }, { type: "window/focused", id: "editor", previous: null }]
// out.effects → [{ type: "render" }, { type: "focus", id: "editor" }]

The 58 built-in commands (COMMANDS), each documented with payload, events, effects and rejections in Commands:

  • Windows: window/create, window/close (cascades to child windows), window/focus, window/blur, focus/next, focus/previous, window/raise, window/lower, window/set-layer, window/move, window/resize, window/set-mode, window/toggle-floating, window/minimize, window/maximize, window/fullscreen, window/restore, window/toggle-maximize, window/toggle-fullscreen, window/pop-out, window/pop-in, window/set-title, window/set-constraints, window/swap, window/promote, window/move-to-workspace, window/set-urgent, focus/urgent
  • Drag and drop: window/drop, window/detach, window/swap-next, window/swap-previous, window/move-before, window/move-after, window/set-draggable
  • Scratchpad and sticky: window/to-scratchpad, scratchpad/toggle, window/from-scratchpad, window/set-sticky, window/toggle-sticky
  • Workspaces: workspace/create, workspace/activate, workspace/remove, workspace/rename, workspace/reorder
  • Outputs: output/create, output/remove, output/focus, output/reorder, workspace/move-to-output
  • Layout: layout/set, layout/set-ratio, layout/rotate-split, layout/resize-split, layout/toggle, layout/to-tree
  • Config and rules: config/set, rules/set

Add your own with update(state, command, { "my/command": handler }), or pass extensions to createWindowManager. The 47 event types are catalogued in Events, and the read-only queries (isVisible, focusable, paintOrder, modalTarget, …) in Queries.

createWindowManager wraps all of this imperatively: wm.dispatch, wm.create/focus/close/…, subscribe, undo/redo, a command log where replay(wm.origin, wm.log) always equals wm.getState(), serialize/load with migration, and one renderer per output. See The manager.