srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/config/src/engine
diff options
context:
space:
mode:
Diffstat (limited to 'crates/config/src/engine')
-rw-r--r--crates/config/src/engine/general.rs27
-rw-r--r--crates/config/src/engine/support.rs14
-rw-r--r--crates/config/src/engine/tests.rs26
3 files changed, 65 insertions, 2 deletions
diff --git a/crates/config/src/engine/general.rs b/crates/config/src/engine/general.rs
index e5147cd..6276854 100644
--- a/crates/config/src/engine/general.rs
+++ b/crates/config/src/engine/general.rs
@@ -128,8 +128,8 @@ impl Engine {
/// class_regex = "...", instance = "..." }, { floating = true,
/// workspace = 2, x = .., y = .., width = .., height = ..,
/// decorated = false, border_color = {r,g,b}, border_width = 2,
- /// corner_radius = 10, maximized = true, opacity = 0.9 })`. At least
- /// one matcher field is
+ /// corner_radius = 10, maximized = true, opacity = 0.9,
+ /// aspect_ratio = "9:16" })`. At least one matcher field is
/// required; unmatched rules apply nothing.
///
/// `title`/`class` are plain substring/exact match, cheap and cover
@@ -172,6 +172,28 @@ impl Engine {
_ => None,
}
};
+ // `aspect_ratio = "9:16"` - the "phone monitor / special
+ // workspace" ask's own real, scoped answer (see `Window::
+ // aspect_ratio`'s own doc comment in `crates/core`): a rule
+ // matching any VM/emulator/`scrcpy` window by `app_id` keeps
+ // it phone-shaped through a resize, with no Android-specific
+ // (or even VM-specific) code anywhere in this compositor.
+ // `"W:H"` (a plain string, not a table) matches this
+ // project's own `border_color = {r,g,b}` precedent for "a
+ // structured value needs its own small parse", just with a
+ // string instead of a table since a ratio is conventionally
+ // written that way everywhere (`16:9`, `9:16`, `4:3`).
+ let aspect_ratio: Option<(u32, u32)> = match actions.get::<_, Option<String>>("aspect_ratio")? {
+ Some(spec) => {
+ let (w, h) = spec
+ .split_once(':')
+ .and_then(|(w, h)| Some((w.trim().parse::<u32>().ok()?, h.trim().parse::<u32>().ok()?)))
+ .filter(|(w, h)| *w > 0 && *h > 0)
+ .ok_or_else(|| mlua::Error::RuntimeError(format!("srd.rule: aspect_ratio must be \"W:H\" with positive integers, got {spec:?}")))?;
+ Some((w, h))
+ }
+ None => None,
+ };
let rule = WindowRule {
matcher: WindowMatch { title_contains, class, title_regex, class_regex, instance },
@@ -187,6 +209,7 @@ impl Engine {
pinned: actions.get("pinned")?,
opacity: actions.get("opacity")?,
resize_margin: actions.get("resize_margin")?,
+ aspect_ratio,
},
};
state.borrow().wm.borrow_mut().add_rule(rule);
diff --git a/crates/config/src/engine/support.rs b/crates/config/src/engine/support.rs
index 7537fce..97c499f 100644
--- a/crates/config/src/engine/support.rs
+++ b/crates/config/src/engine/support.rs
@@ -154,11 +154,25 @@ pub(super) fn default_config() -> HashMap<String, ConfigValue> {
// every other ordinary flag rather than left absent for a backend to
// decide.
set("general.gpu", Bool(false));
+ // `false`: opt-in single-app-at-a-time placement, off by default so
+ // an ordinary desktop session's floating/tiling behavior is
+ // completely unaffected - see `WindowManager::phone_mode`'s own doc
+ // comment.
+ set("general.phone_mode", Bool(false));
// Real desktop icons (Home/Computer/Trash plus `~/Desktop`'s own
// contents) on by default - see `WindowManager::desktop_icons_
// enabled`'s own doc comment for why this, unlike `general.gpu` just
// above, doesn't need an opt-in safety net.
set("general.desktop_icons", Bool(true));
+ // On by default - see `WindowManager::desktop_icons_all_monitors`'s
+ // own doc comment.
+ set("general.desktop_icons_all_monitors", Bool(true));
+ // `0` (no static reservation) by default - see `WindowManager::
+ // reserve_top`'s own doc comment for what this is and why.
+ set("general.reserve_top", Number(0.0));
+ set("general.reserve_bottom", Number(0.0));
+ set("general.reserve_left", Number(0.0));
+ set("general.reserve_right", Number(0.0));
// Empty by default - see `WindowManager::file_manager`'s own doc
// comment: empty means "dispatch via `xdg-open`", not "no file manager
// configured, do nothing".
diff --git a/crates/config/src/engine/tests.rs b/crates/config/src/engine/tests.rs
index f170320..f4f011b 100644
--- a/crates/config/src/engine/tests.rs
+++ b/crates/config/src/engine/tests.rs
@@ -197,6 +197,32 @@
}
#[test]
+ fn srd_rule_aspect_ratio_applies_a_parsed_w_h_pair_on_creation() {
+ let dir = tempfile::tempdir().unwrap();
+ let wm = Rc::new(RefCell::new(WindowManager::new()));
+ let engine = Engine::new(wm.clone(), dir.path()).unwrap();
+ engine.lua.load(r#"srd.rule({ class = "scrcpy" }, { aspect_ratio = "9:16" })"#).exec().unwrap();
+ let id = {
+ let mut wm = wm.borrow_mut();
+ let id = wm.alloc_window_id();
+ let mut w = srdwm_core::Window::new(id, "phone");
+ w.app_id = "scrcpy".into();
+ wm.add_window(w);
+ id
+ };
+ assert_eq!(wm.borrow().window(id).unwrap().aspect_ratio, Some((9, 16)));
+ }
+
+ #[test]
+ fn srd_rule_rejects_a_malformed_aspect_ratio() {
+ let dir = tempfile::tempdir().unwrap();
+ let wm = Rc::new(RefCell::new(WindowManager::new()));
+ let engine = Engine::new(wm.clone(), dir.path()).unwrap();
+ let err = engine.lua.load(r#"srd.rule({ class = "x" }, { aspect_ratio = "sixteen by nine" })"#).exec();
+ assert!(err.is_err());
+ }
+
+ #[test]
fn srd_monitor_split_stores_a_split_request_by_connector_name() {
let dir = tempfile::tempdir().unwrap();
let wm = Rc::new(RefCell::new(WindowManager::new()));