diff --git a/komorebi/src/monitor.rs b/komorebi/src/monitor.rs index 090fe7ee..5e40467e 100644 --- a/komorebi/src/monitor.rs +++ b/komorebi/src/monitor.rs @@ -20,6 +20,7 @@ use crate::workspace::Workspace; use crate::DefaultLayout; use crate::Layout; use crate::OperationDirection; +use crate::WindowsApi; #[derive( Debug, @@ -178,66 +179,90 @@ impl Monitor { bail!("cannot move native maximized window to another monitor or workspace"); } - let container = workspace - .remove_focused_container() - .ok_or_else(|| anyhow!("there is no container"))?; + let foreground_hwnd = WindowsApi::foreground_window()?; + let floating_window_index = workspace + .floating_windows() + .iter() + .position(|w| w.hwnd == foreground_hwnd); - let workspaces = self.workspaces_mut(); + if let Some(idx) = floating_window_index { + let window = workspace.floating_windows_mut().remove(idx); - #[allow(clippy::option_if_let_else)] - let target_workspace = match workspaces.get_mut(target_workspace_idx) { - None => { - workspaces.resize(target_workspace_idx + 1, Workspace::default()); - workspaces.get_mut(target_workspace_idx).unwrap() - } - Some(workspace) => workspace, - }; - - match direction { - Some(OperationDirection::Left) => match target_workspace.layout() { - Layout::Default(layout) => match layout { - DefaultLayout::RightMainVerticalStack => { - target_workspace.add_container_to_front(container); - } - DefaultLayout::UltrawideVerticalStack => { - if target_workspace.containers().len() == 1 { - target_workspace.insert_container_at_idx(0, container); - } else { - target_workspace.add_container_to_back(container); - } - } - _ => { - target_workspace.add_container_to_back(container); - } - }, - Layout::Custom(_) => { - target_workspace.add_container_to_back(container); + let workspaces = self.workspaces_mut(); + #[allow(clippy::option_if_let_else)] + let target_workspace = match workspaces.get_mut(target_workspace_idx) { + None => { + workspaces.resize(target_workspace_idx + 1, Workspace::default()); + workspaces.get_mut(target_workspace_idx).unwrap() } - }, - Some(OperationDirection::Right) => match target_workspace.layout() { - Layout::Default(layout) => { - let target_index = layout.leftmost_index(target_workspace.containers().len()); + Some(workspace) => workspace, + }; - match layout { - DefaultLayout::RightMainVerticalStack - | DefaultLayout::UltrawideVerticalStack => { + target_workspace.floating_windows_mut().push(window); + } else { + let container = workspace + .remove_focused_container() + .ok_or_else(|| anyhow!("there is no container"))?; + + let workspaces = self.workspaces_mut(); + + #[allow(clippy::option_if_let_else)] + let target_workspace = match workspaces.get_mut(target_workspace_idx) { + None => { + workspaces.resize(target_workspace_idx + 1, Workspace::default()); + workspaces.get_mut(target_workspace_idx).unwrap() + } + Some(workspace) => workspace, + }; + + match direction { + Some(OperationDirection::Left) => match target_workspace.layout() { + Layout::Default(layout) => match layout { + DefaultLayout::RightMainVerticalStack => { + target_workspace.add_container_to_front(container); + } + DefaultLayout::UltrawideVerticalStack => { if target_workspace.containers().len() == 1 { - target_workspace.add_container_to_back(container); + target_workspace.insert_container_at_idx(0, container); } else { - target_workspace.insert_container_at_idx(target_index, container); + target_workspace.add_container_to_back(container); } } _ => { - target_workspace.insert_container_at_idx(target_index, container); + target_workspace.add_container_to_back(container); + } + }, + Layout::Custom(_) => { + target_workspace.add_container_to_back(container); + } + }, + Some(OperationDirection::Right) => match target_workspace.layout() { + Layout::Default(layout) => { + let target_index = + layout.leftmost_index(target_workspace.containers().len()); + + match layout { + DefaultLayout::RightMainVerticalStack + | DefaultLayout::UltrawideVerticalStack => { + if target_workspace.containers().len() == 1 { + target_workspace.add_container_to_back(container); + } else { + target_workspace + .insert_container_at_idx(target_index, container); + } + } + _ => { + target_workspace.insert_container_at_idx(target_index, container); + } } } + Layout::Custom(_) => { + target_workspace.add_container_to_front(container); + } + }, + _ => { + target_workspace.add_container_to_back(container); } - Layout::Custom(_) => { - target_workspace.add_container_to_front(container); - } - }, - _ => { - target_workspace.add_container_to_back(container); } } diff --git a/komorebi/src/process_event.rs b/komorebi/src/process_event.rs index 47dbff78..33f28236 100644 --- a/komorebi/src/process_event.rs +++ b/komorebi/src/process_event.rs @@ -150,14 +150,6 @@ impl WindowManager { _ => {} } - for monitor in self.monitors_mut() { - for workspace in monitor.workspaces_mut() { - if let WindowManagerEvent::FocusChange(_, window) = event { - let _ = workspace.focus_changed(window.hwnd); - } - } - } - self.enforce_workspace_rules()?; if matches!(event, WindowManagerEvent::MouseCapture(..)) { @@ -247,24 +239,31 @@ impl WindowManager { self.update_focused_workspace(self.mouse_follows_focus, false)?; let workspace = self.focused_workspace_mut()?; - if !workspace + let floating_window_idx = workspace .floating_windows() .iter() - .any(|w| w.hwnd == window.hwnd) - { - if let Some(w) = workspace.maximized_window() { - if w.hwnd == window.hwnd { - return Ok(()); + .position(|w| w.hwnd == window.hwnd); + + match floating_window_idx { + None => { + if let Some(w) = workspace.maximized_window() { + if w.hwnd == window.hwnd { + return Ok(()); + } + } + + if let Some(monocle) = workspace.monocle_container() { + if let Some(window) = monocle.focused_window() { + window.focus(false)?; + } + } else { + workspace.focus_container_by_window(window.hwnd)?; } } - - if let Some(monocle) = workspace.monocle_container() { - if let Some(window) = monocle.focused_window() { + Some(idx) => { + if let Some(window) = workspace.floating_windows().get(idx) { window.focus(false)?; } - } else { - self.focused_workspace_mut()? - .focus_container_by_window(window.hwnd)?; } } } diff --git a/komorebi/src/workspace.rs b/komorebi/src/workspace.rs index 688c742f..39a846e9 100644 --- a/komorebi/src/workspace.rs +++ b/komorebi/src/workspace.rs @@ -221,18 +221,19 @@ impl Workspace { container.restore(); } - for window in self.floating_windows() { - window.restore(); - } - if let Some(container) = self.focused_container_mut() { container.focus_window(container.focused_window_idx()); } + for window in self.floating_windows() { + window.restore(); + } + // Do this here to make sure that an error doesn't stop the restoration of other windows - // Maximised windows should always be drawn at the top of the Z order + // Maximised windows and floating windows should always be drawn at the top of the Z order + // when switching to a workspace if let Some(window) = to_focus { - if self.maximized_window().is_none() { + if self.maximized_window().is_none() && self.floating_windows().is_empty() { window.focus(mouse_follows_focus)?; } } @@ -393,26 +394,6 @@ impl Workspace { Ok(()) } - // focus_changed performs updates in response to the fact that a focus - // change event has occurred. The focus change is assumed to be valid, and - // should not result in a new focus change - the intent here is to update - // focus-reactive elements, such as the stackbar. - pub fn focus_changed(&mut self, hwnd: isize) -> Result<()> { - if !self.tile() { - return Ok(()); - } - - let containers = self.containers_mut(); - - for container in containers.iter_mut() { - if let Some(idx) = container.idx_for_window(hwnd) { - container.focus_window(idx); - container.restore(); - } - } - Ok(()) - } - pub fn reap_orphans(&mut self) -> Result<(usize, usize)> { let mut hwnds = vec![]; let mut floating_hwnds = vec![];