srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/ctl/src
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2025-11-07 14:04:00 +0200
committersrdusr <[email protected]>2025-11-07 14:04:00 +0200
commitea78f94027ecd2c690904a6d7729e9e3cc190a20 (patch)
treefe622c0cd12a2fe077501a26f0077c51d41b4209 /crates/ctl/src
parenta8991f65602abc5ecee740c443c58fa96ecd15e1 (diff)
downloadsrdwm-ea78f94027ecd2c690904a6d7729e9e3cc190a20.tar.gz
srdwm-ea78f94027ecd2c690904a6d7729e9e3cc190a20.zip
Make tiling's master/stack ratio live, add settings readback everywhere
Investigated the "tiling needs a lot of work" report directly. The MasterStackLayout algorithm itself was already correct; the real gap was that dragging or resizing a tiled window did nothing durable (raw geometry that the next arrange_workspace silently discarded), and master_ratio/master_count had no live path at all (config-file only). A resize-drag on the shared master/stack boundary now live-adjusts TilingConfig::master_ratio and re-arranges the group immediately; srd set master_ratio/master_count do the same for a keybind or script. Found and fixed a real bug while building this: start_resize's own focus_window call re-stacks its target in self.order before the ratio-drag decision used to be made, silently misclassifying real master-column grabs. Fixed by deciding ratio-drag status (and freezing the membership snapshot it depends on) before that raise happens, applying MasterStackLayout directly against the frozen snapshot rather than re-deriving membership from the by-then-reordered live order. Live- verified in a nested compositor, not just unit-tested. Also closes the readback gaps flagged directly by the AGS peer session: border_width/border_color/corner_radius/decoration_mode/gap_inner/ gap_outer/master_ratio/master_count were all live-settable via srd set with no way to read the current value back, and pin_input had no readback at all. SettingsResponse now reports all of them; a new pinned_inputs query (srd pinned inputs) lists every currently pinned pid/window.
Diffstat (limited to 'crates/ctl/src')
-rw-r--r--crates/ctl/src/main.rs26
1 files changed, 24 insertions, 2 deletions
diff --git a/crates/ctl/src/main.rs b/crates/ctl/src/main.rs
index fb896a3..fb7196c 100644
--- a/crates/ctl/src/main.rs
+++ b/crates/ctl/src/main.rs
@@ -145,6 +145,8 @@ fn build_request(args: &[String]) -> Result<String, String> {
Some("monitors") => Ok(r#"{"cmd":"monitors"}"#.to_string()),
Some("workspaces") => Ok(r#"{"cmd":"workspaces"}"#.to_string()),
Some("settings") => Ok(r#"{"cmd":"settings"}"#.to_string()),
+ Some("pinned") if args.get(1).map(String::as_str) == Some("inputs") => Ok(r#"{"cmd":"pinned_inputs"}"#.to_string()),
+ Some("pinned") => Err("did you mean 'srd pinned inputs'?".to_string()),
Some("keyboard") if args.get(1).map(String::as_str) == Some("layout") => Ok(r#"{"cmd":"keyboard_layout"}"#.to_string()),
Some("keyboard") => Err("did you mean 'srd keyboard layout'?".to_string()),
Some("subscribe") => Ok(r#"{"cmd":"subscribe"}"#.to_string()),
@@ -184,13 +186,14 @@ fn build_request(args: &[String]) -> Result<String, String> {
// as booleans at all, not a string it then has to reject.
Some("set") => {
let key = args.get(1).ok_or(
- "set needs a key (border_width/border_color/corner_radius/gap_inner/gap_outer/shadows/rounded_corners/animations/night_light/reading_mode/phone_mode/multi_cursor/decoration_mode)",
+ "set needs a key (border_width/border_color/corner_radius/gap_inner/gap_outer/master_ratio/master_count/shadows/rounded_corners/animations/night_light/reading_mode/phone_mode/multi_cursor/decoration_mode)",
)?;
let raw = args.get(2).ok_or("set needs a value")?;
let value = match key.as_str() {
- "border_width" | "corner_radius" | "gap_inner" | "gap_outer" => {
+ "border_width" | "corner_radius" | "gap_inner" | "gap_outer" | "master_count" => {
raw.parse::<u64>().map_err(|_| format!("{key} needs a numeric value"))?.to_string()
}
+ "master_ratio" => raw.parse::<f64>().map_err(|_| format!("{key} needs a numeric value"))?.to_string(),
"shadows" | "rounded_corners" | "animations" | "night_light" | "reading_mode" | "phone_mode" | "multi_cursor" => match raw.as_str() {
"true" | "false" => raw.clone(),
_ => return Err(format!("{key} needs 'true' or 'false'")),
@@ -394,6 +397,7 @@ fn print_usage() {
eprintln!(" srd monitors");
eprintln!(" srd workspaces");
eprintln!(" srd settings");
+ eprintln!(" srd pinned inputs");
eprintln!(" srd keyboard layout");
eprintln!(" srd subscribe");
eprintln!(" srd dispatch focus <id>");
@@ -654,6 +658,24 @@ mod tests {
fn settings_query_needs_no_further_arguments() {
assert_eq!(build_request(&args(&["settings"])).unwrap(), r#"{"cmd":"settings"}"#);
}
+
+ #[test]
+ fn pinned_inputs_query_reads_as_two_words() {
+ assert_eq!(build_request(&args(&["pinned", "inputs"])).unwrap(), r#"{"cmd":"pinned_inputs"}"#);
+ assert!(build_request(&args(&["pinned"])).is_err());
+ }
+
+ #[test]
+ fn set_master_ratio_accepts_a_fractional_value() {
+ assert_eq!(build_request(&args(&["set", "master_ratio", "0.65"])).unwrap(), r#"{"cmd":"set","key":"master_ratio","value":0.65}"#);
+ assert!(build_request(&args(&["set", "master_ratio", "not-a-number"])).is_err());
+ }
+
+ #[test]
+ fn set_master_count_accepts_a_plain_integer() {
+ assert_eq!(build_request(&args(&["set", "master_count", "2"])).unwrap(), r#"{"cmd":"set","key":"master_count","value":2}"#);
+ assert!(build_request(&args(&["set", "master_count", "not-a-number"])).is_err());
+ }
}
#[cfg(unix)]