From d2d6484e38ace7393ce12db303f6bb79d91b6fb7 Mon Sep 17 00:00:00 2001 From: LGUG2Z Date: Wed, 12 Jun 2024 08:05:56 -0700 Subject: [PATCH] fix(borders): always validate border client area This commit pushes up the calls to BeginPaint and EndPaint in the border callback function to ensure that the client area of the border rect is always validated after calls to InvalidateRect from the update fn. The callback now also logs errors whenever it is not possible to get the border rect to operate on for any reason. There was a call at the end of this logic to ValidateRect which has been removed as the validation is already handled by the call to BeginPaint. re #862 --- komorebi/src/border_manager/border.rs | 98 ++++++++++++++------------- komorebi/src/border_manager/mod.rs | 6 +- 2 files changed, 53 insertions(+), 51 deletions(-) diff --git a/komorebi/src/border_manager/border.rs b/komorebi/src/border_manager/border.rs index ee6d2583..590caf97 100644 --- a/komorebi/src/border_manager/border.rs +++ b/komorebi/src/border_manager/border.rs @@ -32,7 +32,6 @@ use windows::Win32::Graphics::Gdi::InvalidateRect; use windows::Win32::Graphics::Gdi::Rectangle; use windows::Win32::Graphics::Gdi::RoundRect; use windows::Win32::Graphics::Gdi::SelectObject; -use windows::Win32::Graphics::Gdi::ValidateRect; use windows::Win32::Graphics::Gdi::PAINTSTRUCT; use windows::Win32::Graphics::Gdi::PS_INSIDEFRAME; use windows::Win32::Graphics::Gdi::PS_SOLID; @@ -150,63 +149,68 @@ impl Border { unsafe { match message { WM_PAINT => { + let mut ps = PAINTSTRUCT::default(); + let hdc = BeginPaint(window, &mut ps); + // With the rect that we set in Self::update - if let Ok(rect) = WindowsApi::window_rect(window) { - // Grab the focus kind for this border - let focus_kind = { - FOCUS_STATE - .lock() - .get(&window.0) - .copied() - .unwrap_or(WindowKind::Unfocused) - }; + match WindowsApi::window_rect(window) { + Ok(rect) => { + // Grab the focus kind for this border + let focus_kind = { + FOCUS_STATE + .lock() + .get(&window.0) + .copied() + .unwrap_or(WindowKind::Unfocused) + }; - // Set up the brush to draw the border - let mut ps = PAINTSTRUCT::default(); - let hdc = BeginPaint(window, &mut ps); - let hpen = CreatePen( - PS_SOLID | PS_INSIDEFRAME, - BORDER_WIDTH.load(Ordering::SeqCst), - COLORREF(match focus_kind { - WindowKind::Unfocused => UNFOCUSED.load(Ordering::SeqCst), - WindowKind::Single => FOCUSED.load(Ordering::SeqCst), - WindowKind::Stack => STACK.load(Ordering::SeqCst), - WindowKind::Monocle => MONOCLE.load(Ordering::SeqCst), - }), - ); + // Set up the brush to draw the border + let hpen = CreatePen( + PS_SOLID | PS_INSIDEFRAME, + BORDER_WIDTH.load(Ordering::SeqCst), + COLORREF(match focus_kind { + WindowKind::Unfocused => UNFOCUSED.load(Ordering::SeqCst), + WindowKind::Single => FOCUSED.load(Ordering::SeqCst), + WindowKind::Stack => STACK.load(Ordering::SeqCst), + WindowKind::Monocle => MONOCLE.load(Ordering::SeqCst), + }), + ); - let hbrush = WindowsApi::create_solid_brush(0); + let hbrush = WindowsApi::create_solid_brush(0); - // Draw the border - SelectObject(hdc, hpen); - SelectObject(hdc, hbrush); - // TODO(raggi): this is approximately the correct curvature for - // the top left of a Windows 11 window (DWMWCP_DEFAULT), but - // often the bottom right has a different shape. Furthermore if - // the window was made with DWMWCP_ROUNDSMALL then this is the - // wrong size. In the future we should read the DWM properties - // of windows and attempt to match appropriately. - match STYLE.load() { - BorderStyle::System => { - if *WINDOWS_11 { + // Draw the border + SelectObject(hdc, hpen); + SelectObject(hdc, hbrush); + // TODO(raggi): this is approximately the correct curvature for + // the top left of a Windows 11 window (DWMWCP_DEFAULT), but + // often the bottom right has a different shape. Furthermore if + // the window was made with DWMWCP_ROUNDSMALL then this is the + // wrong size. In the future we should read the DWM properties + // of windows and attempt to match appropriately. + match STYLE.load() { + BorderStyle::System => { + if *WINDOWS_11 { + RoundRect(hdc, 0, 0, rect.right, rect.bottom, 20, 20); + } else { + Rectangle(hdc, 0, 0, rect.right, rect.bottom); + } + } + BorderStyle::Rounded => { RoundRect(hdc, 0, 0, rect.right, rect.bottom, 20, 20); - } else { + } + BorderStyle::Square => { Rectangle(hdc, 0, 0, rect.right, rect.bottom); } } - BorderStyle::Rounded => { - RoundRect(hdc, 0, 0, rect.right, rect.bottom, 20, 20); - } - BorderStyle::Square => { - Rectangle(hdc, 0, 0, rect.right, rect.bottom); - } + DeleteObject(hpen); + DeleteObject(hbrush); + } + Err(error) => { + tracing::error!("could not get border rect: {}", error.to_string()) } - EndPaint(window, &ps); - DeleteObject(hpen); - DeleteObject(hbrush); - ValidateRect(window, None); } + EndPaint(window, &ps); LRESULT(0) } WM_DESTROY => { diff --git a/komorebi/src/border_manager/mod.rs b/komorebi/src/border_manager/mod.rs index 13db75be..4aa1ac82 100644 --- a/komorebi/src/border_manager/mod.rs +++ b/komorebi/src/border_manager/mod.rs @@ -155,10 +155,8 @@ pub fn handle_notifications(wm: Arc>) -> color_eyre::Result } // handle the retile edge case - if !should_process_notification { - if BORDER_STATE.lock().is_empty() { - should_process_notification = true; - } + if !should_process_notification && BORDER_STATE.lock().is_empty() { + should_process_notification = true; } if !should_process_notification {