Skip to content

Commit 2bcacc3

Browse files
refactor: handle HandleMenuMsg properly for onecommander compat
1 parent 2b84999 commit 2bcacc3

File tree

6 files changed

+60
-42
lines changed

6 files changed

+60
-42
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ compile_commands.json
33
.xmake
44
.cache
55
build_info.h
6-
/test
6+
/test
7+
Xenos.log

scripts/inject_onecommander.xpr64

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<XenosConfig>
2-
<imagePath>D:\breeze-shell\build\windows\x64\releasedbg\shell.dll</imagePath>
2+
<imagePath>E:\breeze-shell\build\windows\x64\releasedbg\shell.dll</imagePath>
33
<manualMapFlags>0</manualMapFlags>
44
<procName>OneCommander.exe</procName>
55
<hijack>0</hijack>

src/shell/contextmenu/contextmenu.cc

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,18 @@ std::vector<std::string> extract_hotkeys(const std::string &name) {
132132
return keys;
133133
}
134134

135-
menu menu::construct_with_hmenu(HMENU hMenu, HWND hWnd, bool is_top) {
135+
menu menu::construct_with_hmenu(
136+
HMENU hMenu, HWND hWnd, bool is_top,
137+
std::function<void(int, WPARAM, LPARAM)> HandleMenuMsg) {
136138
menu m;
137139

138-
SendMessageW(hWnd, WM_INITMENUPOPUP, reinterpret_cast<WPARAM>(hMenu),
139-
0xFFFFFFFF);
140+
if (!HandleMenuMsg)
141+
HandleMenuMsg = [=](int message, WPARAM wParam, LPARAM lParam) {
142+
SendMessageW(hWnd, message, wParam, lParam);
143+
};
144+
145+
HandleMenuMsg(WM_INITMENUPOPUP, reinterpret_cast<WPARAM>(hMenu),
146+
0xFFFFFFFF);
140147
for (int i = 0; i < GetMenuItemCount(hMenu); i++) {
141148
menu_item item;
142149
wchar_t buffer[256];
@@ -169,13 +176,14 @@ menu menu::construct_with_hmenu(HMENU hMenu, HWND hWnd, bool is_top) {
169176
}
170177

171178
if (info.hSubMenu) {
172-
PostMessageW(hWnd, WM_INITMENUPOPUP,
173-
reinterpret_cast<WPARAM>(info.hSubMenu), 0xFFFFFFFF);
174179
auto main_thread_id = GetCurrentThreadId();
175180
item.submenu = [=](std::shared_ptr<menu_widget> mw) {
176181
auto task = [&]() {
177-
mw->init_from_data(
178-
menu::construct_with_hmenu(info.hSubMenu, hWnd, false));
182+
HandleMenuMsg(WM_INITMENUPOPUP,
183+
reinterpret_cast<WPARAM>(info.hSubMenu),
184+
0xFFFFFFFF);
185+
mw->init_from_data(menu::construct_with_hmenu(
186+
info.hSubMenu, hWnd, false, HandleMenuMsg));
179187
};
180188
if (main_thread_id == GetCurrentThreadId())
181189
task();

src/shell/contextmenu/contextmenu.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,13 @@ struct menu {
1818
void *parent_window = nullptr;
1919
bool is_top_level = false;
2020

21-
static menu construct_with_hmenu(HMENU hMenu, HWND hWnd,
22-
bool is_top = true);
21+
static menu
22+
construct_with_hmenu(HMENU hMenu, HWND hWnd, bool is_top = true,
23+
// This is for handling submenus; messages are required
24+
// to be forwarded to IContextMenu2::HandleMenuMsg for
25+
// submenus and owner-draw menus to work properly
26+
std::function<void(int, WPARAM, LPARAM)>
27+
HandleMenuMsg = {});
2328
};
2429

2530
std::optional<int>

src/shell/contextmenu/hooks.cc

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ mb_shell::track_popup_menu(mb_shell::menu menu, int x, int y,
3131
set_thread_name("breeze::context_menu_renderer");
3232
perf_counter perf("mb_shell::track_popup_menu");
3333

34-
bool shift_pressed =
35-
(GetKeyState(VK_SHIFT) & 0x8000) != 0;
34+
bool shift_pressed = (GetKeyState(VK_SHIFT) & 0x8000) != 0;
3635

3736
auto menu_render = menu_render::create(x, y, menu, run_js);
3837
menu_render.rt->last_time = menu_render.rt->clock.now();
@@ -78,7 +77,6 @@ mb_shell::track_popup_menu(mb_shell::menu menu, int x, int y,
7877
qjs::wait_with_msgloop([&]() { selected_menu_future.wait(); });
7978

8079
auto selected_menu = selected_menu_future.get();
81-
mb_shell::context_menu_hooks::block_js_reload.fetch_sub(1);
8280

8381
return selected_menu;
8482
}
@@ -112,7 +110,7 @@ void mb_shell::context_menu_hooks::install_common_hook() {
112110
PostMessageW(hWnd, WM_COMMAND, *selected_menu, 0);
113111
PostMessageW(hWnd, WM_NULL, 0, 0);
114112
}
115-
113+
mb_shell::context_menu_hooks::block_js_reload.fetch_sub(1);
116114
return (int32_t)selected_menu.value_or(0);
117115
});
118116
}
@@ -224,40 +222,46 @@ void mb_shell::context_menu_hooks::install_SHCreateDefaultContextMenu_hook() {
224222
auto res = SHCreateDefaultContextMenu(def, riid, ppv);
225223
SHCreateDefaultContextMenuHook->install();
226224

227-
IContextMenu *pdcm = (IContextMenu *)*ppv;
225+
IContextMenu *pdcm = (IContextMenu *)(*ppv);
228226
if (SUCCEEDED(res) && pdcm) {
229-
IContextMenu2 *pcm2 = NULL;
230-
231-
int pcmType = 0;
232-
UpgradeContextMenu(pdcm, reinterpret_cast<void **>(&pcm2),
233-
&pcmType);
234-
235-
IContextMenu *pCM(pcm2);
227+
CComPtr<IContextMenu> pCM(pdcm);
236228

237229
HMENU hmenu = CreatePopupMenu();
238230
pCM->QueryContextMenu(hmenu, 0, 1, 0x7FFF,
239231
CMF_EXPLORE | CMF_CANRENAME);
240232

241-
POINT pt;
242-
GetCursorPos(&pt);
243-
244-
int res = TrackPopupMenuEx(
245-
hmenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
246-
pt.x, pt.y, def->hwnd, NULL);
247-
248-
if (res > 0) {
249-
CMINVOKECOMMANDINFOEX ici = {};
250-
ici.cbSize = sizeof(CMINVOKECOMMANDINFOEX);
251-
ici.hwnd = def->hwnd;
252-
ici.fMask = 0x100000; /* CMIC_MASK_UNICODE */
253-
ici.lpVerb = MAKEINTRESOURCEA(res - 1);
254-
ici.lpVerbW = MAKEINTRESOURCEW(res - 1);
255-
ici.nShow = SW_SHOWNORMAL;
233+
CComPtr<IContextMenu2> pCM2 = NULL;
234+
if (SUCCEEDED(pCM->QueryInterface(&pCM2))) {
235+
POINT pt;
236+
GetCursorPos(&pt);
237+
auto hwndOwner = def->hwnd;
238+
entry::main_window_loop_hook.install(hwndOwner);
239+
block_js_reload.fetch_add(1);
240+
perf_counter perf("TrackPopupMenuEx");
241+
menu menu = menu::construct_with_hmenu(
242+
hmenu, hwndOwner, true,
243+
[=](int message, WPARAM wParam, LPARAM lParam) {
244+
pCM2->HandleMenuMsg(message, wParam, lParam);
245+
});
246+
perf.end("construct_with_hmenu");
247+
248+
auto selected_menu = track_popup_menu(menu, pt.x, pt.y);
249+
mb_shell::context_menu_hooks::block_js_reload.fetch_sub(1);
250+
251+
if (selected_menu) {
252+
CMINVOKECOMMANDINFOEX ici = {};
253+
ici.cbSize = sizeof(CMINVOKECOMMANDINFOEX);
254+
ici.hwnd = hwndOwner;
255+
ici.fMask = 0x100000; /* CMIC_MASK_UNICODE */
256+
ici.lpVerb = MAKEINTRESOURCEA(*selected_menu - 1);
257+
ici.lpVerbW = MAKEINTRESOURCEW(*selected_menu - 1);
258+
ici.nShow = SW_SHOWNORMAL;
259+
260+
pCM->InvokeCommand((LPCMINVOKECOMMANDINFO)&ici);
261+
}
256262

257-
pCM->InvokeCommand((LPCMINVOKECOMMANDINFO)&ici);
263+
close_next_create_window_exw_window = true;
258264
}
259-
260-
close_next_create_window_exw_window = true;
261265
}
262266

263267
return res;

xmake.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ includes("dependencies/breeze-ui.lua")
1818

1919
set_runtimes("MT")
2020
add_requires("breeze-glfw", {alias = "glfw"})
21-
add_requires("blook 3524a931af49be471840e5312fb0c18e888706fd", "glad",
21+
add_requires("blook dd51b45ad765274a0b5394b70d9982c948e26c74", "glad",
2222
"reflect-cpp", "wintoast v1.3.1", "cpptrace v0.8.3", "breeze-ui")
2323

2424
if has_config("asan") then

0 commit comments

Comments
 (0)