diff options
| author | srdusr <[email protected]> | 2025-09-26 22:07:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2025-09-26 22:07:00 +0200 |
| commit | 9a9aa8fe9d4f4f9b15860b45244e695942c90afd (patch) | |
| tree | a7a8289731d49713caeaf06f023ab04f78cc663c /crates/wayland/src/udev/mod.rs | |
| parent | b46dfa56504f62ecf969914dfed106bf587c4c4a (diff) | |
| download | srdwm-9a9aa8fe9d4f4f9b15860b45244e695942c90afd.tar.gz srdwm-9a9aa8fe9d4f4f9b15860b45244e695942c90afd.zip | |
Fake (headless) monitors, and fix new windows all opening in one spot
Two independent pieces landed together this pass - both real, both
scoped, see docs/TODO.md for the full narrative on each:
Fake monitors: a genuinely independent, additional wl_output with no DRM
connector/CRTC behind it at all - distinct from srd.monitor.split
(divides one real output's own placement rectangle). Researched niri's
own Headless backend first (cloned at ~/reference-wms/niri): its render()
never actually composites anything, a no-render stub for that project's
test suite only. This one is real: it renders whatever is placed on it,
on demand, whenever a zwlr_screencopy_manager_v1 client asks for a frame.
New crates/wayland/src/udev/virtual_heads.rs (create/remove a real Output
+ global, render-on-demand for screencopy, integrated into platform.rs's
monitors() as a genuine srdwm_core::Monitor so core placement/workspace
code needs zero special-casing). New IPC/CLI: srd dispatch create
fake-monitor <name> <w>x<h> / remove fake-monitor <name>. Core-side
request queue in crates/core/src/manager/fake_monitor.rs.
Placement bug, root-caused and fixed: every new window opened alone
landed in the exact same spot, "not at all like Windows" (reported live).
SmartPlacement::place tried a grid cell first, and grid's own cell count
is existing.len() + 1 - with nothing else open (opening one app at a
time, the ordinary case), that's always 1, so a 1x1 grid returns the same
single cell forever regardless of session history. Cascade had the same
bug in a second form (its own step was existing.len() % max_steps, also
always 0 with nothing open). Fixed: WindowManager::next_cascade_step (a
Cell - add_window's own target_monitor stays borrowed across the call)
advances on every real placement and is never reset by a window closing;
place() now skips grid entirely when nothing else is open, going
straight to cascade, since grid's real job (dividing space among
concurrent windows) has nothing to divide when there's no concurrency.
Full workspace build/test/clippy clean (223 core / 141 wayland / 29
platform / 24 ctl / 28 config / 10 x11 tests, 0 failed, 0 clippy
warnings), built and installed.
Diffstat (limited to 'crates/wayland/src/udev/mod.rs')
| -rw-r--r-- | crates/wayland/src/udev/mod.rs | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/crates/wayland/src/udev/mod.rs b/crates/wayland/src/udev/mod.rs index 27a7c2c..5ed96e4 100644 --- a/crates/wayland/src/udev/mod.rs +++ b/crates/wayland/src/udev/mod.rs @@ -200,6 +200,10 @@ pub(crate) struct UdevState { /// Shared by every head: one GPU, one software renderer. pub(crate) renderer: PixmanRenderer, pub(crate) heads: Vec<UdevHead>, + /// Fully virtual "fake" monitors - no DRM connector/CRTC, never + /// scanned out. See `virtual_heads.rs`'s own module doc comment for + /// the full design and scope. + pub(crate) virtual_heads: Vec<VirtualHead>, pub(crate) active: bool, /// Pointer position in the *global* space, so it can cross between /// monitors; clamped to the union of all head rectangles. @@ -558,5 +562,7 @@ mod outputs; mod platform; mod render; mod session; +mod virtual_heads; pub use platform::UdevPlatform; +pub(crate) use virtual_heads::VirtualHead; |