diff --git a/komorebi/src/process_event.rs b/komorebi/src/process_event.rs index 8b05fd97..97ff56b0 100644 --- a/komorebi/src/process_event.rs +++ b/komorebi/src/process_event.rs @@ -323,7 +323,7 @@ impl WindowManager { for (i, monitor) in self.monitors().iter().enumerate() { for (j, workspace) in monitor.workspaces().iter().enumerate() { - if workspace.container_for_window(window.hwnd).is_some() + if workspace.contains_window(window.hwnd) && i != self.focused_monitor_idx() && j != monitor.focused_workspace_idx() { diff --git a/komorebi/src/window_manager.rs b/komorebi/src/window_manager.rs index b44c0e9a..f5e38139 100644 --- a/komorebi/src/window_manager.rs +++ b/komorebi/src/window_manager.rs @@ -288,6 +288,7 @@ struct EnforceWorkspaceRuleOp { origin_workspace_idx: usize, target_monitor_idx: usize, target_workspace_idx: usize, + floating: bool, } impl EnforceWorkspaceRuleOp { const fn is_origin(&self, monitor_idx: usize, workspace_idx: usize) -> bool { @@ -505,6 +506,7 @@ impl WindowManager { origin_workspace_idx: usize, target_monitor_idx: usize, target_workspace_idx: usize, + floating: bool, to_move: &mut Vec, ) -> () { tracing::trace!( @@ -521,6 +523,7 @@ impl WindowManager { origin_workspace_idx, target_monitor_idx, target_workspace_idx, + floating, }); } @@ -576,6 +579,8 @@ impl WindowManager { }; if matched { + let floating = workspace.floating_windows().contains(window); + if rule.initial_only { if !already_moved_window_handles.contains(&window.hwnd) { already_moved_window_handles.insert(window.hwnd); @@ -587,6 +592,7 @@ impl WindowManager { j, rule.monitor_index, rule.workspace_index, + floating, &mut to_move, ); } @@ -598,6 +604,7 @@ impl WindowManager { j, rule.monitor_index, rule.workspace_index, + floating, &mut to_move, ); } @@ -616,17 +623,34 @@ impl WindowManager { // Parse the operation and remove any windows that are not placed according to their rules for op in &to_move { - let origin_workspace = self + let target_area = *self + .monitors_mut() + .get_mut(op.target_monitor_idx) + .ok_or_else(|| anyhow!("there is no monitor with that index"))? + .work_area_size(); + + let origin_monitor = self .monitors_mut() .get_mut(op.origin_monitor_idx) - .ok_or_else(|| anyhow!("there is no monitor with that index"))? + .ok_or_else(|| anyhow!("there is no monitor with that index"))?; + + let origin_area = *origin_monitor.work_area_size(); + + let origin_workspace = origin_monitor .workspaces_mut() .get_mut(op.origin_workspace_idx) .ok_or_else(|| anyhow!("there is no workspace with that index"))?; + let mut window = Window::from(op.hwnd); + + // If it is a floating window move it to the target area + if op.floating { + window.move_to_area(&origin_area, &target_area)?; + } + // Hide the window we are about to remove if it is on the currently focused workspace if op.is_origin(focused_monitor_idx, focused_workspace_idx) { - Window::from(op.hwnd).hide(); + window.hide(); should_update_focused_workspace = true; } @@ -656,7 +680,21 @@ impl WindowManager { .get_mut(op.target_workspace_idx) .ok_or_else(|| anyhow!("there is no workspace with that index"))?; - target_workspace.new_container_for_window(Window::from(op.hwnd)); + if op.floating { + target_workspace + .floating_windows_mut() + .push(Window::from(op.hwnd)); + } else { + //TODO(alex-ds13): should this take into account the target workspace + //`window_container_behaviour`? + //In the case above a floating window should always be moved as floating, + //because it was set as so either manually by the user or by a + //`floating_applications` rule so it should stay that way. But a tiled window + //when moving to another workspace by a `workspace_rule` should honor that + //workspace `window_container_behaviour` in my opinion! Maybe this should be done + //on the `new_container_for_window` function instead. + target_workspace.new_container_for_window(Window::from(op.hwnd)); + } } // Only re-tile the focused workspace if we need to diff --git a/komorebi/src/workspace.rs b/komorebi/src/workspace.rs index 91e54d77..82fea5a1 100644 --- a/komorebi/src/workspace.rs +++ b/komorebi/src/workspace.rs @@ -431,7 +431,7 @@ impl Workspace { } } - for window in self.visible_windows_mut().into_iter().flatten() { + for window in self.visible_windows().into_iter().flatten() { if !window.is_window() { hwnds.push(window.hwnd); } @@ -1409,16 +1409,41 @@ impl Workspace { pub fn visible_windows(&self) -> Vec> { let mut vec = vec![]; + + vec.push(self.maximized_window().as_ref()); + + if let Some(monocle) = self.monocle_container() { + vec.push(monocle.focused_window()); + } + for container in self.containers() { vec.push(container.focused_window()); } + for window in self.floating_windows() { + vec.push(Some(window)); + } + vec } pub fn visible_window_details(&self) -> Vec { let mut vec: Vec = vec![]; + if let Some(maximized) = self.maximized_window() { + if let Ok(details) = (*maximized).try_into() { + vec.push(details); + } + } + + if let Some(monocle) = self.monocle_container() { + if let Some(focused) = monocle.focused_window() { + if let Ok(details) = (*focused).try_into() { + vec.push(details); + } + } + } + for container in self.containers() { if let Some(focused) = container.focused_window() { if let Ok(details) = (*focused).try_into() { @@ -1427,13 +1452,10 @@ impl Workspace { } } - vec - } - - pub fn visible_windows_mut(&mut self) -> Vec> { - let mut vec = vec![]; - for container in self.containers_mut() { - vec.push(container.focused_window_mut()); + for window in self.floating_windows() { + if let Ok(details) = (*window).try_into() { + vec.push(details); + } } vec