fix(windows): don't drop Menu or MenuChild inside menu proc (#81)

`Menu` or `MenuChild`  are not owned by the menu proc and so it shouldn't drop it, previously this was okay because the `Menu` or `MenuChild` used to be a wrapper around `Rc<RefCell>` but that was changed in the last release.
This commit is contained in:
Amr Bashir 2023-08-01 19:43:04 +03:00 committed by GitHub
parent e5324b7684
commit 7a3bc5505f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 6 additions and 13 deletions

5
.changes/destroy.md Normal file
View file

@ -0,0 +1,5 @@
---
"muda": "patch"
---
On Windows, fix `ContextMenu::detach_menu_subclass_from_hwnd` crashing and terminating the thread.

View file

@ -36,7 +36,7 @@ use windows_sys::Win32::{
MFS_CHECKED, MFS_DISABLED, MF_BYCOMMAND, MF_BYPOSITION, MF_CHECKED, MF_DISABLED, MFS_CHECKED, MFS_DISABLED, MF_BYCOMMAND, MF_BYPOSITION, MF_CHECKED, MF_DISABLED,
MF_ENABLED, MF_GRAYED, MF_POPUP, MF_SEPARATOR, MF_STRING, MF_UNCHECKED, MIIM_BITMAP, MF_ENABLED, MF_GRAYED, MF_POPUP, MF_SEPARATOR, MF_STRING, MF_UNCHECKED, MIIM_BITMAP,
MIIM_STATE, MIIM_STRING, SW_HIDE, SW_MAXIMIZE, SW_MINIMIZE, TPM_LEFTALIGN, WM_CLOSE, MIIM_STATE, MIIM_STRING, SW_HIDE, SW_MAXIMIZE, SW_MINIMIZE, TPM_LEFTALIGN, WM_CLOSE,
WM_COMMAND, WM_DESTROY, WM_COMMAND,
}, },
}, },
}; };
@ -298,7 +298,6 @@ impl Menu {
.ok_or(crate::Error::NotInitialized)?; .ok_or(crate::Error::NotInitialized)?;
self.hwnds.remove(index); self.hwnds.remove(index);
unsafe { unsafe {
SendMessageW(hwnd, WM_CLEAR_MENU_DATA, 0, 0);
RemoveWindowSubclass(hwnd, Some(menu_subclass_proc), MENU_SUBCLASS_ID); RemoveWindowSubclass(hwnd, Some(menu_subclass_proc), MENU_SUBCLASS_ID);
SetMenu(hwnd, 0); SetMenu(hwnd, 0);
DrawMenuBar(hwnd); DrawMenuBar(hwnd);
@ -320,7 +319,6 @@ impl Menu {
pub fn detach_menu_subclass_from_hwnd(&self, hwnd: isize) { pub fn detach_menu_subclass_from_hwnd(&self, hwnd: isize) {
unsafe { unsafe {
SendMessageW(hwnd, WM_CLEAR_MENU_DATA, 0, 0);
RemoveWindowSubclass(hwnd, Some(menu_subclass_proc), MENU_SUBCLASS_ID); RemoveWindowSubclass(hwnd, Some(menu_subclass_proc), MENU_SUBCLASS_ID);
} }
} }
@ -799,7 +797,6 @@ impl MenuChild {
pub fn detach_menu_subclass_from_hwnd(&self, hwnd: isize) { pub fn detach_menu_subclass_from_hwnd(&self, hwnd: isize) {
unsafe { unsafe {
SendMessageW(hwnd, WM_CLEAR_MENU_DATA, 0, 0);
RemoveWindowSubclass(hwnd, Some(menu_subclass_proc), SUBMENU_SUBCLASS_ID); RemoveWindowSubclass(hwnd, Some(menu_subclass_proc), SUBMENU_SUBCLASS_ID);
} }
} }
@ -898,7 +895,6 @@ fn create_icon_item_info(hbitmap: HBITMAP) -> MENUITEMINFOW {
const MENU_SUBCLASS_ID: usize = 200; const MENU_SUBCLASS_ID: usize = 200;
const SUBMENU_SUBCLASS_ID: usize = 201; const SUBMENU_SUBCLASS_ID: usize = 201;
const WM_CLEAR_MENU_DATA: u32 = 600;
unsafe extern "system" fn menu_subclass_proc( unsafe extern "system" fn menu_subclass_proc(
hwnd: HWND, hwnd: HWND,
@ -909,14 +905,6 @@ unsafe extern "system" fn menu_subclass_proc(
dwrefdata: usize, dwrefdata: usize,
) -> LRESULT { ) -> LRESULT {
let mut ret = -1; let mut ret = -1;
if msg == WM_DESTROY || msg == WM_CLEAR_MENU_DATA {
if uidsubclass == MENU_SUBCLASS_ID {
drop(Box::from_raw(dwrefdata as *mut Menu));
} else {
drop(Box::from_raw(dwrefdata as *mut MenuChild));
}
}
if msg == WM_COMMAND { if msg == WM_COMMAND {
let id = util::LOWORD(wparam as _) as u32; let id = util::LOWORD(wparam as _) as u32;
let item = if uidsubclass == MENU_SUBCLASS_ID { let item = if uidsubclass == MENU_SUBCLASS_ID {