srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/ctl
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ctl')
-rw-r--r--crates/ctl/src/main.rs42
1 files changed, 42 insertions, 0 deletions
diff --git a/crates/ctl/src/main.rs b/crates/ctl/src/main.rs
index 929d44c..d714405 100644
--- a/crates/ctl/src/main.rs
+++ b/crates/ctl/src/main.rs
@@ -321,6 +321,27 @@ fn build_dispatch(args: &[String]) -> Result<String, String> {
_ => Err(format!("unknown 'set output' target '{noun}' - {usage_hint}")),
}
}
+ // `srd dispatch create fake-monitor <name> <width>x<height>` /
+ // `srd dispatch remove fake-monitor <name>` - a fully virtual
+ // `wl_output` with no real hardware behind it. See
+ // `crates/wayland/src/udev/virtual_heads.rs`'s own module doc
+ // comment for the full design and scope (content is readable via
+ // any `zwlr_screencopy_manager_v1` client - `grim -o <name>`,
+ // concretely - there is no real display to look at directly).
+ "create" | "remove" => {
+ if args.get(1).map(String::as_str) != Some("fake-monitor") {
+ return Err(format!("'{verb}' only supports 'fake-monitor' - {usage_hint}"));
+ }
+ let name = args.get(2).ok_or("'fake-monitor' needs a name")?;
+ if verb == "remove" {
+ return Ok(format!(r#"{{"cmd":"remove_fake_monitor","name":{name:?}}}"#));
+ }
+ let size = args.get(3).ok_or("'create fake-monitor' needs a <width>x<height>")?;
+ let (w, h) = size.split_once('x').ok_or("size must be '<width>x<height>', e.g. 1920x1080")?;
+ let width: u32 = w.parse().map_err(|_| "width must be a number".to_string())?;
+ let height: u32 = h.parse().map_err(|_| "height must be a number".to_string())?;
+ Ok(format!(r#"{{"cmd":"create_fake_monitor","name":{name:?},"width":{width},"height":{height}}}"#))
+ }
// `srd dispatch pin input <pid> <window-id>` / `srd dispatch
// unpin input <pid>` - the CLI surface for `pin_input`, Phase 2
// of the multi-cursor plan (`docs/TODO.md`). `<pid>` is the
@@ -366,6 +387,8 @@ fn print_usage() {
eprintln!(" srd dispatch set output enabled <name|id> <true|false>");
eprintln!(" srd dispatch pin input <pid> <window-id>");
eprintln!(" srd dispatch unpin input <pid>");
+ eprintln!(" srd dispatch create fake-monitor <name> <width>x<height>");
+ eprintln!(" srd dispatch remove fake-monitor <name>");
eprintln!(" srd capture workspace <id> <path> [<width>x<height>]");
eprintln!(" srd set border_width <n>");
eprintln!(" srd set border_color <#hex>");
@@ -472,6 +495,25 @@ mod tests {
}
#[test]
+ fn create_fake_monitor_builds_a_sized_request() {
+ assert_eq!(
+ build_request(&args(&["dispatch", "create", "fake-monitor", "FAKE-1", "1920x1080"])).unwrap(),
+ r#"{"cmd":"create_fake_monitor","name":"FAKE-1","width":1920,"height":1080}"#
+ );
+ }
+
+ #[test]
+ fn remove_fake_monitor_needs_no_size() {
+ assert_eq!(build_request(&args(&["dispatch", "remove", "fake-monitor", "FAKE-1"])).unwrap(), r#"{"cmd":"remove_fake_monitor","name":"FAKE-1"}"#);
+ }
+
+ #[test]
+ fn create_fake_monitor_rejects_a_malformed_size() {
+ assert!(build_request(&args(&["dispatch", "create", "fake-monitor", "FAKE-1", "1920"])).is_err());
+ assert!(build_request(&args(&["dispatch", "create", "fake-monitor", "FAKE-1", "widexhigh"])).is_err());
+ }
+
+ #[test]
fn pin_input_builds_a_request_with_pid_and_window_id() {
assert_eq!(build_request(&args(&["dispatch", "pin", "input", "12345", "7"])).unwrap(), r#"{"cmd":"pin_input","pid":12345,"id":7}"#);
}