Skip to content

Commit

Permalink
Pass window exclusive and transient properties for subwindow creation
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
alvinhochun committed Jul 24, 2024
1 parent 91eb688 commit 97aa278
Show file tree
Hide file tree
Showing 10 changed files with 45 additions and 25 deletions.
8 changes: 7 additions & 1 deletion platform/linuxbsd/x11/display_server_x11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1735,7 +1735,7 @@ Vector<DisplayServer::WindowID> DisplayServerX11::get_window_list() const {
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_

WindowID id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect);
Expand All @@ -1749,6 +1749,12 @@ DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, V
rendering_device->screen_create(id);
}
#endif

window_set_exclusive(id, p_exclusive);
if (p_transient_parent != INVALID_WINDOW_ID) {
window_set_transient(id, p_transient_parent);
}

return id;
}

Expand Down
2 changes: 1 addition & 1 deletion platform/linuxbsd/x11/display_server_x11.h
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ class DisplayServerX11 : public DisplayServer {

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 delete_sub_window(WindowID p_id) override;

Expand Down
2 changes: 1 addition & 1 deletion platform/macos/display_server_macos.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ class DisplayServerMacOS : public DisplayServer {

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 delete_sub_window(WindowID p_id) override;

Expand Down
8 changes: 7 additions & 1 deletion platform/macos/display_server_macos.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1714,7 +1714,7 @@
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_

WindowID id = _create_window(p_mode, p_vsync_mode, p_rect);
Expand All @@ -1728,6 +1728,12 @@
rendering_device->screen_create(id);
}
#endif

window_set_exclusive(id, p_exclusive);
if (p_transient_parent != INVALID_WINDOW_ID) {
window_set_transient(id, p_transient_parent);
}

return id;
}

Expand Down
28 changes: 23 additions & 5 deletions platform/windows/display_server_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1306,10 +1306,10 @@ DisplayServer::WindowID DisplayServerWindows::get_window_at_screen_position(cons
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_

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.");

WindowData &wd = windows[window_id];
Expand Down Expand Up @@ -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 dwStyle;

Expand Down Expand Up @@ -5376,6 +5376,18 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,

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];

wd.hWnd = CreateWindowExW(
Expand All @@ -5386,7 +5398,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
WindowRect.top,
WindowRect.right - WindowRect.left,
WindowRect.bottom - WindowRect.top,
nullptr,
owner_hwnd,
nullptr,
hInstance,
// tunnel the WindowData we need to handle creation message
Expand All @@ -5408,6 +5420,12 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
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) {
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));
Expand Down Expand Up @@ -6036,7 +6054,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
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.");

joypad = new JoypadWindows(&windows[MAIN_WINDOW_ID].hWnd);
Expand Down
4 changes: 2 additions & 2 deletions platform/windows/display_server_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ class DisplayServerWindows : public DisplayServer {
uint64_t time_since_popup = 0;
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;
RBMap<WindowID, WindowData> windows;

Expand Down Expand Up @@ -652,7 +652,7 @@ class DisplayServerWindows : public DisplayServer {

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 delete_sub_window(WindowID p_window) override;

Expand Down
12 changes: 1 addition & 11 deletions scene/main/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -631,26 +631,16 @@ 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_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);
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_mouse_passthrough(mpath, window_id);
DisplayServer::get_singleton()->window_set_title(tr_title, 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();

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) {
for (const Window *E : transient_children) {
if (E->window_id != DisplayServer::INVALID_WINDOW_ID) {
Expand Down
2 changes: 1 addition & 1 deletion servers/display_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,7 @@ int DisplayServer::get_screen_from_rect(const Rect2 &p_rect) const {
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.");
}

Expand Down
2 changes: 1 addition & 1 deletion servers/display_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ class DisplayServer : public Object {
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 delete_sub_window(WindowID p_id);

Expand Down
2 changes: 1 addition & 1 deletion servers/display_server_headless.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class DisplayServerHeadless : public DisplayServer {

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 delete_sub_window(WindowID p_id) override {}

Expand Down

0 comments on commit 97aa278

Please sign in to comment.