From 4df96fc7ab5c12bc902a87fcff297756cac655e0 Mon Sep 17 00:00:00 2001 From: Riteo Siuga Date: Tue, 21 Oct 2025 08:15:25 +0200 Subject: [PATCH] Wayland: Set window parent before commit Fixes a timing issue where dialogs got configured right before having their parent set. This gave compositors the time to resize/rearrange the dialog as if it were a normal window, only to be marked as "floating" right away. On niri, this manifested as huge dialog windows. This is achieved with the addition of a `p_parent_id` parameter to `window_create`, akin to its popup counterpart. `window_create` now also accepts a single `Size2i` parameter instead of two integers, in line with the rest of the `WaylandThread` API. The original idea was to have a very "barebones" API, akin to the `drivers/` directory, but that didn't pan out. --- platform/linuxbsd/wayland/display_server_wayland.cpp | 6 +----- platform/linuxbsd/wayland/wayland_thread.cpp | 12 +++++++++--- platform/linuxbsd/wayland/wayland_thread.h | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp index 62b6271d7a5..34df102564f 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.cpp +++ b/platform/linuxbsd/wayland/display_server_wayland.cpp @@ -774,16 +774,12 @@ void DisplayServerWayland::show_window(WindowID p_window_id) { wd.rect.position = Point2i(); DEBUG_LOG_WAYLAND(vformat("Creating regular window of size %s", wd.rect.size)); - wayland_thread.window_create(p_window_id, wd.rect.size.width, wd.rect.size.height); + wayland_thread.window_create(p_window_id, wd.rect.size, wd.parent_id); wayland_thread.window_set_min_size(p_window_id, wd.min_size); wayland_thread.window_set_max_size(p_window_id, wd.max_size); wayland_thread.window_set_app_id(p_window_id, _get_app_id_from_context(context)); wayland_thread.window_set_borderless(p_window_id, window_get_flag(WINDOW_FLAG_BORDERLESS, p_window_id)); - if (wd.parent_id != INVALID_WINDOW_ID) { - wayland_thread.window_set_parent(wd.id, wd.parent_id); - } - // Since it can't have a position. Let's tell the window node the news by // the actual rect to it. if (wd.rect_changed_callback.is_valid()) { diff --git a/platform/linuxbsd/wayland/wayland_thread.cpp b/platform/linuxbsd/wayland/wayland_thread.cpp index a845f40c0d6..423554ea411 100644 --- a/platform/linuxbsd/wayland/wayland_thread.cpp +++ b/platform/linuxbsd/wayland/wayland_thread.cpp @@ -3536,7 +3536,7 @@ Ref WaylandThread::pop_message() { return Ref(); } -void WaylandThread::window_create(DisplayServer::WindowID p_window_id, int p_width, int p_height) { +void WaylandThread::window_create(DisplayServer::WindowID p_window_id, const Size2i &p_size, DisplayServer::WindowID p_parent_id) { ERR_FAIL_COND(windows.has(p_window_id)); WindowState &ws = windows[p_window_id]; @@ -3545,8 +3545,7 @@ void WaylandThread::window_create(DisplayServer::WindowID p_window_id, int p_wid ws.registry = ®istry; ws.wayland_thread = this; - ws.rect.size.width = p_width; - ws.rect.size.height = p_height; + ws.rect.size = p_size; ws.wl_surface = wl_compositor_create_surface(registry.wl_compositor); wl_proxy_tag_godot((struct wl_proxy *)ws.wl_surface); @@ -3601,6 +3600,13 @@ void WaylandThread::window_create(DisplayServer::WindowID p_window_id, int p_wid } } + if (p_parent_id != DisplayServer::INVALID_WINDOW_ID) { + // NOTE: It's important to set the parent ASAP to avoid misunderstandings with + // the compositor. For example, niri immediately resizes the window to full + // size as soon as it's configured if it's not parented to another toplevel. + window_set_parent(p_window_id, p_parent_id); + } + ws.frame_callback = wl_surface_frame(ws.wl_surface); wl_callback_add_listener(ws.frame_callback, &frame_wl_callback_listener, &ws); diff --git a/platform/linuxbsd/wayland/wayland_thread.h b/platform/linuxbsd/wayland/wayland_thread.h index 37ae4a27e78..b0add5ec89c 100644 --- a/platform/linuxbsd/wayland/wayland_thread.h +++ b/platform/linuxbsd/wayland/wayland_thread.h @@ -1032,7 +1032,7 @@ public: void set_icon(const Ref &p_icon); - void window_create(DisplayServer::WindowID p_window_id, int p_width, int p_height); + void window_create(DisplayServer::WindowID p_window_id, const Size2i &p_size, DisplayServer::WindowID p_parent_id = DisplayServer::INVALID_WINDOW_ID); void window_create_popup(DisplayServer::WindowID p_window_id, DisplayServer::WindowID p_parent_id, Rect2i p_rect); void window_destroy(DisplayServer::WindowID p_window_Id);