Jelajahi Sumber

Fix some bugs with `Window`s

Michael Alexsander 3 tahun lalu
induk
melakukan
2b86c458bf
3 mengubah file dengan 58 tambahan dan 15 penghapusan
  1. 3 1
      doc/classes/Window.xml
  2. 22 6
      scene/main/viewport.cpp
  3. 33 8
      scene/main/window.cpp

+ 3 - 1
doc/classes/Window.xml

@@ -344,9 +344,11 @@
 		</member>
 		<member name="max_size" type="Vector2i" setter="set_max_size" getter="get_max_size" default="Vector2i(0, 0)">
 			If non-zero, the [Window] can't be resized to be bigger than this size.
+			[b]Note:[/b] This property will be ignored if the value is lower than [member min_size].
 		</member>
 		<member name="min_size" type="Vector2i" setter="set_min_size" getter="get_min_size" default="Vector2i(0, 0)">
 			If non-zero, the [Window] can't be resized to be smaller than this size.
+			[b]Note:[/b] This property will be ignored in favor of [method get_contents_minimum_size] if [member wrap_controls] is enabled and if its size is bigger.
 		</member>
 		<member name="mode" type="int" setter="set_mode" getter="get_mode" enum="Window.Mode" default="0">
 			Set's the window's current mode.
@@ -388,7 +390,7 @@
 			If [code]true[/code], the window is visible.
 		</member>
 		<member name="wrap_controls" type="bool" setter="set_wrap_controls" getter="is_wrapping_controls" default="false">
-			If [code]true[/code], the window's size will automatically update when a child node is added or removed.
+			If [code]true[/code], the window's size will automatically update when a child node is added or removed, ignoring [member min_size] if the new size is bigger.
 			If [code]false[/code], you need to call [method child_controls_changed] manually.
 		</member>
 	</members>

+ 22 - 6
scene/main/viewport.cpp

@@ -2498,17 +2498,20 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
 			if (gui.subwindow_drag == SUB_WINDOW_DRAG_RESIZE) {
 				Vector2i diff = mm->get_position() - gui.subwindow_drag_from;
 				Size2i min_size = gui.subwindow_focused->get_min_size();
+
+				Size2i min_size_adjusted = min_size;
 				if (gui.subwindow_focused->is_wrapping_controls()) {
 					Size2i cms = gui.subwindow_focused->get_contents_minimum_size();
-					min_size.x = MAX(cms.x, min_size.x);
-					min_size.y = MAX(cms.y, min_size.y);
+					min_size_adjusted.x = MAX(cms.x, min_size.x);
+					min_size_adjusted.y = MAX(cms.y, min_size.y);
 				}
-				min_size.x = MAX(min_size.x, 1);
-				min_size.y = MAX(min_size.y, 1);
+
+				min_size_adjusted.x = MAX(min_size_adjusted.x, 1);
+				min_size_adjusted.y = MAX(min_size_adjusted.y, 1);
 
 				Rect2i r = gui.subwindow_resize_from_rect;
 
-				Size2i limit = r.size - min_size;
+				Size2i limit = r.size - min_size_adjusted;
 
 				switch (gui.subwindow_resize_mode) {
 					case SUB_WINDOW_RESIZE_TOP_LEFT: {
@@ -2563,6 +2566,19 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
 					}
 				}
 
+				Size2i max_size = gui.subwindow_focused->get_max_size();
+				if ((max_size.x > 0 || max_size.y > 0) && (max_size.x >= min_size.x && max_size.y >= min_size.y)) {
+					max_size.x = MAX(max_size.x, 1);
+					max_size.y = MAX(max_size.y, 1);
+
+					if (r.size.x > max_size.x) {
+						r.size.x = max_size.x;
+					}
+					if (r.size.y > max_size.y) {
+						r.size.y = max_size.y;
+					}
+				}
+
 				gui.subwindow_focused->_rect_changed_callback(r);
 			}
 
@@ -2600,7 +2616,7 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
 					Ref<Texture2D> close_icon = sw.window->get_theme_icon(SNAME("close"));
 
 					Rect2 close_rect;
-					close_rect.position = Vector2(r.position.x + r.size.x - close_v_ofs, r.position.y - close_h_ofs);
+					close_rect.position = Vector2(r.position.x + r.size.x - close_h_ofs, r.position.y - close_v_ofs);
 					close_rect.size = close_icon->get_size();
 
 					if (gui.subwindow_focused != sw.window) {

+ 33 - 8
scene/main/window.cpp

@@ -242,8 +242,8 @@ void Window::_make_window() {
 	window_id = DisplayServer::get_singleton()->create_sub_window(DisplayServer::WindowMode(mode), vsync_mode, f, Rect2i(position, size));
 	ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID);
 	DisplayServer::get_singleton()->window_set_current_screen(current_screen, window_id);
-	DisplayServer::get_singleton()->window_set_max_size(max_size, window_id);
-	DisplayServer::get_singleton()->window_set_min_size(min_size, window_id);
+	DisplayServer::get_singleton()->window_set_max_size(Size2i(), window_id);
+	DisplayServer::get_singleton()->window_set_min_size(Size2i(), window_id);
 	String tr_title = atr(title);
 #ifdef DEBUG_ENABLED
 	if (window_id == DisplayServer::MAIN_WINDOW_ID) {
@@ -596,20 +596,43 @@ void Window::_update_window_size() {
 	size.x = MAX(size_limit.x, size.x);
 	size.y = MAX(size_limit.y, size.y);
 
-	if (max_size.x > 0 && max_size.x > min_size.x && size.x > max_size.x) {
-		size.x = max_size.x;
-	}
+	bool reset_min_first = false;
+
+	bool max_size_valid = false;
+	if ((max_size.x > 0 || max_size.y > 0) && (max_size.x >= min_size.x && max_size.y >= min_size.y)) {
+		max_size_valid = true;
+
+		if (size.x > max_size.x) {
+			size.x = max_size.x;
+		}
+		if (size_limit.x > max_size.x) {
+			size_limit.x = max_size.x;
+			reset_min_first = true;
+		}
 
-	if (max_size.y > 0 && max_size.y > min_size.y && size.y > max_size.y) {
-		size.y = max_size.y;
+		if (size.y > max_size.y) {
+			size.y = max_size.y;
+		}
+		if (size_limit.y > max_size.y) {
+			size_limit.y = max_size.y;
+			reset_min_first = true;
+		}
 	}
 
 	if (embedder) {
+		size.x = MAX(size.x, 1);
+		size.y = MAX(size.y, 1);
+
 		embedder->_sub_window_update(this);
 	} else if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+		if (reset_min_first && wrap_controls) {
+			// Avoid an error if setting max_size to a value between min_size and the previous size_limit.
+			DisplayServer::get_singleton()->window_set_min_size(Size2i(), window_id);
+		}
+
 		DisplayServer::get_singleton()->window_set_size(size, window_id);
+		DisplayServer::get_singleton()->window_set_max_size(max_size_valid ? max_size : Size2i(), window_id);
 		DisplayServer::get_singleton()->window_set_min_size(size_limit, window_id);
-		DisplayServer::get_singleton()->window_set_max_size(max_size, window_id);
 	}
 
 	//update the viewport
@@ -953,6 +976,8 @@ void Window::set_wrap_controls(bool p_enable) {
 	wrap_controls = p_enable;
 	if (wrap_controls) {
 		child_controls_changed();
+	} else {
+		_update_window_size();
 	}
 }