diff --git a/komorebi/src/border_manager/border.rs b/komorebi/src/border_manager/border.rs index a33b085a..2d0d1e51 100644 --- a/komorebi/src/border_manager/border.rs +++ b/komorebi/src/border_manager/border.rs @@ -313,6 +313,11 @@ impl Border { } pub fn destroy(&self) -> color_eyre::Result<()> { + // clear user data **BEFORE** closing window + // pending messages will see a null pointer and exit early + unsafe { + SetWindowLongPtrW(self.hwnd(), GWLP_USERDATA, 0); + } WindowsApi::close_window(self.hwnd) } diff --git a/komorebi/src/border_manager/mod.rs b/komorebi/src/border_manager/mod.rs index f29f55d1..0280164d 100644 --- a/komorebi/src/border_manager/mod.rs +++ b/komorebi/src/border_manager/mod.rs @@ -767,6 +767,13 @@ fn remove_border( fn destroy_border(border: Box) -> color_eyre::Result<()> { let raw_pointer = Box::into_raw(border); unsafe { + // release d2d resources **BEFORE** destroying window + // this drops render_target and brushes while HWND is still valid + // prevents EndDraw() from accessing freed HWND resources + (*raw_pointer).render_target = None; + (*raw_pointer).brushes.clear(); + + // Now safe to destroy window (*raw_pointer).destroy()?; } Ok(())