diff options
Diffstat (limited to 'scene/main/window.cpp')
-rw-r--r-- | scene/main/window.cpp | 369 |
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); } |