Pass window exclusive and transient properties for subwindow creation

On Windows this allows to avoid having to change the owner of the window
after it has been created, which in rare circumstances may cause the
window to bug out.
This commit is contained in:
Alvin Wong 2024-07-25 00:20:31 +08:00
parent 91eb688e17
commit 97aa278edb
10 changed files with 45 additions and 25 deletions

View File

@ -1735,7 +1735,7 @@ Vector<DisplayServer::WindowID> DisplayServerX11::get_window_list() const {
return ret; return ret;
} }
DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) { DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, bool p_exclusive, WindowID p_transient_parent) {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
WindowID id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect); WindowID id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect);
@ -1749,6 +1749,12 @@ DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, V
rendering_device->screen_create(id); rendering_device->screen_create(id);
} }
#endif #endif
window_set_exclusive(id, p_exclusive);
if (p_transient_parent != INVALID_WINDOW_ID) {
window_set_transient(id, p_transient_parent);
}
return id; return id;
} }

View File

@ -438,7 +438,7 @@ public:
virtual Vector<DisplayServer::WindowID> get_window_list() const override; virtual Vector<DisplayServer::WindowID> get_window_list() const override;
virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override; virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i(), bool p_exclusive = false, WindowID p_transient_parent = INVALID_WINDOW_ID) override;
virtual void show_window(WindowID p_id) override; virtual void show_window(WindowID p_id) override;
virtual void delete_sub_window(WindowID p_id) override; virtual void delete_sub_window(WindowID p_id) override;

View File

@ -326,7 +326,7 @@ public:
virtual Vector<int> get_window_list() const override; virtual Vector<int> get_window_list() const override;
virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override; virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i(), bool p_exclusive = false, WindowID p_transient_parent = INVALID_WINDOW_ID) override;
virtual void show_window(WindowID p_id) override; virtual void show_window(WindowID p_id) override;
virtual void delete_sub_window(WindowID p_id) override; virtual void delete_sub_window(WindowID p_id) override;

View File

@ -1714,7 +1714,7 @@ Vector<DisplayServer::WindowID> DisplayServerMacOS::get_window_list() const {
return ret; return ret;
} }
DisplayServer::WindowID DisplayServerMacOS::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) { DisplayServer::WindowID DisplayServerMacOS::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, bool p_exclusive, WindowID p_transient_parent) {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
WindowID id = _create_window(p_mode, p_vsync_mode, p_rect); WindowID id = _create_window(p_mode, p_vsync_mode, p_rect);
@ -1728,6 +1728,12 @@ DisplayServer::WindowID DisplayServerMacOS::create_sub_window(WindowMode p_mode,
rendering_device->screen_create(id); rendering_device->screen_create(id);
} }
#endif #endif
window_set_exclusive(id, p_exclusive);
if (p_transient_parent != INVALID_WINDOW_ID) {
window_set_transient(id, p_transient_parent);
}
return id; return id;
} }

View File

