diff --git a/docs/cli/named-workspace-container-padding.md b/docs/cli/named-workspace-container-padding.md new file mode 100644 index 00000000..e938ec60 --- /dev/null +++ b/docs/cli/named-workspace-container-padding.md @@ -0,0 +1,17 @@ +```text +Set the container padding for the specified workspace + +Usage: named-workspace-container-padding + +Arguments: + + Target workspace name + + + Pixels to pad with as an integer + +Options: + -h, --help + Print help + +``` diff --git a/docs/cli/named-workspace-padding.md b/docs/cli/named-workspace-padding.md new file mode 100644 index 00000000..dce5962a --- /dev/null +++ b/docs/cli/named-workspace-padding.md @@ -0,0 +1,17 @@ +```text +Set the workspace padding for the specified workspace + +Usage: named-workspace-padding + +Arguments: + + Target workspace name + + + Pixels to pad with as an integer + +Options: + -h, --help + Print help + +``` diff --git a/docs/dev/ARCHITECTURE.md b/docs/dev/ARCHITECTURE.md index 07dc1607..d5a8442e 100644 --- a/docs/dev/ARCHITECTURE.md +++ b/docs/dev/ARCHITECTURE.md @@ -405,13 +405,15 @@ focused is in no container of the focused workspace ([`WindowManager::handle_unmanaged_window_behaviour`]). `WorkspacePadding`, `ContainerPadding` and their `FocusedWorkspace` forms set a workspace's own -padding, and `AdjustWorkspacePadding` and `AdjustContainerPadding` change the focused -workspace's by a number of pixels, which needs a padding of its own to change -([`WindowManager::adjust_workspace_padding`]). `WorkAreaOffset`, `MonitorWorkAreaOffset` and -`WorkspaceWorkAreaOffset` set the offset of the window manager, of a monitor or of a workspace, -and `ToggleWindowBasedWorkAreaOffset` sets whether the focused workspace takes its monitor's -window-based offset ([`Workspace::apply_window_based_work_area_offset`]). Each tiles the -workspace in front again, or every monitor. +padding, and `NamedWorkspacePadding` and `NamedWorkspaceContainerPadding` do the same for the +workspace with a name, which they look up like `NamedWorkspaceLayout` does +([`WindowManager::monitor_workspace_index_by_name`]). `AdjustWorkspacePadding` and +`AdjustContainerPadding` change the focused workspace's by a number of pixels, which needs a padding +of its own to change ([`WindowManager::adjust_workspace_padding`]). `WorkAreaOffset`, +`MonitorWorkAreaOffset` and `WorkspaceWorkAreaOffset` set the offset of the window manager, of a +monitor or of a workspace, and `ToggleWindowBasedWorkAreaOffset` sets whether the focused workspace +takes its monitor's window-based offset ([`Workspace::apply_window_based_work_area_offset`]). Each +tiles the workspace in front again, or every monitor. `ResizeWindowEdge` and `ResizeWindowAxis` resize the focused container ([`WindowManager::resize_window`]). A resize is an adjustment of the container's tile, kept in diff --git a/docs/usage/padding-and-offsets.md b/docs/usage/padding-and-offsets.md index a058c9a6..77e1cdd2 100644 --- a/docs/usage/padding-and-offsets.md +++ b/docs/usage/padding-and-offsets.md @@ -21,11 +21,18 @@ set the paddings of the focused workspace, and [`komorebic container-padding`](../cli/container-padding.md) those of a workspace given by the index of its monitor and its own, counted from 0. +[`komorebic named-workspace-padding`](../cli/named-workspace-padding.md) and +[`komorebic named-workspace-container-padding`](../cli/named-workspace-container-padding.md) find +the workspace by the [name](workspaces.md#names) it was given instead, on whichever monitor has +it. A name no workspace has changes nothing. + ```sh komorebic focused-workspace-padding 20 komorebic focused-workspace-container-padding 10 komorebic workspace-padding 0 1 0 komorebic container-padding 0 1 0 +komorebic named-workspace-padding mail 0 +komorebic named-workspace-container-padding mail 0 ``` [`komorebic adjust-workspace-padding`](../cli/adjust-workspace-padding.md) and diff --git a/komorebi/src/core/mod.rs b/komorebi/src/core/mod.rs index f33eae60..2e6b1622 100644 --- a/komorebi/src/core/mod.rs +++ b/komorebi/src/core/mod.rs @@ -419,8 +419,10 @@ pub enum SocketMessage { FocusMonitorWorkspaceNumber(usize, usize), FocusNamedWorkspace(String), ContainerPadding(usize, usize, i32), + NamedWorkspaceContainerPadding(String, i32), FocusedWorkspaceContainerPadding(i32), WorkspacePadding(usize, usize, i32), + NamedWorkspacePadding(String, i32), FocusedWorkspacePadding(i32), WorkspaceTiling(usize, usize, bool), NamedWorkspaceTiling(String, bool), diff --git a/komorebi/src/process_command.rs b/komorebi/src/process_command.rs index 08b3624a..5e242d99 100644 --- a/komorebi/src/process_command.rs +++ b/komorebi/src/process_command.rs @@ -53,10 +53,12 @@ //! workspace, which komorebi does not move, or puts a floating window back //! ([`WindowManager::toggle_float`]). //! - **WorkspacePadding** and **ContainerPadding** set the paddings of a workspace given by the -//! index of its monitor and its own, **FocusedWorkspacePadding** and -//! **FocusedWorkspaceContainerPadding** those of the focused workspace, and -//! **AdjustWorkspacePadding** and **AdjustContainerPadding** make the focused workspace's larger -//! or smaller ([`WindowManager::set_workspace_padding`], +//! index of its monitor and its own, **NamedWorkspacePadding** and +//! **NamedWorkspaceContainerPadding** those of the workspace with a name +//! ([`WindowManager::monitor_workspace_index_by_name`]; a name no workspace has changes +//! nothing), **FocusedWorkspacePadding** and **FocusedWorkspaceContainerPadding** those of the +//! focused workspace, and **AdjustWorkspacePadding** and **AdjustContainerPadding** make the +//! focused workspace's larger or smaller ([`WindowManager::set_workspace_padding`], //! [`WindowManager::set_container_padding`], [`WindowManager::adjust_workspace_padding`], //! [`WindowManager::adjust_container_padding`]). //! - **WorkAreaOffset**, **MonitorWorkAreaOffset** and **WorkspaceWorkAreaOffset** set the work @@ -1140,9 +1142,23 @@ impl WindowManager { SocketMessage::ContainerPadding(monitor_idx, workspace_idx, size) => { self.set_container_padding(monitor_idx, workspace_idx, size)?; } + SocketMessage::NamedWorkspaceContainerPadding(ref workspace, size) => { + if let Some((monitor_idx, workspace_idx)) = + self.monitor_workspace_index_by_name(workspace) + { + self.set_container_padding(monitor_idx, workspace_idx, size)?; + } + } SocketMessage::WorkspacePadding(monitor_idx, workspace_idx, size) => { self.set_workspace_padding(monitor_idx, workspace_idx, size)?; } + SocketMessage::NamedWorkspacePadding(ref workspace, size) => { + if let Some((monitor_idx, workspace_idx)) = + self.monitor_workspace_index_by_name(workspace) + { + self.set_workspace_padding(monitor_idx, workspace_idx, size)?; + } + } SocketMessage::FocusedWorkspaceContainerPadding(adjustment) => { let focused_monitor_idx = self.focused_monitor_idx(); diff --git a/komorebi/tests/padding.rs b/komorebi/tests/padding.rs index 92c5c936..3abf9d4f 100644 --- a/komorebi/tests/padding.rs +++ b/komorebi/tests/padding.rs @@ -88,6 +88,17 @@ fn one_window_without_padding(id: u32) -> (Arc, WindowManager) { (fake, wm) } +/// The workspace padding and the container padding each workspace of the focused monitor has of +/// its own +fn paddings(wm: &WindowManager) -> Vec<(Option, Option)> { + wm.focused_monitor() + .unwrap() + .workspaces() + .iter() + .map(|workspace| (workspace.workspace_padding, workspace.container_padding)) + .collect() +} + #[test] fn the_paddings_of_the_focused_workspace_are_set_and_adjusted() { let (fake, mut wm) = desktop_with(&[28_001]); @@ -156,6 +167,63 @@ fn the_paddings_of_a_workspace_are_set_by_its_indices() { ); } +#[test] +fn the_paddings_of_a_workspace_are_set_by_its_name_and_a_name_nobody_has_changes_nothing() { + let (fake, mut wm) = desktop_with(&[28_041]); + send( + &fake, + &mut wm, + SocketMessage::EnsureNamedWorkspaces(0, vec![String::from("main"), String::from("side")]), + ) + .unwrap(); + + // the workspace in front is tiled again at once + send( + &fake, + &mut wm, + SocketMessage::NamedWorkspacePadding(String::from("main"), 20), + ) + .unwrap(); + assert_eq!(fake.rect_of(28_041), Some(rect(25, 25, 1870, 1000))); + send( + &fake, + &mut wm, + SocketMessage::NamedWorkspaceContainerPadding(String::from("main"), 0), + ) + .unwrap(); + assert_eq!(fake.rect_of(28_041), Some(rect(20, 20, 1880, 1010))); + + // another workspace takes its own paddings, and the one in front keeps its tile + send( + &fake, + &mut wm, + SocketMessage::NamedWorkspacePadding(String::from("side"), 7), + ) + .unwrap(); + send( + &fake, + &mut wm, + SocketMessage::NamedWorkspaceContainerPadding(String::from("side"), 3), + ) + .unwrap(); + assert_eq!(fake.rect_of(28_041), Some(rect(20, 20, 1880, 1010))); + assert_eq!(paddings(&wm), [(Some(20), Some(0)), (Some(7), Some(3))]); + + send( + &fake, + &mut wm, + SocketMessage::NamedWorkspacePadding(String::from("nowhere"), 99), + ) + .unwrap(); + send( + &fake, + &mut wm, + SocketMessage::NamedWorkspaceContainerPadding(String::from("nowhere"), 99), + ) + .unwrap(); + assert_eq!(paddings(&wm), [(Some(20), Some(0)), (Some(7), Some(3))]); +} + #[test] fn the_workspaces_offset_wins_over_the_monitors_which_wins_over_the_global_one() { let (fake, mut wm) = one_window_without_padding(28_021); diff --git a/komorebic/src/main.rs b/komorebic/src/main.rs index 08a85caf..082a3529 100644 --- a/komorebic/src/main.rs +++ b/komorebic/src/main.rs @@ -47,10 +47,11 @@ //! `cross-monitor-move-behaviour` and `toggle-cross-monitor-move-behaviour` set what `move` does //! at the edge of a monitor, and `display-index-preference` gives a monitor an index. //! `eager-focus` focuses the first window of an executable, on any workspace of any monitor. -//! - `workspace-name` names a workspace, which `focus-named-workspace`, `named-workspace-layout` -//! and `named-workspace-tiling` find by its name; `workspace-layout` and `workspace-tiling` set -//! the layout and the tiling of a workspace by its index, and `ensure-workspaces` and -//! `ensure-named-workspaces` give a monitor workspaces up to a number, or with names. +//! - `workspace-name` names a workspace, which `focus-named-workspace`, `named-workspace-layout`, +//! `named-workspace-tiling`, `named-workspace-padding` and `named-workspace-container-padding` +//! find by its name; `workspace-layout` and `workspace-tiling` set the layout and the tiling of +//! a workspace by its index, and `ensure-workspaces` and `ensure-named-workspaces` give a +//! monitor workspaces up to a number, or with names. //! //! `ignore-rule` and `manage-rule` add a rule that keeps an application out of the layout or //! always in it, `session-float-rule` floats the focused window and every window like it until the @@ -297,6 +298,27 @@ gen_padding_subcommand_args! { WorkspacePadding, } +macro_rules! gen_named_padding_subcommand_args { + // SubCommand Pattern + ( $( $name:ident ),+ $(,)? ) => { + $( + #[derive(clap::Parser)] + pub struct $name { + /// Target workspace name + workspace: String, + + /// Pixels to pad with as an integer + size: i32, + } + )+ + }; +} + +gen_named_padding_subcommand_args! { + NamedWorkspaceContainerPadding, + NamedWorkspacePadding, +} + macro_rules! gen_padding_adjustment_subcommand_args { // SubCommand Pattern ( $( $name:ident ),+ $(,)? ) => { @@ -773,9 +795,15 @@ enum SubCommand { /// Set the container padding for the specified workspace #[clap(arg_required_else_help = true)] ContainerPadding(ContainerPadding), + /// Set the container padding for the specified workspace + #[clap(arg_required_else_help = true)] + NamedWorkspaceContainerPadding(NamedWorkspaceContainerPadding), /// Set the workspace padding for the specified workspace #[clap(arg_required_else_help = true)] WorkspacePadding(WorkspacePadding), + /// Set the workspace padding for the specified workspace + #[clap(arg_required_else_help = true)] + NamedWorkspacePadding(NamedWorkspacePadding), /// Set the layout for the specified workspace #[clap(arg_required_else_help = true)] WorkspaceLayout(WorkspaceLayout), @@ -1223,6 +1251,12 @@ fn main() -> eyre::Result<()> { args.size, ))?; } + SubCommand::NamedWorkspaceContainerPadding(args) => { + send_message(&SocketMessage::NamedWorkspaceContainerPadding( + args.workspace, + args.size, + ))?; + } SubCommand::WorkspacePadding(args) => { send_message(&SocketMessage::WorkspacePadding( args.monitor, @@ -1230,6 +1264,12 @@ fn main() -> eyre::Result<()> { args.size, ))?; } + SubCommand::NamedWorkspacePadding(args) => { + send_message(&SocketMessage::NamedWorkspacePadding( + args.workspace, + args.size, + ))?; + } SubCommand::FocusedWorkspacePadding(args) => { send_message(&SocketMessage::FocusedWorkspacePadding(args.size))?; } diff --git a/komorebic/tests/cli.rs b/komorebic/tests/cli.rs index 747317dc..e2ce00c2 100644 --- a/komorebic/tests/cli.rs +++ b/komorebic/tests/cli.rs @@ -315,6 +315,14 @@ fn the_padding_subcommands_send_the_workspace_and_the_pixels_they_are_given() { &["container-padding", "1", "0", "8"], r#"{"type":"ContainerPadding","content":[1,0,8]}"#, ); + sends( + &["named-workspace-padding", "mail", "12"], + r#"{"type":"NamedWorkspacePadding","content":["mail",12]}"#, + ); + sends( + &["named-workspace-container-padding", "mail", "8"], + r#"{"type":"NamedWorkspaceContainerPadding","content":["mail",8]}"#, + ); sends( &["adjust-workspace-padding", "increase", "5"], r#"{"type":"AdjustWorkspacePadding","content":["Increase",5]}"#, @@ -689,7 +697,9 @@ fn docgen_writes_the_help_of_every_subcommand_in_a_text_fence() { "move-to-workspace.md", "move-workspace-to-monitor.md", "move.md", + "named-workspace-container-padding.md", "named-workspace-layout.md", + "named-workspace-padding.md", "named-workspace-tiling.md", "new-workspace.md", "preselect-direction.md", diff --git a/nix/tests/vm/suites/commands/test.py b/nix/tests/vm/suites/commands/test.py index d2d3a711..64960b8a 100644 --- a/nix/tests/vm/suites/commands/test.py +++ b/nix/tests/vm/suites/commands/test.py @@ -278,6 +278,10 @@ container-padding 0 0 12 container-padding 0 0 10 workspace-padding 0 0 12 workspace-padding 0 0 10 +named-workspace-container-padding one 12 +named-workspace-container-padding one 10 +named-workspace-padding one 12 +named-workspace-padding one 10 cross-monitor-move-behaviour insert cross-monitor-move-behaviour swap toggle-cross-monitor-move-behaviour