diff --git a/packages/wm-common/src/app_command.rs b/packages/wm-common/src/app_command.rs index fd89077b..d39e1b85 100644 --- a/packages/wm-common/src/app_command.rs +++ b/packages/wm-common/src/app_command.rs @@ -167,6 +167,12 @@ pub enum InvokeCommand { }, Position(InvokePositionCommand), Resize(InvokeResizeCommand), + UpdateWorkspaceConfig { + #[clap(long, allow_hyphen_values = true)] + workspace: Option, + #[clap(flatten)] + new_config: InvokeUpdateWorkspaceConfig, + }, SetFloating { #[clap(long, default_missing_value = "true", require_equals = true, num_args = 0..=1)] shown_on_top: Option, @@ -411,3 +417,26 @@ pub struct InvokePositionCommand { #[clap(long, allow_hyphen_values = true)] pub y_pos: Option, } + +#[derive(Args, Clone, Debug, PartialEq, Serialize)] +#[group(required = true, multiple = true)] +pub struct InvokeUpdateWorkspaceConfig { + #[clap(long, allow_hyphen_values = true)] + pub name: Option, + + #[clap( + long, + allow_hyphen_values = true, + conflicts_with = "no_display_name" + )] + pub display_name: Option, + + #[clap(long, conflicts_with = "display_name")] + pub no_display_name: bool, + + #[clap(long)] + pub bind_to_monitor: Option, + + #[clap(long)] + pub keep_alive: Option, +} diff --git a/packages/wm/src/commands/workspace/mod.rs b/packages/wm/src/commands/workspace/mod.rs index c99e1709..60d6c4fb 100644 --- a/packages/wm/src/commands/workspace/mod.rs +++ b/packages/wm/src/commands/workspace/mod.rs @@ -2,10 +2,12 @@ mod activate_workspace; mod deactivate_workspace; mod focus_workspace; mod move_workspace_in_direction; +mod update_workspace_config; mod sort_workspaces; pub use activate_workspace::*; pub use deactivate_workspace::*; pub use focus_workspace::*; pub use move_workspace_in_direction::*; +pub use update_workspace_config::*; pub use sort_workspaces::*; diff --git a/packages/wm/src/commands/workspace/update_workspace_config.rs b/packages/wm/src/commands/workspace/update_workspace_config.rs new file mode 100644 index 00000000..28c4bb12 --- /dev/null +++ b/packages/wm/src/commands/workspace/update_workspace_config.rs @@ -0,0 +1,62 @@ +use anyhow::{bail, Context}; +use wm_common::{InvokeUpdateWorkspaceConfig, WmEvent, WorkspaceConfig}; + +use super::sort_workspaces; +use crate::{ + models::Workspace, traits::CommonGetters, user_config::UserConfig, + wm_state::WmState, +}; + +pub fn update_workspace_config( + workspace: &Workspace, + state: &WmState, + config: &UserConfig, + new_config: &InvokeUpdateWorkspaceConfig, +) -> anyhow::Result<()> { + let WorkspaceConfig { + mut name, + display_name, + bind_to_monitor, + keep_alive, + } = workspace.config(); + + let mut need_sort = false; + + // validate the workspace name change + if let Some(new_name) = &new_config.name { + if new_name != &name { + if let Some(_other_workspace) = state.workspace_by_name(new_name) { + bail!("The workspace \"{}\" already exists", new_name); + } + name.clone_from(new_name); + need_sort = true; + } + } + + // the updated config + let updated_config = WorkspaceConfig { + name, + display_name: if new_config.no_display_name { + None + } else { + new_config.display_name.clone().or(display_name) + }, + bind_to_monitor: new_config.bind_to_monitor.or(bind_to_monitor), + keep_alive: new_config.keep_alive.unwrap_or(keep_alive), + }; + + // Commit the change + workspace.set_config(updated_config); + + if need_sort { + let monitor = + workspace.monitor().context("No displayed workspace.")?; + sort_workspaces(&monitor, config)?; + } + + state.emit_event(WmEvent::WorkspaceUpdated { + updated_workspace: workspace.to_dto()?, + }); + + Ok(()) +} diff --git a/packages/wm/src/wm.rs b/packages/wm/src/wm.rs index fd4ada61..4d257e48 100644 --- a/packages/wm/src/wm.rs +++ b/packages/wm/src/wm.rs @@ -24,7 +24,10 @@ use crate::{ resize_window, set_window_position, set_window_size, update_window_state, WindowPositionTarget, }, - workspace::{focus_workspace, move_workspace_in_direction}, + workspace::{ + focus_workspace, move_workspace_in_direction, + update_workspace_config, + }, }, events::{ handle_display_settings_changed, handle_mouse_move, @@ -431,6 +434,19 @@ impl WindowManager { _ => Ok(()), } } + InvokeCommand::UpdateWorkspaceConfig { + workspace, + new_config, + } => { + let workspace = if let Some(workspace_name) = workspace { + state + .workspace_by_name(workspace_name) + .context("Workspace doesn't exist.")? + } else { + subject_container.workspace().context("No workspace.")? + }; + update_workspace_config(&workspace, state, config, new_config) + } InvokeCommand::Resize(args) => { match subject_container.as_window_container() { Ok(window) => resize_window(