11#include " window_proc_delegate_manager.h"
2+ #include < windows.h>
3+ #include < iostream>
24
35namespace nativeapi {
46
@@ -7,6 +9,108 @@ WindowProcDelegateManager& WindowProcDelegateManager::GetInstance() {
79 return instance;
810}
911
12+ LRESULT CALLBACK WindowProcDelegateManager::InternalWindowProc (HWND hwnd,
13+ UINT message,
14+ WPARAM wparam,
15+ LPARAM lparam) {
16+ WindowProcDelegateManager& manager = GetInstance ();
17+ std::lock_guard<std::mutex> lock (manager.mutex_ );
18+
19+ // Dispatch message to all registered delegates
20+ for (const auto & pair : manager.delegates_ ) {
21+ const auto & delegate = pair.second ;
22+ if (delegate) {
23+ auto result = delegate (hwnd, message, wparam, lparam);
24+ if (result.has_value ()) {
25+ return result.value ();
26+ }
27+ }
28+ }
29+
30+ // If no delegate handled the message, call the original WindowProc
31+ if (manager.original_window_proc_ ) {
32+ return CallWindowProc (manager.original_window_proc_ , hwnd, message, wparam,
33+ lparam);
34+ }
35+
36+ // Fallback to DefWindowProc if no original proc is available
37+ return DefWindowProc (hwnd, message, wparam, lparam);
38+ }
39+
40+ HWND WindowProcDelegateManager::GetTopLevelWindow () {
41+ // Try to get the foreground window first
42+ HWND hwnd = GetForegroundWindow ();
43+ if (hwnd && IsWindow (hwnd)) {
44+ return hwnd;
45+ }
46+
47+ // If no foreground window, try to get the active window
48+ hwnd = GetActiveWindow ();
49+ if (hwnd && IsWindow (hwnd)) {
50+ return hwnd;
51+ }
52+
53+ // If still no window, try to find any top-level window
54+ hwnd = FindWindow (nullptr , nullptr );
55+ if (hwnd && IsWindow (hwnd)) {
56+ return hwnd;
57+ }
58+
59+ return nullptr ;
60+ }
61+
62+ void WindowProcDelegateManager::SetupInternalWindowProc () {
63+ if (window_proc_hooked_) {
64+ return ; // Already hooked
65+ }
66+
67+ top_level_window_ = GetTopLevelWindow ();
68+ if (!top_level_window_) {
69+ std::cerr << " Failed to get top level window for WindowProc hooking"
70+ << std::endl;
71+ return ;
72+ }
73+
74+ // Store the original WindowProc
75+ original_window_proc_ = reinterpret_cast <WNDPROC>(
76+ GetWindowLongPtr (top_level_window_, GWLP_WNDPROC));
77+ if (!original_window_proc_) {
78+ std::cerr << " Failed to get original WindowProc" << std::endl;
79+ return ;
80+ }
81+
82+ // Set our internal WindowProc
83+ if (SetWindowLongPtr (top_level_window_, GWLP_WNDPROC,
84+ reinterpret_cast <LONG_PTR>(InternalWindowProc)) == 0 ) {
85+ DWORD error = GetLastError ();
86+ std::cerr << " Failed to set internal WindowProc. Error: " << error
87+ << std::endl;
88+ return ;
89+ }
90+
91+ window_proc_hooked_ = true ;
92+ }
93+
94+ void WindowProcDelegateManager::RestoreOriginalWindowProc () {
95+ if (!window_proc_hooked_ || !top_level_window_ || !original_window_proc_) {
96+ return ;
97+ }
98+
99+ // Restore the original WindowProc
100+ if (SetWindowLongPtr (top_level_window_, GWLP_WNDPROC,
101+ reinterpret_cast <LONG_PTR>(original_window_proc_)) ==
102+ 0 ) {
103+ DWORD error = GetLastError ();
104+ std::cerr << " Failed to restore original WindowProc. Error: " << error
105+ << std::endl;
106+ }
107+
108+ // Reset state
109+ window_proc_hooked_ = false ;
110+ top_level_window_ = nullptr ;
111+ original_window_proc_ = nullptr ;
112+ }
113+
10114int WindowProcDelegateManager::RegisterDelegate (WindowProcDelegate delegate) {
11115 if (!delegate) {
12116 return -1 ;
@@ -16,6 +120,12 @@ int WindowProcDelegateManager::RegisterDelegate(WindowProcDelegate delegate) {
16120
17121 int id = next_id_++;
18122 delegates_[id] = std::move (delegate);
123+
124+ // If this is the first delegate, setup the internal WindowProc
125+ if (delegates_.size () == 1 ) {
126+ SetupInternalWindowProc ();
127+ }
128+
19129 return id;
20130}
21131
@@ -29,6 +139,12 @@ bool WindowProcDelegateManager::UnregisterDelegate(int id) {
29139 auto it = delegates_.find (id);
30140 if (it != delegates_.end ()) {
31141 delegates_.erase (it);
142+
143+ // If no delegates remain, restore the original WindowProc
144+ if (delegates_.empty ()) {
145+ RestoreOriginalWindowProc ();
146+ }
147+
32148 return true ;
33149 }
34150
0 commit comments