Parcourir la source

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.
Riteo Siuga il y a 1 mois
Parent
commit
4df96fc7ab

+ 1 - 5
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()) {

+ 9 - 3
platform/linuxbsd/wayland/wayland_thread.cpp

@@ -3536,7 +3536,7 @@ Ref<WaylandThread::Message> WaylandThread::pop_message() {
 	return Ref<Message>();
 }
 
-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 = &registry;
 	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);
 

+ 1 - 1
platform/linuxbsd/wayland/wayland_thread.h

@@ -1032,7 +1032,7 @@ public:
 
 	void set_icon(const Ref<Image> &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);