diff --git a/komorebi/src/process_event.rs b/komorebi/src/process_event.rs index ab76c313..6a3d739c 100644 --- a/komorebi/src/process_event.rs +++ b/komorebi/src/process_event.rs @@ -331,7 +331,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 eb6f7cab..2cd7b7a5 100644 --- a/komorebi/src/window_manager.rs +++ b/komorebi/src/window_manager.rs @@ -290,6 +290,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 { @@ -508,6 +509,7 @@ impl WindowManager { origin_workspace_idx: usize, target_monitor_idx: usize, target_workspace_idx: usize, + floating: bool, to_move: &mut Vec, ) -> () { tracing::trace!( @@ -524,6 +526,7 @@ impl WindowManager { origin_workspace_idx, target_monitor_idx, target_workspace_idx, + floating, }); } @@ -579,6 +582,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); @@ -590,6 +595,7 @@ impl WindowManager { j, rule.monitor_index, rule.workspace_index, + floating, &mut to_move, ); } @@ -601,6 +607,7 @@ impl WindowManager { j, rule.monitor_index, rule.workspace_index, + floating, &mut to_move, ); } @@ -619,34 +626,34 @@ impl WindowManager { // Parse the operation and remove any windows that are not placed according to their rules for op in &to_move { - let mut test: bool = false; - 'outer: for (i, m) in self.monitors().iter().enumerate() { - for (j, w) in m.workspaces().iter().enumerate() { - if focused_workspace_idx != j && focused_monitor_idx != i { - if w.contains_managed_window(op.hwnd) { - test = true; - break 'outer; - } - } - } - } - - if !test { - Window::from(op.hwnd).hide(); - should_update_focused_workspace = true; - } + 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_workspace = self + 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; } @@ -676,7 +683,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/windows_api.rs b/komorebi/src/windows_api.rs index aaacb245..6548c0d4 100644 --- a/komorebi/src/windows_api.rs +++ b/komorebi/src/windows_api.rs @@ -300,14 +300,21 @@ impl WindowsApi { } } - if monitors.elements().is_empty() { - monitors.elements_mut().push_back(m); - } else if let Some(preference) = index_preference { - while *preference > monitors.elements().len() { + if let Some(preference) = index_preference { + while *preference >= monitors.elements().len() { monitors.elements_mut().push_back(Monitor::placeholder()); } - monitors.elements_mut().insert(*preference, m); + let current_name = monitors + .elements_mut() + .get(*preference) + .map_or("", |m| m.name()); + if current_name == "PLACEHOLDER" { + let _ = monitors.elements_mut().remove(*preference); + monitors.elements_mut().insert(*preference, m); + } else { + monitors.elements_mut().insert(*preference, m); + } } else { monitors.elements_mut().push_back(m); } diff --git a/komorebi/src/workspace.rs b/komorebi/src/workspace.rs index fb41ed4a..59d4cdf1 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