atagen

monolith

public
Star0
Watch0
82c94edb8c503ce7c87c5fbd1a00410265cbad05
1
ssh://brewery@pls.lobotomise.me:33/atagen/monolith.git
design/decisions.mdMarkdown107 lines8.9 KB

monolith design decisions

Running log of settled decisions and open questions. Research backing lives in research/.

Settled

Project

  • smithay based, Vulkan renderer, EUPL. jay/wry are reference only, nothing is copied.
  • calloop event loop. jay’s async runtime is not ported. Its phase ordering (event handling, layout, post-layout, present) is reproduced as fixed stages in the post-dispatch pipeline.
  • No programmable layouts. TOML config, no scripting.
  • Tree nodes and windows live in generational slotmaps referenced by typed keys, not Rc graphs.

Tags

  • Each window carries exactly one tag. Several tags can be viewed at once.
  • Tag names are global, view state is per output (model B). “View on all outputs” is a command built on top.
  • A “homeless” tag is immutable and always viewed. New windows land there unless a rule or launch context says otherwise. Hiding a window means moving it to an unviewed tag.
  • Windows are bound to an output. New homeless windows go to the output that was active when the spawn was requested.
  • Launch context. Windows are placed on the tag and output that were active when they were launched, not where focus is when they map. Child windows and windows of child processes inherit the parent’s tag and output. A compositor spawn command is acceptable as the launch path.
  • Layout state is one tree per output, filtered by viewed tags (see Planner section).
  • Unplug moves windows to an output viewing their tag, otherwise the tag is disabled there. Replug restores windows that left because of the unplug.
  • Tag order is invocation order, remembered, with a reordering command.
  • Sticky flag exists. Scratchpads are floating sticky sets of windows. Addressing a scratchpad cycles on, next window, …, off, with dimensions kept. A sticky scratchpad stays on the output it was last summoned to. A dismiss-scratchpad command takes an optional target, defaulting to the last active.
  • Tags are exposed through ext-workspace-v1, one group per output, one workspace per tag per output.

Layout

  • One tree per output, edited by the user, not derived from window count. Each tag starts as its own row.
  • Child splits run on the axis opposite their parent. Flipping orientation transposes the whole tree. Orientation is presentation only.
  • Viewing several tags shows the projection of the shared tree. Windows can be interspersed freely. No positional L/C/R merging.
  • An “expand” command at any tree level lets one window or subtree fill its slot. Autotiling on merge is a possible experiment.
  • Floating windows allowed. No pure floating mode.
  • A “deck” monocle (stacked windows with visible edges, selected window popped out) is a later container mode.

Animation

  • Animate by default. No animation under tearing or for fullscreen scanout, or the texture freezes until done.
  • Bezier curves with velocity-matched retargeting on interrupt. Springs may be supported too.
  • Every animation, and every phase of a multiphase plan, takes exactly its configured t. Plan length is phases * t.
  • Interruption restarts from the current visual position and must stay continuous under repeated interruption.
  • wry master (8b7ad7e6) is a worked example of multiphase rules, not law. monolith needs a new planner that handles diagonal moves, cross-output moves and large tag-merge motion groups.
  • Old textures are held during resize, oversize areas fill clamp-to-edge. Alpha blending and transition shaders (wipe, crossfade) are allowed for content swaps.
  • Animation starts without waiting for clients. A short timeout is acceptable.
  • Sample animations at predicted presentation time.
  • Geometry is subpixel (floats), rounded to physical pixels only at render.

Rendering

  • Individually rounded corners, borders, custom transition shaders (niri style). No user-facing transparency, blur or shadows. Normal alpha blending of client content is supported.
  • Fullscreen drops rounding.

Decorations

  • Server-side only, no titlebars in v1. Minimal i3-style titles possibly later.
  • Advertise xdg-decoration and org_kde_kwin_server_decoration_manager defaulting to SERVER. Claim server-side and draw only borders.
  • Send all four tiled states plus xdg-shell v7 constrained states (niri’s “no CSD” signal).

IPC

  • Wayland protocols for things bars consume (ext-workspace, foreign-toplevel).
  • Control and scripting over a unix socket speaking versioned JSONL.

