Using the API
A host has one native owner thread and one seat. Start one host per process; stop it and let run-host! consume the terminal event to join its owner. Sigil handlers and the optional REPL run on the Sigil scheduler. The examples show the complete lifecycle without application-specific code in the native layer.
Host and events
start-host! accepts protocols: (a bit mask, default 0) and request-deadline: (milliseconds, default 1000). Optional protocol bits are 1 for session lock, 2 for client virtual input, 4 for XWayland, 8 for decoration negotiation, 16 for idle notification/inhibitors and 32 for layer-shell. Unsupported bits are rejected. XWayland uses the executable in the environment or the explicit WLR_XWAYLAND path. Core Wayland/xdg-shell, viewports and relative pointer transport are always available.
Bit 1024 enables ext-foreign-toplevel-list-v1; bit 2048 enables wlr-foreign-toplevel-management-unstable-v1. Listing is read-only, but both listing and management are privileged and hidden from security-context clients; native clients retain compatibility access. Handles cover mapped xdg toplevels and managed XWayland surfaces, excluding layers and override-redirect surfaces. Unmapping closes handles; remapping creates fresh identifiers. Metadata changes are forwarded to both protocols. Applied scene plans determine fullscreen state and logical output intersection; native seat focus determines activation.
xwayland_shell_v1 is advertised only to the compositor's Xwayland client. Xwayland activation follows applied seat focus, including focus changes that do not configure a window. Leaving X focus or entering a lock clears XWM focus, so wlroots can authorize clipboard and primary-selection transfers correctly.
Management emits foreign-toplevel-request (raw kind 127), with window id:, request: (1 activate, 2 close, 3 fullscreen, 4 maximize, 5 minimize), enabled?:, output: (0 for unspecified) and lock generation:. Requests are copied, transient and invalidated across overflow rather than retained as snapshot facts. They are ignored by the native owner while locked; consumers must also check current policy state and the current lock generation when processing them. Activation must name the host's seat. Policy decides which operations it supports; requests never directly mutate the scene or close an application. Rectangle hints have no native behavior.
on-event! returns a subscription token; remove-handler! removes it. begin-scene-update! brackets copied pixel changes and the next applied scene into one presentation. Its deadline is between 1 and 200 milliseconds; client frame callbacks continue, lock presentation is immediate, and an abandoned bracket expires. Applying the plan damages the whole output.
record-output-samples! takes an output, file path, 1..64 physical pixel coordinates and a limit of 1..600 frames. It writes one indexed RGB sample row for every buffer commit, including the output commit sequence and PASS/FAIL. It requests one initial frame, then observes natural commits without scheduling extra frames. Unreadable buffers are reported as failure. Sampling ends at the limit or with stop-output-samples!, which takes the host and output. A subsequent query-pointer! reply provides a queue barrier before reading the completed file. This allows transition checks without retaining full-frame streams.
Layer surfaces emit layer-presentation with their kernel-reported client pid:, presented?:, output: and commit-sequence:. A true acknowledgement follows an actual presented output commit containing the mapped layer; unmap clears it. Background providers can use it to keep their predecessor alive until every requested output has presented the replacement.
event-type supplies a symbol such as output-added, window-mapped, window-title, transaction-applied or virtual-device-request. event-ref reads named fields, including id:. The numeric event-kind and copied event-raw vector are also available for ABI diagnostics. Complete UTF-8 title updates are assembled before the window-title event; intermediate transfer records have type metadata-chunk.
host-snapshot returns detached output/window facts and a revision. Output records preserve their advertised modes. A window's committed: rect is its client-local window geometry, distinct from the global desired placement in a scene plan. configure-serial: identifies the associated configure. Container, workspace, placement and focus relationships belong to the manager's immutable (sigil wm model) state.
configure-output! takes an output ID and explicit settings: enabled:, x:, y:, scale:, transform:, mode:, width:, height: and refresh:. A mode index selects an advertised mode; -1 supplies a custom size/refresh in mHz. Nested managers should start with the backend's initial size, then decide how to answer output-state-request events. Configuration completion reports its queue token and success; queue acceptance alone is not hardware acceptance.
configure-device! selects a keyboard's layout, repeat rate and delay. configure-window! answers initial size negotiation. configure-popup! takes the popup ID and an explicit parent-local rect. set-seat-capabilities!, set-pointer-route!, set-decoration-mode!, set-cursor! and set-idle-state! apply caller-selected settings. A virtual-device request includes peer credentials; reply-request! accepts or refuses its token. Unanswered virtual/popup requests expire. Lock focus uses focus-lock! with an explicit output and admitted physical keyboard; emulated and virtual devices cannot become lock input devices. Unlock is exclusively the lock owner's protocol request after real presentation acknowledgement.
Scene and drawing
The native build also supplies build/environment-exec, a generic exec helper for managers that capture a private login environment before entering a build environment. Its arguments are a private NUL-delimited snapshot path, override count, override names, --, then the program and its arguments. Override values arrive as SIGIL_EXEC_VALUE_0, SIGIL_EXEC_VALUE_1, and so on. The caller starts the helper with empty LD_LIBRARY_PATH and LD_PRELOAD values. The helper replaces only its own environment and execs in the same PID. Before exec, it restores default dispositions for all supported catchable signals and empties its signal mask, so launcher settings do not leak into clients. It contains no session, application or variable-selection policy.
An arranger receives a container, rect, snapshot and trigger. Its result is an ordered list of placements; the example managers keep their own selection and geometry rules. submit-plan! takes a complete scene plan with explicit focus and configure deadline. It returns a token or #f for queue refusal. Applied and rejected events refer to that token. Old client buffers remain visible while resized clients acknowledge; output frames continue independently of Sigil.
A complete plan admits up to 256 window records and 6,553 records in total, including pixel decorations. The total fits the bridge's 65,536-word payload; scene-plan-limit exposes it to callers. Pixels do not consume the window budget.
A placement's kind: is window or pixel. Record order controls stacking across both kinds. Visibility, client size, activation, suspension, fullscreen, tiled edges and clipping are explicit. A manager retains hidden tabs and floating restore rectangles in Sigil; no native container kind changes their behavior.
present-pixels! copies a premultiplied native-endian ARGB32 image at a logical rect/scale. Its optional stack: is top, bottom or keep. place-pixels! changes geometry/stacking without reuploading pixels; remove-pixels! retires the node. Native copies outlive their caller's image. The optional drawing module supplies scaled text, shaped cluster-aware ellipsis, canvases, shapes and an image cache. Its cache replaces an old image only after the receiver accepts a copied replacement. Destroy cached images before closing fonts. The core imports no drawing library.
Input and expression IPC
Key hooks receive immutable input-event records with device, time, code, keysyms, modifiers, focus generation and origin (physical, emulated or virtual). Return (forward event), (replace replacement) or (drop). A replacement can change its code/modifier mask; routing/ownership fields stay fixed. A replaced modifier mask applies to the delivered event and is followed by the actual client-visible state. Press/release identities are paired in C; a forwarded press receives its matching release even if that release's hook fails or drops it. Button hooks use the same ownership rule.
set-motion-hook! registers a procedure plus device, minimum period and region filters. Device 0 and a zero-size region mean all devices/positions. Matching samples may coalesce while preserving the latest accumulated position. Removing the hook restores the C path; ordinary motion chooses no keyboard focus or window geometry. A manager implements drag/hover behavior in its hook.
emulate-key!, emulate-motion!, emulate-button! and emulate-axis! take seat 1 and return completion tokens or #f. Axis discrete values are wheel detents. These trusted in-process calls share the ordered hook/routing path with normal input. Client virtual devices are inert until their separate request is granted and remain distinct from emulation authority.
start-repl! takes the host, a Unix-socket path in a user-owned private directory, and an evaluation environment (or evaluator procedure). Frames contain a decimal UTF-8 byte length, LF and the expression bytes. Replies frame a printed (value result) or (error exception). repl-request and scripts/msg implement this framing. Evaluation may yield while other clients are connected; each completed result is formatted into its own reply. Expression output uses the session output port and is separate from the result frame. Keep run-host! and REPL tasks in the same with-async scope; stop-repl! closes clients and removes its own endpoint.
Role and input facts
Output snapshots retain connector name:, nested?:, enabled?: and transform: fields. Disabled-output completions are explicit; a previously returned snapshot remains unchanged. Window snapshots retain initial size hints and parents. The role: field distinguishes toplevel, layer and x11. X11 facts include PID, transient parent, override-redirect, modal and dialog flags, decorations, class as app ID, instance and reported geometry. They do not imply any ownership, stacking, placement or visibility rule.
host-x-display reads the copied display name, including updates after the XWayland server becomes ready. configure-x11! answers a client configure request with an explicit global rect. Scene plans manage X11 and layer surfaces through the same placement and focus operations as other windows. Their native role adapters retain protocol lifetimes and configure bookkeeping only.
For layer-shell, call set-default-layer-output! with a manager-selected output before accepting clients that omit an output. wlroots requires an output before its native role callback returns; no output fallback is selected by the host. layer-state events and snapshots expose anchors, requested size, margins, exclusive zone/edge, keyboard interactivity and initialized?:. configure-layer! supplies a chosen output and client width/height after initialization. The manager computes usable areas, layer order, placement and keyboard focus. Client layer interactivity and session-lock restrictions remain native focus safety checks.
configure-keyboard! takes device, layout, repeat rate and delay, plus optional options:, variant:, rules: and model: strings. set-keyboard-group! selects one explicit group on one device; cycling and device selection belong to the manager. Key events expose active symbols, base-level symbols and first-layout base symbols separately. Modifier changes are copied as modifiers-changed events with device and group facts.
Button and hooked motion events include copied hit-target and output IDs. observe-pointer! optionally reports pointer-target-changed only when the target or output changes. Its moved?: field distinguishes input motion from scene refresh; coordinates use x-milli: and y-milli: fields. Observation chooses no focus and can run independently of interception. Disabled observation and absent motion hooks generate no ordinary motion callback to Sigil. Input replies retry cooperatively when the command ring is full or native startup is still in progress. The hook runs once; its copied disposition stays in FIFO order with earlier commands. A terminated receiver ends retry without raising a queue-full error. Rate-limited INPUT_REPLY lines distinguish queue-full, receiver-starting and receiver-stopped with depth and input kind.
Intercepted input decisions have a 32 ms native observation budget and 10 ms timer granularity. An intercepted key/button over that budget is logged and keeps waiting for policy; it is never forwarded by default. Missing motion decisions retain cursor movement. Nonmatching ordinary keys and buttons bypass the queue. Overflow cancels stale intercepted tokens and balances their queued releases without clearing ordinary native streams. Late tokens are ignored. Physical lock-key delivery and mapped lock-surface focus are native invariants.
set-key-intercepts! and set-button-intercepts! take a host and a list of (code modifiers mask scope target) integer rules. An empty list delegates all presses natively; #f intercepts every unlocked press. Installing a custom hook resets its rules to #f, so publish selective rules after installing the hook and whenever the manager's bindings or modes change. Keys match active, base or first-layout keysyms and masked modifiers; key scopes are 0 either lock state, 1 unlocked and 2 locked. Only explicitly cached lock-eligible chords can wait while locked; ordinary physical lock keys remain native. Button code 0 matches any button; scopes are 0 any target, 1 window, 2 manager pixel, 3 exact signed target, and 4 window other than native keyboard focus. Positive targets are windows and negative targets are pixels. A press retains its interception identity through release even if rules change. button-observed carries the copied input record for an unmatched native click; use decode-input-event on its raw vector to observe held buttons without issuing a disposition. The observation is emitted before client delivery, preserving order with a client's move/resize request. If motion advances during a pending click, its eventual release publishes a fresh observation in the current focus epoch so the manager can reconcile hover.
Output configuration and power intents coalesce over one native event-loop idle. The host prepares swapchains, renders the current scene into enabled output states and submits one backend commit. Lock ownership keeps the normal scene disabled during this render. Per-output fallback normally follows an atomic test failure. A failed wake also retries once per output after rollback, logging the attempt and result. An unanswered power-on request defaults to acceptance at its native deadline; a late policy reply cannot undo it. Set SIGIL_WM_DEBUG_OUTPUTS=1 to log commit grouping and per-output request-to-first- present latency. Set SIGIL_WM_DEBUG_INPUT=1 only for input diagnostics; its eligibility log includes keycodes, keysyms and modifiers and can expose typed input. Ordinary keys wait behind a pending chord for at most its original 32 ms budget, then flow natively in order even if the policy decision still waits.
On event overflow, the host rebuilds its copied snapshot from live native facts, reports lifecycle differences, then sends snapshot-resynced. Invalidate pending input/request reply tokens and resubmit complete scene plans on that event. Keep configuration completion mappings: those replies are retained and replayed after snapshot-resynced, including output batches and keyboard configuration. input-fault is recoverable and reports native input-stream cancellation. Statistic 2 counts event overflows, 9 counts snapshot resyncs, 10 over-budget input decisions, and 11 coalesced queued motions. Text notices carry one complete bounded copied value. warp-pointer! applies an explicit manager-selected position without synthesizing client input or classifying the warp as user motion.
Additional drawing operations
The optional drawing module also exports font/run/image predicates and metrics, render-outline, render-panel, compose-text-image! and write-text-image!. Outline colors are premultiplied RGBA; panel and text colors are straight RGBA. Image composition requires live images at the same scale. No application styling is selected by these helpers.
Output capture temporarily locks rendering to a composed frame, then releases that lock. A direct-scanout source buffer is not treated as a complete output image. Ordinary presentation retains its direct-scanout behavior.
add-headless-output! creates an output on the host's unique headless backend, with an optional caller-selected connector name set before advertisement. remove-headless-output! destroys a headless output. These operations emit the ordinary output lifecycle events with fresh IDs and support reproducible hotplug workloads. X11 client move and resize requests use the same copied window-request events as other roles, including the requested resize edges.
Pixel presentation defaults to input pass-through, including transparent pixels. Use input?: #t to accept pointer input for a manager-owned pixel surface. Button and motion events then expose input-event-target-kind as pixel and input-event-target as its identifier; client targets use window. Raw hit facts use a negative pixel identifier and positive window identifier. Optional output: and bounds: scope the copy to an exact output rectangle. An output change disables stale scoped pixels immediately; a stale replacement is discarded, and a fresh copy with current bounds restores presentation/input. Hit transitions caused by scene updates retain moved?: #f.
(sigil wm dispatch) supplies independent callback owners for applications with event, timer, input and expression producers. Create an owner with make-dispatcher; producers use dispatcher-enqueue! or the synchronous dispatcher-call!. One consumer waits with dispatcher-wait! and drains with dispatcher-drain!. Ownership persists across yielding callbacks. Call producers must run outside the owner they wait on. Closing rejects new work and gives pending requests a terminal error, preserving in-flight work.
Protocol bit64 explicitly exposes desktop capture, output descriptions, presentation, single-pixel buffers, data-control/primary selection and cursor shapes. Exposing capture permits clients to capture outputs through the native protocol; choose the mask before starting the host.
Clipboard/primary requests produce selection-request; pointer drags produce drag-request with the origin window and serial-validity fact. Use reply-data-request! to accept/refuse while the bounded request is alive. The owner rechecks generation, lock isolation and drag serials on acceptance. Source/origin destruction retires requests; expiration refuses them. An accepted drag follows its icon only when follow-icon?: #t is explicit. Drag started/drop/end facts have stable IDs and balanced native ownership.
delegate-client-cursor! caches an explicit policy permission for focused clients to supply cursor surfaces or standard shapes. It defaults to false; disable delegation during a manager-owned interactive grab.
(sigil wm session) exports call-with-host-session: a start thunk returns the host, a body receives it, and application cleanup receives it after join. Normal completion and exceptions both stop/drain/join the owner before library unload. Application callbacks are not entered while unwinding native shutdown.
Queued notifications may provide on-cancel: separately from handler errors. Closing silently drops notifications by default; synchronous calls always receive a terminal cancellation error. This keeps normal shutdown distinct from an application callback failure.
Transaction rejection reason2 identifies a retired resource in object: (positive window ID, negative pixel ID). submitted?: distinguishes a stale submission from retirement while an accepted transaction was waiting. Schema/geometry errors remain reason1, and superseded transactions reason3. Managers can retry only after confirming the copied resource has retired.
Pixel copies normally require source dimensions to match destination geometry and scale. Explicit stretch?: #t resamples a bounded source bitmap into the requested destination rectangle, including reusable transparent input masks. Input acceptance and output scope remain explicit and independent.
Input transport notifies only the pending intercepted head event. Unhooked pointer motion and axes stay native and flow while a decision is pending, without adding motion callbacks. Button modifiers are captured at input time. Pointer presses are refused if their copied hit target has changed.
Inside a press hook, focus-window! may take input-token: for that exact pending press. The native owner validates its target/epoch and explicitly retargets the following ordered input prefix across that focus change. Ordinary focus commands retain their existing input fence; lock epochs cannot be crossed by this authorization.
observe-pointer! accepts after-motion?: #t to reset target observation without a stationary sample. The first subsequent real motion produces a sample even when the target has not changed, useful after an implicit grab.
restack-scene! changes only bottom-to-top resource order. Its list contains (window id), (pixel id) and the symbol drag. It does not send geometry configures or copy pixels. Omitted resources retain their relative order; resources retired before the command is applied are ignored. The list is bounded to 65,535 distinct resources. Explicit drag following initially presents its image above existing resources, and the manager may restack it. Drag images never accept ordinary pointer input.
present-pixels! accepts optional order: with the same bottom-to-top resource list, including (pixel id) for the uploaded image. It takes precedence over stack:. The native command copies both the image and order, then inserts or updates that pixel beside its nearest live neighbour before any frame renders or pointer routing runs. Retired neighbours are skipped; a lone resource goes to the bottom. Other resources are not reordered. This allows new decoration nodes to appear at their final position without a later policy round trip. Existing callers that omit order: retain their stacking semantics.
Output snapshots distinguish pixel-width:/pixel-height: from logical width:/height:. A custom output mode uses physical pixel dimensions; logical bounds reflect scale and transform. Initial window facts already carry the surface role, before its role-specific configuration facts arrive.
Device snapshots contain copied names, type, virtual?:, libinput?: and tap finger count. Removing a device retires its snapshot and balances its forwarded held keys/buttons. Virtual origin is assigned only by native admission. configure-pointer! accepts a dictionary with tap:, dwt:, middle-emulation: and natural-scroll:, each boolean or unset. The manager chooses which devices receive settings. pointer-configuration-result reports one status per setting: -1 untouched, 0 applied, 1 unsupported, 2 invalid. Keyboard rule fields permit255 characters, repeat rate up to1000 and delay up to10000 milliseconds.
set-lock-background! selects an opaque #xRRGGBBFF fill for a specific active lock generation. Stale generations and translucent colours are rejected. Native lock isolation and authenticated unlock remain unconditional.
Protocol bit128 exposes output configuration, power and gamma controls. configure-outputs! takes a list of explicit output dictionaries, each with id:, enabled:, x:, y:, scale:, transform:, mode:, width:, height: and refresh:; optional adaptive-sync?: defaults false. Outputs omitted from the list keep their state. test?: #t tests without applying. Native code tests the complete backend state, commits it and attempts rollback if a backend partially commits. A configuration result includes rollback:: 0 unnecessary, 1 restored, 2 failed. Actual hardware state is published after a failed rollback, so the manager can decide how to recover.
An output-configuration-request carries copied heads:, apply?: and a configuration revision. reply-output-configuration! takes the request ID and an explicit replacement head list, or false to refuse. A dedicated output-configuration-result reports protocol success. Requests expire at the host's declared deadline and become invalid when their output context changes. Copied proposals remain ordinary Sigil data after the native request retires.
output-power-request and output-gamma-request require explicit reply-output-control! admission. set-output-power! is an explicit manager command. Output enabled?: describes configured ownership and powered?: describes hardware power; powering down preserves configured geometry and workspace decisions. Native gamma tables remain native resources and apply with a frame commit after admission. set-output-filter! selects linear or nearest; any rule choosing between them belongs to the manager.
Collections in copied snapshots retain object creation order when facts change. Snapshots also retain inhibitor associations and the last explicit idle state. An inhibitor created before its window role gains that association when the role appears; the manager chooses whether its applied visibility inhibits idle.
Pointer constraints use protocol bit512. They remain inert until policy calls set-active-pointer-constraint! host id generation; id0 deactivates the current lease. The constraints: snapshot contains copied identity, lifetime, seat, visibility, pointer focus, keyboard owner, region membership and focus generation facts. constraint-state arrives only when those facts change. Policy chooses eligibility and selection. Native code enforces the admitted lock or confinement without a callback for ordinary motion, and ends it on scope or surface loss.
A locked client's release hint becomes a bounded pointer-hint-request with window, focus generation and global coordinates. reply-pointer-hint! accepts or refuses it. Acceptance revalidates the live surface, current epoch, input region and output coordinates; expired or retired requests cannot move the pointer. delegate-relative-pointer! host enabled? explicitly controls native relative motion delivery. query-pointer! host returns a token for an asynchronous pointer-state observation and updates pointer-state: in the snapshot.
A pointer-target-changed observation carries pointer-token:. Supplying it as pointer-token: to focus-window! authorizes that copied transition while preserving queued input from the same focus epoch. input-token: supplies the corresponding authorization for the notified head press. Optional input-target: identifies the actual captured window when policy focuses a different recipient, such as that window's owner. The native host checks the token, target and epoch. The call returns an operation token. Its focus-request-result uses that token as id: and copies the input or pointer token as authorization:. A retired, hidden or lock-isolated target returns accepted?: #f, including plain focus operations. Stale authorization also returns accepted?: #f; it does not focus a window or count as a malformed command. The accepted result preserves paired first-click delivery even when the policy handler yields.
Batch output settings accept optional power?:. It defaults to enabled:; setting it false keeps an admitted logical output asleep while changing its explicit layout or mode. enabled: remains the administrative layout decision. Snapshots also copy actual powered?:, current mode:, refresh: and adaptive-sync?: so policy can preserve unchanged backend state in a complete configuration. Previously returned snapshots remain detached.
Protocol bit256 exposes activation requests as copied target, source-window, seat/serial provenance and focus-generation facts. The protocol implementation validates tokens; policy chooses attention or focus. Native activation never changes focus. acknowledge-configure! host window sends an explicit empty xdg configure reply, including when policy declines a maximize request.
start-host! accepts socket: for a chosen Wayland socket basename. Names are copied before startup; unsafe names and occupied endpoints fail cleanly. ready reports session-available?:. configure-session-switches! accepts up to 12 (keysym . vt) pairs as an explicit native escape cache. Matching physical presses and releases bypass a stalled policy handler; virtual/emulated devices cannot trigger this cache. A session backend must exist. The backend call is covered with a native stub, without changing a real terminal session.
Protocol bit8 also exposes the legacy decoration negotiation interface. start-host! accepts legacy-decoration: 'none|'client|'server as the explicit initial protocol default. Both decoration transports appear as detached decorations: records with stable identity, associated window, mode and kind. decoration-state reports changed facts, including association when a legacy object preceded its window role; decoration-destroyed retires that identity. Policy selects border presentation and supplies xdg preference through set-decoration-mode!. Cached preference applies on initial commit, without waking policy or producing new configures on ordinary client frames. Native wrappers are bounded and included in the ownership counters.
Keyboard device facts include nested?: for input supplied by a parent Wayland backend. configure-keyboard! accepts group: (default0) and fixed-group?: (defaultfalse); set-keyboard-group! accepts fixed?:. A fixed group preserves the explicitly chosen group across incoming backend modifier updates. Other modifier state still follows the device. Policy chooses which devices need that cache; the generic host supplies no binding or group selection rule.
query-window! host window returns an operation token. A live initialized window produces paired window-observation and window-observation-geometry events with that token as id:. They copy actual scene position, committed geometry, mapping, visibility, focus, surface offset and acknowledged serial. Committed activation, suspension, fullscreen and tiled protocol state are available when xdg-state?: is true; other roles report those fields as zero. The geometry event includes the bound xdg protocol version. A retired or uninitialized window produces only an observation with accepted?: #f. These explicit queries do not configure a client or change manager state.
Queued keyboard observations still reach the input hook after an ordinary focus change, so semantic bindings can consume a burst without losing later keys. Forwarding and replacement retain the original focus generation and are refused when stale. Scope loss and lock isolation still cancel pending input before it can reach an unauthorized recipient. Policy never receives stale virtual input while locked.
Output-scoped pixels are bounded by the supplied geometry. A malformed rectangle is refused before copying. If a queued image's output or geometry has since retired, the copied image is discarded without rejecting the command or changing the existing image. Host statistics 5 and 6 count current pixel nodes and discarded scoped images; statistic 4 counts retained copied pixel bytes.
set-default-layer-output! returns an operation token. Its layer-output-result reports output: and accepted?:. A retired output refuses the cached-target update without choosing a replacement or rejecting the command. Output 0 explicitly clears the target.
A window placement accepts suspended?: independently of shown?:. It defaults to false. The host forwards the requested protocol state to native toplevels whose bound protocol version supports it; other roles and older versions have no suspension state. Managers explicitly choose when hidden clients suspend.
A placement's resize?: defaults to true. False retains the established client size while applying the requested scene box and protocol state. This lets a manager keep future hidden layout geometry without resizing the client. Unchanged protocol state sends no redundant configure; state-only changes do not wait for a new geometry commit. Pending geometric configures still retain their serial and deadline.
Destroying an output retires its scoped pixel nodes and their copied storage. Changing its geometry disables stale scoped nodes until explicitly replaced or removed. Queued images for retired outputs are discarded without retaining copies.
Window observation surface offsets name the actual root surface tree relative to the window geometry node. Clipping uses root-surface coordinates and leaves popups outside that tree free to extend beyond the client rectangle. Pending visible geometric transactions continue frame callbacks while hidden clients answer their new configure. Invalid keyboard maps return a failed configuration result while retaining the previously applied map and group.
Host statistic7 reports currently retained transaction snapshot trees; statistic8 counts snapshot trees created during the session. Both are mechanism facts. Snapshot ownership ends at application, refusal or destruction of its view.
Window geometry observations also expose requested-suspended?: separately from the committed suspended?: field, plus acknowledged and scheduled configure serials. A state-only configure may be acknowledged without a new surface commit. Native geometry changes refresh the explicit clip rectangle in the root surface coordinate space, including later decoration-margin commits.
Forwarded keys publish their copied origin modifier snapshot for both press and release. Replacement keys retain their explicitly requested modifier snapshot. This includes virtual keyboards that send modifier state without modifier-key presses. Pooled held-key ownership and stale-focus forwarding checks still apply.
Committed xdg size-hint and parent changes after the initial handshake emit window-hints events and update detached window snapshots. They do not emit a second window-initial event or choose a size for the manager.
X11 association catches up an already committed buffer before publishing normal map and geometry facts. Placement and focus still require the manager's scene.
Wayland window credentials
Wayland toplevel window records include pid:, uid: and gid: copied from the client's Unix socket credentials when the window is created. The window-created event exposes the same fields. These identify the connection's process, which can own multiple windows; they do not identify a terminal's foreground process. Window creation facts retain these values during snapshot resynchronization. Layer and X11 creation records use #f; X11's later pid: property is client-reported and does not carry authenticated UID/GID values.
With SIGIL_WM_TRACE_LATENCY=1, latency-mark! stage [token] records a direct monotonic timestamp for stages 1–7; stage 1 establishes the input token. Native key-input, buffer-commit and presentation records use stages 0, 8 and 9. The trace is bounded to 4096 stderr records and is disabled by default. Presentation uses the backend's supplied presentation timestamp; compare it with monotonic owner timestamps only on a backend whose presentation clock is monotonic.