mirror of
https://github.com/elkowar/eww.git
synced 2024-10-05 15:40:12 +03:00
Improve flexibility of monitor configuration (#1003)
* Allow named monitors on wayland * Allow list of monitor matchers
This commit is contained in:
parent
fff40ce1a7
commit
4f1f853b5f
@ -20,6 +20,8 @@ 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 `<primary>`
|
||||
- Add support for multiple matchers in `monitor` field
|
||||
|
||||
## [0.4.0] (04.09.2022)
|
||||
|
||||
|
@ -560,31 +560,16 @@ fn get_monitor_geometry(identifier: Option<MonitorIdentifier>) -> Result<gdk::Re
|
||||
let monitor = match identifier {
|
||||
Some(ident) => {
|
||||
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());
|
||||
}
|
||||
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)
|
||||
}
|
||||
})?
|
||||
}
|
||||
}
|
||||
format!("{}{}", head, body)
|
||||
})?
|
||||
}
|
||||
None => display
|
||||
.primary_monitor()
|
||||
@ -597,12 +582,16 @@ fn get_monitor_geometry(identifier: Option<MonitorIdentifier>) -> Result<gdk::Re
|
||||
/// Outside of x11, only [MonitorIdentifier::Numeric] is supported
|
||||
pub fn get_monitor_from_display(display: &gdk::Display, identifier: &MonitorIdentifier) -> Option<gdk::Monitor> {
|
||||
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),
|
||||
|
||||
#[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()) {
|
||||
|
@ -5,8 +5,10 @@ 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<MonitorIdentifier>),
|
||||
Numeric(i32),
|
||||
Name(String),
|
||||
Primary,
|
||||
}
|
||||
|
||||
impl MonitorIdentifier {
|
||||
@ -18,8 +20,10 @@ 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::<Vec<_>>().join(" ")),
|
||||
Self::Numeric(n) => write!(f, "{}", n),
|
||||
Self::Name(n) => write!(f, "{}", n),
|
||||
Self::Primary => write!(f, "<primary>"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -30,7 +34,13 @@ impl str::FromStr for MonitorIdentifier {
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s.parse::<i32>() {
|
||||
Ok(n) => Ok(Self::Numeric(n)),
|
||||
Err(_) => Ok(Self::Name(s.to_owned())),
|
||||
Err(_) => {
|
||||
if &s.to_lowercase() == "<primary>" {
|
||||
Ok(Self::Primary)
|
||||
} else {
|
||||
Ok(Self::Name(s.to_owned()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<Self> {
|
||||
match x {
|
||||
Ast::Array(_, x) => Ok(Self::List(x.into_iter().map(MonitorIdentifier::from_ast).collect::<DiagResult<_>>()?)),
|
||||
other => Ok(Self::from_str(&String::from_ast(other)?).unwrap()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromAstElementContent for WindowDefinition {
|
||||
const ELEMENT_NAME: &'static str = "defwindow";
|
||||
|
||||
fn from_tail<I: Iterator<Item = Ast>>(_span: Span, mut iter: AstIterator<I>) -> DiagResult<Self> {
|
||||
let (_, name) = iter.expect_symbol()?;
|
||||
let mut attrs = iter.expect_key_values()?;
|
||||
let monitor = attrs.primitive_optional("monitor")?;
|
||||
let monitor = attrs.ast_optional::<MonitorIdentifier>("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")?;
|
||||
|
@ -71,6 +71,8 @@ impl Ast {
|
||||
|
||||
as_func!(AstType::List, as_list as_list_ref<Vec<Ast>> = Ast::List(_, x) => x);
|
||||
|
||||
as_func!(AstType::Array, as_array as_array_ref<Vec<Ast>> = Ast::Array(_, x) => x);
|
||||
|
||||
pub fn expr_type(&self) -> AstType {
|
||||
match self {
|
||||
Ast::List(..) => AstType::List,
|
||||
|
@ -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 `<primary>`, 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: `["<primary>" "HDMI-A-1" "PHL 345B1C" 0]`. Eww will try to find a match in order, allowing you to specify fallbacks.
|
||||
|
||||
|
||||
**`geometry`-properties**
|
||||
|
||||
| Property | Description |
|
||||
|
Loading…
Reference in New Issue
Block a user