Hardware and performance

  • NVIDIA first, must also work on Intel and AMD. An old Intel laptop is available for testing.
  • Hybrid laptops out of v1, but per-output render GPU stays in the data model.
  • VRR soon. HDR later, with room left in the color path.
  • Targets. Compositor CPU per frame p99 under 0.5 ms. Render to scanout at most 1 vblank with deadline scheduling. Fullscreen direct scanout plus tearing adds zero compositor frames. No dropped animation frames at 360 Hz.
  • lavapipe golden tests render to plain Vulkan images, not dmabuf.

Taken from jay/wry (as designs)

  1. Deadline frame scheduler, running from flip timestamps on NVIDIA.
  2. Off-thread shm upload with commit blocked until done.
  3. Vulkan renderer internals, with syncobj handled via DRM ioctls plus binary sync_file semaphores.
  4. Commit blocker taxonomy.
  5. Two-timeline tree, transactions.
  6. In-process integration test harness.
  7. Small items (SCHED_RR with reset-on-fork, Tracy, KMS hygiene, VRR cursor throttling, lazy Xwayland).

Open

  • None. Crates and milestones are in plan.md.

Settled late

  • Interrupts replan, they never stack. No plan-length cap.
  • Velocity matching is best-effort, applied only where the replan continues the current axis.
  • Launch context resolves through a graceful ranking. Window rule, xdg-activation token, parent toplevel, tracked systemd scope or cgroup, PID ancestry, focus at map time. The target is where the user was when the launch command began. Windows placed on an unviewed tag mark it urgent.
  • Nested sessions are a first-class, permanently supported backend.
  • A launch belongs to the focused window’s tag, unless that is homeless, then to the first viewed tag. Homeless is always on screen, so focusing its windows does not mean the user left their tag.
  • VRR defaults to fullscreen, on only while a fullscreen window shows on a capable output. Under VRR frames go out as soon as there is something new, and cursor-only frames are capped at 60 Hz.
  • Layer-shell exclusive zones are insets on the layout output, so fullscreen still covers the whole output. The top layer hides under fullscreen, the overlay layer does not.
  • An activation token takes focus only if monolith made it or its requester held the keyboard, and only within 10 s. Otherwise the window is marked urgent. A token arriving before a window’s first buffer may still move it to its launch context unless a rule placed it.
  • Screen capture renders the scene again into the client’s buffer. A session’s first frame comes at once, later frames wait for the output to draw something new.
  • Xwayland is native, not xwayland-satellite, so X11 games keep a direct path for M8 tearing work. monolith owns the X socket and spawns Xwayland on the first connection.

Planner (see planner.html)

  • Orthogonal style (one axis per window per phase) is the default and flagship look. Direct is a toggle.
  • Shared-separator rule, plans of 1 to 4 phases, the 4-phase grid guarantees a plan for any input. Pinch and lerp are safety nets only.
  • Window moves and container moves both exist as commands. A window move either swaps with its neighbour or merges into its lane, chosen by general.move, and invert-move does the other one for the next move only. The default lives in config rather than in a runtime toggle. Moving a tag directionally was rejected because interspersed tags have no single shape to move. Tag reordering only changes tag order.
  • expand all became maximize, which also sets the xdg maximized state.
  • One curve per motion group.
  • Floating windows travel above the tiled layer, exempt from the overlap rule.
  • Seeds start as a line on the old boundary between neighbours.
  • Floating to tiled and fullscreen use a direct glide above the tiled layer. Expand is a tiled operation planned normally, siblings squeezed to zero-size lines.
  • One layout tree per output, tags filter it. Hidden windows keep their slots, visible moves swap visible slots only, containers collapse by the normal one-child rule counting hidden children, and a hidden only child is demoted into the grandparent. This replaces per-tag layouts and the row-stacking merge rule, row stacking is just the default arrangement.
  • Lanes span only the band of the involved windows, never the whole output.
  • Hidden-slot rules confirmed. A window moving toward a lane that holds only hidden windows joins that lane rather than opening a new one beside it.
  • Input hit-tests against final layout geometry, never animated geometry.
  • smithay is pinned by git rev. The repo uses jj.

Deferred

  • Tearing. At the scanout milestone, carry rebased smithay #1948, #1949 and #1325 as patches and push them upstream.