Files
feresaria/docs/desktop-reconciliation.md
T
Samuel Onoja eb84104940 Publish topic guides to the wiki and document tabbed windows
Publish the guides from this repository to the GitHub Wiki. Organize them into Usage, Configuration and Development, with 15 separate configuration topics and redirects for the former website guide URLs.

Add a tabbed-windows guide covering grouping, switching tabs and taking windows out. Document the scrolling indicator's defaults and limits, and link the guide from the README, shortcuts and IPC pages. Update from main, including the latest tabbed-layout changes.

Separate Activities setup, configuration and publishing documentation. Review the guide prose with the unslop skill, keeping existing examples and heading links. The wiki workflow uses GitHub's built-in token to publish documentation changes on main.

Validation:

- 20 documentation tests pass, including README links and Activities/tab-indicator field coverage.
- The publisher builds 46 wiki pages; the site build and Python syntax checks pass.
- All 115 code examples from main are preserved.
- The Python suite passes: 90 tests passed and 31 opt-in integration tests skipped, with the system GI module available.
2026-10-13 00:32:23 +01:00

8.9 KiB

Desktop reconciliation and presentation

During an output topology change, Ferese publishes one logical desktop after the usable hardware inventory is known. The boundary is synchronous within one event-loop dispatch; it does not wait for client commits, animation completion or page flips.

Previous flow

direct/topology.rs::reconcile_outputs already centralized hotplug, profile changes, retry and resume. It debounced connector events, validated device-wide KMS requests, applied devices independently and attempted compensation on failure. Its reconciling guard suppressed relayout, shell broadcasts and frame scheduling.

Inside that guard, apply_device still changed live Wayland output metadata, registered each output and updated output/workspace geometry. Registration could restore evacuated workspaces and reposition floating windows. Retirement called unregister_output, which combined render/capture/lock cleanup with workspace migration, focus changes, floating movement and relayout. Thus later devices or rollback operated on desktop policy already changed by earlier devices.

The end of reconciliation restored focus, performed global relayout (including client configures, surface preferences, a shell snapshot and redraw), then made another global redraw request. Profile configuration reload could relayout again.

Current phases

  1. Observe and choose desired hardware. Reconciliation uses the existing monitor identities, profile selection, position policy, hotplug coalescer and lid/resume handling.
  2. Validate and apply hardware. The backend uses device-wide atomic TEST_ONLY validation, Smithay resource staging/commits, per-device rollback, cross-device compensation and last-output recovery. These operations update resource metadata, not live workspace ownership or published output geometry.
  3. Plan the publishable desktop. After all hardware outcomes are known, publish_runtime_desktop reports usable logical outputs. Physical mirror scanouts do not acquire workspaces. OutputWorkspaceMap::plan_desktop stages a small copy of ownership, geometry, focus and evacuation history. It uses the existing connect/reclaim/evacuate policy and reserves any needed workspace IDs. It rejects duplicate IDs and invalid geometry without changing the source map.
  4. Publish logical state. Ferese::publish_desktop computes floating moves from the old geometry directly to the final geometry, then installs output registries, Wayland output metadata, ownership, floating destinations and logical focus. Slides that reference evacuated workspaces are retired. Unaffected viewport, world-coordinate, window-animation and resize state remain intact.
  5. Configure and finalize. finish_desktop_transition performs one relayout when needed, restores keyboard/lock focus, refreshes lock/idle policy, releases the shell publication guard and requests redraws for affected outputs. Existing layout remains responsible for tiled destinations, layer work areas, surface-tree scale/transform preferences, XDG configures and animation target ownership.
  6. Present asynchronously. The existing resize barriers, native-content snapshots, animations, frame scheduling and DisplayPresentation handle client readiness, motion, frame submission and displayed-content tracking. Logical publication does not assert that new pixels were displayed.

The desired hardware plan precedes application; the ownership plan is calculated from the result of application and recovery. This avoids computing and then undoing migrations to requested outputs that never became usable.

