Skip to content

Commit

Permalink
fix(borders): always validate border client area
Browse files Browse the repository at this point in the history
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
  • Loading branch information
LGUG2Z committed Jun 12, 2024
1 parent 67a3c35 commit d2d6484
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 54 deletions.
104 changes: 54 additions & 50 deletions komorebi/src/border_manager/border.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
};

// 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),
}),
);

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 {
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 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);

// 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 => {
Expand Down
6 changes: 2 additions & 4 deletions komorebi/src/border_manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,8 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> 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 {
Expand Down

0 comments on commit d2d6484

Please sign in to comment.