fix(borders): update monitor_idx on all borders

This fixes the issue where borders moved to other monitors would
sometimes be removed by their initial monitor because this data wasn't
being updated.

This effectively reverts commit 5919f88b38.
This commit is contained in:
alex-ds13
2025-03-17 09:34:39 +00:00
committed by LGUG2Z
parent c083484ef0
commit be2af9fdcb
+15 -37
View File
@@ -340,24 +340,6 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
continue 'receiver; continue 'receiver;
} }
// we may need multiple render passes if a window is moved from a monitor
// with a higher index to a monitor with a lower index
//
// this is because the border on the window will be removed in a later iteration
// (due to the higher monitor index), but without an extra render pass, we will
// never render a new border for it on the earlier monitor index which has already
// been processed
let mut render_pass_required = true;
let mut render_pass_count = 0;
while render_pass_required {
render_pass_count += 1;
tracing::debug!("executing render pass {render_pass_count}");
// optimistically assume this will be the last render pass
render_pass_required = false;
'monitors: for (monitor_idx, m) in monitors.elements().iter().enumerate() { 'monitors: for (monitor_idx, m) in monitors.elements().iter().enumerate() {
// Only operate on the focused workspace of each monitor // Only operate on the focused workspace of each monitor
if let Some(ws) = m.focused_workspace() { if let Some(ws) = m.focused_workspace() {
@@ -406,9 +388,7 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
// Update the borders tracking_hwnd in case it changed and remove the // Update the borders tracking_hwnd in case it changed and remove the
// old `tracking_hwnd` from `WINDOWS_BORDERS` if needed. // old `tracking_hwnd` from `WINDOWS_BORDERS` if needed.
if border.tracking_hwnd != focused_window_hwnd { if border.tracking_hwnd != focused_window_hwnd {
if let Some(previous) = if let Some(previous) = windows_borders.get(&border.tracking_hwnd) {
windows_borders.get(&border.tracking_hwnd)
{
// Only remove the border from `windows_borders` if it // Only remove the border from `windows_borders` if it
// still corresponds to the same border, if doesn't then // still corresponds to the same border, if doesn't then
// it means it was already updated by another border for // it means it was already updated by another border for
@@ -423,6 +403,9 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
} }
} }
// Update the border's monitor idx in case it changed
border.monitor_idx = Some(monitor_idx);
let rect = WindowsApi::window_rect(focused_window_hwnd)?; let rect = WindowsApi::window_rect(focused_window_hwnd)?;
border.window_rect = rect; border.window_rect = rect;
@@ -446,8 +429,7 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
continue 'monitors; continue 'monitors;
} }
let foreground_hwnd = let foreground_hwnd = WindowsApi::foreground_window().unwrap_or_default();
WindowsApi::foreground_window().unwrap_or_default();
let foreground_monitor_id = let foreground_monitor_id =
WindowsApi::monitor_from_window(foreground_hwnd); WindowsApi::monitor_from_window(foreground_hwnd);
let is_maximized = foreground_monitor_id == m.id() let is_maximized = foreground_monitor_id == m.id()
@@ -477,18 +459,13 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
} }
// Remove any borders not associated with the focused workspace // Remove any borders not associated with the focused workspace
let removed = remove_borders( remove_borders(
&mut borders, &mut borders,
&mut windows_borders, &mut windows_borders,
monitor_idx, monitor_idx,
|id, _| !container_and_floating_window_ids.contains(id), |id, _| !container_and_floating_window_ids.contains(id),
)?; )?;
if removed > 0 && monitor_idx > 0 {
render_pass_required = true;
tracing::debug!("another rendering pass required");
}
'containers: for (idx, c) in ws.containers().iter().enumerate() { 'containers: for (idx, c) in ws.containers().iter().enumerate() {
let focused_window_hwnd = let focused_window_hwnd =
c.focused_window().map(|w| w.hwnd).unwrap_or_default(); c.focused_window().map(|w| w.hwnd).unwrap_or_default();
@@ -528,9 +505,7 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
// Update the borders `tracking_hwnd` in case it changed and remove the // Update the borders `tracking_hwnd` in case it changed and remove the
// old `tracking_hwnd` from `WINDOWS_BORDERS` if needed. // old `tracking_hwnd` from `WINDOWS_BORDERS` if needed.
if border.tracking_hwnd != focused_window_hwnd { if border.tracking_hwnd != focused_window_hwnd {
if let Some(previous) = if let Some(previous) = windows_borders.get(&border.tracking_hwnd) {
windows_borders.get(&border.tracking_hwnd)
{
// Only remove the border from `windows_borders` if it // Only remove the border from `windows_borders` if it
// still corresponds to the same border, if doesn't then // still corresponds to the same border, if doesn't then
// it means it was already updated by another border for // it means it was already updated by another border for
@@ -545,6 +520,9 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
} }
} }
// Update the border's monitor idx in case it changed
border.monitor_idx = Some(monitor_idx);
// avoid getting into a thread restart loop if we try to look up // avoid getting into a thread restart loop if we try to look up
// rect info for a window that has been destroyed by the time // rect info for a window that has been destroyed by the time
// we get here // we get here
@@ -601,6 +579,9 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
border.window_kind = new_focus_state; border.window_kind = new_focus_state;
// Update the border's monitor idx in case it changed
border.monitor_idx = Some(monitor_idx);
let rect = WindowsApi::window_rect(window.hwnd)?; let rect = WindowsApi::window_rect(window.hwnd)?;
border.window_rect = rect; border.window_rect = rect;
@@ -622,7 +603,6 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
} }
} }
} }
}
previous_snapshot = monitors; previous_snapshot = monitors;
previous_pending_move_op = pending_move_op; previous_pending_move_op = pending_move_op;
@@ -643,7 +623,7 @@ fn remove_borders(
windows_borders: &mut HashMap<isize, String>, windows_borders: &mut HashMap<isize, String>,
monitor_idx: usize, monitor_idx: usize,
condition: impl Fn(&String, &Border) -> bool, condition: impl Fn(&String, &Border) -> bool,
) -> color_eyre::Result<usize> { ) -> color_eyre::Result<()> {
let mut to_remove = vec![]; let mut to_remove = vec![];
for (id, border) in borders.iter() { for (id, border) in borders.iter() {
// if border is on this monitor // if border is on this monitor
@@ -658,13 +638,11 @@ fn remove_borders(
} }
} }
let len = to_remove.len();
for id in &to_remove { for id in &to_remove {
remove_border(id, borders, windows_borders)?; remove_border(id, borders, windows_borders)?;
} }
Ok(len) Ok(())
} }
/// Removes the border with `id` and all its related info from all maps /// Removes the border with `id` and all its related info from all maps