From 11f351dbeb937a7de1de2f15b08c81f3682e423b Mon Sep 17 00:00:00 2001 From: FluxTape Date: Fri, 29 Nov 2024 06:46:13 +0100 Subject: Implement empty-workspace-above-first (#745) * Implement empty-workspace-above-first option * add two failing tests * fix interactive_move_onto_empty_output_ewaf and interactive_move_onto_first_empty_workspace tests * Add two failing ewaf option toggle tests * Fix adding/removing first empty workspace on option toggle * Don't remove first empty workspace if focused * Stop workspace switch when enabling ewaf * layout/monitor: Offset workspace switch on adding workspace above * Fix some initial active workspace ids with ewaf * wiki: Document empty-workspace-above-first --------- Co-authored-by: Ivan Molodetskikh --- src/layout/monitor.rs | 93 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 84 insertions(+), 9 deletions(-) (limited to 'src/layout/monitor.rs') diff --git a/src/layout/monitor.rs b/src/layout/monitor.rs index 52e73cce..b2afb9e3 100644 --- a/src/layout/monitor.rs +++ b/src/layout/monitor.rs @@ -86,6 +86,20 @@ impl WorkspaceSwitch { } } + pub fn offset(&mut self, delta: isize) { + match self { + WorkspaceSwitch::Animation(anim) => anim.offset(delta as f64), + WorkspaceSwitch::Gesture(gesture) => { + if delta >= 0 { + gesture.center_idx += delta as usize; + } else { + gesture.center_idx -= (-delta) as usize; + } + gesture.current_idx += delta as f64; + } + } + } + /// Returns `true` if the workspace switch is [`Animation`]. /// /// [`Animation`]: WorkspaceSwitch::Animation @@ -158,6 +172,20 @@ impl Monitor { self.windows().any(|win| win.id() == window) } + pub fn add_workspace_top(&mut self) { + let ws = Workspace::new( + self.output.clone(), + self.clock.clone(), + self.options.clone(), + ); + self.workspaces.insert(0, ws); + self.active_workspace_idx += 1; + + if let Some(switch) = &mut self.workspace_switch { + switch.offset(1); + } + } + pub fn add_workspace_bottom(&mut self) { let ws = Workspace::new( self.output.clone(), @@ -194,7 +222,7 @@ impl Monitor { pub fn add_window( &mut self, - workspace_idx: usize, + mut workspace_idx: usize, window: W, activate: bool, width: ColumnWidth, @@ -208,10 +236,14 @@ impl Monitor { workspace.original_output = OutputId::new(&self.output); if workspace_idx == self.workspaces.len() - 1 { - // Insert a new empty workspace. self.add_workspace_bottom(); } + if self.options.empty_workspace_above_first && workspace_idx == 0 { + self.add_workspace_top(); + workspace_idx += 1; + } + if activate { self.activate_workspace(workspace_idx); } @@ -240,7 +272,7 @@ impl Monitor { // cannot be the last one, so we never need to insert a new empty workspace. } - pub fn add_column(&mut self, workspace_idx: usize, column: Column, activate: bool) { + pub fn add_column(&mut self, mut workspace_idx: usize, column: Column, activate: bool) { let workspace = &mut self.workspaces[workspace_idx]; workspace.add_column(None, column, activate, None); @@ -249,9 +281,12 @@ impl Monitor { workspace.original_output = OutputId::new(&self.output); if workspace_idx == self.workspaces.len() - 1 { - // Insert a new empty workspace. self.add_workspace_bottom(); } + if self.options.empty_workspace_above_first && workspace_idx == 0 { + self.add_workspace_top(); + workspace_idx += 1; + } if activate { self.activate_workspace(workspace_idx); @@ -260,7 +295,7 @@ impl Monitor { pub fn add_tile( &mut self, - workspace_idx: usize, + mut workspace_idx: usize, column_idx: Option, tile: Tile, activate: bool, @@ -279,6 +314,11 @@ impl Monitor { self.add_workspace_bottom(); } + if self.options.empty_workspace_above_first && workspace_idx == 0 { + self.add_workspace_top(); + workspace_idx += 1; + } + if activate { self.activate_workspace(workspace_idx); } @@ -310,18 +350,32 @@ impl Monitor { pub fn clean_up_workspaces(&mut self) { assert!(self.workspace_switch.is_none()); - for idx in (0..self.workspaces.len() - 1).rev() { + let range_start = if self.options.empty_workspace_above_first { + 1 + } else { + 0 + }; + for idx in (range_start..self.workspaces.len() - 1).rev() { if self.active_workspace_idx == idx { continue; } - if !self.workspaces[idx].has_windows() && self.workspaces[idx].name.is_none() { + if !self.workspaces[idx].has_windows_or_name() { self.workspaces.remove(idx); if self.active_workspace_idx > idx { self.active_workspace_idx -= 1; } } } + + // Special case handling when empty_workspace_above_first is set and all workspaces + // are empty. + if self.options.empty_workspace_above_first && self.workspaces.len() == 2 { + assert!(!self.workspaces[0].has_windows_or_name()); + assert!(!self.workspaces[1].has_windows_or_name()); + self.workspaces.remove(1); + self.active_workspace_idx = 0; + } } pub fn unname_workspace(&mut self, workspace_name: &str) -> bool { @@ -792,6 +846,17 @@ impl Monitor { } pub fn update_config(&mut self, options: Rc) { + if self.options.empty_workspace_above_first != options.empty_workspace_above_first + && self.workspaces.len() > 1 + { + if options.empty_workspace_above_first { + self.add_workspace_top(); + } else if self.workspace_switch.is_none() && self.active_workspace_idx != 0 { + self.workspaces.remove(0); + self.active_workspace_idx = self.active_workspace_idx.saturating_sub(1); + } + } + for ws in &mut self.workspaces { ws.update_config(options.clone()); } @@ -823,7 +888,7 @@ impl Monitor { } pub fn move_workspace_down(&mut self) { - let new_idx = min(self.active_workspace_idx + 1, self.workspaces.len() - 1); + let mut new_idx = min(self.active_workspace_idx + 1, self.workspaces.len() - 1); if new_idx == self.active_workspace_idx { return; } @@ -835,6 +900,11 @@ impl Monitor { self.add_workspace_bottom(); } + if self.options.empty_workspace_above_first && self.active_workspace_idx == 0 { + self.add_workspace_top(); + new_idx += 1; + } + let previous_workspace_id = self.previous_workspace_id; self.activate_workspace(new_idx); self.workspace_switch = None; @@ -844,7 +914,7 @@ impl Monitor { } pub fn move_workspace_up(&mut self) { - let new_idx = self.active_workspace_idx.saturating_sub(1); + let mut new_idx = self.active_workspace_idx.saturating_sub(1); if new_idx == self.active_workspace_idx { return; } @@ -856,6 +926,11 @@ impl Monitor { self.add_workspace_bottom(); } + if self.options.empty_workspace_above_first && new_idx == 0 { + self.add_workspace_top(); + new_idx += 1; + } + let previous_workspace_id = self.previous_workspace_id; self.activate_workspace(new_idx); self.workspace_switch = None; -- cgit