Skip to content

Commit c510a21

Browse files
committed
Implement consistent WindowId allocation for Linux windows
Replaces pointer casting with a thread-safe mapping from GdkWindow pointers to WindowIds using IdAllocator. Ensures consistent WindowId retrieval and management across window and window manager implementations, improving reliability and future extensibility.
1 parent 563c727 commit c510a21

File tree

2 files changed

+65
-7
lines changed

2 files changed

+65
-7
lines changed

src/platform/linux/window_linux.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#include <iostream>
2+
#include <unordered_map>
3+
#include <mutex>
24
#include "../../window.h"
35
#include "../../window_manager.h"
46

@@ -22,8 +24,27 @@ Window::Window(void* window) : pimpl_(std::make_unique<Impl>((GdkWindow*)window)
2224
Window::~Window() {}
2325

2426
WindowId Window::GetId() const {
25-
// Use pointer address as ID since GDK doesn't provide direct window IDs
26-
return pimpl_->gdk_window_ ? (WindowId)pimpl_->gdk_window_ : 0;
27+
// Use IdAllocator to generate unique IDs instead of casting pointers
28+
if (!pimpl_->gdk_window_) {
29+
return IdAllocator::kInvalidId;
30+
}
31+
32+
// Store the allocated ID in a static map to ensure consistency
33+
static std::unordered_map<GdkWindow*, WindowId> window_id_map;
34+
static std::mutex map_mutex;
35+
36+
std::lock_guard<std::mutex> lock(map_mutex);
37+
auto it = window_id_map.find(pimpl_->gdk_window_);
38+
if (it != window_id_map.end()) {
39+
return it->second;
40+
}
41+
42+
// Allocate new ID using the IdAllocator
43+
WindowId new_id = IdAllocator::Allocate<Window>();
44+
if (new_id != IdAllocator::kInvalidId) {
45+
window_id_map[pimpl_->gdk_window_] = new_id;
46+
}
47+
return new_id;
2748
}
2849

2950
void Window::Focus() {

src/platform/linux/window_manager_linux.cpp

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include <cstring>
22
#include <iostream>
33
#include <string>
4+
#include <unordered_map>
5+
#include <mutex>
46

57
#include "../../window.h"
68
#include "../../window_manager.h"
@@ -11,6 +13,41 @@
1113

1214
namespace nativeapi {
1315

16+
// Shared static variables for window ID mapping
17+
static std::unordered_map<GdkWindow*, WindowId> g_window_id_map;
18+
static std::mutex g_map_mutex;
19+
20+
// Helper function to manage mapping between GdkWindow pointers and WindowIds
21+
static WindowId GetOrCreateWindowId(GdkWindow* gdk_window) {
22+
if (!gdk_window) {
23+
return IdAllocator::kInvalidId;
24+
}
25+
26+
std::lock_guard<std::mutex> lock(g_map_mutex);
27+
auto it = g_window_id_map.find(gdk_window);
28+
if (it != g_window_id_map.end()) {
29+
return it->second;
30+
}
31+
32+
// Allocate new ID using the IdAllocator
33+
WindowId new_id = IdAllocator::Allocate<Window>();
34+
if (new_id != IdAllocator::kInvalidId) {
35+
g_window_id_map[gdk_window] = new_id;
36+
}
37+
return new_id;
38+
}
39+
40+
// Helper function to find GdkWindow by WindowId
41+
static GdkWindow* FindGdkWindowById(WindowId id) {
42+
std::lock_guard<std::mutex> lock(g_map_mutex);
43+
for (const auto& pair : g_window_id_map) {
44+
if (pair.second == id) {
45+
return pair.first;
46+
}
47+
}
48+
return nullptr;
49+
}
50+
1451
// Private implementation for Linux (stub for now)
1552
class WindowManager::Impl {
1653
public:
@@ -86,7 +123,7 @@ std::shared_ptr<Window> WindowManager::Get(WindowId id) {
86123
GtkWindow* gtk_window = GTK_WINDOW(l->data);
87124
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(gtk_window));
88125

89-
if (gdk_window && (WindowId)gdk_window == id) {
126+
if (gdk_window && GetOrCreateWindowId(gdk_window) == id) {
90127
auto window = std::make_shared<Window>((void*)gdk_window);
91128
windows_[id] = window;
92129
g_list_free(toplevels);
@@ -112,7 +149,7 @@ std::vector<std::shared_ptr<Window>> WindowManager::GetAll() {
112149
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(gtk_window));
113150

114151
if (gdk_window) {
115-
WindowId window_id = (WindowId)gdk_window;
152+
WindowId window_id = GetOrCreateWindowId(gdk_window);
116153
auto it = windows_.find(window_id);
117154
if (it == windows_.end()) {
118155
auto window = std::make_shared<Window>((void*)gdk_window);
@@ -142,7 +179,7 @@ std::shared_ptr<Window> WindowManager::GetCurrent() {
142179
if (keyboard) {
143180
GdkWindow* focused_window = gdk_device_get_window_at_position(keyboard, nullptr, nullptr);
144181
if (focused_window) {
145-
WindowId window_id = (WindowId)focused_window;
182+
WindowId window_id = GetOrCreateWindowId(focused_window);
146183
return Get(window_id);
147184
}
148185
}
@@ -155,7 +192,7 @@ std::shared_ptr<Window> WindowManager::GetCurrent() {
155192
if (gtk_widget_get_visible(GTK_WIDGET(gtk_window))) {
156193
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(gtk_window));
157194
if (gdk_window) {
158-
WindowId window_id = (WindowId)gdk_window;
195+
WindowId window_id = GetOrCreateWindowId(gdk_window);
159196
g_list_free(toplevels);
160197
return Get(window_id);
161198
}
@@ -231,7 +268,7 @@ std::shared_ptr<Window> WindowManager::Create(const WindowOptions& options) {
231268

232269
// Create our Window wrapper
233270
auto window = std::make_shared<Window>((void*)gdk_window);
234-
WindowId window_id = (WindowId)gdk_window;
271+
WindowId window_id = GetOrCreateWindowId(gdk_window);
235272

236273
// Store in our cache
237274
windows_[window_id] = window;

0 commit comments

Comments
 (0)