From ff39adddd10fd8d9ad07ac3ae9f6d5d4f81aab25 Mon Sep 17 00:00:00 2001 From: Lars Pettersson Date: Sun, 29 Dec 2024 16:58:47 +0100 Subject: [PATCH] Prevent tooltip from showing when hovering past end of script line --- doc/classes/TextEdit.xml | 7 +++++-- .../4.3-stable.expected | 7 +++++++ scene/gui/code_edit.cpp | 10 +++++----- scene/gui/text_edit.compat.inc | 5 +++++ scene/gui/text_edit.cpp | 20 +++++++++++++------ scene/gui/text_edit.h | 3 ++- 6 files changed, 38 insertions(+), 14 deletions(-) diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index 89e2a2017af..826a491888d 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -349,9 +349,12 @@ - + + - Returns the line and column at the given position. In the returned vector, [code]x[/code] is the column, [code]y[/code] is the line. If [param allow_out_of_bounds] is [code]false[/code] and the position is not over the text, both vector values will be set to [code]-1[/code]. + Returns the line and column at the given position. In the returned vector, [code]x[/code] is the column and [code]y[/code] is the line. + If [param clamp_line] is [code]false[/code] and [param position] is below the last line, [code]Vector2i(-1, -1)[/code] is returned. + If [param clamp_column] is [code]false[/code] and [param position] is outside the column range of the line, [code]Vector2i(-1, -1)[/code] is returned. diff --git a/misc/extension_api_validation/4.3-stable.expected b/misc/extension_api_validation/4.3-stable.expected index 7b5889f464b..9c96811f875 100644 --- a/misc/extension_api_validation/4.3-stable.expected +++ b/misc/extension_api_validation/4.3-stable.expected @@ -309,3 +309,10 @@ Validate extension JSON: API was removed: classes/EditorSceneFormatImporter/meth This virtual method, and the internal public `get_import_flags`, were never used by the engine, since it was open sourced. So we're removing it despite the compat breakage as there's no way for users to rely on this affecting engine behavior. + + +GH-100913 +--------- +Validate extension JSON: Error: Field 'classes/TextEdit/methods/get_line_column_at_pos/arguments': size changed value in new API, from 2 to 3. + +Added optional argument to disallow positions that are outside the column range of the line. Compatibility method registered. diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 7f8b4dca786..be8b6f075d9 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -421,7 +421,7 @@ void CodeEdit::gui_input(const Ref &p_gui_input) { mpos.x = get_size().x - mpos.x; } - Point2i pos = get_line_column_at_pos(mpos, false); + Point2i pos = get_line_column_at_pos(mpos, false, false); int line = pos.y; int col = pos.x; @@ -443,18 +443,18 @@ void CodeEdit::gui_input(const Ref &p_gui_input) { if (symbol_lookup_on_click_enabled) { if (mm->is_command_or_control_pressed() && mm->get_button_mask().is_empty()) { - symbol_lookup_pos = get_line_column_at_pos(mpos); + symbol_lookup_pos = get_line_column_at_pos(mpos, false, false); symbol_lookup_new_word = get_word_at_pos(mpos); if (symbol_lookup_new_word != symbol_lookup_word) { emit_signal(SNAME("symbol_validate"), symbol_lookup_new_word); } - } else if (!mm->is_command_or_control_pressed() || (!mm->get_button_mask().is_empty() && symbol_lookup_pos != get_line_column_at_pos(mpos))) { + } else if (!mm->is_command_or_control_pressed() || (!mm->get_button_mask().is_empty() && symbol_lookup_pos != get_line_column_at_pos(mpos, false, false))) { set_symbol_lookup_word_as_valid(false); } } if (symbol_tooltip_on_hover_enabled) { - symbol_tooltip_pos = get_line_column_at_pos(mpos, false); + symbol_tooltip_pos = get_line_column_at_pos(mpos, false, false); symbol_tooltip_word = get_word_at_pos(mpos); symbol_tooltip_timer->start(); } @@ -2388,7 +2388,7 @@ bool CodeEdit::is_symbol_lookup_on_click_enabled() const { String CodeEdit::get_text_for_symbol_lookup() const { Point2i mp = get_local_mouse_pos(); - Point2i pos = get_line_column_at_pos(mp, false); + Point2i pos = get_line_column_at_pos(mp, false, false); int line = pos.y; int col = pos.x; diff --git a/scene/gui/text_edit.compat.inc b/scene/gui/text_edit.compat.inc index bf73229868e..d15740390e9 100644 --- a/scene/gui/text_edit.compat.inc +++ b/scene/gui/text_edit.compat.inc @@ -34,8 +34,13 @@ void TextEdit::_set_selection_mode_compat_86978(SelectionMode p_mode, int p_line set_selection_mode(p_mode); } +Point2i TextEdit::_get_line_column_at_pos_bind_compat_100913(const Point2i &p_pos, bool p_allow_out_of_bounds) const { + return get_line_column_at_pos(p_pos, p_allow_out_of_bounds, true); +} + void TextEdit::_bind_compatibility_methods() { ClassDB::bind_compatibility_method(D_METHOD("set_selection_mode", "mode", "line", "column", "caret_index"), &TextEdit::_set_selection_mode_compat_86978, DEFVAL(-1), DEFVAL(-1), DEFVAL(0)); + ClassDB::bind_compatibility_method(D_METHOD("get_line_column_at_pos", "position", "allow_out_of_bounds"), &TextEdit::_get_line_column_at_pos_bind_compat_100913, DEFVAL(true)); } #endif diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index addbff1e979..b707a5a9334 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -4397,9 +4397,12 @@ Point2 TextEdit::get_local_mouse_pos() const { } String TextEdit::get_word_at_pos(const Vector2 &p_pos) const { - Point2i pos = get_line_column_at_pos(p_pos); + Point2i pos = get_line_column_at_pos(p_pos, false, false); int row = pos.y; int col = pos.x; + if (row < 0 || col < 0) { + return ""; + } String s = text[row]; if (s.length() == 0) { @@ -4435,7 +4438,7 @@ String TextEdit::get_word_at_pos(const Vector2 &p_pos) const { return String(); } -Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_of_bounds) const { +Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_clamp_line, bool p_clamp_column) const { float rows = p_pos.y - theme_cache.style_normal->get_margin(SIDE_TOP); if (!editable) { rows -= theme_cache.style_readonly->get_offset().y / 2; @@ -4462,10 +4465,10 @@ Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_ int visible_lines = get_visible_line_count_in_range(first_vis_line, row); if (rows > visible_lines) { - if (!p_allow_out_of_bounds) { - return Point2i(-1, -1); + if (p_clamp_line) { + return Point2i(text[row].length(), row); } - return Point2i(text[row].length(), row); + return Point2i(-1, -1); } int colx = p_pos.x - (theme_cache.style_normal->get_margin(SIDE_LEFT) + gutters_width + gutter_padding); @@ -4482,6 +4485,11 @@ Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_ } else { colx -= wrap_indent; } + + if (!p_clamp_column && (colx < 0 || colx > TS->shaped_text_get_size(text_rid).x)) { + return Point2i(-1, -1); + } + int col = TS->shaped_text_hit_test_position(text_rid, colx); if (!caret_mid_grapheme_enabled) { col = TS->shaped_text_closest_character_pos(text_rid, col); @@ -6740,7 +6748,7 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("get_word_at_pos", "position"), &TextEdit::get_word_at_pos); - ClassDB::bind_method(D_METHOD("get_line_column_at_pos", "position", "allow_out_of_bounds"), &TextEdit::get_line_column_at_pos, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("get_line_column_at_pos", "position", "clamp_line", "clamp_column"), &TextEdit::get_line_column_at_pos, DEFVAL(true), DEFVAL(true)); ClassDB::bind_method(D_METHOD("get_pos_at_line_column", "line", "column"), &TextEdit::get_pos_at_line_column); ClassDB::bind_method(D_METHOD("get_rect_at_line_column", "line", "column"), &TextEdit::get_rect_at_line_column); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index ef511096302..8609b86eccf 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -658,6 +658,7 @@ protected: #ifndef DISABLE_DEPRECATED void _set_selection_mode_compat_86978(SelectionMode p_mode, int p_line = -1, int p_column = -1, int p_caret = 0); + Point2i _get_line_column_at_pos_bind_compat_100913(const Point2i &p_pos, bool p_allow_out_of_bounds = true) const; static void _bind_compatibility_methods(); #endif // DISABLE_DEPRECATED @@ -860,7 +861,7 @@ public: String get_word_at_pos(const Vector2 &p_pos) const; - Point2i get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_of_bounds = true) const; + Point2i get_line_column_at_pos(const Point2i &p_pos, bool p_clamp_line = true, bool p_clamp_column = true) const; Point2i get_pos_at_line_column(int p_line, int p_column) const; Rect2i get_rect_at_line_column(int p_line, int p_column) const;