diff options
| author | srdusr <[email protected]> | 2025-10-26 22:58:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2025-10-26 22:58:00 +0200 |
| commit | 304f3a374408bb6a5a04ebb7d4652c631395f5c6 (patch) | |
| tree | 8a40628fe016bd3e31c295cc76985d65c6354561 /crates/ctl/src | |
| parent | 9f07715b469a481849ee35ffa33d6dab34356c7d (diff) | |
| download | srdwm-304f3a374408bb6a5a04ebb7d4652c631395f5c6.tar.gz srdwm-304f3a374408bb6a5a04ebb7d4652c631395f5c6.zip | |
Live-expose monitor split, clean up leftover debug diagnostics
srd.monitor.split only ever ran at Lua config load despite being a plain
WindowManager mutation that every backend's monitors() already reads
fresh on each call. Adds srd dispatch set output split <name|id> <parts>
[rows|columns] (IPC set_monitor_split), same id-resolves-to-name pattern
set_output_enabled already uses.
Also removes eight log::warn!("XXX-DIAG ...") lines left behind from live
debugging in the multi-session shift that landed in 3c41fc4 - the same
"temporary, never removed" pattern already fixed twice earlier this
session. Several fired on genuinely constant interaction (every title
change, every workspace switch, every layer-shell surface hide), not
just a one-off leftover. Left xdg_shell.rs's own POPUP-GEOM-DIAG/
POPUP-GRAB-DIAG alone - that one is a still-open, self-documented
investigation, not litter.
Also documents (docs/TODO.md, not a code change) a live incident where
creating a second fake monitor visibly corrupted the real monitor's
position and kept drifting with no further input - not root-caused
srdwm-side, flagged to the AGS peer session since a fake monitor's real
wl_output global is indistinguishable from a real hotplug to GDK/GTK.
And documents a deliberate decision not to blind-port window decoration
rendering onto the experimental, never-live-tested GPU render path.
Diffstat (limited to 'crates/ctl/src')
| -rw-r--r-- | crates/ctl/src/main.rs | 55 |
1 files changed, 53 insertions, 2 deletions
diff --git a/crates/ctl/src/main.rs b/crates/ctl/src/main.rs index 3cf3bfd..fb896a3 100644 --- a/crates/ctl/src/main.rs +++ b/crates/ctl/src/main.rs @@ -43,6 +43,12 @@ //! disabled output stops presenting //! and its `wl_output` global goes away //! until re-enabled +//! srd dispatch set output split NAME|ID PARTS [rows|columns] divides +//! one real output into PARTS logical +//! monitors for placement/tiling -- +//! columns (default) side by side, +//! rows stacked; PARTS <= 1 clears an +//! existing split. Live, no restart. //! srd set border_width 3 live theme values, applied immediately //! srd set border_color '#cba6f7' (hex string) //! srd set corner_radius 10 @@ -294,9 +300,9 @@ fn build_dispatch(args: &[String]) -> Result<String, String> { // back. "set" => { if args.get(1).map(String::as_str) != Some("output") { - return Err(format!("'set' only supports 'output position'/'output enabled' - {usage_hint}")); + return Err(format!("'set' only supports 'output position'/'output enabled'/'output split' - {usage_hint}")); } - let noun = args.get(2).ok_or("'set output' needs a target: position or enabled")?; + let noun = args.get(2).ok_or("'set output' needs a target: position, enabled or split")?; let target = args.get(3).ok_or("'set output' needs a monitor name or id")?; match noun.as_str() { "position" => { @@ -318,6 +324,25 @@ fn build_dispatch(args: &[String]) -> Result<String, String> { Err(_) => Ok(format!(r#"{{"cmd":"set_output_enabled","name":"{target}","enabled":{enabled}}}"#)), } } + // `srd dispatch set output split <name|id> <parts> [rows|columns]` + // - the live equivalent of `srd.monitor.split(name, parts, + // direction)` in Lua config, which previously only ever took + // effect at config load/reload. `parts <= 1` clears an + // existing split. `columns` (side-by-side, splitting width) + // is the default when the direction is omitted, matching the + // Lua function's own default. + "split" => { + let parts: u64 = args.get(4).ok_or("'set output split' needs a part count")?.parse().map_err(|_| "parts must be a number".to_string())?; + let rows = match args.get(5).map(String::as_str) { + None | Some("columns") => false, + Some("rows") => true, + Some(other) => return Err(format!("'set output split' direction must be 'rows' or 'columns', got '{other}'")), + }; + match target.parse::<u64>() { + Ok(id) => Ok(format!(r#"{{"cmd":"set_monitor_split","id":{id},"parts":{parts},"rows":{rows}}}"#)), + Err(_) => Ok(format!(r#"{{"cmd":"set_monitor_split","name":"{target}","parts":{parts},"rows":{rows}}}"#)), + } + } _ => Err(format!("unknown 'set output' target '{noun}' - {usage_hint}")), } } @@ -385,6 +410,7 @@ fn print_usage() { eprintln!(" srd dispatch cycle keyboard layout"); eprintln!(" srd dispatch set output position <name|id> <x> <y>"); eprintln!(" srd dispatch set output enabled <name|id> <true|false>"); + eprintln!(" srd dispatch set output split <name|id> <parts> [rows|columns]"); eprintln!(" srd dispatch pin input <pid> <window-id>"); eprintln!(" srd dispatch unpin input <pid>"); eprintln!(" srd dispatch create fake-monitor <name> <width>x<height>"); @@ -503,6 +529,31 @@ mod tests { } #[test] + fn set_output_split_accepts_a_numeric_id_and_a_name() { + assert_eq!(build_request(&args(&["dispatch", "set", "output", "split", "1", "2"])).unwrap(), r#"{"cmd":"set_monitor_split","id":1,"parts":2,"rows":false}"#); + assert_eq!( + build_request(&args(&["dispatch", "set", "output", "split", "HDMI-A-1", "3", "rows"])).unwrap(), + r#"{"cmd":"set_monitor_split","name":"HDMI-A-1","parts":3,"rows":true}"# + ); + } + + #[test] + fn set_output_split_defaults_direction_to_columns() { + assert_eq!(build_request(&args(&["dispatch", "set", "output", "split", "eDP-1", "2", "columns"])).unwrap(), r#"{"cmd":"set_monitor_split","name":"eDP-1","parts":2,"rows":false}"#); + } + + #[test] + fn set_output_split_rejects_an_unknown_direction() { + assert!(build_request(&args(&["dispatch", "set", "output", "split", "eDP-1", "2", "sideways"])).is_err()); + } + + #[test] + fn set_output_split_needs_a_part_count() { + assert!(build_request(&args(&["dispatch", "set", "output", "split", "eDP-1"])).is_err()); + assert!(build_request(&args(&["dispatch", "set", "output", "split", "eDP-1", "not-a-number"])).is_err()); + } + + #[test] fn create_fake_monitor_builds_a_sized_request() { assert_eq!( build_request(&args(&["dispatch", "create", "fake-monitor", "FAKE-1", "1920x1080"])).unwrap(), |