11#include < windows.h>
22#include < iostream>
3- #include < mutex>
4- #include < unordered_map>
53#include " ../../foundation/id_allocator.h"
64#include " ../../window.h"
75#include " ../../window_manager.h"
119
1210namespace nativeapi {
1311
12+ // Property name for storing window ID in HWND
13+ static const wchar_t * kWindowIdProperty = L" NativeAPIWindowId" ;
14+
1415// Forward declaration
1516static LRESULT CALLBACK WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
1617
1718// Private implementation class
1819class Window ::Impl {
1920 public:
20- Impl (HWND hwnd) : hwnd_(hwnd) {}
21+ Impl (HWND hwnd, WindowId id ) : hwnd_(hwnd), window_id_(id ) {}
2122 HWND hwnd_;
23+ WindowId window_id_;
2224};
2325
2426// Custom window procedure to handle window messages
@@ -28,14 +30,19 @@ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l
2830 // Intercept visibility changes BEFORE they happen (pre-show/hide "swizzle")
2931 WINDOWPOS* pos = reinterpret_cast <WINDOWPOS*>(lParam);
3032 if (pos) {
31- auto & manager = WindowManager::GetInstance ();
32- Window temp_window (hwnd);
33- WindowId window_id = temp_window.GetId ();
34- if (pos->flags & SWP_SHOWWINDOW) {
35- manager.InvokeWillShowHook (window_id);
36- }
37- if (pos->flags & SWP_HIDEWINDOW) {
38- manager.InvokeWillHideHook (window_id);
33+ // Get window ID from window's custom property (stored during window creation)
34+ HANDLE prop_handle = GetProp (hwnd, kWindowIdProperty );
35+ if (prop_handle) {
36+ WindowId window_id = static_cast <WindowId>(reinterpret_cast <uintptr_t >(prop_handle));
37+ if (window_id != IdAllocator::kInvalidId ) {
38+ auto & manager = WindowManager::GetInstance ();
39+ if (pos->flags & SWP_SHOWWINDOW) {
40+ manager.InvokeWillShowHook (window_id);
41+ }
42+ if (pos->flags & SWP_HIDEWINDOW) {
43+ manager.InvokeWillHideHook (window_id);
44+ }
45+ }
3946 }
4047 }
4148 return DefWindowProc (hwnd, uMsg, wParam, lParam);
@@ -75,7 +82,9 @@ Window::Window() {
7582 DWORD error = GetLastError ();
7683 if (error != ERROR_CLASS_ALREADY_EXISTS) {
7784 std::cerr << " Failed to register window class. Error: " << error << std::endl;
78- pimpl_ = std::make_unique<Impl>(nullptr );
85+ // Allocate ID even for failed window creation to maintain consistency
86+ WindowId id = IdAllocator::Allocate<Window>();
87+ pimpl_ = std::make_unique<Impl>(nullptr , id);
7988 return ;
8089 }
8190 class_registered = true ;
@@ -91,18 +100,78 @@ Window::Window() {
91100
92101 if (!hwnd) {
93102 std::cerr << " Failed to create window. Error: " << GetLastError () << std::endl;
94- pimpl_ = std::make_unique<Impl>(nullptr );
103+ // Allocate ID even for failed window creation to maintain consistency
104+ WindowId id = IdAllocator::Allocate<Window>();
105+ pimpl_ = std::make_unique<Impl>(nullptr , id);
95106 return ;
96107 }
97108
98- // Only create the instance, don't show the window
99- pimpl_ = std::make_unique<Impl>(hwnd);
109+ // Allocate window ID using IdAllocator
110+ WindowId id = IdAllocator::Allocate<Window>();
111+ if (id == IdAllocator::kInvalidId ) {
112+ std::cerr << " Failed to allocate window ID" << std::endl;
113+ DestroyWindow (hwnd);
114+ pimpl_ = std::make_unique<Impl>(nullptr , IdAllocator::kInvalidId );
115+ return ;
116+ }
117+
118+ // Store window ID as a custom property in HWND for easy retrieval in WindowProc
119+ SetProp (hwnd, kWindowIdProperty , reinterpret_cast <HANDLE>(static_cast <uintptr_t >(id)));
120+
121+ // Create the instance with allocated ID
122+ pimpl_ = std::make_unique<Impl>(hwnd, id);
123+
124+ // Note: Window registration in WindowRegistry is now handled by WindowManager::GetAll()
125+ // which uses EnumWindows to discover and register all windows dynamically
100126}
101127
102- Window::Window (void * native_window)
103- : pimpl_(std::make_unique<Impl>(static_cast <HWND>(native_window))) {}
128+ Window::Window (void * native_window) {
129+ HWND hwnd = static_cast <HWND>(native_window);
130+
131+ if (!hwnd) {
132+ // Allocate ID even for null window to maintain consistency
133+ WindowId id = IdAllocator::Allocate<Window>();
134+ pimpl_ = std::make_unique<Impl>(nullptr , id);
135+ return ;
136+ }
137+
138+ // Check if window already has an ID stored as a custom property
139+ HANDLE prop_handle = GetProp (hwnd, kWindowIdProperty );
140+ WindowId id = IdAllocator::kInvalidId ;
141+
142+ if (prop_handle) {
143+ id = static_cast <WindowId>(reinterpret_cast <uintptr_t >(prop_handle));
144+ }
145+
146+ if (id == IdAllocator::kInvalidId || id == 0 ) {
147+ // Allocate new ID if window doesn't have one
148+ id = IdAllocator::Allocate<Window>();
149+ if (id == IdAllocator::kInvalidId ) {
150+ std::cerr << " Failed to allocate window ID" << std::endl;
151+ pimpl_ = std::make_unique<Impl>(nullptr , IdAllocator::kInvalidId );
152+ return ;
153+ }
154+ // Store the ID as a custom property in HWND
155+ SetProp (hwnd, kWindowIdProperty , reinterpret_cast <HANDLE>(static_cast <uintptr_t >(id)));
156+ }
157+
158+ pimpl_ = std::make_unique<Impl>(hwnd, id);
104159
105- Window::~Window () {}
160+ // Note: Window registration in WindowRegistry is now handled by WindowManager::GetAll()
161+ // which uses EnumWindows to discover and register all windows dynamically
162+ }
163+
164+ Window::~Window () {
165+ // Remove window from registry on destruction
166+ if (pimpl_ && pimpl_->window_id_ != IdAllocator::kInvalidId ) {
167+ WindowRegistry::GetInstance ().Remove (pimpl_->window_id_ );
168+
169+ // Remove the custom property from HWND if window is still valid
170+ if (pimpl_->hwnd_ ) {
171+ RemoveProp (pimpl_->hwnd_ , kWindowIdProperty );
172+ }
173+ }
174+ }
106175
107176void Window::Focus () {
108177 if (pimpl_->hwnd_ ) {
@@ -654,36 +723,10 @@ void Window::StartResizing() {
654723}
655724
656725WindowId Window::GetId () const {
657- // Use IdAllocator to generate unique IDs instead of casting pointers
658- if (!pimpl_->hwnd_ ) {
726+ if (!pimpl_) {
659727 return IdAllocator::kInvalidId ;
660728 }
661-
662- // Store the allocated ID in a static map to ensure consistency
663- static std::unordered_map<HWND, WindowId> window_id_map;
664- static std::mutex map_mutex;
665-
666- std::lock_guard<std::mutex> lock (map_mutex);
667- auto it = window_id_map.find (pimpl_->hwnd_ );
668- if (it != window_id_map.end ()) {
669- return it->second ;
670- }
671-
672- // Allocate new ID using the IdAllocator
673- WindowId new_id = IdAllocator::Allocate<Window>();
674- if (new_id != IdAllocator::kInvalidId ) {
675- window_id_map[pimpl_->hwnd_ ] = new_id;
676-
677- // Register window in registry (delayed registration)
678- // This requires the Window to be managed by shared_ptr
679- try {
680- WindowRegistry::GetInstance ().Add (new_id, const_cast <Window*>(this )->shared_from_this ());
681- } catch (const std::bad_weak_ptr&) {
682- // Window not yet managed by shared_ptr, skip registration
683- // Registration will happen when window is properly managed by shared_ptr
684- }
685- }
686- return new_id;
729+ return pimpl_->window_id_ ;
687730}
688731
689732void * Window::GetNativeObjectInternal () const {
0 commit comments