From 0881c81c136e3b133a480bedd14a7517bd8a373b Mon Sep 17 00:00:00 2001 From: Koyper Date: Wed, 27 Dec 2023 10:19:52 -0600 Subject: [PATCH] Fix non-embedded Windows resizing to match Viewport content scale factor --- scene/gui/dialogs.cpp | 2 +- scene/gui/popup.cpp | 5 +++-- scene/gui/popup_menu.cpp | 38 ++++++++++++++++++++++++-------------- scene/gui/tree.cpp | 14 +++++++++++--- scene/main/viewport.cpp | 16 +++++++++++++--- 5 files changed, 52 insertions(+), 23 deletions(-) diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index c13a2e281a6..4d006463919 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -202,7 +202,7 @@ void AcceptDialog::register_text_enter(LineEdit *p_line_edit) { } void AcceptDialog::_update_child_rects() { - Size2 dlg_size = get_size(); + Size2 dlg_size = Vector2(get_size()) / get_content_scale_factor(); float h_margins = theme_cache.panel_style->get_margin(SIDE_LEFT) + theme_cache.panel_style->get_margin(SIDE_RIGHT); float v_margins = theme_cache.panel_style->get_margin(SIDE_TOP) + theme_cache.panel_style->get_margin(SIDE_BOTTOM); diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index 09274049474..72ec4e4eb7e 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -232,7 +232,8 @@ Size2 PopupPanel::_get_contents_minimum_size() const { void PopupPanel::_update_child_rects() { Vector2 cpos(theme_cache.panel_style->get_offset()); - Vector2 csize(get_size() - theme_cache.panel_style->get_minimum_size()); + Vector2 panel_size = Vector2(get_size()) / get_content_scale_factor(); + Vector2 csize = panel_size - theme_cache.panel_style->get_minimum_size(); for (int i = 0; i < get_child_count(); i++) { Control *c = Object::cast_to(get_child(i)); @@ -246,7 +247,7 @@ void PopupPanel::_update_child_rects() { if (c == panel) { c->set_position(Vector2()); - c->set_size(get_size()); + c->set_size(panel_size); } else { c->set_position(cpos); c->set_size(csize); diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 56346f5edcc..e91a33f1589 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -312,18 +312,17 @@ int PopupMenu::_get_items_total_height() const { } int PopupMenu::_get_mouse_over(const Point2 &p_over) const { - if (p_over.x < 0 || p_over.x >= get_size().width || p_over.y < theme_cache.panel_style->get_margin(Side::SIDE_TOP)) { + float win_scale = get_content_scale_factor(); + if (p_over.x < 0 || p_over.x >= get_size().width * win_scale || p_over.y < theme_cache.panel_style->get_margin(Side::SIDE_TOP) * win_scale) { return -1; } - Point2 ofs; + Point2 ofs = Point2(0, theme_cache.v_separation * 0.5) * win_scale; for (int i = 0; i < items.size(); i++) { - ofs.y += theme_cache.v_separation; - - ofs.y += _get_item_height(i); - - if (p_over.y - control->get_position().y < ofs.y) { + ofs.y += i > 0 ? (float)theme_cache.v_separation * win_scale : (float)theme_cache.v_separation * win_scale * 0.5; + ofs.y += _get_item_height(i) * win_scale; + if (p_over.y - control->get_position().y * win_scale < ofs.y) { return i; } } @@ -341,15 +340,17 @@ void PopupMenu::_activate_submenu(int p_over, bool p_by_keyboard) { Rect2 this_rect(this_pos, get_size()); float scroll_offset = control->get_position().y; + float scaled_ofs_cache = items[p_over]._ofs_cache * get_content_scale_factor(); + float scaled_height_cache = items[p_over]._height_cache * get_content_scale_factor(); submenu_popup->reset_size(); // Shrink the popup size to its contents. Size2 submenu_size = submenu_popup->get_size(); Point2 submenu_pos; if (control->is_layout_rtl()) { - submenu_pos = this_pos + Point2(-submenu_size.width, items[p_over]._ofs_cache + scroll_offset - theme_cache.v_separation / 2); + submenu_pos = this_pos + Point2(-submenu_size.width, scaled_ofs_cache + scroll_offset - theme_cache.v_separation / 2); } else { - submenu_pos = this_pos + Point2(this_rect.size.width, items[p_over]._ofs_cache + scroll_offset - theme_cache.v_separation / 2); + submenu_pos = this_pos + Point2(this_rect.size.width, scaled_ofs_cache + scroll_offset - theme_cache.v_separation / 2); } // Fix pos if going outside parent rect. @@ -386,8 +387,8 @@ void PopupMenu::_activate_submenu(int p_over, bool p_by_keyboard) { // Set autohide areas. Rect2 safe_area = this_rect; - safe_area.position.y += items[p_over]._ofs_cache + scroll_offset + theme_cache.panel_style->get_offset().height - theme_cache.v_separation / 2; - safe_area.size.y = items[p_over]._height_cache + theme_cache.v_separation; + safe_area.position.y += scaled_ofs_cache + scroll_offset + theme_cache.panel_style->get_offset().height - theme_cache.v_separation / 2; + safe_area.size.y = scaled_height_cache + theme_cache.v_separation; Viewport *vp = submenu_popup->get_embedder(); if (vp) { vp->subwindow_set_popup_safe_rect(submenu_popup, safe_area); @@ -400,11 +401,11 @@ void PopupMenu::_activate_submenu(int p_over, bool p_by_keyboard) { // Autohide area above the submenu item. submenu_pum->clear_autohide_areas(); - submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y, this_rect.size.x, items[p_over]._ofs_cache + scroll_offset + theme_cache.panel_style->get_offset().height - theme_cache.v_separation / 2)); + submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y, this_rect.size.x, scaled_ofs_cache + scroll_offset + theme_cache.panel_style->get_offset().height - theme_cache.v_separation / 2)); // If there is an area below the submenu item, add an autohide area there. - if (items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset <= control->get_size().height) { - int from = items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset + theme_cache.v_separation / 2 + theme_cache.panel_style->get_offset().height; + if (scaled_ofs_cache + scaled_height_cache + scroll_offset <= control->get_size().height) { + int from = scaled_ofs_cache + scaled_height_cache + scroll_offset + theme_cache.v_separation / 2 + theme_cache.panel_style->get_offset().height; submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y + from, this_rect.size.x, this_rect.size.y - from)); } } @@ -576,6 +577,7 @@ void PopupMenu::_input_from_window_internal(const Ref &p_event) { } item_clickable_area.size.width -= scroll_container->get_v_scroll_bar()->get_size().width; } + item_clickable_area.size = item_clickable_area.size * get_content_scale_factor(); Ref b = p_event; @@ -2821,6 +2823,14 @@ void PopupMenu::popup(const Rect2i &p_bounds) { } else { moved = Vector2(); popup_time_msec = OS::get_singleton()->get_ticks_msec(); + if (!is_embedded()) { + float win_scale = get_parent_visible_window()->get_content_scale_factor(); + set_content_scale_factor(win_scale); + Size2 minsize = get_contents_minimum_size(); + minsize.height += 0.5 * win_scale; // Ensures enough height at fractional content scales to prevent the v_scroll_bar from showing. + set_min_size(minsize * win_scale); + set_size(Vector2(0, 0)); // Shrinkwraps to min size. + } Popup::popup(p_bounds); } } diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 1daf86fe0fb..1242d3bd16e 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -3995,12 +3995,14 @@ bool Tree::edit_selected(bool p_force_edit) { return false; } + float popup_scale = popup_editor->is_embedded() ? 1.0 : popup_editor->get_parent_visible_window()->get_content_scale_factor(); Rect2 rect; if (select_mode == SELECT_ROW) { rect = s->get_meta("__focus_col_" + itos(selected_col)); } else { rect = s->get_meta("__focus_rect"); } + rect.position *= popup_scale; popup_edited_item = s; popup_edited_item_col = col; @@ -4043,7 +4045,7 @@ bool Tree::edit_selected(bool p_force_edit) { popup_rect.size = rect.size; // Account for icon. - Size2 icon_size = _get_cell_icon_size(c); + Size2 icon_size = _get_cell_icon_size(c) * popup_scale; popup_rect.position.x += icon_size.x; popup_rect.size.x -= icon_size.x; @@ -4070,7 +4072,10 @@ bool Tree::edit_selected(bool p_force_edit) { } popup_editor->set_position(popup_rect.position); - popup_editor->set_size(popup_rect.size); + popup_editor->set_size(popup_rect.size * popup_scale); + if (!popup_editor->is_embedded()) { + popup_editor->set_content_scale_factor(popup_scale); + } popup_editor->popup(); popup_editor->child_controls_changed(); @@ -4086,7 +4091,10 @@ bool Tree::edit_selected(bool p_force_edit) { text_editor->show(); popup_editor->set_position(get_screen_position() + rect.position); - popup_editor->set_size(rect.size); + popup_editor->set_size(rect.size * popup_scale); + if (!popup_editor->is_embedded()) { + popup_editor->set_content_scale_factor(popup_scale); + } popup_editor->popup(); popup_editor->child_controls_changed(); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 17d7fec230b..2d30ea345de 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1461,6 +1461,8 @@ void Viewport::_gui_show_tooltip() { panel->set_flag(Window::FLAG_NO_FOCUS, true); panel->set_flag(Window::FLAG_POPUP, false); panel->set_flag(Window::FLAG_MOUSE_PASSTHROUGH, true); + // A non-embedded tooltip window will only be transparent if per_pixel_transparency is allowed in the main Viewport. + panel->set_flag(Window::FLAG_TRANSPARENT, true); panel->set_wrap_controls(true); panel->add_child(base_tooltip); panel->gui_parent = this; @@ -1469,17 +1471,25 @@ void Viewport::_gui_show_tooltip() { tooltip_owner->add_child(gui.tooltip_popup); + Window *window = Object::cast_to(gui.tooltip_popup->get_embedder()); + if (!window) { // Not embedded. + window = gui.tooltip_popup->get_parent_visible_window(); + } + float win_scale = window->content_scale_factor; Point2 tooltip_offset = GLOBAL_GET("display/mouse_cursor/tooltip_position_offset"); + if (!gui.tooltip_popup->is_embedded()) { + tooltip_offset *= win_scale; + } Rect2 r(gui.tooltip_pos + tooltip_offset, gui.tooltip_popup->get_contents_minimum_size()); - r.size = r.size.min(panel->get_max_size()); - - Window *window = gui.tooltip_popup->get_parent_visible_window(); Rect2i vr; if (gui.tooltip_popup->is_embedded()) { vr = gui.tooltip_popup->get_embedder()->get_visible_rect(); } else { + panel->content_scale_factor = win_scale; + r.size *= win_scale; vr = window->get_usable_parent_rect(); } + r.size = r.size.min(panel->get_max_size()); if (r.size.x + r.position.x > vr.size.x + vr.position.x) { // Place it in the opposite direction. If it fails, just hug the border.