[WIP, incomplete] Port config to TOML

This commit is contained in:
Ivan Molodetskikh
2024-01-07 08:02:40 +04:00
parent 0a54db6b93
commit a4adf56b49
9 changed files with 469 additions and 451 deletions

316
Cargo.lock generated
View File

@@ -30,12 +30,6 @@ dependencies = [
"memchr",
]
[[package]]
name = "allocator-api2"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
[[package]]
name = "android-activity"
version = "0.5.1"
@@ -63,6 +57,21 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04"
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "anstream"
version = "0.6.5"
@@ -552,12 +561,16 @@ dependencies = [
]
[[package]]
name = "chumsky"
version = "0.9.3"
name = "chrono"
version = "0.4.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eebd66744a15ded14960ab4ccdbfb51ad3b81f51f3f04a80adac98c985396c9"
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
dependencies = [
"hashbrown",
"android-tzdata",
"iana-time-zone",
"num-traits",
"serde",
"windows-targets 0.48.5",
]
[[package]]
@@ -734,6 +747,41 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991"
[[package]]
name = "darling"
version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 2.0.48",
]
[[package]]
name = "darling_macro"
version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
dependencies = [
"darling_core",
"quote",
"syn 2.0.48",
]
[[package]]
name = "deranged"
version = "0.3.11"
@@ -741,6 +789,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
"powerfmt",
"serde",
]
[[package]]
@@ -1196,24 +1245,23 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
dependencies = [
"ahash",
"allocator-api2",
]
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hermit-abi"
@@ -1227,6 +1275,29 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "iana-time-zone"
version = "0.1.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "icrate"
version = "0.0.4"
@@ -1238,6 +1309,12 @@ dependencies = [
"objc2",
]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
version = "0.5.0"
@@ -1248,6 +1325,17 @@ dependencies = [
"unicode-normalization",
]
[[package]]
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown 0.12.3",
"serde",
]
[[package]]
name = "indexmap"
version = "2.1.0"
@@ -1255,7 +1343,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
dependencies = [
"equivalent",
"hashbrown",
"hashbrown 0.14.3",
"serde",
]
[[package]]
@@ -1306,6 +1395,12 @@ version = "2.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a611371471e98973dbcab4e0ec66c31a10bc356eeb4d54a0e05eac8158fe38c"
[[package]]
name = "itoa"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "jni"
version = "0.21.1"
@@ -1361,33 +1456,6 @@ version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
[[package]]
name = "knuffel"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04bee6ddc6071011314b1ce4f7705fef6c009401dba4fd22cb0009db6a177413"
dependencies = [
"base64",
"chumsky",
"knuffel-derive",
"miette",
"thiserror",
"unicode-width",
]
[[package]]
name = "knuffel-derive"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91977f56c49cfb961e3d840e2e7c6e4a56bde7283898cf606861f1421348283d"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
@@ -1622,29 +1690,6 @@ dependencies = [
"autocfg",
]
[[package]]
name = "miette"
version = "5.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e"
dependencies = [
"miette-derive",
"once_cell",
"thiserror",
"unicode-width",
]
[[package]]
name = "miette-derive"
version = "5.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
@@ -1704,11 +1749,9 @@ dependencies = [
"directories",
"git-version",
"keyframe",
"knuffel",
"libc",
"log",
"logind-zbus",
"miette",
"notify-rust",
"pipewire",
"png",
@@ -1718,8 +1761,10 @@ dependencies = [
"proptest-derive",
"sd-notify",
"serde",
"serde_with",
"smithay",
"smithay-drm-extras",
"toml",
"tracing",
"tracing-subscriber",
"tracy-client",
@@ -1799,7 +1844,7 @@ version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e"
dependencies = [
"proc-macro-crate 2.0.1",
"proc-macro-crate 2.0.0",
"proc-macro2",
"quote",
"syn 2.0.48",
@@ -2041,36 +2086,11 @@ dependencies = [
[[package]]
name = "proc-macro-crate"
version = "2.0.1"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a"
checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8"
dependencies = [
"toml_datetime",
"toml_edit 0.20.2",
]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn 1.0.109",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
"toml_edit 0.20.7",
]
[[package]]
@@ -2326,6 +2346,12 @@ dependencies = [
"wait-timeout",
]
[[package]]
name = "ryu"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
[[package]]
name = "same-file"
version = "1.0.6"
@@ -2373,6 +2399,17 @@ dependencies = [
"syn 2.0.48",
]
[[package]]
name = "serde_json"
version = "1.0.111"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_repr"
version = "0.1.18"
@@ -2393,6 +2430,35 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_with"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23"
dependencies = [
"base64",
"chrono",
"hex",
"indexmap 1.9.3",
"indexmap 2.1.0",
"serde",
"serde_json",
"serde_with_macros",
"time",
]
[[package]]
name = "serde_with_macros"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]]
name = "sha1"
version = "0.10.6"
@@ -2467,7 +2533,7 @@ dependencies = [
"errno",
"gbm",
"gl_generator",
"indexmap",
"indexmap 2.1.0",
"input",
"lazy_static",
"libc",
@@ -2661,9 +2727,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e"
dependencies = [
"deranged",
"itoa",
"powerfmt",
"serde",
"time-core",
"time-macros",
]
[[package]]
@@ -2672,6 +2740,15 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f"
dependencies = [
"time-core",
]
[[package]]
name = "tinyvec"
version = "1.6.0"
@@ -2689,21 +2766,21 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "toml"
version = "0.8.2"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d"
checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit 0.20.2",
"toml_edit 0.21.0",
]
[[package]]
name = "toml_datetime"
version = "0.6.3"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
dependencies = [
"serde",
]
@@ -2714,18 +2791,29 @@ version = "0.19.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
dependencies = [
"indexmap",
"indexmap 2.1.0",
"toml_datetime",
"winnow",
]
[[package]]
name = "toml_edit"
version = "0.20.2"
version = "0.20.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338"
checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81"
dependencies = [
"indexmap",
"indexmap 2.1.0",
"toml_datetime",
"winnow",
]
[[package]]
name = "toml_edit"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03"
dependencies = [
"indexmap 2.1.0",
"serde",
"serde_spanned",
"toml_datetime",
@@ -2886,12 +2974,6 @@ version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
[[package]]
name = "unicode-width"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
[[package]]
name = "url"
version = "2.5.0"
@@ -3500,9 +3582,9 @@ dependencies = [
[[package]]
name = "winnow"
version = "0.5.32"
version = "0.5.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8434aeec7b290e8da5c3f0d628cb0eac6cabcb31d14bb74f779a08109a5914d6"
checksum = "b7520bbdec7211caa7c4e682eb1fbe07abe20cee6756b6e00f537c82c11816aa"
dependencies = [
"memchr",
]

View File

@@ -20,11 +20,9 @@ clap = { version = "4.4.13", features = ["derive"] }
directories = "5.0.1"
git-version = "0.3.9"
keyframe = { version = "1.1.1", default-features = false }
knuffel = "3.2.0"
libc = "0.2.151"
logind-zbus = { version = "3.1.2", optional = true }
log = { version = "0.4.20", features = ["max_level_trace", "release_max_level_debug"] }
miette = "5.10.0"
notify-rust = { version = "4.10.0", optional = true }
pipewire = { version = "0.7.2", optional = true }
png = "0.17.10"
@@ -32,6 +30,8 @@ portable-atomic = { version = "1.6.0", default-features = false, features = ["fl
profiling = "1.0.13"
sd-notify = "0.4.1"
serde = { version = "1.0.195", features = ["derive"] }
serde_with = "3.4.0"
toml = { version = "0.8.8", default-features = false, features = ["parse"] }
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
tracing = { version = "0.1.40", features = ["max_level_trace", "release_max_level_debug"] }
tracy-client = { version = "0.16.5", default-features = false }

View File

@@ -595,9 +595,8 @@ impl Tty {
let config = self
.config
.borrow()
.outputs
.iter()
.find(|o| o.name == output_name)
.output
.get(&output_name)
.cloned()
.unwrap_or_default();

View File

@@ -41,9 +41,8 @@ impl Winit {
let output_config = config
.borrow()
.outputs
.iter()
.find(|o| o.name == "winit")
.output
.get("winit")
.cloned()
.unwrap_or_default();

View File

@@ -1,86 +1,104 @@
use std::collections::HashMap;
use std::path::PathBuf;
use std::str::FromStr;
use anyhow::{bail, Context};
use bitflags::bitflags;
use directories::ProjectDirs;
use miette::{miette, Context, IntoDiagnostic};
use serde::Deserialize;
use serde_with::DeserializeFromStr;
use smithay::input::keyboard::keysyms::KEY_NoSymbol;
use smithay::input::keyboard::xkb::{keysym_from_name, KEYSYM_CASE_INSENSITIVE};
use smithay::input::keyboard::{Keysym, XkbConfig};
#[derive(knuffel::Decode, Debug, PartialEq)]
#[derive(Deserialize, Debug, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct Config {
#[knuffel(child, default)]
#[serde(default)]
pub input: Input,
#[knuffel(children(name = "output"))]
pub outputs: Vec<Output>,
#[knuffel(child, default)]
#[serde(default)]
pub output: HashMap<String, Output>,
#[serde(default)]
pub layout: Layout,
#[knuffel(child, default)]
#[serde(default)]
pub clients: Clients,
#[knuffel(child, default)]
#[serde(default)]
pub cursor: Cursor,
#[knuffel(child, default)]
#[serde(default)]
pub screenshot_ui: ScreenshotUi,
#[knuffel(child, default)]
pub binds: Binds,
#[knuffel(child, default)]
// Running niri without binds doesn't make much sense.
pub binds: HashMap<Key, Action>,
#[serde(default)]
pub debug: DebugConfig,
}
// FIXME: Add other devices.
#[derive(knuffel::Decode, Debug, Default, PartialEq)]
#[derive(Deserialize, Debug, Default, PartialEq)]
#[serde(deny_unknown_fields, default)]
pub struct Input {
#[knuffel(child, default)]
pub keyboard: Keyboard,
#[knuffel(child, default)]
pub touchpad: Touchpad,
#[knuffel(child, default)]
pub tablet: Tablet,
#[knuffel(child)]
pub disable_power_key_handling: bool,
}
#[derive(knuffel::Decode, Debug, Default, PartialEq, Eq)]
#[derive(Deserialize, Debug, PartialEq, Eq)]
#[serde(deny_unknown_fields, default)]
pub struct Keyboard {
#[knuffel(child, default)]
pub xkb: Xkb,
// The defaults were chosen to match wlroots and sway.
#[knuffel(child, unwrap(argument), default = 600)]
pub repeat_delay: u16,
#[knuffel(child, unwrap(argument), default = 25)]
pub repeat_rate: u8,
#[knuffel(child, unwrap(argument), default)]
pub track_layout: TrackLayout,
}
#[derive(knuffel::Decode, Debug, Default, PartialEq, Eq, Clone)]
impl Default for Keyboard {
fn default() -> Self {
Self {
xkb: Default::default(),
// The defaults were chosen to match wlroots and sway.
repeat_delay: 600,
repeat_rate: 25,
track_layout: Default::default(),
}
}
}
#[derive(Deserialize, Debug, PartialEq, Eq, Clone)]
#[serde(deny_unknown_fields, default)]
pub struct Xkb {
#[knuffel(child, unwrap(argument), default)]
pub rules: String,
#[knuffel(child, unwrap(argument), default)]
pub model: String,
#[knuffel(child, unwrap(argument))]
pub layout: Option<String>,
#[knuffel(child, unwrap(argument), default)]
pub layout: String,
pub variant: String,
#[knuffel(child, unwrap(argument))]
pub options: Option<String>,
}
impl Default for Xkb {
fn default() -> Self {
Self {
rules: String::new(),
model: String::new(),
layout: String::from("us"),
variant: String::new(),
options: None,
}
}
}
impl Xkb {
pub fn to_xkb_config(&self) -> XkbConfig {
XkbConfig {
rules: &self.rules,
model: &self.model,
layout: self.layout.as_deref().unwrap_or("us"),
layout: &self.layout,
variant: &self.variant,
options: self.options.clone(),
}
}
}
#[derive(knuffel::DecodeScalar, Debug, Default, PartialEq, Eq)]
#[derive(Deserialize, Debug, Default, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum TrackLayout {
/// The layout change is global.
#[default]
@@ -90,33 +108,26 @@ pub enum TrackLayout {
}
// FIXME: Add the rest of the settings.
#[derive(knuffel::Decode, Debug, Default, PartialEq)]
#[derive(Deserialize, Debug, Default, PartialEq)]
#[serde(deny_unknown_fields, default)]
pub struct Touchpad {
#[knuffel(child)]
pub tap: bool,
#[knuffel(child)]
pub natural_scroll: bool,
#[knuffel(child, unwrap(argument), default)]
pub accel_speed: f64,
}
#[derive(knuffel::Decode, Debug, Default, PartialEq)]
#[derive(Deserialize, Debug, Default, PartialEq)]
#[serde(deny_unknown_fields, default)]
pub struct Tablet {
#[knuffel(child, unwrap(argument))]
pub map_to_output: Option<String>,
}
#[derive(knuffel::Decode, Debug, Clone, PartialEq)]
#[derive(Deserialize, Debug, Clone, PartialEq)]
#[serde(deny_unknown_fields, default)]
pub struct Output {
#[knuffel(child)]
pub off: bool,
#[knuffel(argument)]
pub name: String,
#[knuffel(child, unwrap(argument), default = 1.)]
pub scale: f64,
#[knuffel(child)]
pub position: Option<Position>,
#[knuffel(child, unwrap(argument, str))]
pub mode: Option<Mode>,
}
@@ -124,7 +135,6 @@ impl Default for Output {
fn default() -> Self {
Self {
off: false,
name: String::new(),
scale: 1.,
position: None,
mode: None,
@@ -132,52 +142,55 @@ impl Default for Output {
}
}
#[derive(knuffel::Decode, Debug, Clone, PartialEq, Eq)]
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct Position {
#[knuffel(property)]
pub x: i32,
#[knuffel(property)]
pub y: i32,
}
#[derive(Debug, Clone, PartialEq)]
#[derive(DeserializeFromStr, Debug, Clone, PartialEq)]
pub struct Mode {
pub width: u16,
pub height: u16,
pub refresh: Option<f64>,
}
#[derive(knuffel::Decode, Debug, Default, Clone, PartialEq)]
#[derive(Deserialize, Debug, Clone, PartialEq)]
#[serde(deny_unknown_fields, default)]
pub struct Layout {
#[knuffel(child, default)]
pub focus_ring: FocusRing,
#[knuffel(child, default = default_border())]
pub border: FocusRing,
#[knuffel(child, unwrap(children), default)]
pub preset_column_widths: Vec<PresetWidth>,
#[knuffel(child)]
pub default_column_width: Option<DefaultColumnWidth>,
#[knuffel(child, unwrap(argument), default = 16)]
// TODO
pub default_column_width: Option<PresetWidth>,
pub gaps: u16,
#[knuffel(child, default)]
pub struts: Struts,
}
#[derive(knuffel::Decode, Debug, Clone, PartialEq, Eq)]
pub struct SpawnAtStartup {
#[knuffel(arguments)]
pub command: Vec<String>,
impl Default for Layout {
fn default() -> Self {
Self {
focus_ring: Default::default(),
border: default_border(),
preset_column_widths: vec![
PresetWidth::Proportion(0.333),
PresetWidth::Proportion(0.5),
PresetWidth::Proportion(0.667),
],
default_column_width: Some(PresetWidth::Proportion(0.5)),
gaps: 16,
struts: Default::default(),
}
}
}
#[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)]
#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
#[serde(deny_unknown_fields, default)]
pub struct FocusRing {
#[knuffel(child)]
pub off: bool,
#[knuffel(child, unwrap(argument), default = 4)]
pub width: u16,
#[knuffel(child, default = Color::new(127, 200, 255, 255))]
pub active_color: Color,
#[knuffel(child, default = Color::new(80, 80, 80, 255))]
pub inactive_color: Color,
}
@@ -201,15 +214,12 @@ pub const fn default_border() -> FocusRing {
}
}
#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq, Eq)]
#[derive(Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
#[serde(from = "[u8; 4]")]
pub struct Color {
#[knuffel(argument)]
pub r: u8,
#[knuffel(argument)]
pub g: u8,
#[knuffel(argument)]
pub b: u8,
#[knuffel(argument)]
pub a: u8,
}
@@ -225,19 +235,30 @@ impl From<Color> for [f32; 4] {
}
}
#[derive(knuffel::Decode, Debug, Default, PartialEq, Eq)]
impl From<[u8; 4]> for Color {
fn from(value: [u8; 4]) -> Self {
let [r, g, b, a] = value;
Self { r, g, b, a }
}
}
#[derive(Deserialize, Debug, Default, PartialEq, Eq)]
#[serde(deny_unknown_fields, default)]
pub struct Clients {
#[knuffel(child, default)]
pub prefer_no_csd: bool,
#[knuffel(children(name = "spawn-at-startup"))]
pub spawn_at_startup: Vec<SpawnAtStartup>,
}
#[derive(knuffel::Decode, Debug, PartialEq)]
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct SpawnAtStartup {
pub command: Vec<String>,
}
#[derive(Deserialize, Debug, PartialEq)]
#[serde(deny_unknown_fields, default)]
pub struct Cursor {
#[knuffel(child, unwrap(argument), default = String::from("default"))]
pub xcursor_theme: String,
#[knuffel(child, unwrap(argument), default = 24)]
pub xcursor_size: u8,
}
@@ -250,38 +271,26 @@ impl Default for Cursor {
}
}
#[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)]
#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum PresetWidth {
Proportion(#[knuffel(argument)] f64),
Fixed(#[knuffel(argument)] i32),
Proportion(f64),
Fixed(i32),
}
#[derive(knuffel::Decode, Debug, Clone, PartialEq)]
pub struct DefaultColumnWidth(#[knuffel(children)] pub Vec<PresetWidth>);
#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq, Eq)]
#[derive(Deserialize, Debug, Default, Clone, Copy, PartialEq, Eq)]
#[serde(deny_unknown_fields, default)]
pub struct Struts {
#[knuffel(child, unwrap(argument), default)]
pub left: u16,
#[knuffel(child, unwrap(argument), default)]
pub right: u16,
#[knuffel(child, unwrap(argument), default)]
pub top: u16,
#[knuffel(child, unwrap(argument), default)]
pub bottom: u16,
}
#[derive(knuffel::Decode, Debug, PartialEq, Eq)]
#[derive(Deserialize, Debug, PartialEq, Eq)]
#[serde(deny_unknown_fields, default)]
pub struct ScreenshotUi {
#[knuffel(child)]
pub disable_saving_to_disk: bool,
#[knuffel(
child,
unwrap(argument),
default = String::from(
"~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png"
))
]
pub screenshot_path: String,
}
@@ -296,25 +305,14 @@ impl Default for ScreenshotUi {
}
}
#[derive(knuffel::Decode, Debug, Default, PartialEq)]
pub struct Binds(#[knuffel(children)] pub Vec<Bind>);
#[derive(knuffel::Decode, Debug, PartialEq)]
pub struct Bind {
#[knuffel(node_name)]
pub key: Key,
#[knuffel(children)]
pub actions: Vec<Action>,
}
#[derive(Debug, PartialEq, Eq)]
#[derive(DeserializeFromStr, Debug, PartialEq, Eq, Hash)]
pub struct Key {
pub keysym: Keysym,
pub modifiers: Modifiers,
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Modifiers : u8 {
const CTRL = 1;
const SHIFT = 2;
@@ -324,18 +322,19 @@ bitflags! {
}
}
#[derive(knuffel::Decode, Debug, Clone, PartialEq)]
#[derive(Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum Action {
Quit,
#[knuffel(skip)]
#[serde(skip)]
ChangeVt(i32),
Suspend,
PowerOffMonitors,
ToggleDebugTint,
Spawn(#[knuffel(arguments)] Vec<String>),
#[knuffel(skip)]
Spawn(Vec<String>),
#[serde(skip)]
ConfirmScreenshot,
#[knuffel(skip)]
#[serde(skip)]
CancelScreenshot,
Screenshot,
ScreenshotScreen,
@@ -363,10 +362,10 @@ pub enum Action {
CenterColumn,
FocusWorkspaceDown,
FocusWorkspaceUp,
FocusWorkspace(#[knuffel(argument)] u8),
FocusWorkspace(u8),
MoveWindowToWorkspaceDown,
MoveWindowToWorkspaceUp,
MoveWindowToWorkspace(#[knuffel(argument)] u8),
MoveWindowToWorkspace(u8),
MoveWorkspaceDown,
MoveWorkspaceUp,
FocusMonitorLeft,
@@ -377,14 +376,14 @@ pub enum Action {
MoveWindowToMonitorRight,
MoveWindowToMonitorDown,
MoveWindowToMonitorUp,
SetWindowHeight(#[knuffel(argument, str)] SizeChange),
SetWindowHeight(SizeChange),
SwitchPresetColumnWidth,
MaximizeColumn,
SetColumnWidth(#[knuffel(argument, str)] SizeChange),
SwitchLayout(#[knuffel(argument)] LayoutAction),
SetColumnWidth(SizeChange),
SwitchLayout(LayoutAction),
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[derive(DeserializeFromStr, Debug, Clone, Copy, PartialEq)]
pub enum SizeChange {
SetFixed(i32),
SetProportion(f64),
@@ -392,27 +391,22 @@ pub enum SizeChange {
AdjustProportion(f64),
}
#[derive(knuffel::DecodeScalar, Debug, Clone, Copy, PartialEq)]
#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum LayoutAction {
Next,
Prev,
}
#[derive(knuffel::Decode, Debug, PartialEq)]
#[derive(Deserialize, Debug, PartialEq)]
#[serde(deny_unknown_fields, default)]
pub struct DebugConfig {
#[knuffel(child, unwrap(argument), default = 1.)]
pub animation_slowdown: f64,
#[knuffel(child)]
pub dbus_interfaces_in_non_session_instances: bool,
#[knuffel(child)]
pub wait_for_frame_completion_before_queueing: bool,
#[knuffel(child)]
pub enable_color_transformations_capability: bool,
#[knuffel(child)]
pub enable_overlay_planes: bool,
#[knuffel(child)]
pub disable_cursor_plane: bool,
#[knuffel(child, unwrap(argument))]
pub render_drm_device: Option<PathBuf>,
}
@@ -431,67 +425,55 @@ impl Default for DebugConfig {
}
impl Config {
pub fn load(path: Option<PathBuf>) -> miette::Result<(Self, PathBuf)> {
pub fn load(path: Option<PathBuf>) -> anyhow::Result<(Self, PathBuf)> {
let path = if let Some(path) = path {
path
} else {
let mut path = ProjectDirs::from("", "", "niri")
.ok_or_else(|| miette!("error retrieving home directory"))?
.context("error retrieving home directory")?
.config_dir()
.to_owned();
path.push("config.kdl");
path
};
let contents = std::fs::read_to_string(&path)
.into_diagnostic()
.with_context(|| format!("error reading {path:?}"))?;
let contents =
std::fs::read_to_string(&path).with_context(|| format!("error reading {path:?}"))?;
let config = Self::parse("config.kdl", &contents).context("error parsing")?;
let config = Self::parse(&contents).context("error parsing")?;
debug!("loaded config from {path:?}");
Ok((config, path))
}
pub fn parse(filename: &str, text: &str) -> Result<Self, knuffel::Error> {
knuffel::parse(filename, text)
pub fn parse(text: &str) -> Result<Self, toml::de::Error> {
toml::from_str(text)
}
}
impl Default for Config {
fn default() -> Self {
Config::parse(
"default-config.kdl",
include_str!("../resources/default-config.kdl"),
)
.unwrap()
Config::parse(include_str!("../resources/default-config.kdl"))
.context("error parsing default config")
.unwrap()
}
}
impl FromStr for Mode {
type Err = miette::Error;
type Err = anyhow::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 (width, rest) = s.split_once('x').context("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 width = width.parse().context("error parsing width")?;
let height = height.parse().context("error parsing height")?;
let refresh = refresh
.map(str::parse)
.transpose()
.into_diagnostic()
.context("error parsing refresh rate")?;
Ok(Self {
@@ -503,7 +485,7 @@ impl FromStr for Mode {
}
impl FromStr for Key {
type Err = miette::Error;
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut modifiers = Modifiers::empty();
@@ -524,13 +506,13 @@ impl FromStr for Key {
} else if part.eq_ignore_ascii_case("super") || part.eq_ignore_ascii_case("win") {
modifiers |= Modifiers::SUPER;
} else {
return Err(miette!("invalid modifier: {part}"));
bail!("invalid modifier: {part}");
}
}
let keysym = keysym_from_name(key, KEYSYM_CASE_INSENSITIVE);
if keysym.raw() == KEY_NoSymbol {
return Err(miette!("invalid key: {key}"));
bail!("invalid key: {key}");
}
Ok(Key { keysym, modifiers })
@@ -538,51 +520,39 @@ impl FromStr for Key {
}
impl FromStr for SizeChange {
type Err = miette::Error;
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.split_once('%') {
Some((value, empty)) => {
if !empty.is_empty() {
return Err(miette!("trailing characters after '%' are not allowed"));
bail!("trailing characters after '%' are not allowed");
}
match value.bytes().next() {
Some(b'-' | b'+') => {
let value = value
.parse()
.into_diagnostic()
.context("error parsing value")?;
let value = value.parse().context("error parsing value")?;
Ok(Self::AdjustProportion(value))
}
Some(_) => {
let value = value
.parse()
.into_diagnostic()
.context("error parsing value")?;
let value = value.parse().context("error parsing value")?;
Ok(Self::SetProportion(value))
}
None => Err(miette!("value is missing")),
None => bail!("value is missing"),
}
}
None => {
let value = s;
match value.bytes().next() {
Some(b'-' | b'+') => {
let value = value
.parse()
.into_diagnostic()
.context("error parsing value")?;
let value = value.parse().context("error parsing value")?;
Ok(Self::AdjustFixed(value))
}
Some(_) => {
let value = value
.parse()
.into_diagnostic()
.context("error parsing value")?;
let value = value.parse().context("error parsing value")?;
Ok(Self::SetFixed(value))
}
None => Err(miette!("value is missing")),
None => bail!("value is missing"),
}
}
}
@@ -591,17 +561,11 @@ impl FromStr for SizeChange {
#[cfg(test)]
mod tests {
use miette::NarratableReportHandler;
use super::*;
#[track_caller]
fn check(text: &str, expected: Config) {
let _ = miette::set_hook(Box::new(|_| Box::new(NarratableReportHandler::new())));
let parsed = Config::parse("test.kdl", text)
.map_err(miette::Report::new)
.unwrap();
let parsed = Config::parse(text).map_err(anyhow::Error::new).unwrap();
assert_eq!(parsed, expected);
}
@@ -609,101 +573,80 @@ mod tests {
fn parse() {
check(
r#"
input {
keyboard {
repeat-delay 600
repeat-rate 25
track-layout "window"
xkb {
layout "us,ru"
options "grp:win_space_toggle"
}
}
[input]
disable_power_key_handling = true
touchpad {
tap
accel-speed 0.2
}
[input.keyboard]
repeat_delay = 600
repeat_rate = 25
track_layout = 'window'
xkb.layout = 'us,ru'
xkb.options = 'grp:win_space_toggle'
tablet {
map-to-output "eDP-1"
}
[input.touchpad]
tap = true
accel_speed = 0.2
disable-power-key-handling
}
[input.tablet]
map_to_output = 'eDP-1'
output "eDP-1" {
scale 2.0
position x=10 y=20
mode "1920x1080@144"
}
[output.'eDP-1']
scale = 2.0
position = { x = 10, y = 20 }
mode = '1920x1080@144'
layout {
focus-ring {
width 5
active-color 0 100 200 255
inactive-color 255 200 100 0
}
[layout]
gaps = 8
preset_column_widths = [
{ proportion = 0.25 },
{ proportion = 0.5 },
{ fixed = 960 },
{ fixed = 1280 },
]
default_column_width = { proportion = 0.25 }
struts = { left = 1, right = 2, top = 3 }
border {
width 3
active-color 0 100 200 255
inactive-color 255 200 100 0
}
[layout.focus_ring]
width = 5
active_color = [0, 100, 200, 255]
inactive_color = [255, 200, 100, 0]
preset-column-widths {
proportion 0.25
proportion 0.5
fixed 960
fixed 1280
}
[layout.border]
width = 3
active_color = [0, 100, 200, 255]
inactive_color = [255, 200, 100, 0]
default-column-width { proportion 0.25; }
[clients]
prefer_no_csd = true
spawn_at_startup = [
{ command = ['alacritty', '-e', 'fish'] },
]
gaps 8
[cursor]
xcursor_theme = 'breeze_cursors'
xcursor_size = 16
struts {
left 1
right 2
top 3
}
}
[screenshot_ui]
screenshot_path = '~/Screenshots/screenshot.png'
disable_saving_to_disk = true
clients {
prefer-no-csd
[binds]
'Mod+T' = { spawn = ['alacritty'] }
'Mod+Q' = 'close_window'
'Mod+Shift+H' = 'focus_monitor_left'
'Mod+Ctrl+Shift+L' = 'move_window_to_monitor_right'
'Mod+Comma' = 'consume_window_into_column'
'Mod+1' = { focus_workspace = 1 }
spawn-at-startup "alacritty" "-e" "fish"
}
cursor {
xcursor-theme "breeze_cursors"
xcursor-size 16
}
screenshot-ui {
screenshot-path "~/Screenshots/screenshot.png"
disable-saving-to-disk
}
binds {
Mod+T { spawn "alacritty"; }
Mod+Q { close-window; }
Mod+Shift+H { focus-monitor-left; }
Mod+Ctrl+Shift+L { move-window-to-monitor-right; }
Mod+Comma { consume-window-into-column; }
Mod+1 { focus-workspace 1;}
}
debug {
animation-slowdown 2.0
render-drm-device "/dev/dri/renderD129"
}
[debug]
animation_slowdown = 2.0
render_drm_device = '/dev/dri/renderD129'
"#,
Config {
input: Input {
keyboard: Keyboard {
xkb: Xkb {
layout: Some("us,ru".to_owned()),
layout: "us,ru".to_owned(),
options: Some("grp:win_space_toggle".to_owned()),
..Default::default()
},
@@ -721,17 +664,19 @@ mod tests {
},
disable_power_key_handling: true,
},
outputs: vec![Output {
off: false,
name: "eDP-1".to_owned(),
scale: 2.,
position: Some(Position { x: 10, y: 20 }),
mode: Some(Mode {
width: 1920,
height: 1080,
refresh: Some(144.),
}),
}],
output: HashMap::from([(
"eDP-1".to_owned(),
Output {
off: false,
scale: 2.,
position: Some(Position { x: 10, y: 20 }),
mode: Some(Mode {
width: 1920,
height: 1080,
refresh: Some(144.),
}),
},
)]),
layout: Layout {
focus_ring: FocusRing {
off: false,
@@ -771,9 +716,7 @@ mod tests {
PresetWidth::Fixed(960),
PresetWidth::Fixed(1280),
],
default_column_width: Some(DefaultColumnWidth(vec![PresetWidth::Proportion(
0.25,
)])),
default_column_width: Some(PresetWidth::Proportion(0.25)),
gaps: 8,
struts: Struts {
left: 1,
@@ -796,49 +739,49 @@ mod tests {
disable_saving_to_disk: true,
screenshot_path: String::from("~/Screenshots/screenshot.png"),
},
binds: Binds(vec![
Bind {
key: Key {
binds: HashMap::from([
(
Key {
keysym: Keysym::t,
modifiers: Modifiers::COMPOSITOR,
},
actions: vec![Action::Spawn(vec!["alacritty".to_owned()])],
},
Bind {
key: Key {
Action::Spawn(vec!["alacritty".to_owned()]),
),
(
Key {
keysym: Keysym::q,
modifiers: Modifiers::COMPOSITOR,
},
actions: vec![Action::CloseWindow],
},
Bind {
key: Key {
Action::CloseWindow,
),
(
Key {
keysym: Keysym::h,
modifiers: Modifiers::COMPOSITOR | Modifiers::SHIFT,
},
actions: vec![Action::FocusMonitorLeft],
},
Bind {
key: Key {
Action::FocusMonitorLeft,
),
(
Key {
keysym: Keysym::l,
modifiers: Modifiers::COMPOSITOR | Modifiers::SHIFT | Modifiers::CTRL,
},
actions: vec![Action::MoveWindowToMonitorRight],
},
Bind {
key: Key {
Action::MoveWindowToMonitorRight,
),
(
Key {
keysym: Keysym::comma,
modifiers: Modifiers::COMPOSITOR,
},
actions: vec![Action::ConsumeWindowIntoColumn],
},
Bind {
key: Key {
Action::ConsumeWindowIntoColumn,
),
(
Key {
keysym: Keysym::_1,
modifiers: Modifiers::COMPOSITOR,
},
actions: vec![Action::FocusWorkspace(1)],
},
Action::FocusWorkspace(1),
),
]),
debug: DebugConfig {
animation_slowdown: 2.,

View File

@@ -1,5 +1,5 @@
use std::any::Any;
use std::collections::HashSet;
use std::collections::{HashMap, HashSet};
use smithay::backend::input::{
AbsolutePositionEvent, Axis, AxisSource, ButtonState, Device, DeviceCapability, Event,
@@ -20,7 +20,7 @@ use smithay::utils::{Logical, Point, SERIAL_COUNTER};
use smithay::wayland::pointer_constraints::{with_pointer_constraint, PointerConstraint};
use smithay::wayland::tablet_manager::{TabletDescriptor, TabletSeatTrait};
use crate::config::{Action, Binds, LayoutAction, Modifiers};
use crate::config::{Action, Key, LayoutAction, Modifiers};
use crate::niri::State;
use crate::screenshot_ui::ScreenshotUi;
use crate::utils::{center, get_monotonic_time, spawn};
@@ -1179,7 +1179,7 @@ impl State {
#[allow(clippy::too_many_arguments)]
fn should_intercept_key(
suppressed_keys: &mut HashSet<u32>,
bindings: &Binds,
bindings: &HashMap<Key, Action>,
comp_mod: CompositorMod,
key_code: u32,
modified: Keysym,
@@ -1235,7 +1235,7 @@ fn should_intercept_key(
}
fn action(
bindings: &Binds,
bindings: &HashMap<Key, Action>,
comp_mod: CompositorMod,
modified: Keysym,
raw: Option<Keysym>,
@@ -1284,13 +1284,13 @@ fn action(
return None;
};
for bind in &bindings.0 {
if bind.key.keysym != raw {
for (key, action) in bindings {
if key.keysym != raw {
continue;
}
if bind.key.modifiers | comp_mod == modifiers {
return bind.actions.first().cloned();
if key.modifiers | comp_mod == modifiers {
return Some(action.clone());
}
}
@@ -1339,18 +1339,18 @@ fn allowed_during_screenshot(action: &Action) -> bool {
#[cfg(test)]
mod tests {
use super::*;
use crate::config::{Action, Bind, Binds, Key, Modifiers};
use crate::config::{Action, Key, Modifiers};
#[test]
fn bindings_suppress_keys() {
let close_keysym = Keysym::q;
let bindings = Binds(vec![Bind {
key: Key {
let bindings = HashMap::from([(
Key {
keysym: close_keysym,
modifiers: Modifiers::COMPOSITOR | Modifiers::CTRL,
},
actions: vec![Action::CloseWindow],
}]);
Action::CloseWindow,
)]);
let comp_mod = CompositorMod::Super;
let mut suppressed_keys = HashSet::new();

View File

@@ -181,8 +181,7 @@ impl Options {
// while present, but empty, maps to None.
let default_width = layout
.default_column_width
.as_ref()
.map(|w| w.0.first().copied().map(ColumnWidth::from))
.map(|w| Some(ColumnWidth::from(w))) // TODO
.unwrap_or(Some(ColumnWidth::Proportion(0.5)));
Self {

View File

@@ -27,12 +27,12 @@ use std::path::PathBuf;
use std::process::Command;
use std::{env, mem};
use anyhow::Context;
use clap::{Parser, Subcommand};
use config::Config;
#[cfg(not(feature = "xdp-gnome-screencast"))]
use dummy_pw_utils as pw_utils;
use git_version::git_version;
use miette::{Context, NarratableReportHandler};
use niri::{Niri, State};
use portable_atomic::Ordering;
use sd_notify::NotifyState;
@@ -109,9 +109,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let _client = tracy_client::Client::start();
// Set a better error printer for config loading.
miette::set_hook(Box::new(|_| Box::new(NarratableReportHandler::new()))).unwrap();
// Handle subcommands.
if let Some(subcommand) = cli.subcommand {
match subcommand {

View File

@@ -831,9 +831,8 @@ impl Niri {
let config = self
.config
.borrow()
.outputs
.iter()
.find(|o| o.name == name)
.output
.get(&name)
.cloned()
.unwrap_or_default();