Types and scope

  • DesktopPlan is pure data: the staged OutputWorkspaceMap, reserved workspace IDs, affected output IDs and focus dirtiness. It copies neither window layouts nor client buffers nor the whole compositor.
  • DesktopOutput adapts actual backend resources to that planner. Its Wayland handles, mode, scale and transform stay in the compositor, outside the pure map.
  • DesktopTransition holds short-lived resource retirement/redraw bookkeeping and guards shell publication while the synchronous transition is in progress.
  • DesktopChanges distinguishes layout, focus, shell and redraw consequences for the finalizer. Resume can request fresh frames without forcing a topology change.

Registration/removal outside DRM and nested output resizing use the same logical publication path. Profile reload carries accompanying scene dirtiness into its finalization rather than immediately relayouting the desktop a second time. Pointer movement, client damage, ordinary focus, title changes, cursor updates and frame callbacks do not construct or run a desktop plan.

Failure, retirement and security

A rejected hardware configuration leaves the desktop unchanged if the previous hardware remains usable. After physical loss or failed restoration, unusable scanouts are retired immediately, and the final plan excludes them. There is no atomicity guarantee across independent DRM devices.

Low-level retirement still disables globals, cancels frame timers and removes DRM presentation clocks. retire_output_resources clears records of displayed client content, output render caches, pending screencopies and lock resources. It does not migrate workspaces, change logical focus or relayout. Repeated retirement within the same boundary is harmless. Publication removes the output from Space and the logical registries once the final inventory is available.

If every physical output disappears, a headless desktop is valid: windows and workspace restoration history survive, while output ownership and keyboard focus are cleared. A requested all-disabled configuration still follows the existing validation/recovery policy. A powered-off output is not the same as a retired output; runtime output power remains independent of topology.

Session-lock protection remains mandatory for new/reconfigured scanouts. Hardware resets invalidate records of previously displayed content and lock frames. The boundary does not allow a saved desktop frame to substitute for a protected lock frame.

Readiness, motion and shell visibility

ResizeTransaction remains the only configure readiness barrier. Its existing 300 ms deadline and workspace coupling are unchanged: neighbors sharing the same viewport may pause together, but an unrelated workspace/output continues advancing. Existing committed client size/content may lag a newly published logical size. Reconciliation does not acknowledge client configures, advance springs itself, reset unrelated velocity or introduce another snapshot/animation system.

Shell broadcasts and initial subscription snapshots are deferred while the boundary is open. The finalizer releases that guard only after output ownership, focus, workspace cleanup and logical window layout agree. The existing shell snapshot protocol and deduplication remain in use. A snapshot describes the committed logical state; it does not mean every output has displayed that state.

DisplayPresentation remains a record of queued/displayed client visibility, not a topology transaction or a frame buffer store. Existing native resize snapshots survive output-cache retirement; GPU context loss still invalidates textures owned by that context. No new cross-GPU snapshot transport is introduced. Hardware preparation still uses a black modeset frame where required by the existing backend. This change prevents unintended logical intermediate desktops; it does not guarantee uninterrupted physical scanout through a modeset or device loss.

Regression coverage

Pure planner tests cover addition/removal, focused and non-focused removal, replacement of multiple outputs, reconnect/explicit reassignment, a returning output whose donor retires in the same plan, headless recovery, failed planning, no-op/idempotent reconciliation and deterministic 512-step ownership sequences. A separate 256-step sequence mutates topology, focus, workspace/window membership and validates ownership and preservation of every window after each step.

The fake hardware transaction test applies commit and rollback failures, then plans from survivors: successful rollback produces no logical change; failed rollback produces a coherent reduced desktop without the requested new output.

The private Wayland integration regression uses actual shell, XDG toplevel and session-lock resources. It checks no intermediate shell generation, one complete final snapshot, repeated retirement, floating clamping, focused-window migration, removal during a workspace slide, pending XDG resize after publication, another workspace's progress during the wait, deadline expiry, no-op inventories and locked headless loss/recovery. Fractional-scale/rotation tests compare planner geometry directly with Smithay's Space geometry.

Physical KMS commits, cross-GPU recovery and resume still require the native checks in output-management-testing.md. Pure and private-protocol tests do not validate a DRM driver's behavior.