AtlatestRepositorysigil-wm
1
# Using the API3
A host has one native owner thread and one seat. Start one host per process;4
stop it and let `run-host!` consume the terminal event to join its owner. Sigil5
handlers and the optional REPL run on the Sigil scheduler. The examples show the6
complete lifecycle without application-specific code in the native layer.8
## Host and events10
`start-host!` accepts `protocols:` (a bit mask, default 0) and11
`request-deadline:` (milliseconds, default 1000). Optional protocol bits are 112
for session lock, 2 for client virtual input, 4 for XWayland, 8 for decoration13
negotiation, 16 for idle notification/inhibitors and 32 for layer-shell.14
Unsupported bits are rejected. XWayland uses the executable in the environment15
or the explicit WLR_XWAYLAND path. Core16
Wayland/xdg-shell, viewports and relative pointer transport are always available.18
Bit 1024 enables `ext-foreign-toplevel-list-v1`; bit 2048 enables19
`wlr-foreign-toplevel-management-unstable-v1`. Listing is read-only, but both20
listing and management are privileged and hidden from security-context clients;21
native clients retain compatibility access. Handles cover mapped xdg toplevels22
and managed XWayland surfaces, excluding layers and override-redirect surfaces.23
Unmapping closes handles; remapping creates fresh identifiers. Metadata changes24
are forwarded to both protocols. Applied scene plans determine fullscreen state25
and logical output intersection; native seat focus determines activation.27
`xwayland_shell_v1` is advertised only to the compositor's Xwayland client.28
Xwayland activation follows applied seat focus, including focus changes that29
do not configure a window. Leaving X focus or entering a lock clears XWM focus,30
so wlroots can authorize clipboard and primary-selection transfers correctly.32
Management 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 are35
copied, transient36
and invalidated across overflow rather than retained as snapshot facts. They37
are ignored by the native owner while locked; consumers must also check current38
policy state and the current lock generation when processing them. Activation39
must name the host's seat.40
Policy decides which operations it supports; requests never directly mutate41
the 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 scene45
into one presentation. Its deadline is between 1 and 200 milliseconds; client46
frame callbacks continue, lock presentation is immediate, and an abandoned47
bracket expires. Applying the plan damages the whole output.49
`record-output-samples!` takes an output, file path, 1..64 physical pixel50
coordinates and a limit of 1..600 frames. It writes one indexed RGB sample row51
for every buffer commit, including the output commit sequence and PASS/FAIL.52
It requests one initial frame, then observes natural commits without scheduling53
extra frames. Unreadable buffers are reported as failure. Sampling ends at the54
limit or with `stop-output-samples!`, which takes the host and output. A subsequent55
`query-pointer!` reply provides a queue barrier before reading the completed56
file. This allows transition checks without retaining full-frame streams.58
Layer surfaces emit `layer-presentation` with their kernel-reported client59
`pid:`, `presented?:`, `output:` and `commit-sequence:`. A true acknowledgement60
follows an actual presented output commit containing the mapped layer; unmap61
clears it. Background providers can use it to keep their predecessor alive62
until 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`66
reads named fields, including `id:`. The numeric `event-kind` and copied67
`event-raw` vector are also available for ABI diagnostics. Complete UTF-8 title68
updates are assembled before the `window-title` event; intermediate transfer69
records have type `metadata-chunk`.71
`host-snapshot` returns detached output/window facts and a revision. Output72
records preserve their advertised modes. A window's `committed:` rect is its73
client-local window geometry, distinct from the global desired placement in a74
scene plan. `configure-serial:` identifies the associated configure. Container,75
workspace, placement and focus relationships belong to the manager's immutable76
`(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 mode80
index selects an advertised mode; -1 supplies a custom size/refresh in mHz.81
Nested managers should start with the backend's initial size, then decide how82
to answer `output-state-request` events. Configuration completion reports its83
queue 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!` takes87
the popup ID and an explicit parent-local rect. `set-seat-capabilities!`,88
`set-pointer-route!`, `set-decoration-mode!`, `set-cursor!` and89
`set-idle-state!` apply caller-selected settings. A virtual-device request90
includes peer credentials; `reply-request!` accepts or refuses its token.91
Unanswered virtual/popup requests expire. Lock focus uses `focus-lock!` with an92
explicit output and admitted physical keyboard; emulated and virtual devices93
cannot become lock input devices. Unlock is exclusively the lock owner's94
protocol request after real presentation acknowledgement.96
## Scene and drawing98
The native build also supplies `build/environment-exec`, a generic exec helper99
for managers that capture a private login environment before entering a build100
environment. Its arguments are a private NUL-delimited snapshot path, override101
count, override names, `--`, then the program and its arguments. Override102
values arrive as `SIGIL_EXEC_VALUE_0`, `SIGIL_EXEC_VALUE_1`, and so on. The103
caller starts the helper with empty `LD_LIBRARY_PATH` and `LD_PRELOAD` values.104
The helper replaces only its own environment and execs in the same PID. Before105
exec, it restores default dispositions for all supported catchable signals and106
empties its signal mask, so launcher settings do not leak into clients. It107
contains no session, application or variable-selection policy.109
An arranger receives a container, rect, snapshot and trigger. Its result is an110
ordered list of placements; the example managers keep their own selection and111
geometry rules. `submit-plan!` takes a complete scene plan with explicit focus112
and configure deadline. It returns a token or #f for queue refusal. Applied and113
rejected events refer to that token. Old client buffers remain visible while114
resized clients acknowledge; output frames continue independently of Sigil.116
A complete plan admits up to 256 window records and 6,553 records in total,117
including 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 window119
budget.121
A placement's `kind:` is `window` or `pixel`. Record order controls stacking122
across both kinds. Visibility, client size, activation, suspension, fullscreen, tiled edges123
and clipping are explicit. A manager retains hidden tabs and floating restore124
rectangles in Sigil; no native container kind changes their behavior.126
`present-pixels!` copies a premultiplied native-endian ARGB32 image at a logical127
rect/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.130
The optional drawing module supplies scaled text, shaped cluster-aware ellipsis,131
canvases, shapes and an image cache. Its cache replaces an old image only after132
the receiver accepts a copied replacement. Destroy cached images before closing133
fonts. The core imports no drawing library.135
## Input and expression IPC137
Key hooks receive immutable `input-event` records with device, time, code,138
keysyms, modifiers, focus generation and origin (`physical`, `emulated` or139
`virtual`). Return `(forward event)`, `(replace replacement)` or `(drop)`.140
A replacement can change its code/modifier mask; routing/ownership fields stay141
fixed. A replaced modifier mask applies to the delivered event and is followed142
by the actual client-visible state. Press/release identities are paired in C;143
a forwarded press receives its matching release even if that release's hook144
fails or drops it. Button hooks use the same ownership rule.146
`set-motion-hook!` registers a procedure plus device, minimum period and region147
filters. Device 0 and a zero-size region mean all devices/positions. Matching148
samples may coalesce while preserving the latest accumulated position. Removing149
the hook restores the C path; ordinary motion chooses no keyboard focus or150
window geometry. A manager implements drag/hover behavior in its hook.152
`emulate-key!`, `emulate-motion!`, `emulate-button!` and `emulate-axis!` take seat153
1 and return completion tokens or #f. Axis discrete values are wheel detents.154
These trusted in-process calls share the ordered hook/routing path with normal155
input. Client virtual devices are inert until their separate request is granted156
and remain distinct from emulation authority.158
`start-repl!` takes the host, a Unix-socket path in a user-owned private directory,159
and an evaluation environment (or evaluator procedure). Frames contain a decimal160
UTF-8 byte length, LF and the expression bytes. Replies frame a printed161
`(value result)` or `(error exception)`. `repl-request` and `scripts/msg` implement162
this framing. Evaluation may yield while other clients are connected; each163
completed result is formatted into its own reply. Expression output uses the164
session 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 facts169
Output snapshots retain connector `name:`, `nested?:`, `enabled?:` and170
`transform:` fields. Disabled-output completions are explicit; a previously171
returned snapshot remains unchanged. Window snapshots retain initial size172
hints and parents. The `role:` field distinguishes `toplevel`, `layer` and173
`x11`. X11 facts include PID, transient parent, override-redirect, modal and174
dialog flags, decorations, class as app ID, instance and reported geometry.175
They do not imply any ownership, stacking, placement or visibility rule.177
`host-x-display` reads the copied display name, including updates after the178
XWayland server becomes ready. `configure-x11!` answers a client configure179
request with an explicit global rect. Scene plans manage X11 and layer surfaces180
through the same placement and focus operations as other windows. Their native181
role adapters retain protocol lifetimes and configure bookkeeping only.183
For layer-shell, call `set-default-layer-output!` with a manager-selected output184
before accepting clients that omit an output. wlroots requires an output before185
its native role callback returns; no output fallback is selected by the host.186
`layer-state` events and snapshots expose anchors, requested size, margins,187
exclusive zone/edge, keyboard interactivity and `initialized?:`.188
`configure-layer!` supplies a chosen output and client width/height after189
initialization. The manager computes usable areas, layer order, placement and190
keyboard focus. Client layer interactivity and session-lock restrictions remain191
native focus safety checks.193
`configure-keyboard!` takes device, layout, repeat rate and delay, plus optional194
`options:`, `variant:`, `rules:` and `model:` strings.195
`set-keyboard-group!` selects one explicit group on one device; cycling and196
device selection belong to the manager. Key events expose active symbols,197
base-level symbols and first-layout base symbols separately. Modifier changes198
are copied as `modifiers-changed` events with device and group facts.200
Button and hooked motion events include copied hit-target and output IDs.201
`observe-pointer!` optionally reports `pointer-target-changed` only when the202
target or output changes. Its `moved?:` field distinguishes input motion from203
scene refresh; coordinates use `x-milli:` and `y-milli:` fields. Observation204
chooses no focus and can run independently of interception. Disabled observation205
and absent motion hooks generate no ordinary motion callback to Sigil.206
Input replies retry cooperatively when the command ring is full or native207
startup is still in progress. The hook runs once; its copied disposition stays208
in FIFO order with earlier commands. A terminated receiver ends retry without209
raising a queue-full error. Rate-limited `INPUT_REPLY` lines distinguish210
`queue-full`, `receiver-starting` and `receiver-stopped` with depth and input kind.212
Intercepted input decisions have a 32 ms native observation budget and 10 ms213
timer granularity. An intercepted key/button over that budget is logged and214
keeps waiting for policy; it is never forwarded by default. Missing motion215
decisions retain cursor movement. Nonmatching ordinary keys and buttons bypass216
the queue. Overflow cancels stale intercepted tokens and balances their queued217
releases without clearing ordinary native streams. Late tokens are ignored.218
Physical 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 of221
`(code modifiers mask scope target)` integer rules. An empty list delegates all222
presses natively; `#f` intercepts every unlocked press. Installing a custom hook resets223
its rules to `#f`, so publish selective rules after installing the hook and224
whenever the manager's bindings or modes change. Keys match active, base or225
first-layout keysyms and masked modifiers; key scopes are 0 either lock state,226
1 unlocked and 2 locked. Only explicitly cached lock-eligible chords can wait227
while locked; ordinary physical lock keys remain native. Button code 0 matches any button;228
scopes are 0 any target, 1 window, 2 manager pixel, 3 exact signed target, and229
4 window other than native keyboard focus. Positive targets are windows and230
negative targets are pixels. A press retains its interception identity through231
release even if rules change. `button-observed` carries the copied input record232
for an unmatched native click; use `decode-input-event` on its raw vector to233
observe held buttons without issuing a disposition. The observation is emitted234
before client delivery, preserving order with a client's move/resize request.235
If motion advances during a pending click, its eventual release publishes a236
fresh observation in the current focus epoch so the manager can reconcile hover.238
Output configuration and power intents coalesce over one native event-loop239
idle. The host prepares swapchains, renders the current scene into enabled240
output states and submits one backend commit. Lock ownership keeps the normal241
scene disabled during this render. Per-output fallback normally follows an242
atomic test failure. A failed wake also retries once per output after rollback,243
logging the attempt and result. An unanswered power-on request defaults to244
acceptance at its native deadline; a late policy reply cannot undo it. Set245
`SIGIL_WM_DEBUG_OUTPUTS=1` to log commit grouping and per-output request-to-first-246
present latency. Set `SIGIL_WM_DEBUG_INPUT=1` only for input diagnostics; its247
eligibility log includes keycodes, keysyms and modifiers and can expose typed248
input. Ordinary keys wait behind a pending chord for at most its original 32 ms249
budget, then flow natively in order even if the policy decision still waits.251
On event overflow, the host rebuilds its copied snapshot from live native facts,252
reports lifecycle differences, then sends snapshot-resynced. Invalidate pending253
input/request reply tokens and resubmit complete scene plans on that event.254
Keep configuration completion mappings: those replies are retained and replayed255
after snapshot-resynced, including output batches and keyboard configuration.256
input-fault is257
recoverable and reports native input-stream cancellation. Statistic 2 counts258
event overflows, 9 counts snapshot resyncs, 10 over-budget input decisions, and 11259
coalesced queued motions. Text notices carry one complete bounded copied value.260
`warp-pointer!` applies an explicit manager-selected position without261
synthesizing client input or classifying the warp as user motion.263
## Additional drawing operations265
The optional drawing module also exports font/run/image predicates and metrics,266
`render-outline`, `render-panel`, `compose-text-image!` and267
`write-text-image!`. Outline colors are premultiplied RGBA; panel and text268
colors are straight RGBA. Image composition requires live images at the same269
scale. No application styling is selected by these helpers.271
Output capture temporarily locks rendering to a composed frame, then releases272
that lock. A direct-scanout source buffer is not treated as a complete output273
image. Ordinary presentation retains its direct-scanout behavior.275
`add-headless-output!` creates an output on the host's unique headless backend,276
with an optional caller-selected connector name set before advertisement.277
`remove-headless-output!` destroys a headless output. These operations emit the278
ordinary output lifecycle events with fresh IDs and support reproducible hotplug279
workloads. X11 client move and resize requests use the same copied280
`window-request` events as other roles, including the requested resize edges.282
Pixel presentation defaults to input pass-through, including transparent pixels.283
Use `input?: #t` to accept pointer input for a manager-owned pixel surface.284
Button and motion events then expose `input-event-target-kind` as `pixel`285
and `input-event-target` as its identifier; client targets use `window`.286
Raw hit facts use a negative pixel identifier and positive window identifier.287
Optional `output:` and `bounds:` scope the copy to an exact output rectangle.288
An output change disables stale scoped pixels immediately; a stale replacement289
is discarded, and a fresh copy with current bounds restores presentation/input.290
Hit transitions caused by scene updates retain `moved?: #f`.292
`(sigil wm dispatch)` supplies independent callback owners for applications293
with event, timer, input and expression producers. Create an owner with294
`make-dispatcher`; producers use `dispatcher-enqueue!` or the synchronous295
`dispatcher-call!`. One consumer waits with `dispatcher-wait!` and drains296
with `dispatcher-drain!`. Ownership persists across yielding callbacks.297
Call producers must run outside the owner they wait on. Closing rejects new298
work and gives pending requests a terminal error, preserving in-flight work.300
Protocol bit64 explicitly exposes desktop capture, output descriptions,301
presentation, single-pixel buffers, data-control/primary selection and cursor302
shapes. Exposing capture permits clients to capture outputs through the native303
protocol; choose the mask before starting the host.305
Clipboard/primary requests produce `selection-request`; pointer drags produce306
`drag-request` with the origin window and serial-validity fact. Use307
`reply-data-request!` to accept/refuse while the bounded request is alive.308
The owner rechecks generation, lock isolation and drag serials on acceptance.309
Source/origin destruction retires requests; expiration refuses them.310
An accepted drag follows its icon only when `follow-icon?: #t` is explicit.311
Drag started/drop/end facts have stable IDs and balanced native ownership.313
`delegate-client-cursor!` caches an explicit policy permission for focused314
clients to supply cursor surfaces or standard shapes. It defaults to false;315
disable delegation during a manager-owned interactive grab.317
`(sigil wm session)` exports `call-with-host-session`: a start thunk returns318
the host, a body receives it, and application cleanup receives it after join.319
Normal completion and exceptions both stop/drain/join the owner before library320
unload. Application callbacks are not entered while unwinding native shutdown.322
Queued notifications may provide `on-cancel:` separately from handler errors.323
Closing silently drops notifications by default; synchronous calls always324
receive a terminal cancellation error. This keeps normal shutdown distinct325
from an application callback failure.327
Transaction rejection reason2 identifies a retired resource in `object:`328
(positive window ID, negative pixel ID). `submitted?:` distinguishes a stale329
submission from retirement while an accepted transaction was waiting.330
Schema/geometry errors remain reason1, and superseded transactions reason3.331
Managers can retry only after confirming the copied resource has retired.333
Pixel copies normally require source dimensions to match destination geometry334
and scale. Explicit `stretch?: #t` resamples a bounded source bitmap into the335
requested destination rectangle, including reusable transparent input masks.336
Input acceptance and output scope remain explicit and independent.338
Input transport notifies only the pending intercepted head event. Unhooked339
pointer motion and axes stay native and flow while a decision is pending,340
without adding motion callbacks. Button modifiers are captured at input time.341
Pointer presses are refused if their copied hit target has changed.343
Inside a press hook, `focus-window!` may take `input-token:` for that exact344
pending press. The native owner validates its target/epoch and explicitly345
retargets the following ordered input prefix across that focus change.346
Ordinary focus commands retain their existing input fence; lock epochs cannot347
be crossed by this authorization.349
`observe-pointer!` accepts `after-motion?: #t` to reset target observation350
without a stationary sample. The first subsequent real motion produces a351
sample even when the target has not changed, useful after an implicit grab.353
`restack-scene!` changes only bottom-to-top resource order. Its list contains354
`(window id)`, `(pixel id)` and the symbol `drag`. It does not send geometry355
configures or copy pixels. Omitted resources retain their relative order;356
resources retired before the command is applied are ignored. The list is357
bounded to 65,535 distinct resources. Explicit drag following initially presents358
its image above existing resources, and the manager may restack it. Drag images359
never accept ordinary pointer input.361
`present-pixels!` accepts optional `order:` with the same bottom-to-top resource362
list, including `(pixel id)` for the uploaded image. It takes precedence over363
`stack:`. The native command copies both the image and order, then inserts or364
updates that pixel beside its nearest live neighbour before any frame renders365
or pointer routing runs. Retired neighbours are skipped; a lone resource goes366
to the bottom. Other resources are not reordered. This allows new decoration367
nodes to appear at their final position without a later policy round trip.368
Existing callers that omit `order:` retain their stacking semantics.370
Output snapshots distinguish `pixel-width:`/`pixel-height:` from logical371
`width:`/`height:`. A custom output mode uses physical pixel dimensions;372
logical bounds reflect scale and transform. Initial window facts already carry373
the surface role, before its role-specific configuration facts arrive.375
Device snapshots contain copied names, type, `virtual?:`, `libinput?:` and tap376
finger count. Removing a device retires its snapshot and balances its forwarded377
held 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 manager380
chooses which devices receive settings. `pointer-configuration-result` reports381
one status per setting: -1 untouched, 0 applied, 1 unsupported, 2 invalid.382
Keyboard rule fields permit255 characters, repeat rate up to1000 and delay up383
to10000 milliseconds.385
`set-lock-background!` selects an opaque #xRRGGBBFF fill for a specific active386
lock generation. Stale generations and translucent colours are rejected.387
Native lock isolation and authenticated unlock remain unconditional.389
Protocol bit128 exposes output configuration, power and gamma controls.390
`configure-outputs!` takes a list of explicit output dictionaries, each with391
`id:`, `enabled:`, `x:`, `y:`, `scale:`, `transform:`, `mode:`, `width:`,392
`height:` and `refresh:`; optional `adaptive-sync?:` defaults false. Outputs393
omitted from the list keep their state. `test?: #t` tests without applying.394
Native code tests the complete backend state, commits it and attempts rollback395
if a backend partially commits. A configuration result includes `rollback:`:396
0 unnecessary, 1 restored, 2 failed. Actual hardware state is published after a397
failed rollback, so the manager can decide how to recover.399
An `output-configuration-request` carries copied `heads:`, `apply?:` and a400
configuration revision. `reply-output-configuration!` takes the request ID and401
an explicit replacement head list, or false to refuse. A dedicated402
`output-configuration-result` reports protocol success. Requests expire at the403
host's declared deadline and become invalid when their output context changes.404
Copied proposals remain ordinary Sigil data after the native request retires.406
`output-power-request` and `output-gamma-request` require explicit407
`reply-output-control!` admission. `set-output-power!` is an explicit manager408
command. Output `enabled?:` describes configured ownership and `powered?:`409
describes hardware power; powering down preserves configured geometry and410
workspace decisions. Native gamma tables remain native resources and apply411
with a frame commit after admission. `set-output-filter!` selects `linear` or412
`nearest`; any rule choosing between them belongs to the manager.414
Collections in copied snapshots retain object creation order when facts change.415
Snapshots also retain inhibitor associations and the last explicit idle state.416
An inhibitor created before its window role gains that association when the417
role appears; the manager chooses whether its applied visibility inhibits idle.419
Pointer constraints use protocol bit512. They remain inert until policy calls420
`set-active-pointer-constraint! host id generation`; id0 deactivates the current421
lease. The `constraints:` snapshot contains copied identity, lifetime, seat,422
visibility, pointer focus, keyboard owner, region membership and focus generation423
facts. `constraint-state` arrives only when those facts change. Policy chooses424
eligibility and selection. Native code enforces the admitted lock or confinement425
without a callback for ordinary motion, and ends it on scope or surface loss.427
A locked client's release hint becomes a bounded `pointer-hint-request` with428
window, focus generation and global coordinates. `reply-pointer-hint!` accepts or429
refuses it. Acceptance revalidates the live surface, current epoch, input region430
and output coordinates; expired or retired requests cannot move the pointer.431
`delegate-relative-pointer! host enabled?` explicitly controls native relative432
motion delivery. `query-pointer! host` returns a token for an asynchronous433
`pointer-state` observation and updates `pointer-state:` in the snapshot.435
A `pointer-target-changed` observation carries `pointer-token:`. Supplying it436
as `pointer-token:` to `focus-window!` authorizes that copied transition while437
preserving queued input from the same focus epoch. `input-token:` supplies the438
corresponding authorization for the notified head press. Optional `input-target:`439
identifies the actual captured window when policy focuses a different recipient,440
such as that window's owner. The native host checks the token, target and epoch.441
The call returns an operation token. Its `focus-request-result` uses that token442
as `id:` and copies the input or pointer token as `authorization:`. A retired,443
hidden or lock-isolated target returns `accepted?: #f`, including plain focus444
operations. Stale authorization also returns `accepted?: #f`; it does445
not focus a window or count as a malformed command. The accepted result preserves446
paired first-click delivery even when the policy handler yields.448
Batch output settings accept optional `power?:`. It defaults to `enabled:`;449
setting it false keeps an admitted logical output asleep while changing its450
explicit layout or mode. `enabled:` remains the administrative layout decision.451
Snapshots also copy actual `powered?:`, current `mode:`, `refresh:` and452
`adaptive-sync?:` so policy can preserve unchanged backend state in a complete453
configuration. Previously returned snapshots remain detached.455
Protocol bit256 exposes activation requests as copied target, source-window,456
seat/serial provenance and focus-generation facts. The protocol implementation457
validates tokens; policy chooses attention or focus. Native activation never458
changes focus. `acknowledge-configure! host window` sends an explicit empty xdg459
configure reply, including when policy declines a maximize request.461
`start-host!` accepts `socket:` for a chosen Wayland socket basename. Names are462
copied before startup; unsafe names and occupied endpoints fail cleanly.463
`ready` reports `session-available?:`. `configure-session-switches!` accepts up to464
12 `(keysym . vt)` pairs as an explicit native escape cache. Matching physical465
presses and releases bypass a stalled policy handler; virtual/emulated devices466
cannot trigger this cache. A session backend must exist. The backend call is467
covered with a native stub, without changing a real terminal session.469
Protocol bit8 also exposes the legacy decoration negotiation interface.470
`start-host!` accepts `legacy-decoration: 'none|'client|'server` as the explicit471
initial protocol default. Both decoration transports appear as detached472
`decorations:` records with stable identity, associated window, mode and kind.473
`decoration-state` reports changed facts, including association when a legacy474
object preceded its window role; `decoration-destroyed` retires that identity.475
Policy selects border presentation and supplies xdg preference through476
`set-decoration-mode!`. Cached preference applies on initial commit, without477
waking policy or producing new configures on ordinary client frames. Native478
wrappers are bounded and included in the ownership counters.480
Keyboard device facts include `nested?:` for input supplied by a parent Wayland481
backend. `configure-keyboard!` accepts `group:` (default0) and482
`fixed-group?:` (defaultfalse); `set-keyboard-group!` accepts `fixed?:`.483
A fixed group preserves the explicitly chosen group across incoming backend484
modifier updates. Other modifier state still follows the device. Policy chooses485
which devices need that cache; the generic host supplies no binding or group486
selection rule.488
`query-window! host window` returns an operation token. A live initialized489
window produces paired `window-observation` and `window-observation-geometry`490
events with that token as `id:`. They copy actual scene position, committed491
geometry, mapping, visibility, focus, surface offset and acknowledged serial.492
Committed activation, suspension, fullscreen and tiled protocol state are493
available when `xdg-state?:` is true; other roles report those fields as zero.494
The geometry event includes the bound xdg protocol version. A retired or495
uninitialized window produces only an observation with `accepted?: #f`.496
These explicit queries do not configure a client or change manager state.498
Queued keyboard observations still reach the input hook after an ordinary focus499
change, so semantic bindings can consume a burst without losing later keys.500
Forwarding and replacement retain the original focus generation and are refused501
when stale. Scope loss and lock isolation still cancel pending input before it502
can reach an unauthorized recipient. Policy never receives stale virtual input503
while locked.505
Output-scoped pixels are bounded by the supplied geometry. A malformed rectangle506
is refused before copying. If a queued image's output or geometry has since507
retired, the copied image is discarded without rejecting the command or changing508
the existing image. Host statistics 5 and 6 count current pixel nodes and discarded509
scoped images; statistic 4 counts retained copied pixel bytes.512
`set-default-layer-output!` returns an operation token. Its513
`layer-output-result` reports `output:` and `accepted?:`. A retired output514
refuses the cached-target update without choosing a replacement or rejecting515
the command. Output 0 explicitly clears the target.517
A window placement accepts `suspended?:` independently of `shown?:`. It defaults518
to false. The host forwards the requested protocol state to native toplevels519
whose bound protocol version supports it; other roles and older versions have520
no suspension state. Managers explicitly choose when hidden clients suspend.522
A placement's `resize?:` defaults to true. False retains the established523
client size while applying the requested scene box and protocol state. This524
lets a manager keep future hidden layout geometry without resizing the client.525
Unchanged protocol state sends no redundant configure; state-only changes do526
not wait for a new geometry commit. Pending geometric configures still retain527
their serial and deadline.529
Destroying an output retires its scoped pixel nodes and their copied storage.530
Changing its geometry disables stale scoped nodes until explicitly replaced or531
removed. Queued images for retired outputs are discarded without retaining copies.533
Window observation surface offsets name the actual root surface tree relative534
to the window geometry node. Clipping uses root-surface coordinates and leaves535
popups outside that tree free to extend beyond the client rectangle. Pending536
visible geometric transactions continue frame callbacks while hidden clients537
answer their new configure. Invalid keyboard maps return a failed configuration538
result while retaining the previously applied map and group.540
Host statistic7 reports currently retained transaction snapshot trees; statistic8541
counts snapshot trees created during the session. Both are mechanism facts.542
Snapshot ownership ends at application, refusal or destruction of its view.544
Window geometry observations also expose requested-suspended?: separately from545
the committed suspended?: field, plus acknowledged and scheduled configure546
serials. A state-only configure may be acknowledged without a new surface547
commit. Native geometry changes refresh the explicit clip rectangle in the548
root surface coordinate space, including later decoration-margin commits.550
Forwarded keys publish their copied origin modifier snapshot for both press and551
release. Replacement keys retain their explicitly requested modifier snapshot.552
This includes virtual keyboards that send modifier state without modifier-key553
presses. Pooled held-key ownership and stale-focus forwarding checks still apply.555
Committed xdg size-hint and parent changes after the initial handshake emit556
window-hints events and update detached window snapshots. They do not emit a557
second window-initial event or choose a size for the manager.559
X11 association catches up an already committed buffer before publishing normal560
map and geometry facts. Placement and focus still require the manager's scene.561
# Wayland window credentials563
Wayland toplevel window records include `pid:`, `uid:` and `gid:` copied from564
the client's Unix socket credentials when the window is created. The565
`window-created` event exposes the same fields. These identify the connection's566
process, which can own multiple windows; they do not identify a terminal's567
foreground process. Window creation facts retain these values during snapshot568
resynchronization. Layer and X11 creation records use `#f`; X11's later `pid:`569
property is client-reported and does not carry authenticated UID/GID values.572
With `SIGIL_WM_TRACE_LATENCY=1`, `latency-mark! stage [token]` records a direct573
monotonic timestamp for stages 1–7; stage 1 establishes the input token. Native574
key-input, buffer-commit and presentation records use stages 0, 8 and 9. The575
trace is bounded to 4096 stderr records and is disabled by default. Presentation576
uses the backend's supplied presentation timestamp; compare it with monotonic577
owner timestamps only on a backend whose presentation clock is monotonic.