Skip to content

Commit 326a789

Browse files
committed
Refactor window show/hide hooks and add bypass logic
Refactored the window show/hide hook mechanism to allow hooks to intercept and optionally bypass the original show/hide implementation. Added HasWillShowHook and HasWillHideHook checks, and introduced HandleWillShow/HandleWillHide methods. Updated Windows-specific code to support skipping the original implementation if a hook handles the event, and provided methods to call the original show/hide logic if needed.
1 parent 8f60e7c commit 326a789

File tree

3 files changed

+96
-34
lines changed

3 files changed

+96
-34
lines changed

src/capi/window_manager_c.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ native_window_list_t native_window_manager_get_all(void) {
153153
return result;
154154
}
155155

156-
result.count = windows.size();
156+
result.count = static_cast<long>(windows.size());
157157

158158
for (size_t i = 0; i < windows.size(); ++i) {
159159
result.windows[i] = CreateNativeWindowHandle(windows[i]);

src/platform/windows/window_manager_windows.cpp

Lines changed: 80 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ static PFN_ShowWindow g_original_show_window = nullptr;
5555
static PFN_ShowWindowAsync g_original_show_window_async = nullptr;
5656
static bool g_hooks_installed = false;
5757

58-
static bool IsShowCommandVisible(int cmd) {
58+
static bool IsShowCommand(int cmd) {
5959
switch (cmd) {
6060
case SW_SHOW:
6161
case SW_SHOWNORMAL:
@@ -69,42 +69,54 @@ static bool IsShowCommandVisible(int cmd) {
6969
}
7070
}
7171

72-
static void InvokePreShowHideHooks(HWND hwnd, int cmd) {
72+
// Intercept show/hide commands and invoke hooks if registered
73+
// Returns true if hook handled the operation (skip original implementation)
74+
static bool TryHandleWithHook(HWND hwnd, int cmd) {
7375
WindowId window_id = GetWindowIdFromHwnd(hwnd);
7476
if (window_id == IdAllocator::kInvalidId) {
75-
return;
77+
return false;
7678
}
7779

7880
auto& manager = WindowManager::GetInstance();
79-
if (cmd == SW_HIDE) {
80-
manager.InvokeWillHideHook(window_id);
81-
} else if (IsShowCommandVisible(cmd)) {
82-
manager.InvokeWillShowHook(window_id);
81+
82+
if (cmd == SW_HIDE && manager.HasWillHideHook()) {
83+
manager.HandleWillHide(window_id);
84+
return true;
8385
}
86+
87+
if (IsShowCommand(cmd) && manager.HasWillShowHook()) {
88+
manager.HandleWillShow(window_id);
89+
return true;
90+
}
91+
92+
return false;
8493
}
8594

8695
static BOOL WINAPI HookedShowWindow(HWND hwnd, int nCmdShow) {
87-
InvokePreShowHideHooks(hwnd, nCmdShow);
96+
if (TryHandleWithHook(hwnd, nCmdShow)) {
97+
return TRUE;
98+
}
99+
88100
if (g_original_show_window) {
89101
return g_original_show_window(hwnd, nCmdShow);
90102
}
91-
// Fallback to direct call if original not captured
103+
92104
auto p = reinterpret_cast<PFN_ShowWindow>(
93105
GetProcAddress(GetModuleHandleW(L"user32.dll"), "ShowWindow"));
94106
return p ? p(hwnd, nCmdShow) : FALSE;
95107
}
96108

97109
static BOOL WINAPI HookedShowWindowAsync(HWND hwnd, int nCmdShow) {
98-
std::cout << "HookedShowWindowAsync called for hwnd: " << hwnd << " with nCmdShow: " << nCmdShow
99-
<< std::endl;
100-
InvokePreShowHideHooks(hwnd, nCmdShow);
110+
if (TryHandleWithHook(hwnd, nCmdShow)) {
111+
return TRUE;
112+
}
113+
101114
if (g_original_show_window_async) {
102-
std::cout << "Calling original ShowWindowAsync" << std::endl;
103115
return g_original_show_window_async(hwnd, nCmdShow);
104116
}
117+
105118
auto p = reinterpret_cast<PFN_ShowWindowAsync>(
106119
GetProcAddress(GetModuleHandleW(L"user32.dll"), "ShowWindowAsync"));
107-
std::cout << "Calling fallback ShowWindowAsync" << std::endl;
108120
return p ? p(hwnd, nCmdShow) : FALSE;
109121
}
110122

@@ -245,9 +257,10 @@ static void ForEachProcessModule(std::function<void(HMODULE)> fn) {
245257
}
246258
}
247259

248-
static void InstallGlobalShowHooks() {
260+
static void InstallHooks() {
249261
if (g_hooks_installed)
250262
return;
263+
251264
HMODULE user32 = GetModuleHandleW(L"user32.dll");
252265
if (!user32)
253266
user32 = LoadLibraryW(L"user32.dll");
@@ -272,9 +285,10 @@ static void InstallGlobalShowHooks() {
272285
g_hooks_installed = true;
273286
}
274287

275-
static void UninstallGlobalShowHooks() {
288+
static void UninstallHooks() {
276289
if (!g_hooks_installed)
277290
return;
291+
278292
ForEachProcessModule([](HMODULE m) {
279293
if (g_original_show_window) {
280294
RestoreIATInModule(m, reinterpret_cast<FARPROC>(g_original_show_window), "ShowWindow");
@@ -433,37 +447,72 @@ std::shared_ptr<Window> WindowManager::GetCurrent() {
433447

434448
void WindowManager::SetWillShowHook(std::optional<WindowWillShowHook> hook) {
435449
pimpl_->will_show_hook_ = std::move(hook);
436-
// Install or uninstall global hooks based on whether any hook is present
437-
bool has_any = pimpl_->will_show_hook_.has_value() || pimpl_->will_hide_hook_.has_value();
438-
if (has_any) {
439-
InstallGlobalShowHooks();
440-
} else {
441-
UninstallGlobalShowHooks();
442-
}
450+
451+
bool has_any_hook = pimpl_->will_show_hook_.has_value() || pimpl_->will_hide_hook_.has_value();
452+
has_any_hook ? InstallHooks() : UninstallHooks();
443453
}
444454

445455
void WindowManager::SetWillHideHook(std::optional<WindowWillHideHook> hook) {
446456
pimpl_->will_hide_hook_ = std::move(hook);
447-
bool has_any = pimpl_->will_show_hook_.has_value() || pimpl_->will_hide_hook_.has_value();
448-
if (has_any) {
449-
InstallGlobalShowHooks();
450-
} else {
451-
UninstallGlobalShowHooks();
452-
}
457+
458+
bool has_any_hook = pimpl_->will_show_hook_.has_value() || pimpl_->will_hide_hook_.has_value();
459+
has_any_hook ? InstallHooks() : UninstallHooks();
453460
}
454461

455-
void WindowManager::InvokeWillShowHook(WindowId id) {
462+
bool WindowManager::HasWillShowHook() const {
463+
return pimpl_->will_show_hook_.has_value();
464+
}
465+
466+
bool WindowManager::HasWillHideHook() const {
467+
return pimpl_->will_hide_hook_.has_value();
468+
}
469+
470+
void WindowManager::HandleWillShow(WindowId id) {
456471
if (pimpl_->will_show_hook_) {
457472
(*pimpl_->will_show_hook_)(id);
458473
}
459474
}
460475

461-
void WindowManager::InvokeWillHideHook(WindowId id) {
476+
void WindowManager::HandleWillHide(WindowId id) {
462477
if (pimpl_->will_hide_hook_) {
463478
(*pimpl_->will_hide_hook_)(id);
464479
}
465480
}
466481

482+
bool WindowManager::CallOriginalShow(WindowId id) {
483+
auto window = Get(id);
484+
if (!window) {
485+
return false;
486+
}
487+
void* native = window->GetNativeObject();
488+
if (!native) {
489+
return false;
490+
}
491+
HWND hwnd = static_cast<HWND>(native);
492+
// On Windows, call the original ShowWindow through the function pointer
493+
if (g_original_show_window) {
494+
return g_original_show_window(hwnd, SW_SHOW) != FALSE;
495+
}
496+
return false;
497+
}
498+
499+
bool WindowManager::CallOriginalHide(WindowId id) {
500+
auto window = Get(id);
501+
if (!window) {
502+
return false;
503+
}
504+
void* native = window->GetNativeObject();
505+
if (!native) {
506+
return false;
507+
}
508+
HWND hwnd = static_cast<HWND>(native);
509+
// On Windows, call the original ShowWindow through the function pointer
510+
if (g_original_show_window) {
511+
return g_original_show_window(hwnd, SW_HIDE) != FALSE;
512+
}
513+
return false;
514+
}
515+
467516
void WindowManager::StartEventListening() {
468517
pimpl_->StartEventListening();
469518
}

src/platform/windows/window_windows.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,24 @@ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l
3636
WindowId window_id = static_cast<WindowId>(reinterpret_cast<uintptr_t>(prop_handle));
3737
if (window_id != IdAllocator::kInvalidId) {
3838
auto& manager = WindowManager::GetInstance();
39+
bool hook_handled = false;
40+
3941
if (pos->flags & SWP_SHOWWINDOW) {
40-
manager.InvokeWillShowHook(window_id);
42+
if (manager.HasWillShowHook()) {
43+
manager.HandleWillShow(window_id);
44+
hook_handled = true;
45+
}
4146
}
4247
if (pos->flags & SWP_HIDEWINDOW) {
43-
manager.InvokeWillHideHook(window_id);
48+
if (manager.HasWillHideHook()) {
49+
manager.HandleWillHide(window_id);
50+
hook_handled = true;
51+
}
52+
}
53+
54+
// If hook handled it, cancel the visibility change
55+
if (hook_handled) {
56+
pos->flags &= ~(SWP_SHOWWINDOW | SWP_HIDEWINDOW);
4457
}
4558
}
4659
}

0 commit comments

Comments
 (0)