@ -1306,10 +1306,10 @@ DisplayServer::WindowID DisplayServerWindows::get_window_at_screen_position(cons
return INVALID_WINDOW_ID; return INVALID_WINDOW_ID;
} }
DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) { DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, bool p_exclusive, WindowID p_transient_parent) {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
WindowID window_id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect); WindowID window_id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect, p_exclusive, p_transient_parent);
ERR_FAIL_COND_V_MSG(window_id == INVALID_WINDOW_ID, INVALID_WINDOW_ID, "Failed to create sub window."); ERR_FAIL_COND_V_MSG(window_id == INVALID_WINDOW_ID, INVALID_WINDOW_ID, "Failed to create sub window.");
WindowData &wd = windows[window_id]; WindowData &wd = windows[window_id];
@ -5326,7 +5326,7 @@ void DisplayServerWindows::_update_tablet_ctx(const String &p_old_driver, const
} }
} }
DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) { DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, bool p_exclusive, WindowID p_transient_parent) {
DWORD dwExStyle; DWORD dwExStyle;
DWORD dwStyle; DWORD dwStyle;
@ -5376,6 +5376,18 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
WindowID id = window_id_counter; WindowID id = window_id_counter;
{ {
WindowData *wd_transient_parent = nullptr;
HWND owner_hwnd = nullptr;
if (p_transient_parent != INVALID_WINDOW_ID && !windows.has(p_transient_parent)) {
ERR_PRINT("Condition \"!windows.has(p_transient_parent)\" is true.");
p_transient_parent = INVALID_WINDOW_ID;
} else {
wd_transient_parent = &windows[p_transient_parent];
if (p_exclusive) {
owner_hwnd = wd_transient_parent->hWnd;
}
}
WindowData &wd = windows[id]; WindowData &wd = windows[id];
wd.hWnd = CreateWindowExW( wd.hWnd = CreateWindowExW(
@ -5386,7 +5398,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
WindowRect.top, WindowRect.top,
WindowRect.right - WindowRect.left, WindowRect.right - WindowRect.left,
WindowRect.bottom - WindowRect.top, WindowRect.bottom - WindowRect.top,
nullptr, owner_hwnd,
nullptr, nullptr,
hInstance, hInstance,
// tunnel the WindowData we need to handle creation message // tunnel the WindowData we need to handle creation message
@ -5408,6 +5420,12 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
wd.pre_fs_valid = true; wd.pre_fs_valid = true;
} }
wd.exclusive = p_exclusive;
if (wd_transient_parent) {
wd.transient_parent = p_transient_parent;
wd_transient_parent->transient_children.insert(id);
}
if (is_dark_mode_supported() && dark_title_available) { if (is_dark_mode_supported() && dark_title_available) {
BOOL value = is_dark_mode(); BOOL value = is_dark_mode();
::DwmSetWindowAttribute(wd.hWnd, use_legacy_dark_mode_before_20H1 ? DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 : DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value)); ::DwmSetWindowAttribute(wd.hWnd, use_legacy_dark_mode_before_20H1 ? DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 : DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));
@ -6036,7 +6054,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
window_position = scr_rect.position + (scr_rect.size - p_resolution) / 2; window_position = scr_rect.position + (scr_rect.size - p_resolution) / 2;
} }
WindowID main_window = _create_window(p_mode, p_vsync_mode, p_flags, Rect2i(window_position, p_resolution)); WindowID main_window = _create_window(p_mode, p_vsync_mode, p_flags, Rect2i(window_position, p_resolution), false, INVALID_WINDOW_ID);
ERR_FAIL_COND_MSG(main_window == INVALID_WINDOW_ID, "Failed to create main window."); ERR_FAIL_COND_MSG(main_window == INVALID_WINDOW_ID, "Failed to create main window.");
joypad = new JoypadWindows(&windows[MAIN_WINDOW_ID].hWnd); joypad = new JoypadWindows(&windows[MAIN_WINDOW_ID].hWnd);

View File

@ -517,7 +517,7 @@ class DisplayServerWindows : public DisplayServer {
uint64_t time_since_popup = 0; uint64_t time_since_popup = 0;
Ref<Image> icon; Ref<Image> icon;
WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect); WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, bool p_exclusive, WindowID p_transient_parent);
WindowID window_id_counter = MAIN_WINDOW_ID; WindowID window_id_counter = MAIN_WINDOW_ID;
RBMap<WindowID, WindowData> windows; RBMap<WindowID, WindowData> windows;
@ -652,7 +652,7 @@ public:
virtual Vector<DisplayServer::WindowID> get_window_list() const override; virtual Vector<DisplayServer::WindowID> get_window_list() const override;
virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override; virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i(), bool p_exclusive = false, WindowID p_transient_parent = INVALID_WINDOW_ID) override;
virtual void show_window(WindowID p_window) override; virtual void show_window(WindowID p_window) override;
virtual void delete_sub_window(WindowID p_window) override; virtual void delete_sub_window(WindowID p_window) override;

View File

