From 834dfcbcaf3a3c7c448d19f4b973f6f970217d58 Mon Sep 17 00:00:00 2001 From: Anish Kumar Date: Thu, 20 Nov 2025 22:45:12 +0530 Subject: [PATCH] Fix completion popup placement and adjust lines to available space --- scene/gui/code_edit.cpp | 32 +++++++++++++++++++++++++++----- tests/scene/test_code_edit.h | 6 +++--- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index de5173d0ea1..f9eeb2a841e 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -138,14 +138,14 @@ void CodeEdit::_notification(int p_what) { /* Code completion */ if (draw_code_completion) { const int code_completion_options_count = code_completion_options.size(); - const int lines = MIN(code_completion_options_count, theme_cache.code_completion_max_lines); + int lines = MIN(code_completion_options_count, theme_cache.code_completion_max_lines); const Size2 icon_area_size(row_height, row_height); code_completion_rect.size.width = code_completion_longest_line + theme_cache.code_completion_icon_separation + icon_area_size.width + 2; code_completion_rect.size.height = lines * row_height; const Point2 caret_pos = get_caret_draw_pos(); - const int total_height = theme_cache.code_completion_style->get_minimum_size().y + code_completion_rect.size.height; + int total_height = theme_cache.code_completion_style->get_minimum_size().y + code_completion_rect.size.height; int min_y = caret_pos.y - row_height; int max_y = caret_pos.y + row_height + total_height; if (draw_code_hint) { @@ -156,9 +156,31 @@ void CodeEdit::_notification(int p_what) { } } - const bool can_fit_completion_above = (min_y > total_height); - const bool can_fit_completion_below = (max_y <= get_size().height); - if (!can_fit_completion_below && can_fit_completion_above) { + const bool can_fit_completion_above = min_y > total_height; + const bool can_fit_completion_below = max_y <= get_size().height; + + bool should_place_above = !can_fit_completion_below && can_fit_completion_above; + + if (!can_fit_completion_below && !can_fit_completion_above) { + const int space_above = caret_pos.y - row_height; + const int space_below = get_size().height - caret_pos.y; + should_place_above = space_above > space_below; + + // Reduce the line count and recalculate heights to better fit the completion popup. + int space_avail; + if (should_place_above) { + space_avail = space_above - theme_cache.code_completion_style->get_minimum_size().y; + } else { + space_avail = space_below - theme_cache.code_completion_style->get_minimum_size().y; + } + + int max_lines_fit = MAX(1, space_avail / row_height); + lines = MIN(lines, max_lines_fit); + code_completion_rect.size.height = lines * row_height; + total_height = theme_cache.code_completion_style->get_minimum_size().y + code_completion_rect.size.height; + } + + if (should_place_above) { code_completion_rect.position.y = (caret_pos.y - total_height - row_height) + theme_cache.line_spacing; if (draw_code_hint && !code_hint_draw_below) { code_completion_rect.position.y -= code_hint_minsize.y; diff --git a/tests/scene/test_code_edit.h b/tests/scene/test_code_edit.h index a5ce805388f..62c9552a562 100644 --- a/tests/scene/test_code_edit.h +++ b/tests/scene/test_code_edit.h @@ -4158,15 +4158,15 @@ TEST_CASE("[SceneTree][CodeEdit] completion") { CHECK(code_edit->get_code_completion_selected_index() == 0); /* Single click selects. */ - caret_pos.y += code_edit->get_line_height() * 2; + caret_pos.y += code_edit->get_line_height(); SEND_GUI_MOUSE_BUTTON_EVENT(caret_pos, MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE); SEND_GUI_MOUSE_BUTTON_RELEASED_EVENT(caret_pos, MouseButton::LEFT, MouseButtonMask::NONE, Key::NONE); - CHECK(code_edit->get_code_completion_selected_index() == 2); + CHECK(code_edit->get_code_completion_selected_index() == 1); /* Double click inserts. */ SEND_GUI_DOUBLE_CLICK(caret_pos, Key::NONE); CHECK(code_edit->get_code_completion_selected_index() == -1); - CHECK(code_edit->get_line(0) == "item_2"); + CHECK(code_edit->get_line(0) == "item_1"); code_edit->set_auto_brace_completion_enabled(false);