mirror of
https://github.com/godotengine/godot.git
synced 2025-10-19 07:53:26 +00:00
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
4 changed files with 140 additions and 50 deletions
|
@ -275,7 +275,6 @@ void CodeEdit::_notification(int p_what) {
|
|||
} break;
|
||||
|
||||
case NOTIFICATION_MOUSE_EXIT: {
|
||||
queue_redraw();
|
||||
symbol_tooltip_timer->stop();
|
||||
} break;
|
||||
}
|
||||
|
|
|
@ -1675,6 +1675,10 @@ void TextEdit::_notification(int p_what) {
|
|||
drag_caret_force_displayed = false;
|
||||
queue_redraw();
|
||||
}
|
||||
if (hovered_gutter != Vector2i(-1, -1)) {
|
||||
hovered_gutter = Vector2i(-1, -1);
|
||||
queue_redraw();
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
@ -1843,18 +1847,18 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
|
|||
int col = pos.x;
|
||||
|
||||
// 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);
|
||||
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) {
|
||||
emit_signal(SNAME("gutter_clicked"), line, i);
|
||||
return;
|
||||
}
|
||||
|
||||
left_margin += gutters[i].width;
|
||||
if (mpos.x < left_margin + gutters_width + gutter_padding) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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.
|
||||
Vector2i current_hovered_gutter = Vector2i(-1, -1);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Update hovered gutter.
|
||||
Vector2i current_hovered_gutter = _get_hovered_gutter(mpos);
|
||||
if (current_hovered_gutter != hovered_gutter) {
|
||||
hovered_gutter = current_hovered_gutter;
|
||||
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 {
|
||||
Point2i pos = get_line_column_at_pos(p_pos);
|
||||
int row = pos.y;
|
||||
|
||||
int left_margin = theme_cache.style_normal->get_margin(SIDE_LEFT);
|
||||
int gutter = left_margin + gutters_width;
|
||||
if (p_pos.x < gutter) {
|
||||
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;
|
||||
Vector2i current_hovered_gutter = _get_hovered_gutter(p_pos);
|
||||
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)) {
|
||||
return CURSOR_POINTING_HAND;
|
||||
} else {
|
||||
return CURSOR_ARROW;
|
||||
}
|
||||
}
|
||||
int left_margin = theme_cache.style_normal->get_margin(SIDE_LEFT);
|
||||
if (p_pos.x < left_margin + gutters_width + gutter_padding) {
|
||||
return CURSOR_ARROW;
|
||||
}
|
||||
|
||||
|
@ -8321,9 +8298,35 @@ void TextEdit::_update_gutter_width() {
|
|||
if (gutters_width > 0) {
|
||||
gutter_padding = 2;
|
||||
}
|
||||
if (get_viewport()) {
|
||||
hovered_gutter = _get_hovered_gutter(get_local_mouse_position());
|
||||
}
|
||||
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. */
|
||||
Vector<Pair<int64_t, Color>> TextEdit::_get_line_syntax_highlighting(int p_line) {
|
||||
if (syntax_highlighter.is_null() || setting_text) {
|
||||
|
|
|
@ -565,6 +565,7 @@ private:
|
|||
Vector2i hovered_gutter = Vector2i(-1, -1); // X = gutter index, Y = row.
|
||||
|
||||
void _update_gutter_width();
|
||||
Vector2i _get_hovered_gutter(const Point2 &p_mouse_pos) const;
|
||||
|
||||
/* Syntax highlighting. */
|
||||
Ref<SyntaxHighlighter> syntax_highlighter;
|
||||
|
|
|
@ -8151,6 +8151,93 @@ TEST_CASE("[SceneTree][TextEdit] 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_added");
|
||||
SIGNAL_UNWATCH(text_edit, "gutter_removed");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue