summaryrefslogtreecommitdiffstats
path: root/scene/main/window.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/main/window.cpp')
-rw-r--r--scene/main/window.cpp369
1 files changed, 285 insertions, 84 deletions
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 3ea53da141..36d7d079b2 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -270,20 +270,27 @@ void Window::set_title(const String &p_title) {
ERR_MAIN_THREAD_GUARD;
title = p_title;
+ tr_title = atr(p_title);
+#ifdef DEBUG_ENABLED
+ if (window_id == DisplayServer::MAIN_WINDOW_ID) {
+ // Append a suffix to the window title to denote that the project is running
+ // from a debug build (including the editor). Since this results in lower performance,
+ // this should be clearly presented to the user.
+ tr_title = vformat("%s (DEBUG)", tr_title);
+ }
+#endif
if (embedder) {
embedder->_sub_window_update(this);
} else if (window_id != DisplayServer::INVALID_WINDOW_ID) {
- String tr_title = atr(p_title);
-#ifdef DEBUG_ENABLED
- if (window_id == DisplayServer::MAIN_WINDOW_ID) {
- // Append a suffix to the window title to denote that the project is running
- // from a debug build (including the editor). Since this results in lower performance,
- // this should be clearly presented to the user.
- tr_title = vformat("%s (DEBUG)", tr_title);
- }
-#endif
DisplayServer::get_singleton()->window_set_title(tr_title, window_id);
+ if (keep_title_visible) {
+ Size2i title_size = DisplayServer::get_singleton()->window_get_title_size(tr_title, window_id);
+ Size2i size_limit = get_clamped_minimum_size();
+ if (title_size.x > size_limit.x || title_size.y > size_limit.y) {
+ _update_window_size();
+ }
+ }
}
}
@@ -342,6 +349,25 @@ Point2i Window::get_position() const {
return position;
}
+void Window::move_to_center() {
+ ERR_MAIN_THREAD_GUARD;
+ ERR_FAIL_COND(!is_inside_tree());
+
+ Rect2 parent_rect;
+
+ if (is_embedded()) {
+ parent_rect = get_embedder()->get_visible_rect();
+ } else {
+ int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(get_window_id());
+ parent_rect.position = DisplayServer::get_singleton()->screen_get_position(parent_screen);
+ parent_rect.size = DisplayServer::get_singleton()->screen_get_size(parent_screen);
+ }
+
+ if (parent_rect != Rect2()) {
+ set_position(parent_rect.position + (parent_rect.size - get_size()) / 2);
+ }
+}
+
void Window::set_size(const Size2i &p_size) {
ERR_MAIN_THREAD_GUARD;
@@ -567,15 +593,6 @@ void Window::_make_window() {
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);
- String tr_title = atr(title);
-#ifdef DEBUG_ENABLED
- if (window_id == DisplayServer::MAIN_WINDOW_ID) {
- // Append a suffix to the window title to denote that the project is running
- // from a debug build (including the editor). Since this results in lower performance,
- // this should be clearly presented to the user.
- tr_title = vformat("%s (DEBUG)", tr_title);
- }
-#endif
DisplayServer::get_singleton()->window_set_title(tr_title, window_id);
DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id);
@@ -618,12 +635,6 @@ void Window::_clear_window() {
bool had_focus = has_focus();
- DisplayServer::get_singleton()->window_set_rect_changed_callback(Callable(), window_id);
- DisplayServer::get_singleton()->window_set_window_event_callback(Callable(), window_id);
- DisplayServer::get_singleton()->window_set_input_event_callback(Callable(), window_id);
- DisplayServer::get_singleton()->window_set_input_text_callback(Callable(), window_id);
- DisplayServer::get_singleton()->window_set_drop_files_callback(Callable(), window_id);
-
if (transient_parent && transient_parent->window_id != DisplayServer::INVALID_WINDOW_ID) {
DisplayServer::get_singleton()->window_set_transient(window_id, DisplayServer::INVALID_WINDOW_ID);
}
@@ -676,17 +687,38 @@ void Window::_propagate_window_notification(Node *p_node, int p_notification) {
void Window::_event_callback(DisplayServer::WindowEvent p_event) {
switch (p_event) {
case DisplayServer::WINDOW_EVENT_MOUSE_ENTER: {
+ if (!is_inside_tree()) {
+ return;
+ }
+ Window *root = get_tree()->get_root();
+ if (root->gui.windowmanager_window_over) {
+#ifdef DEV_ENABLED
+ WARN_PRINT_ONCE("Entering a window while a window is hovered should never happen in DisplayServer.");
+#endif // DEV_ENABLED
+ root->gui.windowmanager_window_over->_event_callback(DisplayServer::WINDOW_EVENT_MOUSE_EXIT);
+ }
_propagate_window_notification(this, NOTIFICATION_WM_MOUSE_ENTER);
- emit_signal(SNAME("mouse_entered"));
- notification(NOTIFICATION_VP_MOUSE_ENTER);
+ root->gui.windowmanager_window_over = this;
+ mouse_in_window = true;
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CURSOR_SHAPE)) {
DisplayServer::get_singleton()->cursor_set_shape(DisplayServer::CURSOR_ARROW); //restore cursor shape
}
} break;
case DisplayServer::WINDOW_EVENT_MOUSE_EXIT: {
- notification(NOTIFICATION_VP_MOUSE_EXIT);
+ if (!is_inside_tree()) {
+ return;
+ }
+ Window *root = get_tree()->get_root();
+ if (!root->gui.windowmanager_window_over) {
+#ifdef DEV_ENABLED
+ WARN_PRINT_ONCE("Exiting a window while no window is hovered should never happen in DisplayServer.");
+#endif // DEV_ENABLED
+ return;
+ }
+ mouse_in_window = false;
+ root->gui.windowmanager_window_over->_mouse_leave_viewport();
+ root->gui.windowmanager_window_over = nullptr;
_propagate_window_notification(this, NOTIFICATION_WM_MOUSE_EXIT);
- emit_signal(SNAME("mouse_exited"));
} break;
case DisplayServer::WINDOW_EVENT_FOCUS_IN: {
focused = true;
@@ -759,7 +791,7 @@ void Window::set_visible(bool p_visible) {
return;
}
- ERR_FAIL_COND_MSG(get_parent() == nullptr, "Can't change visibility of main window.");
+ ERR_FAIL_NULL_MSG(get_parent(), "Can't change visibility of main window.");
visible = p_visible;
@@ -801,16 +833,7 @@ void Window::set_visible(bool p_visible) {
//update transient exclusive
if (transient_parent) {
- if (exclusive && visible) {
- if (!is_in_edited_scene_root()) {
- ERR_FAIL_COND_MSG(transient_parent->exclusive_child && transient_parent->exclusive_child != this, "Transient parent has another exclusive child.");
- transient_parent->exclusive_child = this;
- }
- } else {
- if (transient_parent->exclusive_child == this) {
- transient_parent->exclusive_child = nullptr;
- }
- }
+ _set_transient_exclusive_child(true);
}
}
@@ -850,15 +873,7 @@ void Window::_make_transient() {
if (window) {
transient_parent = window;
window->transient_children.insert(this);
- if (is_inside_tree() && is_visible() && exclusive) {
- if (transient_parent->exclusive_child == nullptr) {
- if (!is_in_edited_scene_root()) {
- transient_parent->exclusive_child = this;
- }
- } else if (transient_parent->exclusive_child != this) {
- ERR_PRINT("Making child transient exclusive, but parent has another exclusive child");
- }
- }
+ _set_transient_exclusive_child();
}
//see if we can make transient
@@ -867,6 +882,22 @@ void Window::_make_transient() {
}
}
+void Window::_set_transient_exclusive_child(bool p_clear_invalid) {
+ if (exclusive && visible && is_inside_tree()) {
+ if (!is_in_edited_scene_root()) {
+ // Transient parent has another exclusive child.
+ if (transient_parent->exclusive_child && transient_parent->exclusive_child != this) {
+ ERR_PRINT(vformat("Attempting to make child window exclusive, but the parent window already has another exclusive child. This window: %s, parent window: %s, current exclusive child window: %s", this->get_description(), transient_parent->get_description(), transient_parent->exclusive_child->get_description()));
+ }
+ transient_parent->exclusive_child = this;
+ }
+ } else if (p_clear_invalid) {
+ if (transient_parent->exclusive_child == this) {
+ transient_parent->exclusive_child = nullptr;
+ }
+ }
+}
+
void Window::set_transient(bool p_transient) {
ERR_MAIN_THREAD_GUARD;
if (transient == p_transient) {
@@ -908,16 +939,7 @@ void Window::set_exclusive(bool p_exclusive) {
}
if (transient_parent) {
- if (p_exclusive && is_inside_tree() && is_visible()) {
- ERR_FAIL_COND_MSG(transient_parent->exclusive_child && transient_parent->exclusive_child != this, "Transient parent has another exclusive child.");
- if (!is_in_edited_scene_root()) {
- transient_parent->exclusive_child = this;
- }
- } else {
- if (transient_parent->exclusive_child == this) {
- transient_parent->exclusive_child = nullptr;
- }
- }
+ _set_transient_exclusive_child(true);
}
}
@@ -945,6 +967,10 @@ Size2i Window::_clamp_window_size(const Size2i &p_size) {
void Window::_update_window_size() {
Size2i size_limit = get_clamped_minimum_size();
+ if (!embedder && window_id != DisplayServer::INVALID_WINDOW_ID && keep_title_visible) {
+ Size2i title_size = DisplayServer::get_singleton()->window_get_title_size(tr_title, window_id);
+ size_limit = size_limit.max(title_size);
+ }
size = size.max(size_limit);
@@ -993,6 +1019,17 @@ void Window::_update_viewport_size() {
float font_oversampling = 1.0;
window_transform = Transform2D();
+ if (content_scale_stretch == Window::CONTENT_SCALE_STRETCH_INTEGER) {
+ // We always want to make sure that the content scale factor is a whole
+ // number, else there will be pixel wobble no matter what.
+ content_scale_factor = Math::floor(content_scale_factor);
+
+ // A content scale factor of zero is pretty useless.
+ if (content_scale_factor < 1) {
+ content_scale_factor = 1;
+ }
+ }
+
if (content_scale_mode == CONTENT_SCALE_MODE_DISABLED || content_scale_size.x == 0 || content_scale_size.y == 0) {
font_oversampling = content_scale_factor;
final_size = size;
@@ -1046,13 +1083,26 @@ void Window::_update_viewport_size() {
screen_size = screen_size.floor();
viewport_size = viewport_size.floor();
+ if (content_scale_stretch == Window::CONTENT_SCALE_STRETCH_INTEGER) {
+ Size2i screen_scale = (screen_size / viewport_size).floor();
+ int scale_factor = MIN(screen_scale.x, screen_scale.y);
+
+ if (scale_factor < 1) {
+ scale_factor = 1;
+ }
+
+ screen_size = viewport_size * scale_factor;
+ }
+
Size2 margin;
Size2 offset;
- if (content_scale_aspect != CONTENT_SCALE_ASPECT_EXPAND && screen_size.x < video_mode.x) {
+ if (screen_size.x < video_mode.x) {
margin.x = Math::round((video_mode.x - screen_size.x) / 2.0);
offset.x = Math::round(margin.x * viewport_size.y / screen_size.y);
- } else if (content_scale_aspect != CONTENT_SCALE_ASPECT_EXPAND && screen_size.y < video_mode.y) {
+ }
+
+ if (screen_size.y < video_mode.y) {
margin.y = Math::round((video_mode.y - screen_size.y) / 2.0);
offset.y = Math::round(margin.y * viewport_size.x / screen_size.x);
}
@@ -1217,7 +1267,9 @@ void Window::_notification(int p_what) {
notification(NOTIFICATION_TRANSLATION_CHANGED);
}
#endif
- notification(NOTIFICATION_THEME_CHANGED);
+
+ // Emits NOTIFICATION_THEME_CHANGED internally.
+ set_theme_context(ThemeDB::get_singleton()->get_nearest_theme_context(this));
} break;
case NOTIFICATION_READY: {
@@ -1237,17 +1289,25 @@ void Window::_notification(int p_what) {
_invalidate_theme_cache();
_update_theme_item_cache();
- if (!embedder && window_id != DisplayServer::INVALID_WINDOW_ID) {
- String tr_title = atr(title);
+ tr_title = atr(title);
#ifdef DEBUG_ENABLED
- if (window_id == DisplayServer::MAIN_WINDOW_ID) {
- // Append a suffix to the window title to denote that the project is running
- // from a debug build (including the editor). Since this results in lower performance,
- // this should be clearly presented to the user.
- tr_title = vformat("%s (DEBUG)", tr_title);
- }
+ if (window_id == DisplayServer::MAIN_WINDOW_ID) {
+ // Append a suffix to the window title to denote that the project is running
+ // from a debug build (including the editor). Since this results in lower performance,
+ // this should be clearly presented to the user.
+ tr_title = vformat("%s (DEBUG)", tr_title);
+ }
#endif
+
+ if (!embedder && window_id != DisplayServer::INVALID_WINDOW_ID) {
DisplayServer::get_singleton()->window_set_title(tr_title, window_id);
+ if (keep_title_visible) {
+ Size2i title_size = DisplayServer::get_singleton()->window_get_title_size(tr_title, window_id);
+ Size2i size_limit = get_clamped_minimum_size();
+ if (title_size.x > size_limit.x || title_size.y > size_limit.y) {
+ _update_window_size();
+ }
+ }
}
} break;
@@ -1261,6 +1321,8 @@ void Window::_notification(int p_what) {
} break;
case NOTIFICATION_EXIT_TREE: {
+ set_theme_context(nullptr, false);
+
if (transient) {
_clear_transient();
}
@@ -1283,6 +1345,14 @@ void Window::_notification(int p_what) {
RS::get_singleton()->viewport_set_active(get_viewport_rid(), false);
} break;
+
+ case NOTIFICATION_VP_MOUSE_ENTER: {
+ emit_signal(SceneStringNames::get_singleton()->mouse_entered);
+ } break;
+
+ case NOTIFICATION_VP_MOUSE_EXIT: {
+ emit_signal(SceneStringNames::get_singleton()->mouse_exited);
+ } break;
}
}
@@ -1321,6 +1391,29 @@ Window::ContentScaleAspect Window::get_content_scale_aspect() const {
return content_scale_aspect;
}
+void Window::set_content_scale_stretch(ContentScaleStretch p_stretch) {
+ content_scale_stretch = p_stretch;
+ _update_viewport_size();
+}
+
+Window::ContentScaleStretch Window::get_content_scale_stretch() const {
+ return content_scale_stretch;
+}
+
+void Window::set_keep_title_visible(bool p_title_visible) {
+ if (keep_title_visible == p_title_visible) {
+ return;
+ }
+ keep_title_visible = p_title_visible;
+ if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+ _update_window_size();
+ }
+}
+
+bool Window::get_keep_title_visible() const {
+ return keep_title_visible;
+}
+
void Window::set_content_scale_factor(real_t p_factor) {
ERR_MAIN_THREAD_GUARD;
ERR_FAIL_COND(p_factor <= 0);
@@ -1731,7 +1824,7 @@ Rect2i Window::fit_rect_in_parent(Rect2i p_rect, const Rect2i &p_parent_rect) co
p_rect.position.x = 0;
}
- int title_height = get_flag(Window::FLAG_BORDERLESS) ? 0 : get_theme_constant(SNAME("title_height"));
+ int title_height = get_flag(Window::FLAG_BORDERLESS) ? 0 : theme_cache.title_height;
if (p_rect.position.y < title_height) {
p_rect.position.y = title_height;
@@ -1742,6 +1835,10 @@ Rect2i Window::fit_rect_in_parent(Rect2i p_rect, const Rect2i &p_parent_rect) co
Size2 Window::get_contents_minimum_size() const {
ERR_READ_THREAD_GUARD_V(Size2());
+ Vector2 ms;
+ if (GDVIRTUAL_CALL(_get_contents_minimum_size, ms)) {
+ return ms;
+ }
return _get_contents_minimum_size();
}
@@ -1816,6 +1913,11 @@ bool Window::has_theme_owner_node() const {
return theme_owner->has_owner_node();
}
+void Window::set_theme_context(ThemeContext *p_context, bool p_propagate) {
+ ERR_MAIN_THREAD_GUARD;
+ theme_owner->set_owner_context(p_context, p_propagate);
+}
+
void Window::set_theme(const Ref<Theme> &p_theme) {
ERR_MAIN_THREAD_GUARD;
if (theme == p_theme) {
@@ -1883,6 +1985,8 @@ void Window::_update_theme_item_cache() {
} else {
child_controls_changed();
}
+
+ ThemeDB::get_singleton()->update_class_instance_items(this);
}
void Window::_update_embedded_window() {
@@ -1915,7 +2019,7 @@ StringName Window::get_theme_type_variation() const {
Ref<Texture2D> Window::get_theme_icon(const StringName &p_name, const StringName &p_theme_type) const {
ERR_READ_THREAD_GUARD_V(Ref<Texture2D>());
if (!initialized) {
- WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED");
+ WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description()));
}
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) {
@@ -1939,7 +2043,7 @@ Ref<Texture2D> Window::get_theme_icon(const StringName &p_name, const StringName
Ref<StyleBox> Window::get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const {
ERR_READ_THREAD_GUARD_V(Ref<StyleBox>());
if (!initialized) {
- WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED");
+ WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description()));
}
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) {
@@ -1963,7 +2067,7 @@ Ref<StyleBox> Window::get_theme_stylebox(const StringName &p_name, const StringN
Ref<Font> Window::get_theme_font(const StringName &p_name, const StringName &p_theme_type) const {
ERR_READ_THREAD_GUARD_V(Ref<Font>());
if (!initialized) {
- WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED");
+ WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description()));
}
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) {
@@ -1987,7 +2091,7 @@ Ref<Font> Window::get_theme_font(const StringName &p_name, const StringName &p_t
int Window::get_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const {
ERR_READ_THREAD_GUARD_V(0);
if (!initialized) {
- WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED");
+ WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description()));
}
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) {
@@ -2011,7 +2115,7 @@ int Window::get_theme_font_size(const StringName &p_name, const StringName &p_th
Color Window::get_theme_color(const StringName &p_name, const StringName &p_theme_type) const {
ERR_READ_THREAD_GUARD_V(Color());
if (!initialized) {
- WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED");
+ WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description()));
}
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) {
@@ -2035,7 +2139,7 @@ Color Window::get_theme_color(const StringName &p_name, const StringName &p_them
int Window::get_theme_constant(const StringName &p_name, const StringName &p_theme_type) const {
ERR_READ_THREAD_GUARD_V(0);
if (!initialized) {
- WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED");
+ WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description()));
}
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) {
@@ -2056,10 +2160,37 @@ int Window::get_theme_constant(const StringName &p_name, const StringName &p_the
return constant;
}
+Variant Window::get_theme_item(Theme::DataType p_data_type, const StringName &p_name, const StringName &p_theme_type) const {
+ switch (p_data_type) {
+ case Theme::DATA_TYPE_COLOR:
+ return get_theme_color(p_name, p_theme_type);
+ case Theme::DATA_TYPE_CONSTANT:
+ return get_theme_constant(p_name, p_theme_type);
+ case Theme::DATA_TYPE_FONT:
+ return get_theme_font(p_name, p_theme_type);
+ case Theme::DATA_TYPE_FONT_SIZE:
+ return get_theme_font_size(p_name, p_theme_type);
+ case Theme::DATA_TYPE_ICON:
+ return get_theme_icon(p_name, p_theme_type);
+ case Theme::DATA_TYPE_STYLEBOX:
+ return get_theme_stylebox(p_name, p_theme_type);
+ case Theme::DATA_TYPE_MAX:
+ break; // Can't happen, but silences warning.
+ }
+
+ return Variant();
+}
+
+#ifdef TOOLS_ENABLED
+Ref<Texture2D> Window::get_editor_theme_icon(const StringName &p_name) const {
+ return get_theme_icon(p_name, SNAME("EditorIcons"));
+}
+#endif
+
bool Window::has_theme_icon(const StringName &p_name, const StringName &p_theme_type) const {
ERR_READ_THREAD_GUARD_V(false);
if (!initialized) {
- WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED");
+ WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description()));
}
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) {
@@ -2076,7 +2207,7 @@ bool Window::has_theme_icon(const StringName &p_name, const StringName &p_theme_
bool Window::has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const {
ERR_READ_THREAD_GUARD_V(false);
if (!initialized) {
- WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED");
+ WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description()));
}
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) {
@@ -2093,7 +2224,7 @@ bool Window::has_theme_stylebox(const StringName &p_name, const StringName &p_th
bool Window::has_theme_font(const StringName &p_name, const StringName &p_theme_type) const {
ERR_READ_THREAD_GUARD_V(false);
if (!initialized) {
- WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED");
+ WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description()));
}
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) {
@@ -2110,7 +2241,7 @@ bool Window::has_theme_font(const StringName &p_name, const StringName &p_theme_
bool Window::has_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const {
ERR_READ_THREAD_GUARD_V(false);
if (!initialized) {
- WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED");
+ WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description()));
}
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) {
@@ -2127,7 +2258,7 @@ bool Window::has_theme_font_size(const StringName &p_name, const StringName &p_t
bool Window::has_theme_color(const StringName &p_name, const StringName &p_theme_type) const {
ERR_READ_THREAD_GUARD_V(false);
if (!initialized) {
- WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED");
+ WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description()));
}
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) {
@@ -2144,7 +2275,7 @@ bool Window::has_theme_color(const StringName &p_name, const StringName &p_theme
bool Window::has_theme_constant(const StringName &p_name, const StringName &p_theme_type) const {
ERR_READ_THREAD_GUARD_V(false);
if (!initialized) {
- WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED");
+ WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description()));
}
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) {
@@ -2495,6 +2626,45 @@ bool Window::is_directly_attached_to_screen() const {
return is_inside_tree();
}
+bool Window::is_attached_in_viewport() const {
+ return get_embedder();
+}
+
+void Window::_update_mouse_over(Vector2 p_pos) {
+ if (!mouse_in_window) {
+ if (is_embedded()) {
+ mouse_in_window = true;
+ _propagate_window_notification(this, NOTIFICATION_WM_MOUSE_ENTER);
+ } else {
+ // Prevent update based on delayed InputEvents from DisplayServer.
+ return;
+ }
+ }
+
+ bool new_in = get_visible_rect().has_point(p_pos);
+ if (new_in == gui.mouse_in_viewport) {
+ if (new_in) {
+ Viewport::_update_mouse_over(p_pos);
+ }
+ return;
+ }
+
+ if (new_in) {
+ notification(NOTIFICATION_VP_MOUSE_ENTER);
+ Viewport::_update_mouse_over(p_pos);
+ } else {
+ Viewport::_mouse_leave_viewport();
+ }
+}
+
+void Window::_mouse_leave_viewport() {
+ Viewport::_mouse_leave_viewport();
+ if (is_embedded()) {
+ mouse_in_window = false;
+ _propagate_window_notification(this, NOTIFICATION_WM_MOUSE_EXIT);
+ }
+}
+
void Window::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_title", "title"), &Window::set_title);
ClassDB::bind_method(D_METHOD("get_title"), &Window::get_title);
@@ -2509,6 +2679,7 @@ void Window::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_position", "position"), &Window::set_position);
ClassDB::bind_method(D_METHOD("get_position"), &Window::get_position);
+ ClassDB::bind_method(D_METHOD("move_to_center"), &Window::move_to_center);
ClassDB::bind_method(D_METHOD("set_size", "size"), &Window::set_size);
ClassDB::bind_method(D_METHOD("get_size"), &Window::get_size);
@@ -2569,6 +2740,12 @@ void Window::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_content_scale_aspect", "aspect"), &Window::set_content_scale_aspect);
ClassDB::bind_method(D_METHOD("get_content_scale_aspect"), &Window::get_content_scale_aspect);
+ ClassDB::bind_method(D_METHOD("set_content_scale_stretch", "stretch"), &Window::set_content_scale_stretch);
+ ClassDB::bind_method(D_METHOD("get_content_scale_stretch"), &Window::get_content_scale_stretch);
+
+ ClassDB::bind_method(D_METHOD("set_keep_title_visible", "title_visible"), &Window::set_keep_title_visible);
+ ClassDB::bind_method(D_METHOD("get_keep_title_visible"), &Window::get_keep_title_visible);
+
ClassDB::bind_method(D_METHOD("set_content_scale_factor", "factor"), &Window::set_content_scale_factor);
ClassDB::bind_method(D_METHOD("get_content_scale_factor"), &Window::get_content_scale_factor);
@@ -2682,12 +2859,14 @@ void Window::_bind_methods() {
ADD_GROUP("Limits", "");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "min_size", PROPERTY_HINT_NONE, "suffix:px"), "set_min_size", "get_min_size");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "max_size", PROPERTY_HINT_NONE, "suffix:px"), "set_max_size", "get_max_size");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_title_visible"), "set_keep_title_visible", "get_keep_title_visible");
ADD_GROUP("Content Scale", "content_scale_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "content_scale_size"), "set_content_scale_size", "get_content_scale_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_mode", PROPERTY_HINT_ENUM, "Disabled,Canvas Items,Viewport"), "set_content_scale_mode", "get_content_scale_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_aspect", PROPERTY_HINT_ENUM, "Ignore,Keep,Keep Width,Keep Height,Expand"), "set_content_scale_aspect", "get_content_scale_aspect");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "content_scale_factor"), "set_content_scale_factor", "get_content_scale_factor");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_stretch", PROPERTY_HINT_ENUM, "Fractional,Integer"), "set_content_scale_stretch", "get_content_scale_stretch");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "content_scale_factor", PROPERTY_HINT_RANGE, "0.5,8.0,0.01"), "set_content_scale_factor", "get_content_scale_factor");
ADD_GROUP("Localization", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_translate"), "set_auto_translate", "is_auto_translating");
@@ -2739,6 +2918,9 @@ void Window::_bind_methods() {
BIND_ENUM_CONSTANT(CONTENT_SCALE_ASPECT_KEEP_HEIGHT);
BIND_ENUM_CONSTANT(CONTENT_SCALE_ASPECT_EXPAND);
+ BIND_ENUM_CONSTANT(CONTENT_SCALE_STRETCH_FRACTIONAL);
+ BIND_ENUM_CONSTANT(CONTENT_SCALE_STRETCH_INTEGER);
+
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_INHERITED);
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LOCALE);
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LTR);
@@ -2750,6 +2932,25 @@ void Window::_bind_methods() {
BIND_ENUM_CONSTANT(WINDOW_INITIAL_POSITION_CENTER_OTHER_SCREEN);
BIND_ENUM_CONSTANT(WINDOW_INITIAL_POSITION_CENTER_SCREEN_WITH_MOUSE_FOCUS);
BIND_ENUM_CONSTANT(WINDOW_INITIAL_POSITION_CENTER_SCREEN_WITH_KEYBOARD_FOCUS);
+
+ GDVIRTUAL_BIND(_get_contents_minimum_size);
+
+ BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Window, embedded_border);
+ BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Window, embedded_unfocused_border);
+
+ BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, Window, title_font);
+ BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, Window, title_font_size);
+ BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Window, title_color);
+ BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Window, title_height);
+ BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Window, title_outline_modulate);
+ BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Window, title_outline_size);
+
+ BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, Window, close);
+ BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, Window, close_pressed);
+ BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Window, close_h_offset);
+ BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Window, close_v_offset);
+
+ BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Window, resize_margin);
}
Window::Window() {
@@ -2759,7 +2960,7 @@ Window::Window() {
max_size_used = max_size; // Update max_size_used.
}
- theme_owner = memnew(ThemeOwner);
+ theme_owner = memnew(ThemeOwner(this));
RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_DISABLED);
}