@ -631,7 +631,7 @@ void Window::_make_window() {
window_rect = Rect2i(DisplayServer::get_singleton()->screen_get_position(DisplayServer::SCREEN_WITH_KEYBOARD_FOCUS) + (DisplayServer::get_singleton()->screen_get_size(DisplayServer::SCREEN_WITH_KEYBOARD_FOCUS) - size) / 2, size); window_rect = Rect2i(DisplayServer::get_singleton()->screen_get_position(DisplayServer::SCREEN_WITH_KEYBOARD_FOCUS) + (DisplayServer::get_singleton()->screen_get_size(DisplayServer::SCREEN_WITH_KEYBOARD_FOCUS) - size) / 2, size);
} }
window_id = DisplayServer::get_singleton()->create_sub_window(DisplayServer::WindowMode(mode), vsync_mode, f, window_rect); window_id = DisplayServer::get_singleton()->create_sub_window(DisplayServer::WindowMode(mode), vsync_mode, f, window_rect, is_in_edited_scene_root() ? false : exclusive, transient_parent ? transient_parent->window_id : DisplayServer::INVALID_WINDOW_ID);
ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID); ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID);
DisplayServer::get_singleton()->window_set_max_size(Size2i(), window_id); DisplayServer::get_singleton()->window_set_max_size(Size2i(), window_id);
DisplayServer::get_singleton()->window_set_min_size(Size2i(), window_id); DisplayServer::get_singleton()->window_set_min_size(Size2i(), window_id);
@ -639,18 +639,8 @@ void Window::_make_window() {
DisplayServer::get_singleton()->window_set_title(tr_title, window_id); DisplayServer::get_singleton()->window_set_title(tr_title, window_id);
DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id); DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id);
if (is_in_edited_scene_root()) {
DisplayServer::get_singleton()->window_set_exclusive(window_id, false);
} else {
DisplayServer::get_singleton()->window_set_exclusive(window_id, exclusive);
}
_update_window_size(); _update_window_size();
if (transient_parent && transient_parent->window_id != DisplayServer::INVALID_WINDOW_ID) {
DisplayServer::get_singleton()->window_set_transient(window_id, transient_parent->window_id);
}
if (transient_parent) { if (transient_parent) {
for (const Window *E : transient_children) { for (const Window *E : transient_children) {
if (E->window_id != DisplayServer::INVALID_WINDOW_ID) { if (E->window_id != DisplayServer::INVALID_WINDOW_ID) {

View File

@ -570,7 +570,7 @@ int DisplayServer::get_screen_from_rect(const Rect2 &p_rect) const {
return pos_screen; return pos_screen;
} }
DisplayServer::WindowID DisplayServer::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) { DisplayServer::WindowID DisplayServer::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, bool p_exclusive, WindowID p_transient_parent) {
ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Sub-windows not supported by this display server."); ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Sub-windows not supported by this display server.");
} }

View File

@ -396,7 +396,7 @@ public:
WINDOW_FLAG_MOUSE_PASSTHROUGH_BIT = (1 << WINDOW_FLAG_MOUSE_PASSTHROUGH), WINDOW_FLAG_MOUSE_PASSTHROUGH_BIT = (1 << WINDOW_FLAG_MOUSE_PASSTHROUGH),
}; };
virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()); virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i(), bool p_exclusive = false, WindowID p_transient_parent = INVALID_WINDOW_ID);
virtual void show_window(WindowID p_id); virtual void show_window(WindowID p_id);
virtual void delete_sub_window(WindowID p_id); virtual void delete_sub_window(WindowID p_id);

View File

@ -85,7 +85,7 @@ public:
Vector<DisplayServer::WindowID> get_window_list() const override { return Vector<DisplayServer::WindowID>(); } Vector<DisplayServer::WindowID> get_window_list() const override { return Vector<DisplayServer::WindowID>(); }
WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override { return 0; } WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i(), bool p_exclusive = false, WindowID p_transient_parent = INVALID_WINDOW_ID) override { return 0; }
void show_window(WindowID p_id) override {} void show_window(WindowID p_id) override {}
void delete_sub_window(WindowID p_id) override {} void delete_sub_window(WindowID p_id) override {}