From e4226ce62373504c6c04190389a141c1e634b69e Mon Sep 17 00:00:00 2001 From: alex-ds13 <145657253+alex-ds13@users.noreply.github.com> Date: Fri, 21 Mar 2025 15:54:35 +0000 Subject: [PATCH] feat(wm): show float windows in order on layer toggle This commit raises and lowers all the floating windows so that they show up with the smaller windows on top and the bigger windows on the bottom when we toggle between layers. --- komorebi/src/process_command.rs | 42 +++++++++++++++++++++++++++++---- komorebi/src/ring.rs | 6 +++++ komorebi/src/workspace.rs | 2 +- 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/komorebi/src/process_command.rs b/komorebi/src/process_command.rs index ac872916..ac271929 100644 --- a/komorebi/src/process_command.rs +++ b/komorebi/src/process_command.rs @@ -1197,11 +1197,33 @@ impl WindowManager { WorkspaceLayer::Tiling => { workspace.set_layer(WorkspaceLayer::Floating); - for (i, window) in workspace.floating_windows().iter().enumerate() { - if i == 0 { + let focused_idx = workspace.focused_floating_window_idx(); + let mut window_idx_pairs = workspace + .floating_windows_mut() + .make_contiguous() + .iter() + .enumerate() + .collect::>(); + + // Sort by window area + window_idx_pairs.sort_by_key(|(_, w)| { + let rect = WindowsApi::window_rect(w.hwnd).unwrap_or_default(); + rect.right * rect.bottom + }); + window_idx_pairs.reverse(); + + for (i, window) in window_idx_pairs { + if i == focused_idx { to_focus = Some(*window); + } else { + window.raise()?; } - window.raise()?; + } + + if let Some(focused_window) = &to_focus { + // The focused window should be the last one raised to make sure it is + // on top + focused_window.raise()?; } for container in workspace.containers() { @@ -1223,7 +1245,19 @@ impl WindowManager { } } - for window in workspace.floating_windows() { + let mut window_idx_pairs = workspace + .floating_windows_mut() + .make_contiguous() + .iter() + .collect::>(); + + // Sort by window area + window_idx_pairs.sort_by_key(|w| { + let rect = WindowsApi::window_rect(w.hwnd).unwrap_or_default(); + rect.right * rect.bottom + }); + + for window in window_idx_pairs { window.lower()?; } } diff --git a/komorebi/src/ring.rs b/komorebi/src/ring.rs index 3dd7d49c..04751502 100644 --- a/komorebi/src/ring.rs +++ b/komorebi/src/ring.rs @@ -76,6 +76,12 @@ macro_rules! impl_ring_elements { } } }; + // This allows passing a different name to be used for the functions. For instance, the + // `floating_windows` ring calls this as: + // ```rust + // impl_ring_elements!(Workspace, Window, "floating_window"); + // ``` + // Which allows using the `Window` element but name the functions as `floating_window` ($name:ty, $element:ident, $el_name:literal) => { paste::paste! { impl $name { diff --git a/komorebi/src/workspace.rs b/komorebi/src/workspace.rs index ccb6bfb1..93da3b32 100644 --- a/komorebi/src/workspace.rs +++ b/komorebi/src/workspace.rs @@ -1747,7 +1747,7 @@ mod tests { // unfloat - have to do this semi-manually becuase of calls to WindowsApi in // new_container_for_floating_window which usually handles unfloating - let window = ws.floating_windows_mut().pop().unwrap(); + let window = ws.floating_windows_mut().pop_back().unwrap(); let mut container = Container::default(); container.add_window(window); ws.insert_container_at_idx(ws.focused_container_idx(), container);