From 85550cc6d3ca69b0fcb5878ef83df270194c6205 Mon Sep 17 00:00:00 2001 From: ElKowar <5300871+elkowar@users.noreply.github.com> Date: Wed, 20 Dec 2023 15:28:18 +0100 Subject: [PATCH 1/2] Allow named monitors on wayland --- CHANGELOG.md | 1 + crates/eww/src/app.rs | 39 ++++++++----------------------- crates/yuck/src/config/monitor.rs | 10 +++++++- 3 files changed, 20 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b8ad175..fbc6c7e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ All notable changes to eww will be listed here, starting at changes since versio - Add trigonometric functions (`sin`, `cos`, `tan`, `cot`) and degree/radian conversions (`degtorad`, `radtodeg`) (By: end-4) - Add `substring` function to simplexpr - Add `--duration` flag to `eww open` +- Add support for referring to monitor with `` ## [0.4.0] (04.09.2022) diff --git a/crates/eww/src/app.rs b/crates/eww/src/app.rs index 3b306be7..42b65d01 100644 --- a/crates/eww/src/app.rs +++ b/crates/eww/src/app.rs @@ -560,31 +560,16 @@ fn get_monitor_geometry(identifier: Option) -> Result { let mon = get_monitor_from_display(&display, &ident); - - #[cfg(feature = "x11")] - { - mon.with_context(|| { - let head = format!("Failed to get monitor {}\nThe available monitors are:", ident); - let mut body = String::new(); - for m in 0..display.n_monitors() { - if let Some(model) = display.monitor(m).and_then(|x| x.model()) { - body.push_str(format!("\n\t[{}] {}", m, model).as_str()); - } - } - format!("{}{}", head, body) - })? - } - - #[cfg(not(feature = "x11"))] - { - mon.with_context(|| { - if ident.is_numeric() { - format!("Failed to get monitor {}", ident) - } else { - format!("Using ouput names (\"{}\" in the configuration) is not supported outside of x11 yet", ident) + mon.with_context(|| { + let head = format!("Failed to get monitor {}\nThe available monitors are:", ident); + let mut body = String::new(); + for m in 0..display.n_monitors() { + if let Some(model) = display.monitor(m).and_then(|x| x.model()) { + body.push_str(format!("\n\t[{}] {}", m, model).as_str()); } - })? - } + } + format!("{}{}", head, body) + })? } None => display .primary_monitor() @@ -597,12 +582,8 @@ fn get_monitor_geometry(identifier: Option) -> Result Option { match identifier { + MonitorIdentifier::Primary => display.primary_monitor(), MonitorIdentifier::Numeric(num) => display.monitor(*num), - - #[cfg(not(feature = "x11"))] - MonitorIdentifier::Name(_) => return None, - - #[cfg(feature = "x11")] MonitorIdentifier::Name(name) => { for m in 0..display.n_monitors() { if let Some(model) = display.monitor(m).and_then(|x| x.model()) { diff --git a/crates/yuck/src/config/monitor.rs b/crates/yuck/src/config/monitor.rs index 53d6a393..e023096a 100644 --- a/crates/yuck/src/config/monitor.rs +++ b/crates/yuck/src/config/monitor.rs @@ -7,6 +7,7 @@ use serde::{Deserialize, Serialize}; pub enum MonitorIdentifier { Numeric(i32), Name(String), + Primary, } impl MonitorIdentifier { @@ -20,6 +21,7 @@ impl fmt::Display for MonitorIdentifier { match self { Self::Numeric(n) => write!(f, "{}", n), Self::Name(n) => write!(f, "{}", n), + Self::Primary => write!(f, ""), } } } @@ -30,7 +32,13 @@ impl str::FromStr for MonitorIdentifier { fn from_str(s: &str) -> Result { match s.parse::() { Ok(n) => Ok(Self::Numeric(n)), - Err(_) => Ok(Self::Name(s.to_owned())), + Err(_) => { + if &s.to_lowercase() == "" { + Ok(Self::Primary) + } else { + Ok(Self::Name(s.to_owned())) + } + } } } } From 73403027905bc5a06954bff598e305cce4547120 Mon Sep 17 00:00:00 2001 From: elkowar <5300871+elkowar@users.noreply.github.com> Date: Wed, 20 Dec 2023 15:49:02 +0100 Subject: [PATCH 2/2] Allow list of monitor matchers --- CHANGELOG.md | 1 + crates/eww/src/app.rs | 8 ++++++++ crates/yuck/src/config/monitor.rs | 2 ++ crates/yuck/src/config/window_definition.rs | 13 +++++++++++-- crates/yuck/src/parser/ast.rs | 2 ++ docs/src/configuration.md | 12 +++++++++++- 6 files changed, 35 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbc6c7e7..f93a74ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to eww will be listed here, starting at changes since versio - Add `substring` function to simplexpr - Add `--duration` flag to `eww open` - Add support for referring to monitor with `` +- Add support for multiple matchers in `monitor` field ## [0.4.0] (04.09.2022) diff --git a/crates/eww/src/app.rs b/crates/eww/src/app.rs index 42b65d01..57cf1b1b 100644 --- a/crates/eww/src/app.rs +++ b/crates/eww/src/app.rs @@ -582,6 +582,14 @@ fn get_monitor_geometry(identifier: Option) -> Result Option { match identifier { + MonitorIdentifier::List(list) => { + for ident in list { + if let Some(monitor) = get_monitor_from_display(display, ident) { + return Some(monitor); + } + } + None + } MonitorIdentifier::Primary => display.primary_monitor(), MonitorIdentifier::Numeric(num) => display.monitor(*num), MonitorIdentifier::Name(name) => { diff --git a/crates/yuck/src/config/monitor.rs b/crates/yuck/src/config/monitor.rs index e023096a..a6432912 100644 --- a/crates/yuck/src/config/monitor.rs +++ b/crates/yuck/src/config/monitor.rs @@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize}; /// The type of the identifier used to select a monitor #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum MonitorIdentifier { + List(Vec), Numeric(i32), Name(String), Primary, @@ -19,6 +20,7 @@ impl MonitorIdentifier { impl fmt::Display for MonitorIdentifier { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { + Self::List(l) => write!(f, "[{}]", l.iter().map(|x| x.to_string()).collect::>().join(" ")), Self::Numeric(n) => write!(f, "{}", n), Self::Name(n) => write!(f, "{}", n), Self::Primary => write!(f, ""), diff --git a/crates/yuck/src/config/window_definition.rs b/crates/yuck/src/config/window_definition.rs index afe3fd52..f62ed364 100644 --- a/crates/yuck/src/config/window_definition.rs +++ b/crates/yuck/src/config/window_definition.rs @@ -1,4 +1,4 @@ -use std::fmt::Display; +use std::{fmt::Display, str::FromStr}; use crate::{ config::monitor::MonitorIdentifier, @@ -24,13 +24,22 @@ pub struct WindowDefinition { pub backend_options: BackendWindowOptions, } +impl FromAst for MonitorIdentifier { + fn from_ast(x: Ast) -> DiagResult { + match x { + Ast::Array(_, x) => Ok(Self::List(x.into_iter().map(MonitorIdentifier::from_ast).collect::>()?)), + other => Ok(Self::from_str(&String::from_ast(other)?).unwrap()), + } + } +} + impl FromAstElementContent for WindowDefinition { const ELEMENT_NAME: &'static str = "defwindow"; fn from_tail>(_span: Span, mut iter: AstIterator) -> DiagResult { let (_, name) = iter.expect_symbol()?; let mut attrs = iter.expect_key_values()?; - let monitor = attrs.primitive_optional("monitor")?; + let monitor = attrs.ast_optional::("monitor")?; let resizable = attrs.primitive_optional("resizable")?.unwrap_or(true); let stacking = attrs.primitive_optional("stacking")?.unwrap_or(WindowStacking::Foreground); let geometry = attrs.ast_optional("geometry")?; diff --git a/crates/yuck/src/parser/ast.rs b/crates/yuck/src/parser/ast.rs index d80d208f..5a901299 100644 --- a/crates/yuck/src/parser/ast.rs +++ b/crates/yuck/src/parser/ast.rs @@ -71,6 +71,8 @@ impl Ast { as_func!(AstType::List, as_list as_list_ref> = Ast::List(_, x) => x); + as_func!(AstType::Array, as_array as_array_ref> = Ast::Array(_, x) => x); + pub fn expr_type(&self) -> AstType { match self { Ast::List(..) => AstType::List, diff --git a/docs/src/configuration.md b/docs/src/configuration.md index af7397e8..975099b5 100644 --- a/docs/src/configuration.md +++ b/docs/src/configuration.md @@ -50,10 +50,20 @@ You can now open your first window by running `eww open example`! Glorious! | Property | Description | | ---------: | ------------------------------------------------------------ | -| `monitor` | Which monitor this window should be displayed on. Can be either a number (X11 and Wayland) or an output name (X11 only). | +| `monitor` | Which monitor this window should be displayed on. See below for details.| | `geometry` | Geometry of the window. | +**`monitor`-property** + +This field can be: + +- the string ``, in which case eww tries to identify the primary display (which may fail, especially on wayland) +- an integer, declaring the monitor index +- the name of the monitor +- an array of monitor matchers, such as: `["" "HDMI-A-1" "PHL 345B1C" 0]`. Eww will try to find a match in order, allowing you to specify fallbacks. + + **`geometry`-properties** | Property | Description |