AtlatestRepositorysigil-wm
1# Using the API
2
3A host has one native owner thread and one seat. Start one host per process;
4stop it and let `run-host!` consume the terminal event to join its owner. Sigil
5handlers and the optional REPL run on the Sigil scheduler. The examples show the
6complete lifecycle without application-specific code in the native layer.
7
8## Host and events
9
10`start-host!` accepts `protocols:` (a bit mask, default 0) and
11`request-deadline:` (milliseconds, default 1000). Optional protocol bits are 1
12for session lock, 2 for client virtual input, 4 for XWayland, 8 for decoration
13negotiation, 16 for idle notification/inhibitors and 32 for layer-shell.
14Unsupported bits are rejected. XWayland uses the executable in the environment
15or the explicit WLR_XWAYLAND path. Core
16Wayland/xdg-shell, viewports and relative pointer transport are always available.
18Bit 1024 enables `ext-foreign-toplevel-list-v1`; bit 2048 enables
19`wlr-foreign-toplevel-management-unstable-v1`. Listing is read-only, but both
20listing and management are privileged and hidden from security-context clients;
21native clients retain compatibility access. Handles cover mapped xdg toplevels
22and managed XWayland surfaces, excluding layers and override-redirect surfaces.
23Unmapping closes handles; remapping creates fresh identifiers. Metadata changes
24are forwarded to both protocols. Applied scene plans determine fullscreen state
25and logical output intersection; native seat focus determines activation.
27`xwayland_shell_v1` is advertised only to the compositor's Xwayland client.
28Xwayland activation follows applied seat focus, including focus changes that
29do not configure a window. Leaving X focus or entering a lock clears XWM focus,
30so wlroots can authorize clipboard and primary-selection transfers correctly.
32Management emits `foreign-toplevel-request` (raw kind 127), with window `id:`,
33`request:` (1 activate, 2 close, 3 fullscreen, 4 maximize, 5 minimize),
34`enabled?:`, `output:` (0 for unspecified) and lock `generation:`. Requests are
35copied, transient
36and invalidated across overflow rather than retained as snapshot facts. They
37are ignored by the native owner while locked; consumers must also check current
38policy state and the current lock generation when processing them. Activation
39must name the host's seat.
40Policy decides which operations it supports; requests never directly mutate
41the scene or close an application. Rectangle hints have no native behavior.
43`on-event!` returns a subscription token; `remove-handler!` removes it.
44`begin-scene-update!` brackets copied pixel changes and the next applied scene
45into one presentation. Its deadline is between 1 and 200 milliseconds; client
46frame callbacks continue, lock presentation is immediate, and an abandoned
47bracket expires. Applying the plan damages the whole output.
49`record-output-samples!` takes an output, file path, 1..64 physical pixel
50coordinates and a limit of 1..600 frames. It writes one indexed RGB sample row
51for every buffer commit, including the output commit sequence and PASS/FAIL.
52It requests one initial frame, then observes natural commits without scheduling
53extra frames. Unreadable buffers are reported as failure. Sampling ends at the
54limit or with `stop-output-samples!`, which takes the host and output. A subsequent
55`query-pointer!` reply provides a queue barrier before reading the completed
56file. This allows transition checks without retaining full-frame streams.
58Layer surfaces emit `layer-presentation` with their kernel-reported client
59`pid:`, `presented?:`, `output:` and `commit-sequence:`. A true acknowledgement
60follows an actual presented output commit containing the mapped layer; unmap
61clears it. Background providers can use it to keep their predecessor alive
62until every requested output has presented the replacement.
64`event-type` supplies a symbol such as `output-added`, `window-mapped`,
65`window-title`, `transaction-applied` or `virtual-device-request`. `event-ref`
66reads named fields, including `id:`. The numeric `event-kind` and copied
67`event-raw` vector are also available for ABI diagnostics. Complete UTF-8 title
68updates are assembled before the `window-title` event; intermediate transfer
69records have type `metadata-chunk`.
71`host-snapshot` returns detached output/window facts and a revision. Output
72records preserve their advertised modes. A window's `committed:` rect is its
73client-local window geometry, distinct from the global desired placement in a
74scene plan. `configure-serial:` identifies the associated configure. Container,
75workspace, placement and focus relationships belong to the manager's immutable
76`(sigil wm model)` state.
78`configure-output!` takes an output ID and explicit settings: `enabled:`, `x:`,
79`y:`, `scale:`, `transform:`, `mode:`, `width:`, `height:` and `refresh:`. A mode
80index selects an advertised mode; -1 supplies a custom size/refresh in mHz.
81Nested managers should start with the backend's initial size, then decide how
82to answer `output-state-request` events. Configuration completion reports its
83queue token and success; queue acceptance alone is not hardware acceptance.
85`configure-device!` selects a keyboard's layout, repeat rate and delay.
86`configure-window!` answers initial size negotiation. `configure-popup!` takes
87the popup ID and an explicit parent-local rect. `set-seat-capabilities!`,
88`set-pointer-route!`, `set-decoration-mode!`, `set-cursor!` and
89`set-idle-state!` apply caller-selected settings. A virtual-device request
90includes peer credentials; `reply-request!` accepts or refuses its token.
91Unanswered virtual/popup requests expire. Lock focus uses `focus-lock!` with an
92explicit output and admitted physical keyboard; emulated and virtual devices
93cannot become lock input devices. Unlock is exclusively the lock owner's
94protocol request after real presentation acknowledgement.
96## Scene and drawing
98The native build also supplies `build/environment-exec`, a generic exec helper
99for managers that capture a private login environment before entering a build
100environment. Its arguments are a private NUL-delimited snapshot path, override
101count, override names, `--`, then the program and its arguments. Override
102values arrive as `SIGIL_EXEC_VALUE_0`, `SIGIL_EXEC_VALUE_1`, and so on. The
103caller starts the helper with empty `LD_LIBRARY_PATH` and `LD_PRELOAD` values.
104The helper replaces only its own environment and execs in the same PID. Before
105exec, it restores default dispositions for all supported catchable signals and
106empties its signal mask, so launcher settings do not leak into clients. It
107contains no session, application or variable-selection policy.
109An arranger receives a container, rect, snapshot and trigger. Its result is an
110ordered list of placements; the example managers keep their own selection and
111geometry rules. `submit-plan!` takes a complete scene plan with explicit focus
112and configure deadline. It returns a token or #f for queue refusal. Applied and
113rejected events refer to that token. Old client buffers remain visible while
114resized clients acknowledge; output frames continue independently of Sigil.
116A complete plan admits up to 256 window records and 6,553 records in total,
117including pixel decorations. The total fits the bridge's 65,536-word payload;
118`scene-plan-limit` exposes it to callers. Pixels do not consume the window
119budget.
121A placement's `kind:` is `window` or `pixel`. Record order controls stacking
122across both kinds. Visibility, client size, activation, suspension, fullscreen, tiled edges
123and clipping are explicit. A manager retains hidden tabs and floating restore
124rectangles in Sigil; no native container kind changes their behavior.
126`present-pixels!` copies a premultiplied native-endian ARGB32 image at a logical
127rect/scale. Its optional `stack:` is `top`, `bottom` or `keep`.
128`place-pixels!` changes geometry/stacking without reuploading pixels;
129`remove-pixels!` retires the node. Native copies outlive their caller's image.
130The optional drawing module supplies scaled text, shaped cluster-aware ellipsis,
131canvases, shapes and an image cache. Its cache replaces an old image only after
132the receiver accepts a copied replacement. Destroy cached images before closing
133fonts. The core imports no drawing library.
135## Input and expression IPC
137Key hooks receive immutable `input-event` records with device, time, code,
138keysyms, modifiers, focus generation and origin (`physical`, `emulated` or
139`virtual`). Return `(forward event)`, `(replace replacement)` or `(drop)`.
140A replacement can change its code/modifier mask; routing/ownership fields stay
141fixed. A replaced modifier mask applies to the delivered event and is followed
142by the actual client-visible state. Press/release identities are paired in C;
143a forwarded press receives its matching release even if that release's hook
144fails or drops it. Button hooks use the same ownership rule.
146`set-motion-hook!` registers a procedure plus device, minimum period and region
147filters. Device 0 and a zero-size region mean all devices/positions. Matching
148samples may coalesce while preserving the latest accumulated position. Removing
149the hook restores the C path; ordinary motion chooses no keyboard focus or
150window geometry. A manager implements drag/hover behavior in its hook.
152`emulate-key!`, `emulate-motion!`, `emulate-button!` and `emulate-axis!` take seat
1531 and return completion tokens or #f. Axis discrete values are wheel detents.
154These trusted in-process calls share the ordered hook/routing path with normal
155input. Client virtual devices are inert until their separate request is granted
156and remain distinct from emulation authority.
158`start-repl!` takes the host, a Unix-socket path in a user-owned private directory,
159and an evaluation environment (or evaluator procedure). Frames contain a decimal
160UTF-8 byte length, LF and the expression bytes. Replies frame a printed
161`(value result)` or `(error exception)`. `repl-request` and `scripts/msg` implement
162this framing. Evaluation may yield while other clients are connected; each
163completed result is formatted into its own reply. Expression output uses the
164session output port and is separate from the result frame. Keep `run-host!` and REPL tasks in the same `with-async` scope;
165`stop-repl!` closes clients and removes its own endpoint.
167## Role and input facts
169Output snapshots retain connector `name:`, `nested?:`, `enabled?:` and
170`transform:` fields. Disabled-output completions are explicit; a previously
171returned snapshot remains unchanged. Window snapshots retain initial size
172hints and parents. The `role:` field distinguishes `toplevel`, `layer` and
173`x11`. X11 facts include PID, transient parent, override-redirect, modal and
174dialog flags, decorations, class as app ID, instance and reported geometry.
175They do not imply any ownership, stacking, placement or visibility rule.
177`host-x-display` reads the copied display name, including updates after the
178XWayland server becomes ready. `configure-x11!` answers a client configure
179request with an explicit global rect. Scene plans manage X11 and layer surfaces
180through the same placement and focus operations as other windows. Their native
181role adapters retain protocol lifetimes and configure bookkeeping only.
183For layer-shell, call `set-default-layer-output!` with a manager-selected output
184before accepting clients that omit an output. wlroots requires an output before
185its native role callback returns; no output fallback is selected by the host.
186`layer-state` events and snapshots expose anchors, requested size, margins,
187exclusive zone/edge, keyboard interactivity and `initialized?:`.
188`configure-layer!` supplies a chosen output and client width/height after
189initialization. The manager computes usable areas, layer order, placement and
190keyboard focus. Client layer interactivity and session-lock restrictions remain
191native focus safety checks.
193`configure-keyboard!` takes device, layout, repeat rate and delay, plus optional
194`options:`, `variant:`, `rules:` and `model:` strings.
195`set-keyboard-group!` selects one explicit group on one device; cycling and
196device selection belong to the manager. Key events expose active symbols,
197base-level symbols and first-layout base symbols separately. Modifier changes
198are copied as `modifiers-changed` events with device and group facts.
200Button and hooked motion events include copied hit-target and output IDs.
201`observe-pointer!` optionally reports `pointer-target-changed` only when the
202target or output changes. Its `moved?:` field distinguishes input motion from
203scene refresh; coordinates use `x-milli:` and `y-milli:` fields. Observation
204chooses no focus and can run independently of interception. Disabled observation
205and absent motion hooks generate no ordinary motion callback to Sigil.
206Input replies retry cooperatively when the command ring is full or native
207startup is still in progress. The hook runs once; its copied disposition stays
208in FIFO order with earlier commands. A terminated receiver ends retry without
209raising a queue-full error. Rate-limited `INPUT_REPLY` lines distinguish
210`queue-full`, `receiver-starting` and `receiver-stopped` with depth and input kind.
212Intercepted input decisions have a 32 ms native observation budget and 10 ms
213timer granularity. An intercepted key/button over that budget is logged and
214keeps waiting for policy; it is never forwarded by default. Missing motion
215decisions retain cursor movement. Nonmatching ordinary keys and buttons bypass
216the queue. Overflow cancels stale intercepted tokens and balances their queued
217releases without clearing ordinary native streams. Late tokens are ignored.
218Physical lock-key delivery and mapped lock-surface focus are native invariants.
220`set-key-intercepts!` and `set-button-intercepts!` take a host and a list of
221`(code modifiers mask scope target)` integer rules. An empty list delegates all
222presses natively; `#f` intercepts every unlocked press. Installing a custom hook resets
223its rules to `#f`, so publish selective rules after installing the hook and
224whenever the manager's bindings or modes change. Keys match active, base or
225first-layout keysyms and masked modifiers; key scopes are 0 either lock state,
2261 unlocked and 2 locked. Only explicitly cached lock-eligible chords can wait
227while locked; ordinary physical lock keys remain native. Button code 0 matches any button;
228scopes are 0 any target, 1 window, 2 manager pixel, 3 exact signed target, and
2294 window other than native keyboard focus. Positive targets are windows and
230negative targets are pixels. A press retains its interception identity through
231release even if rules change. `button-observed` carries the copied input record
232for an unmatched native click; use `decode-input-event` on its raw vector to
233observe held buttons without issuing a disposition. The observation is emitted
234before client delivery, preserving order with a client's move/resize request.
235If motion advances during a pending click, its eventual release publishes a
236fresh observation in the current focus epoch so the manager can reconcile hover.
238Output configuration and power intents coalesce over one native event-loop
239idle. The host prepares swapchains, renders the current scene into enabled
240output states and submits one backend commit. Lock ownership keeps the normal
241scene disabled during this render. Per-output fallback normally follows an
242atomic test failure. A failed wake also retries once per output after rollback,
243logging the attempt and result. An unanswered power-on request defaults to
244acceptance at its native deadline; a late policy reply cannot undo it. Set
245`SIGIL_WM_DEBUG_OUTPUTS=1` to log commit grouping and per-output request-to-first-
246present latency. Set `SIGIL_WM_DEBUG_INPUT=1` only for input diagnostics; its
247eligibility log includes keycodes, keysyms and modifiers and can expose typed
248input. Ordinary keys wait behind a pending chord for at most its original 32 ms
249budget, then flow natively in order even if the policy decision still waits.
251On event overflow, the host rebuilds its copied snapshot from live native facts,
252reports lifecycle differences, then sends snapshot-resynced. Invalidate pending
253input/request reply tokens and resubmit complete scene plans on that event.
254Keep configuration completion mappings: those replies are retained and replayed
255after snapshot-resynced, including output batches and keyboard configuration.
256input-fault is
257recoverable and reports native input-stream cancellation. Statistic 2 counts
258event overflows, 9 counts snapshot resyncs, 10 over-budget input decisions, and 11
259coalesced queued motions. Text notices carry one complete bounded copied value.
260`warp-pointer!` applies an explicit manager-selected position without
261synthesizing client input or classifying the warp as user motion.
263## Additional drawing operations
265The optional drawing module also exports font/run/image predicates and metrics,
266`render-outline`, `render-panel`, `compose-text-image!` and
267`write-text-image!`. Outline colors are premultiplied RGBA; panel and text
268colors are straight RGBA. Image composition requires live images at the same
269scale. No application styling is selected by these helpers.
271Output capture temporarily locks rendering to a composed frame, then releases
272that lock. A direct-scanout source buffer is not treated as a complete output
273image. Ordinary presentation retains its direct-scanout behavior.
275`add-headless-output!` creates an output on the host's unique headless backend,
276with an optional caller-selected connector name set before advertisement.
277`remove-headless-output!` destroys a headless output. These operations emit the
278ordinary output lifecycle events with fresh IDs and support reproducible hotplug
279workloads. X11 client move and resize requests use the same copied
280`window-request` events as other roles, including the requested resize edges.
282Pixel presentation defaults to input pass-through, including transparent pixels.
283Use `input?: #t` to accept pointer input for a manager-owned pixel surface.
284Button and motion events then expose `input-event-target-kind` as `pixel`
285and `input-event-target` as its identifier; client targets use `window`.
286Raw hit facts use a negative pixel identifier and positive window identifier.
287Optional `output:` and `bounds:` scope the copy to an exact output rectangle.
288An output change disables stale scoped pixels immediately; a stale replacement
289is discarded, and a fresh copy with current bounds restores presentation/input.
290Hit transitions caused by scene updates retain `moved?: #f`.
292`(sigil wm dispatch)` supplies independent callback owners for applications
293with event, timer, input and expression producers. Create an owner with
294`make-dispatcher`; producers use `dispatcher-enqueue!` or the synchronous
295`dispatcher-call!`. One consumer waits with `dispatcher-wait!` and drains
296with `dispatcher-drain!`. Ownership persists across yielding callbacks.
297Call producers must run outside the owner they wait on. Closing rejects new
298work and gives pending requests a terminal error, preserving in-flight work.
300Protocol bit64 explicitly exposes desktop capture, output descriptions,
301presentation, single-pixel buffers, data-control/primary selection and cursor
302shapes. Exposing capture permits clients to capture outputs through the native
303protocol; choose the mask before starting the host.
305Clipboard/primary requests produce `selection-request`; pointer drags produce
306`drag-request` with the origin window and serial-validity fact. Use
307`reply-data-request!` to accept/refuse while the bounded request is alive.
308The owner rechecks generation, lock isolation and drag serials on acceptance.
309Source/origin destruction retires requests; expiration refuses them.
310An accepted drag follows its icon only when `follow-icon?: #t` is explicit.
311Drag started/drop/end facts have stable IDs and balanced native ownership.
313`delegate-client-cursor!` caches an explicit policy permission for focused
314clients to supply cursor surfaces or standard shapes. It defaults to false;
315disable delegation during a manager-owned interactive grab.
317`(sigil wm session)` exports `call-with-host-session`: a start thunk returns
318the host, a body receives it, and application cleanup receives it after join.
319Normal completion and exceptions both stop/drain/join the owner before library
320unload. Application callbacks are not entered while unwinding native shutdown.
322Queued notifications may provide `on-cancel:` separately from handler errors.
323Closing silently drops notifications by default; synchronous calls always
324receive a terminal cancellation error. This keeps normal shutdown distinct
325from an application callback failure.
327Transaction rejection reason2 identifies a retired resource in `object:`
328(positive window ID, negative pixel ID). `submitted?:` distinguishes a stale
329submission from retirement while an accepted transaction was waiting.
330Schema/geometry errors remain reason1, and superseded transactions reason3.
331Managers can retry only after confirming the copied resource has retired.
333Pixel copies normally require source dimensions to match destination geometry
334and scale. Explicit `stretch?: #t` resamples a bounded source bitmap into the
335requested destination rectangle, including reusable transparent input masks.
336Input acceptance and output scope remain explicit and independent.
338Input transport notifies only the pending intercepted head event. Unhooked
339pointer motion and axes stay native and flow while a decision is pending,
340without adding motion callbacks. Button modifiers are captured at input time.
341Pointer presses are refused if their copied hit target has changed.
343Inside a press hook, `focus-window!` may take `input-token:` for that exact
344pending press. The native owner validates its target/epoch and explicitly
345retargets the following ordered input prefix across that focus change.
346Ordinary focus commands retain their existing input fence; lock epochs cannot
347be crossed by this authorization.
349`observe-pointer!` accepts `after-motion?: #t` to reset target observation
350without a stationary sample. The first subsequent real motion produces a
351sample even when the target has not changed, useful after an implicit grab.
353`restack-scene!` changes only bottom-to-top resource order. Its list contains
354`(window id)`, `(pixel id)` and the symbol `drag`. It does not send geometry
355configures or copy pixels. Omitted resources retain their relative order;
356resources retired before the command is applied are ignored. The list is
357bounded to 65,535 distinct resources. Explicit drag following initially presents
358its image above existing resources, and the manager may restack it. Drag images
359never accept ordinary pointer input.
361`present-pixels!` accepts optional `order:` with the same bottom-to-top resource
362list, including `(pixel id)` for the uploaded image. It takes precedence over
363`stack:`. The native command copies both the image and order, then inserts or
364updates that pixel beside its nearest live neighbour before any frame renders
365or pointer routing runs. Retired neighbours are skipped; a lone resource goes
366to the bottom. Other resources are not reordered. This allows new decoration
367nodes to appear at their final position without a later policy round trip.
368Existing callers that omit `order:` retain their stacking semantics.
370Output snapshots distinguish `pixel-width:`/`pixel-height:` from logical
371`width:`/`height:`. A custom output mode uses physical pixel dimensions;
372logical bounds reflect scale and transform. Initial window facts already carry
373the surface role, before its role-specific configuration facts arrive.
375Device snapshots contain copied names, type, `virtual?:`, `libinput?:` and tap
376finger count. Removing a device retires its snapshot and balances its forwarded
377held keys/buttons. Virtual origin is assigned only by native admission.
378`configure-pointer!` accepts a dictionary with `tap:`, `dwt:`,
379`middle-emulation:` and `natural-scroll:`, each boolean or `unset`. The manager
380chooses which devices receive settings. `pointer-configuration-result` reports
381one status per setting: -1 untouched, 0 applied, 1 unsupported, 2 invalid.
382Keyboard rule fields permit255 characters, repeat rate up to1000 and delay up
383to10000 milliseconds.
385`set-lock-background!` selects an opaque #xRRGGBBFF fill for a specific active
386lock generation. Stale generations and translucent colours are rejected.
387Native lock isolation and authenticated unlock remain unconditional.
389Protocol bit128 exposes output configuration, power and gamma controls.
390`configure-outputs!` takes a list of explicit output dictionaries, each with
391`id:`, `enabled:`, `x:`, `y:`, `scale:`, `transform:`, `mode:`, `width:`,
392`height:` and `refresh:`; optional `adaptive-sync?:` defaults false. Outputs
393omitted from the list keep their state. `test?: #t` tests without applying.
394Native code tests the complete backend state, commits it and attempts rollback
395if a backend partially commits. A configuration result includes `rollback:`:
3960 unnecessary, 1 restored, 2 failed. Actual hardware state is published after a
397failed rollback, so the manager can decide how to recover.
399An `output-configuration-request` carries copied `heads:`, `apply?:` and a
400configuration revision. `reply-output-configuration!` takes the request ID and
401an explicit replacement head list, or false to refuse. A dedicated
402`output-configuration-result` reports protocol success. Requests expire at the
403host's declared deadline and become invalid when their output context changes.
404Copied proposals remain ordinary Sigil data after the native request retires.
406`output-power-request` and `output-gamma-request` require explicit
407`reply-output-control!` admission. `set-output-power!` is an explicit manager
408command. Output `enabled?:` describes configured ownership and `powered?:`
409describes hardware power; powering down preserves configured geometry and
410workspace decisions. Native gamma tables remain native resources and apply
411with a frame commit after admission. `set-output-filter!` selects `linear` or
412`nearest`; any rule choosing between them belongs to the manager.
414Collections in copied snapshots retain object creation order when facts change.
415Snapshots also retain inhibitor associations and the last explicit idle state.
416An inhibitor created before its window role gains that association when the
417role appears; the manager chooses whether its applied visibility inhibits idle.
419Pointer constraints use protocol bit512. They remain inert until policy calls
420`set-active-pointer-constraint! host id generation`; id0 deactivates the current
421lease. The `constraints:` snapshot contains copied identity, lifetime, seat,
422visibility, pointer focus, keyboard owner, region membership and focus generation
423facts. `constraint-state` arrives only when those facts change. Policy chooses
424eligibility and selection. Native code enforces the admitted lock or confinement
425without a callback for ordinary motion, and ends it on scope or surface loss.
427A locked client's release hint becomes a bounded `pointer-hint-request` with
428window, focus generation and global coordinates. `reply-pointer-hint!` accepts or
429refuses it. Acceptance revalidates the live surface, current epoch, input region
430and output coordinates; expired or retired requests cannot move the pointer.
431`delegate-relative-pointer! host enabled?` explicitly controls native relative
432motion delivery. `query-pointer! host` returns a token for an asynchronous
433`pointer-state` observation and updates `pointer-state:` in the snapshot.
435A `pointer-target-changed` observation carries `pointer-token:`. Supplying it
436as `pointer-token:` to `focus-window!` authorizes that copied transition while
437preserving queued input from the same focus epoch. `input-token:` supplies the
438corresponding authorization for the notified head press. Optional `input-target:`
439identifies the actual captured window when policy focuses a different recipient,
440such as that window's owner. The native host checks the token, target and epoch.
441The call returns an operation token. Its `focus-request-result` uses that token
442as `id:` and copies the input or pointer token as `authorization:`. A retired,
443hidden or lock-isolated target returns `accepted?: #f`, including plain focus
444operations. Stale authorization also returns `accepted?: #f`; it does
445not focus a window or count as a malformed command. The accepted result preserves
446paired first-click delivery even when the policy handler yields.
448Batch output settings accept optional `power?:`. It defaults to `enabled:`;
449setting it false keeps an admitted logical output asleep while changing its
450explicit layout or mode. `enabled:` remains the administrative layout decision.
451Snapshots also copy actual `powered?:`, current `mode:`, `refresh:` and
452`adaptive-sync?:` so policy can preserve unchanged backend state in a complete
453configuration. Previously returned snapshots remain detached.
455Protocol bit256 exposes activation requests as copied target, source-window,
456seat/serial provenance and focus-generation facts. The protocol implementation
457validates tokens; policy chooses attention or focus. Native activation never
458changes focus. `acknowledge-configure! host window` sends an explicit empty xdg
459configure reply, including when policy declines a maximize request.
461`start-host!` accepts `socket:` for a chosen Wayland socket basename. Names are
462copied before startup; unsafe names and occupied endpoints fail cleanly.
463`ready` reports `session-available?:`. `configure-session-switches!` accepts up to
46412 `(keysym . vt)` pairs as an explicit native escape cache. Matching physical
465presses and releases bypass a stalled policy handler; virtual/emulated devices
466cannot trigger this cache. A session backend must exist. The backend call is
467covered with a native stub, without changing a real terminal session.
469Protocol bit8 also exposes the legacy decoration negotiation interface.
470`start-host!` accepts `legacy-decoration: 'none|'client|'server` as the explicit
471initial protocol default. Both decoration transports appear as detached
472`decorations:` records with stable identity, associated window, mode and kind.
473`decoration-state` reports changed facts, including association when a legacy
474object preceded its window role; `decoration-destroyed` retires that identity.
475Policy selects border presentation and supplies xdg preference through
476`set-decoration-mode!`. Cached preference applies on initial commit, without
477waking policy or producing new configures on ordinary client frames. Native
478wrappers are bounded and included in the ownership counters.
480Keyboard device facts include `nested?:` for input supplied by a parent Wayland
481backend. `configure-keyboard!` accepts `group:` (default0) and
482`fixed-group?:` (defaultfalse); `set-keyboard-group!` accepts `fixed?:`.
483A fixed group preserves the explicitly chosen group across incoming backend
484modifier updates. Other modifier state still follows the device. Policy chooses
485which devices need that cache; the generic host supplies no binding or group
486selection rule.
488`query-window! host window` returns an operation token. A live initialized
489window produces paired `window-observation` and `window-observation-geometry`
490events with that token as `id:`. They copy actual scene position, committed
491geometry, mapping, visibility, focus, surface offset and acknowledged serial.
492Committed activation, suspension, fullscreen and tiled protocol state are
493available when `xdg-state?:` is true; other roles report those fields as zero.
494The geometry event includes the bound xdg protocol version. A retired or
495uninitialized window produces only an observation with `accepted?: #f`.
496These explicit queries do not configure a client or change manager state.
498Queued keyboard observations still reach the input hook after an ordinary focus
499change, so semantic bindings can consume a burst without losing later keys.
500Forwarding and replacement retain the original focus generation and are refused
501when stale. Scope loss and lock isolation still cancel pending input before it
502can reach an unauthorized recipient. Policy never receives stale virtual input
503while locked.
505Output-scoped pixels are bounded by the supplied geometry. A malformed rectangle
506is refused before copying. If a queued image's output or geometry has since
507retired, the copied image is discarded without rejecting the command or changing
508the existing image. Host statistics 5 and 6 count current pixel nodes and discarded
509scoped images; statistic 4 counts retained copied pixel bytes.
512`set-default-layer-output!` returns an operation token. Its
513`layer-output-result` reports `output:` and `accepted?:`. A retired output
514refuses the cached-target update without choosing a replacement or rejecting
515the command. Output 0 explicitly clears the target.
517A window placement accepts `suspended?:` independently of `shown?:`. It defaults
518to false. The host forwards the requested protocol state to native toplevels
519whose bound protocol version supports it; other roles and older versions have
520no suspension state. Managers explicitly choose when hidden clients suspend.
522A placement's `resize?:` defaults to true. False retains the established
523client size while applying the requested scene box and protocol state. This
524lets a manager keep future hidden layout geometry without resizing the client.
525Unchanged protocol state sends no redundant configure; state-only changes do
526not wait for a new geometry commit. Pending geometric configures still retain
527their serial and deadline.
529Destroying an output retires its scoped pixel nodes and their copied storage.
530Changing its geometry disables stale scoped nodes until explicitly replaced or
531removed. Queued images for retired outputs are discarded without retaining copies.
533Window observation surface offsets name the actual root surface tree relative
534to the window geometry node. Clipping uses root-surface coordinates and leaves
535popups outside that tree free to extend beyond the client rectangle. Pending
536visible geometric transactions continue frame callbacks while hidden clients
537answer their new configure. Invalid keyboard maps return a failed configuration
538result while retaining the previously applied map and group.
540Host statistic7 reports currently retained transaction snapshot trees; statistic8
541counts snapshot trees created during the session. Both are mechanism facts.
542Snapshot ownership ends at application, refusal or destruction of its view.
544Window geometry observations also expose requested-suspended?: separately from
545the committed suspended?: field, plus acknowledged and scheduled configure
546serials. A state-only configure may be acknowledged without a new surface
547commit. Native geometry changes refresh the explicit clip rectangle in the
548root surface coordinate space, including later decoration-margin commits.
550Forwarded keys publish their copied origin modifier snapshot for both press and
551release. Replacement keys retain their explicitly requested modifier snapshot.
552This includes virtual keyboards that send modifier state without modifier-key
553presses. Pooled held-key ownership and stale-focus forwarding checks still apply.
555Committed xdg size-hint and parent changes after the initial handshake emit
556window-hints events and update detached window snapshots. They do not emit a
557second window-initial event or choose a size for the manager.
559X11 association catches up an already committed buffer before publishing normal
560map and geometry facts. Placement and focus still require the manager's scene.
561# Wayland window credentials
563Wayland toplevel window records include `pid:`, `uid:` and `gid:` copied from
564the client's Unix socket credentials when the window is created. The
565`window-created` event exposes the same fields. These identify the connection's
566process, which can own multiple windows; they do not identify a terminal's
567foreground process. Window creation facts retain these values during snapshot
568resynchronization. Layer and X11 creation records use `#f`; X11's later `pid:`
569property is client-reported and does not carry authenticated UID/GID values.
572With `SIGIL_WM_TRACE_LATENCY=1`, `latency-mark! stage [token]` records a direct
573monotonic timestamp for stages 1–7; stage 1 establishes the input token. Native
574key-input, buffer-commit and presentation records use stages 0, 8 and 9. The
575trace is bounded to 4096 stderr records and is disabled by default. Presentation
576uses the backend's supplied presentation timestamp; compare it with monotonic
577owner timestamps only on a backend whose presentation clock is monotonic.