aboutsummaryrefslogtreecommitdiff
path: root/niri-config/src
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2025-09-20 09:37:52 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2025-10-02 09:33:08 +0300
commitd5f4e79e4c35d4f5a7a4a64e85e72fb1545ef2db (patch)
tree4f5d4a299c1e8305aa147f326ac2b5c98de2873e /niri-config/src
parentd015c7e55bf455698cc4115af39549d9c8e20efc (diff)
downloadniri-d5f4e79e4c35d4f5a7a4a64e85e72fb1545ef2db.tar.gz
niri-d5f4e79e4c35d4f5a7a4a64e85e72fb1545ef2db.tar.bz2
niri-d5f4e79e4c35d4f5a7a4a64e85e72fb1545ef2db.zip
Add per-workspace layout config
Per-workspace background-color doesn't work yet.
Diffstat (limited to 'niri-config/src')
-rw-r--r--niri-config/src/lib.rs5
-rw-r--r--niri-config/src/workspace.rs36
2 files changed, 39 insertions, 2 deletions
diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs
index 6dd32620..e969b250 100644
--- a/niri-config/src/lib.rs
+++ b/niri-config/src/lib.rs
@@ -38,7 +38,7 @@ pub use crate::output::{Output, OutputName, Outputs, Position, Vrr};
pub use crate::utils::FloatOrInt;
use crate::utils::MergeWith as _;
pub use crate::window_rule::{FloatingPosition, RelativeTo, WindowRule};
-pub use crate::workspace::Workspace;
+pub use crate::workspace::{Workspace, WorkspaceLayoutPart};
#[derive(knuffel::Decode, Debug, PartialEq)]
pub struct Config {
@@ -1795,18 +1795,21 @@ mod tests {
open_on_output: Some(
"eDP-1",
),
+ layout: None,
},
Workspace {
name: WorkspaceName(
"workspace-2",
),
open_on_output: None,
+ layout: None,
},
Workspace {
name: WorkspaceName(
"workspace-3",
),
open_on_output: None,
+ layout: None,
},
],
}
diff --git a/niri-config/src/workspace.rs b/niri-config/src/workspace.rs
index e502bdb7..d34dcf46 100644
--- a/niri-config/src/workspace.rs
+++ b/niri-config/src/workspace.rs
@@ -1,16 +1,50 @@
use knuffel::errors::DecodeError;
-#[derive(knuffel::Decode, Debug, Clone, PartialEq, Eq)]
+use crate::LayoutPart;
+
+#[derive(knuffel::Decode, Debug, Clone, PartialEq)]
pub struct Workspace {
#[knuffel(argument)]
pub name: WorkspaceName,
#[knuffel(child, unwrap(argument))]
pub open_on_output: Option<String>,
+ #[knuffel(child)]
+ pub layout: Option<WorkspaceLayoutPart>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WorkspaceName(pub String);
+#[derive(Debug, Clone, PartialEq)]
+pub struct WorkspaceLayoutPart(pub LayoutPart);
+
+impl<S: knuffel::traits::ErrorSpan> knuffel::Decode<S> for WorkspaceLayoutPart {
+ fn decode_node(
+ node: &knuffel::ast::SpannedNode<S>,
+ ctx: &mut knuffel::decode::Context<S>,
+ ) -> Result<Self, DecodeError<S>> {
+ for child in node.children() {
+ let name = &**child.node_name;
+
+ // Check for disallowed properties.
+ //
+ // - empty-workspace-above-first is a monitor-level concept.
+ // - insert-hint customization could make sense for workspaces, however currently it is
+ // also handled at the monitor level (since insert hints in-between workspaces are a
+ // monitor-level concept), so for now this config option would do nothing.
+ if matches!(name, "empty-workspace-above-first" | "insert-hint") {
+ ctx.emit_error(DecodeError::unexpected(
+ child,
+ "node",
+ format!("node `{name}` is not allowed inside `workspace.layout`"),
+ ));
+ }
+ }
+
+ LayoutPart::decode_node(node, ctx).map(Self)
+ }
+}
+
impl<S: knuffel::traits::ErrorSpan> knuffel::DecodeScalar<S> for WorkspaceName {
fn type_check(
type_name: &Option<knuffel::span::Spanned<knuffel::ast::TypeName, S>>,