mirror of https://github.com/godotengine/godot
Merge pull request #101613 from kitbdev/fix-te-hover-mouse-exit
Fix TextEdit breakpoint hover not hiding on mouse exit
This commit is contained in:
commit
c032ce4050
|
|
@ -275,7 +275,6 @@ void CodeEdit::_notification(int p_what) {
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NOTIFICATION_MOUSE_EXIT: {
|
case NOTIFICATION_MOUSE_EXIT: {
|
||||||
queue_redraw();
|
|
||||||
symbol_tooltip_timer->stop();
|
symbol_tooltip_timer->stop();
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1675,6 +1675,10 @@ void TextEdit::_notification(int p_what) {
|
||||||
drag_caret_force_displayed = false;
|
drag_caret_force_displayed = false;
|
||||||
queue_redraw();
|
queue_redraw();
|
||||||
}
|
}
|
||||||
|
if (hovered_gutter != Vector2i(-1, -1)) {
|
||||||
|
hovered_gutter = Vector2i(-1, -1);
|
||||||
|
queue_redraw();
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1843,18 +1847,18 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
|
||||||
int col = pos.x;
|
int col = pos.x;
|
||||||
|
|
||||||
// Gutters.
|
// Gutters.
|
||||||
|
Vector2i current_hovered_gutter = _get_hovered_gutter(mpos);
|
||||||
|
if (current_hovered_gutter != hovered_gutter) {
|
||||||
|
hovered_gutter = current_hovered_gutter;
|
||||||
|
queue_redraw();
|
||||||
|
}
|
||||||
|
if (hovered_gutter != Vector2i(-1, -1)) {
|
||||||
|
emit_signal(SNAME("gutter_clicked"), hovered_gutter.y, hovered_gutter.x);
|
||||||
|
return;
|
||||||
|
}
|
||||||
int left_margin = theme_cache.style_normal->get_margin(SIDE_LEFT);
|
int left_margin = theme_cache.style_normal->get_margin(SIDE_LEFT);
|
||||||
for (int i = 0; i < gutters.size(); i++) {
|
if (mpos.x < left_margin + gutters_width + gutter_padding) {
|
||||||
if (!gutters[i].draw || gutters[i].width <= 0) {
|
return;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mpos.x >= left_margin && mpos.x <= left_margin + gutters[i].width) {
|
|
||||||
emit_signal(SNAME("gutter_clicked"), line, i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
left_margin += gutters[i].width;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Minimap.
|
// Minimap.
|
||||||
|
|
@ -2066,27 +2070,8 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if user is hovering a different gutter, and update if yes.
|
// Update hovered gutter.
|
||||||
Vector2i current_hovered_gutter = Vector2i(-1, -1);
|
Vector2i current_hovered_gutter = _get_hovered_gutter(mpos);
|
||||||
|
|
||||||
int left_margin = theme_cache.style_normal->get_margin(SIDE_LEFT);
|
|
||||||
if (mpos.x <= left_margin + gutters_width + gutter_padding) {
|
|
||||||
int hovered_row = get_line_column_at_pos(mpos).y;
|
|
||||||
for (int i = 0; i < gutters.size(); i++) {
|
|
||||||
if (!gutters[i].draw || gutters[i].width <= 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mpos.x >= left_margin && mpos.x < left_margin + gutters[i].width) {
|
|
||||||
// We are in this gutter i's horizontal area.
|
|
||||||
current_hovered_gutter = Vector2i(i, hovered_row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
left_margin += gutters[i].width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_hovered_gutter != hovered_gutter) {
|
if (current_hovered_gutter != hovered_gutter) {
|
||||||
hovered_gutter = current_hovered_gutter;
|
hovered_gutter = current_hovered_gutter;
|
||||||
queue_redraw();
|
queue_redraw();
|
||||||
|
|
@ -3115,24 +3100,16 @@ void TextEdit::drop_data(const Point2 &p_point, const Variant &p_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const {
|
Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const {
|
||||||
Point2i pos = get_line_column_at_pos(p_pos);
|
Vector2i current_hovered_gutter = _get_hovered_gutter(p_pos);
|
||||||
int row = pos.y;
|
if (current_hovered_gutter != Vector2i(-1, -1)) {
|
||||||
|
if (gutters[current_hovered_gutter.x].clickable || is_line_gutter_clickable(current_hovered_gutter.y, current_hovered_gutter.x)) {
|
||||||
int left_margin = theme_cache.style_normal->get_margin(SIDE_LEFT);
|
return CURSOR_POINTING_HAND;
|
||||||
int gutter = left_margin + gutters_width;
|
} else {
|
||||||
if (p_pos.x < gutter) {
|
return CURSOR_ARROW;
|
||||||
for (int i = 0; i < gutters.size(); i++) {
|
|
||||||
if (!gutters[i].draw) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p_pos.x >= left_margin && p_pos.x < left_margin + gutters[i].width) {
|
|
||||||
if (gutters[i].clickable || is_line_gutter_clickable(row, i)) {
|
|
||||||
return CURSOR_POINTING_HAND;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
left_margin += gutters[i].width;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
int left_margin = theme_cache.style_normal->get_margin(SIDE_LEFT);
|
||||||
|
if (p_pos.x < left_margin + gutters_width + gutter_padding) {
|
||||||
return CURSOR_ARROW;
|
return CURSOR_ARROW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -8321,9 +8298,35 @@ void TextEdit::_update_gutter_width() {
|
||||||
if (gutters_width > 0) {
|
if (gutters_width > 0) {
|
||||||
gutter_padding = 2;
|
gutter_padding = 2;
|
||||||
}
|
}
|
||||||
|
if (get_viewport()) {
|
||||||
|
hovered_gutter = _get_hovered_gutter(get_local_mouse_position());
|
||||||
|
}
|
||||||
queue_redraw();
|
queue_redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector2i TextEdit::_get_hovered_gutter(const Point2 &p_mouse_pos) const {
|
||||||
|
int left_margin = theme_cache.style_normal->get_margin(SIDE_LEFT);
|
||||||
|
if (p_mouse_pos.x > left_margin + gutters_width + gutter_padding) {
|
||||||
|
return Vector2i(-1, -1);
|
||||||
|
}
|
||||||
|
int hovered_row = get_line_column_at_pos(p_mouse_pos, false).y;
|
||||||
|
if (hovered_row == -1) {
|
||||||
|
return Vector2i(-1, -1);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < gutters.size(); i++) {
|
||||||
|
if (!gutters[i].draw || gutters[i].width <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_mouse_pos.x >= left_margin && p_mouse_pos.x < left_margin + gutters[i].width) {
|
||||||
|
return Vector2i(i, hovered_row);
|
||||||
|
}
|
||||||
|
|
||||||
|
left_margin += gutters[i].width;
|
||||||
|
}
|
||||||
|
return Vector2i(-1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Syntax highlighting. */
|
/* Syntax highlighting. */
|
||||||
Vector<Pair<int64_t, Color>> TextEdit::_get_line_syntax_highlighting(int p_line) {
|
Vector<Pair<int64_t, Color>> TextEdit::_get_line_syntax_highlighting(int p_line) {
|
||||||
if (syntax_highlighter.is_null() || setting_text) {
|
if (syntax_highlighter.is_null() || setting_text) {
|
||||||
|
|
|
||||||
|
|
@ -565,6 +565,7 @@ private:
|
||||||
Vector2i hovered_gutter = Vector2i(-1, -1); // X = gutter index, Y = row.
|
Vector2i hovered_gutter = Vector2i(-1, -1); // X = gutter index, Y = row.
|
||||||
|
|
||||||
void _update_gutter_width();
|
void _update_gutter_width();
|
||||||
|
Vector2i _get_hovered_gutter(const Point2 &p_mouse_pos) const;
|
||||||
|
|
||||||
/* Syntax highlighting. */
|
/* Syntax highlighting. */
|
||||||
Ref<SyntaxHighlighter> syntax_highlighter;
|
Ref<SyntaxHighlighter> syntax_highlighter;
|
||||||
|
|
|
||||||
|
|
@ -8151,6 +8151,93 @@ TEST_CASE("[SceneTree][TextEdit] gutters") {
|
||||||
// Merging tested via CodeEdit gutters.
|
// Merging tested via CodeEdit gutters.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SUBCASE("[TextEdit] gutter mouse") {
|
||||||
|
DisplayServerMock *DS = (DisplayServerMock *)(DisplayServer::get_singleton());
|
||||||
|
// Set size for mouse input.
|
||||||
|
text_edit->set_size(Size2(200, 200));
|
||||||
|
|
||||||
|
text_edit->set_text("test1\ntest2\ntest3\ntest4");
|
||||||
|
text_edit->grab_focus();
|
||||||
|
|
||||||
|
text_edit->add_gutter();
|
||||||
|
text_edit->set_gutter_name(0, "test_gutter");
|
||||||
|
text_edit->set_gutter_width(0, 10);
|
||||||
|
text_edit->set_gutter_clickable(0, true);
|
||||||
|
|
||||||
|
text_edit->add_gutter();
|
||||||
|
text_edit->set_gutter_name(1, "test_gutter_not_clickable");
|
||||||
|
text_edit->set_gutter_width(1, 10);
|
||||||
|
text_edit->set_gutter_clickable(1, false);
|
||||||
|
|
||||||
|
text_edit->add_gutter();
|
||||||
|
CHECK(text_edit->get_gutter_count() == 3);
|
||||||
|
text_edit->set_gutter_name(2, "test_gutter_3");
|
||||||
|
text_edit->set_gutter_width(2, 10);
|
||||||
|
text_edit->set_gutter_clickable(2, true);
|
||||||
|
|
||||||
|
MessageQueue::get_singleton()->flush();
|
||||||
|
const int line_height = text_edit->get_line_height();
|
||||||
|
|
||||||
|
// Defaults to none.
|
||||||
|
CHECK(text_edit->get_hovered_gutter() == Vector2i(-1, -1));
|
||||||
|
CHECK(DS->get_cursor_shape() == DisplayServer::CURSOR_ARROW);
|
||||||
|
|
||||||
|
// Hover over gutter.
|
||||||
|
SEND_GUI_MOUSE_MOTION_EVENT(Point2(5, line_height + line_height / 2), MouseButtonMask::NONE, Key::NONE);
|
||||||
|
CHECK(text_edit->get_hovered_gutter() == Vector2i(0, 1));
|
||||||
|
SIGNAL_CHECK_FALSE("gutter_clicked");
|
||||||
|
CHECK(DS->get_cursor_shape() == DisplayServer::CURSOR_POINTING_HAND);
|
||||||
|
|
||||||
|
// Click on gutter.
|
||||||
|
SEND_GUI_MOUSE_BUTTON_EVENT(Point2(5, line_height / 2), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);
|
||||||
|
CHECK(text_edit->get_hovered_gutter() == Vector2i(0, 0));
|
||||||
|
SIGNAL_CHECK("gutter_clicked", build_array(build_array(0, 0)));
|
||||||
|
|
||||||
|
// Click on gutter on another line.
|
||||||
|
SEND_GUI_MOUSE_BUTTON_EVENT(Point2(5, line_height * 3 + line_height / 2), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);
|
||||||
|
CHECK(text_edit->get_hovered_gutter() == Vector2i(0, 3));
|
||||||
|
SIGNAL_CHECK("gutter_clicked", build_array(build_array(3, 0)));
|
||||||
|
|
||||||
|
// Unclickable gutter can be hovered.
|
||||||
|
SEND_GUI_MOUSE_MOTION_EVENT(Point2(15, line_height + line_height / 2), MouseButtonMask::NONE, Key::NONE);
|
||||||
|
CHECK(text_edit->get_hovered_gutter() == Vector2i(1, 1));
|
||||||
|
SIGNAL_CHECK_FALSE("gutter_clicked");
|
||||||
|
CHECK(DS->get_cursor_shape() == DisplayServer::CURSOR_ARROW);
|
||||||
|
|
||||||
|
// Unclickable gutter can be clicked.
|
||||||
|
SEND_GUI_MOUSE_BUTTON_EVENT(Point2(15, line_height * 2 + line_height / 2), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);
|
||||||
|
CHECK(text_edit->get_hovered_gutter() == Vector2i(1, 2));
|
||||||
|
SIGNAL_CHECK("gutter_clicked", build_array(build_array(2, 1)));
|
||||||
|
CHECK(DS->get_cursor_shape() == DisplayServer::CURSOR_ARROW);
|
||||||
|
|
||||||
|
// Hover past last line.
|
||||||
|
SEND_GUI_MOUSE_MOTION_EVENT(Point2(5, line_height * 5), MouseButtonMask::NONE, Key::NONE);
|
||||||
|
CHECK(text_edit->get_hovered_gutter() == Vector2i(-1, -1));
|
||||||
|
SIGNAL_CHECK_FALSE("gutter_clicked");
|
||||||
|
CHECK(DS->get_cursor_shape() == DisplayServer::CURSOR_ARROW);
|
||||||
|
|
||||||
|
// Click on gutter past last line.
|
||||||
|
SEND_GUI_MOUSE_BUTTON_EVENT(Point2(5, line_height * 5), MouseButton::LEFT, MouseButtonMask::LEFT, Key::NONE);
|
||||||
|
CHECK(text_edit->get_hovered_gutter() == Vector2i(-1, -1));
|
||||||
|
SIGNAL_CHECK_FALSE("gutter_clicked");
|
||||||
|
|
||||||
|
// Mouse exit resets hover.
|
||||||
|
SEND_GUI_MOUSE_MOTION_EVENT(Point2(5, line_height + line_height / 2), MouseButtonMask::NONE, Key::NONE);
|
||||||
|
CHECK(text_edit->get_hovered_gutter() == Vector2i(0, 1));
|
||||||
|
SEND_GUI_MOUSE_MOTION_EVENT(Point2(-1, -1), MouseButtonMask::NONE, Key::NONE);
|
||||||
|
CHECK(text_edit->get_hovered_gutter() == Vector2i(-1, -1));
|
||||||
|
|
||||||
|
// Removing gutter updates hover.
|
||||||
|
SEND_GUI_MOUSE_MOTION_EVENT(Point2(25, line_height + line_height / 2), MouseButtonMask::NONE, Key::NONE);
|
||||||
|
CHECK(text_edit->get_hovered_gutter() == Vector2i(2, 1));
|
||||||
|
text_edit->remove_gutter(2);
|
||||||
|
CHECK(text_edit->get_hovered_gutter() == Vector2i(-1, -1));
|
||||||
|
|
||||||
|
// Updating size updates hover.
|
||||||
|
text_edit->set_gutter_width(1, 20);
|
||||||
|
CHECK(text_edit->get_hovered_gutter() == Vector2i(1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
SIGNAL_UNWATCH(text_edit, "gutter_clicked");
|
SIGNAL_UNWATCH(text_edit, "gutter_clicked");
|
||||||
SIGNAL_UNWATCH(text_edit, "gutter_added");
|
SIGNAL_UNWATCH(text_edit, "gutter_added");
|
||||||
SIGNAL_UNWATCH(text_edit, "gutter_removed");
|
SIGNAL_UNWATCH(text_edit, "gutter_removed");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue