From 26f90cc9eefc5d4c90af2edee8197e1ba3cb885e Mon Sep 17 00:00:00 2001 From: alex-ds13 <145657253+alex-ds13@users.noreply.github.com> Date: Mon, 9 Dec 2024 18:56:37 +0000 Subject: [PATCH] fix(borders): floating window z-order handling This commit makes it so a floating window only has the floating border when it is focused, if not it has the `Unfocused` border. It also makes the 'focused_container' have the `Unfocused` border when it is not the foreground window, for example when we have a floating window focused instead. This commit also changes the border's `window_kind` so that the stored borders actually have that value so we can check it later (This value wasn't being updated). This commit also makes it so we properly invalidate the borders in the situations discussed above (for example when changing focus to/from a floating window we need the floating window border to update its ZOrder as well as the previously focused window). Lastly this commit, changes the `WM_PAINT` code part of the border so that it now sets the position of border so that the border's ZOrder updates to it's tracking window ZOrder. --- komorebi/src/border_manager/border.rs | 12 ++++ komorebi/src/border_manager/mod.rs | 98 +++++++++++++-------------- 2 files changed, 60 insertions(+), 50 deletions(-) diff --git a/komorebi/src/border_manager/border.rs b/komorebi/src/border_manager/border.rs index a367ee9f..0c90fbe0 100644 --- a/komorebi/src/border_manager/border.rs +++ b/komorebi/src/border_manager/border.rs @@ -425,6 +425,18 @@ impl Border { return LRESULT(0); } + let reference_hwnd = (*border_pointer).tracking_hwnd; + + // Update position to update the ZOrder + let border_window_rect = (*border_pointer).window_rect; + + tracing::trace!("updating border position"); + if let Err(error) = + (*border_pointer).set_position(&border_window_rect, reference_hwnd) + { + tracing::error!("failed to update border position {error}"); + } + if let Some(render_target) = (*border_pointer).render_target.get() { (*border_pointer).width = BORDER_WIDTH.load(Ordering::Relaxed); (*border_pointer).offset = BORDER_OFFSET.load(Ordering::Relaxed); diff --git a/komorebi/src/border_manager/mod.rs b/komorebi/src/border_manager/mod.rs index 13326535..4d9d6a9d 100644 --- a/komorebi/src/border_manager/mod.rs +++ b/komorebi/src/border_manager/mod.rs @@ -169,6 +169,7 @@ pub fn handle_notifications(wm: Arc>) -> color_eyre::Result .iter() .map(|w| w.hwnd) .collect::>(); + let foreground_window = WindowsApi::foreground_window().unwrap_or_default(); drop(state); @@ -238,10 +239,19 @@ pub fn handle_notifications(wm: Arc>) -> color_eyre::Result should_process_notification = true; } - // when we switch focus to a floating window - if !should_process_notification - && floating_window_hwnds.contains(¬ification.0.unwrap_or_default()) - { + // when we switch focus to/from a floating window + let switch_focus_to_from_floating_window = floating_window_hwnds.iter().any(|fw| { + // if we switch focus to a floating window + fw == ¬ification.0.unwrap_or_default() || + // if there is any floating window with a `WindowKind::Floating` border + // that no longer is the foreground window then we need to update that + // border. + (fw != &foreground_window + && window_border(*fw) + .map(|b| b.window_kind == WindowKind::Floating) + .unwrap_or_default()) + }); + if !should_process_notification && switch_focus_to_from_floating_window { should_process_notification = true; } @@ -321,22 +331,15 @@ pub fn handle_notifications(wm: Arc>) -> color_eyre::Result } }; - borders_monitors.insert(monocle.id().clone(), monitor_idx); - windows_borders.insert( - monocle.focused_window().cloned().unwrap_or_default().hwnd, - border.clone(), - ); - + let new_focus_state = if monitor_idx != focused_monitor_idx { + WindowKind::Unfocused + } else { + WindowKind::Monocle + }; + border.window_kind = new_focus_state; { let mut focus_state = FOCUS_STATE.lock(); - focus_state.insert( - border.hwnd, - if monitor_idx != focused_monitor_idx { - WindowKind::Unfocused - } else { - WindowKind::Monocle - }, - ); + focus_state.insert(border.hwnd, new_focus_state); } let reference_hwnd = @@ -350,6 +353,12 @@ pub fn handle_notifications(wm: Arc>) -> color_eyre::Result border.invalidate(); + borders_monitors.insert(monocle.id().clone(), monitor_idx); + windows_borders.insert( + monocle.focused_window().cloned().unwrap_or_default().hwnd, + border.clone(), + ); + let border_hwnd = border.hwnd; let mut to_remove = vec![]; for (id, b) in borders.iter() { @@ -436,17 +445,14 @@ pub fn handle_notifications(wm: Arc>) -> color_eyre::Result } }; - borders_monitors.insert(c.id().clone(), monitor_idx); - windows_borders.insert( - c.focused_window().cloned().unwrap_or_default().hwnd, - border.clone(), - ); - #[allow(unused_assignments)] let mut last_focus_state = None; let new_focus_state = if idx != ws.focused_container_idx() || monitor_idx != focused_monitor_idx + || c.focused_window() + .map(|w| w.hwnd != foreground_window) + .unwrap_or_default() { WindowKind::Unfocused } else if c.windows().len() > 1 { @@ -454,6 +460,7 @@ pub fn handle_notifications(wm: Arc>) -> color_eyre::Result } else { WindowKind::Single }; + border.window_kind = new_focus_state; // Update the focused state for all containers on this workspace { @@ -478,10 +485,16 @@ pub fn handle_notifications(wm: Arc>) -> color_eyre::Result if should_invalidate { border.invalidate(); } + + borders_monitors.insert(c.id().clone(), monitor_idx); + windows_borders.insert( + c.focused_window().cloned().unwrap_or_default().hwnd, + border.clone(), + ); } { - 'windows: for window in ws.floating_windows() { + for window in ws.floating_windows() { let mut new_border = false; let border = match borders.entry(window.hwnd.to_string()) { Entry::Occupied(entry) => entry.into_mut(), @@ -497,33 +510,15 @@ pub fn handle_notifications(wm: Arc>) -> color_eyre::Result } }; - borders_monitors.insert(window.hwnd.to_string(), monitor_idx); - windows_borders.insert(window.hwnd, border.clone()); - - let mut should_destroy = false; - - if let Some(notification_hwnd) = notification.0 { - if notification_hwnd != window.hwnd { - should_destroy = true; - } - } - - if WindowsApi::foreground_window().unwrap_or_default() - != window.hwnd - { - should_destroy = true; - } - - if should_destroy { - border.destroy()?; - borders.remove(&window.hwnd.to_string()); - borders_monitors.remove(&window.hwnd.to_string()); - continue 'windows; - } - #[allow(unused_assignments)] let mut last_focus_state = None; - let new_focus_state = WindowKind::Floating; + let mut new_focus_state = WindowKind::Unfocused; + + if foreground_window == window.hwnd { + new_focus_state = WindowKind::Floating; + } + + border.window_kind = new_focus_state; { let mut focus_state = FOCUS_STATE.lock(); last_focus_state = @@ -544,6 +539,9 @@ pub fn handle_notifications(wm: Arc>) -> color_eyre::Result if should_invalidate { border.invalidate(); } + + borders_monitors.insert(window.hwnd.to_string(), monitor_idx); + windows_borders.insert(window.hwnd, border.clone()); } } }