aboutsummaryrefslogtreecommitdiff
path: root/src/config.rs
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2023-10-03 08:35:24 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2023-10-03 08:35:24 +0400
commitbb3fbe2e83e5173b7e0df40908280aec02dc1a4b (patch)
tree96b6cfb0dcc56ef13f0213aa45b3ff765bcd6793 /src/config.rs
parentef76b1df0483eb1913405316ee888b6ec5af1bf5 (diff)
downloadniri-bb3fbe2e83e5173b7e0df40908280aec02dc1a4b.tar.gz
niri-bb3fbe2e83e5173b7e0df40908280aec02dc1a4b.tar.bz2
niri-bb3fbe2e83e5173b7e0df40908280aec02dc1a4b.zip
Make output modes configurable
Diffstat (limited to 'src/config.rs')
-rw-r--r--src/config.rs77
1 files changed, 77 insertions, 0 deletions
diff --git a/src/config.rs b/src/config.rs
index 6bf31323..7ff7e338 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -81,6 +81,8 @@ pub struct Output {
pub scale: f64,
#[knuffel(child)]
pub position: Option<Position>,
+ #[knuffel(child, unwrap(argument, str))]
+ pub mode: Option<Mode>,
}
impl Default for Output {
@@ -89,6 +91,7 @@ impl Default for Output {
name: String::new(),
scale: 1.,
position: None,
+ mode: None,
}
}
}
@@ -101,6 +104,13 @@ pub struct Position {
pub y: i32,
}
+#[derive(Debug, Clone, PartialEq)]
+pub struct Mode {
+ pub width: u16,
+ pub height: u16,
+ pub refresh: Option<f64>,
+}
+
#[derive(knuffel::Decode, Debug, Clone, PartialEq, Eq)]
pub struct SpawnAtStartup {
#[knuffel(arguments)]
@@ -303,6 +313,41 @@ impl Default for Config {
}
}
+impl FromStr for Mode {
+ type Err = miette::Error;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let Some((width, rest)) = s.split_once('x') else {
+ return Err(miette!("no 'x' separator found"));
+ };
+
+ let (height, refresh) = match rest.split_once('@') {
+ Some((height, refresh)) => (height, Some(refresh)),
+ None => (rest, None),
+ };
+
+ let width = width
+ .parse()
+ .into_diagnostic()
+ .context("error parsing width")?;
+ let height = height
+ .parse()
+ .into_diagnostic()
+ .context("error parsing height")?;
+ let refresh = refresh
+ .map(str::parse)
+ .transpose()
+ .into_diagnostic()
+ .context("error parsing refresh rate")?;
+
+ Ok(Self {
+ width,
+ height,
+ refresh,
+ })
+ }
+}
+
impl FromStr for Key {
type Err = miette::Error;
@@ -377,6 +422,7 @@ mod tests {
output "eDP-1" {
scale 2.0
position x=10 y=20
+ mode "1920x1080@144"
}
spawn-at-startup "alacritty" "-e" "fish"
@@ -428,6 +474,11 @@ mod tests {
name: "eDP-1".to_owned(),
scale: 2.,
position: Some(Position { x: 10, y: 20 }),
+ mode: Some(Mode {
+ width: 1920,
+ height: 1080,
+ refresh: Some(144.),
+ }),
}],
spawn_at_startup: vec![SpawnAtStartup {
command: vec!["alacritty".to_owned(), "-e".to_owned(), "fish".to_owned()],
@@ -509,4 +560,30 @@ mod tests {
fn can_create_default_config() {
let _ = Config::default();
}
+
+ #[test]
+ fn parse_mode() {
+ assert_eq!(
+ "2560x1600@165.004".parse::<Mode>().unwrap(),
+ Mode {
+ width: 2560,
+ height: 1600,
+ refresh: Some(165.004),
+ },
+ );
+
+ assert_eq!(
+ "1920x1080".parse::<Mode>().unwrap(),
+ Mode {
+ width: 1920,
+ height: 1080,
+ refresh: None,
+ },
+ );
+
+ assert!("1920".parse::<Mode>().is_err());
+ assert!("1920x".parse::<Mode>().is_err());
+ assert!("1920x1080@".parse::<Mode>().is_err());
+ assert!("1920x1080@60Hz".parse::<Mode>().is_err());
+ }
}