From ab3f1d3fa0656be2a8c46c53f22dd61418124b78 Mon Sep 17 00:00:00 2001 From: Lars Berger Date: Wed, 31 Jul 2024 01:52:13 +0800 Subject: [PATCH] feat: sort workspaces by config index --- .../wm/src/common/commands/reload_config.rs | 15 +++++++++++++++ .../wm/src/monitors/commands/remove_monitor.rs | 7 ++----- packages/wm/src/monitors/monitor.rs | 8 ++++++++ packages/wm/src/user_config.rs | 17 +++++++++++++++++ packages/wm/src/wm_state.rs | 16 ++++------------ .../workspaces/commands/activate_workspace.rs | 17 +++++++++++++++-- 6 files changed, 61 insertions(+), 19 deletions(-) diff --git a/packages/wm/src/common/commands/reload_config.rs b/packages/wm/src/common/commands/reload_config.rs index be50ab30a..501da2212 100644 --- a/packages/wm/src/common/commands/reload_config.rs +++ b/packages/wm/src/common/commands/reload_config.rs @@ -2,6 +2,7 @@ use anyhow::Context; use tracing::{info, warn}; use crate::{ + common::vec_deque_ext::VecDequeExt, containers::traits::{CommonGetters, TilingSizeGetters}, user_config::{ParsedConfig, UserConfig, WindowRuleEvent}, windows::{commands::run_window_rules, traits::WindowGetters}, @@ -92,6 +93,20 @@ fn update_workspace_configs( if *workspace_config != workspace.config() { workspace.set_config(workspace_config.clone()); + let mut workspaces = monitor.workspaces(); + config.sort_workspaces(&mut workspaces); + + let target_index = workspaces + .iter() + .position(|sorted_workspace| { + sorted_workspace.id() == workspace.id() + }) + .context("Failed to get workspace target index.")?; + + monitor + .borrow_children_mut() + .shift_to_index(target_index, workspace.clone().into()); + state.emit_event(WmEvent::WorkspaceUpdated { updated_workspace: workspace.to_dto()?, }); diff --git a/packages/wm/src/monitors/commands/remove_monitor.rs b/packages/wm/src/monitors/commands/remove_monitor.rs index ebca19445..ee1e7c731 100644 --- a/packages/wm/src/monitors/commands/remove_monitor.rs +++ b/packages/wm/src/monitors/commands/remove_monitor.rs @@ -31,11 +31,8 @@ pub fn remove_monitor( .context("No target monitor to move workspaces.")?; // Avoid moving empty workspaces. - let workspaces_to_move = monitor - .children() - .into_iter() - .filter_map(|container| container.as_workspace().cloned()) - .filter(|workspace| { + let workspaces_to_move = + monitor.workspaces().into_iter().filter(|workspace| { workspace.has_children() || workspace.config().keep_alive }); diff --git a/packages/wm/src/monitors/monitor.rs b/packages/wm/src/monitors/monitor.rs index 445b86adf..89dfbad6d 100644 --- a/packages/wm/src/monitors/monitor.rs +++ b/packages/wm/src/monitors/monitor.rs @@ -81,6 +81,14 @@ impl Monitor { .and_then(|child| child.as_workspace().cloned()) } + pub fn workspaces(&self) -> Vec { + self + .children() + .into_iter() + .filter_map(|container| container.as_workspace().cloned()) + .collect::>() + } + /// Whether there is a difference in DPI between this monitor and the /// parent monitor of another container. pub fn has_dpi_difference( diff --git a/packages/wm/src/user_config.rs b/packages/wm/src/user_config.rs index fc1523deb..f1732ef52 100644 --- a/packages/wm/src/user_config.rs +++ b/packages/wm/src/user_config.rs @@ -309,6 +309,23 @@ impl UserConfig { .or(inactive_configs.first()) .cloned() } + + pub fn workspace_config_index( + &self, + workspace_name: &str, + ) -> Option { + self + .value + .workspaces + .iter() + .position(|config| config.name == workspace_name) + } + + pub fn sort_workspaces(&self, workspaces: &mut Vec) { + workspaces.sort_by_key(|workspace| { + self.workspace_config_index(&workspace.config().name) + }); + } } #[derive(Clone, Debug, Deserialize, Serialize)] diff --git a/packages/wm/src/wm_state.rs b/packages/wm/src/wm_state.rs index 2c9edf28c..60ebb973d 100644 --- a/packages/wm/src/wm_state.rs +++ b/packages/wm/src/wm_state.rs @@ -154,7 +154,7 @@ impl WmState { .root_container .children() .iter() - .filter_map(|c| c.as_monitor().cloned()) + .filter_map(|container| container.as_monitor().cloned()) .collect() } @@ -162,22 +162,14 @@ impl WmState { self .monitors() .iter() - .flat_map(|c| c.children()) - .filter_map(|c| c.as_workspace().cloned()) + .flat_map(|monitor| monitor.workspaces()) .collect() } /// Gets workspaces sorted by their position in the user config. pub fn sorted_workspaces(&self, config: &UserConfig) -> Vec { - let workspace_configs = &config.value.workspaces; let mut workspaces = self.workspaces(); - - workspaces.sort_by_key(|workspace| { - workspace_configs - .iter() - .position(|config| config.name == workspace.config().name) - }); - + config.sort_workspaces(&mut workspaces); workspaces } @@ -210,7 +202,7 @@ impl WmState { self .monitors() .into_iter() - .find(|m| m.native() == *native_monitor) + .find(|monitor| monitor.native() == *native_monitor) } /// Gets the closest monitor in a given direction. diff --git a/packages/wm/src/workspaces/commands/activate_workspace.rs b/packages/wm/src/workspaces/commands/activate_workspace.rs index 14bc0c306..2d2be2ac1 100644 --- a/packages/wm/src/workspaces/commands/activate_workspace.rs +++ b/packages/wm/src/workspaces/commands/activate_workspace.rs @@ -2,7 +2,10 @@ use anyhow::Context; use crate::{ common::TilingDirection, - containers::{commands::attach_container, traits::PositionGetters}, + containers::{ + commands::attach_container, + traits::{CommonGetters, PositionGetters}, + }, monitors::Monitor, user_config::{UserConfig, WorkspaceConfig}, wm_event::WmEvent, @@ -36,11 +39,21 @@ pub fn activate_workspace( tiling_direction, ); + // Get the existing workspaces + the new workspace, and sort them. + let mut workspaces = target_monitor.workspaces(); + workspaces.extend([workspace.clone()]); + config.sort_workspaces(&mut workspaces); + + let target_index = workspaces + .iter() + .position(|sorted_workspace| sorted_workspace.id() == workspace.id()) + .context("Failed to get workspace target index.")?; + // Attach the created workspace to the specified monitor. attach_container( &workspace.clone().into(), &target_monitor.clone().into(), - None, + Some(target_index), )?; state.emit_event(WmEvent::WorkspaceActivated {