diff --git a/crates/komorebi-core/src/workspace.rs b/crates/komorebi-core/src/workspace.rs index a91a2eaa..6863d74b 100644 --- a/crates/komorebi-core/src/workspace.rs +++ b/crates/komorebi-core/src/workspace.rs @@ -150,9 +150,11 @@ pub trait WorkspacePlatform: Sized + Clone + std::fmt::Debug + PartialEq + 'stat /// Tells the scrolling layout that the container at `idx` is about to leave the workspace. fn note_scrolling_departure(workspace: &Workspace, idx: usize); - /// Called after a floating window was taken out of the workspace; KDE refocuses a floating - /// window, Windows does nothing. - fn after_floating_removed(_workspace: &mut Workspace) {} + /// Called by [`Workspace::remove_floating_window`] before the floating window is taken out of the + /// workspace, while it is still in the ring: KDE and macOS move the focus to the previous + /// floating window first (the focus index moves back by one whatever the length), Windows does + /// nothing. + fn before_floating_removed(_workspace: &mut Workspace) {} /// The index at which [`Workspace::promote_container`] inserts the container: the primary /// position of the layout. The default layouts have it first. @@ -1161,7 +1163,7 @@ impl Workspace

{ None => None, Some(idx) => { if self.floating_windows().get(idx).is_some() { - P::after_floating_removed(self); + P::before_floating_removed(self); self.floating_windows_mut().remove(idx) } else { None @@ -1985,6 +1987,13 @@ mod tests { fn note_scrolling_departure(_: &Workspace, _: usize) {} + fn before_floating_removed(workspace: &mut Workspace) { + LOG.with(|log| { + log.borrow_mut() + .push(format!("floating {}", workspace.floating_windows().len())) + }); + } + fn begin_update(_: &mut Workspace) -> eyre::Result { LOG.with(|log| log.borrow_mut().push("begin".to_string())); Ok(Flow::Run(None)) @@ -2089,6 +2098,20 @@ mod tests { assert_eq!(workspace.resize_dimensions.len(), 2); } + #[test] + fn the_hook_for_a_removed_floating_window_runs_before_the_removal() { + let mut workspace = Workspace::::default(); + workspace.floating_windows_mut().push_back(W(1)); + workspace.floating_windows_mut().push_back(W(2)); + log(); + + assert_eq!(workspace.remove_floating_window(2), Some(W(2))); + + // the ring still had both windows when the hook ran: the focus moves first + assert_eq!(log(), ["floating 2"]); + assert_eq!(workspace.floating_windows().len(), 1); + } + #[test] fn promoting_a_container_puts_it_first_and_focuses_it() { let mut workspace = workspace_of(&[1, 2, 3]); diff --git a/komorebi-for-kde/komorebi/src/workspace.rs b/komorebi-for-kde/komorebi/src/workspace.rs index 228fabd1..751aea0d 100644 --- a/komorebi-for-kde/komorebi/src/workspace.rs +++ b/komorebi-for-kde/komorebi/src/workspace.rs @@ -119,7 +119,7 @@ impl komorebi_core::WorkspacePlatform for KdePlatform { workspace.note_scrolling_departure(idx); } - fn after_floating_removed(workspace: &mut Workspace) { + fn before_floating_removed(workspace: &mut Workspace) { workspace.focus_previous_floating_window(); } diff --git a/komorebi-for-mac/komorebi/src/workspace.rs b/komorebi-for-mac/komorebi/src/workspace.rs index 4845a177..bdacfb6c 100644 --- a/komorebi-for-mac/komorebi/src/workspace.rs +++ b/komorebi-for-mac/komorebi/src/workspace.rs @@ -143,7 +143,7 @@ impl komorebi_core::WorkspacePlatform for MacosPlatform { workspace.note_scrolling_departure(idx); } - fn after_floating_removed(workspace: &mut Workspace) { + fn before_floating_removed(workspace: &mut Workspace) { workspace.focus_previous_floating_window(); } }