This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch reproducible-widget-previews
in repository efl.
View the commit online.
commit f3a3d7adfe2b008e94e682aefd8be22ecffcb21e
Author: Alastair Poole <[email protected]>
AuthorDate: Fri Apr 24 07:20:33 2026 +0100
elm_code_widget: fix mouse selection off-by-one and stale expander repaint after cut
Fix selection/cursor math for mouse drags and repaint behavior after cut.
- Treat mouse selection end as caret-style exclusive during normalization
so selected text/cursor no longer overshoot by one character.
- Anchor drag selection from the click cursor position.
- Stop adding an extra column when positioning the cursor for mouse selection.
- Fix selection-clear repaint path to refresh the current viewport instead of
repainting a top-of-file range, preventing stale/rogue rows near EOF.
- Add bounds check before drawing newline whitespace marker to avoid
out-of-bounds cell writes.
- Add regression tests for mouse single-line and two-line selection ranges.
---
src/lib/elementary/elm_code_widget.c | 20 ++---
src/lib/elementary/elm_code_widget_selection.c | 92 +++++++++++++++++++---
.../elementary/elm_code_test_widget_selection.c | 67 ++++++++++++++++
3 files changed, 152 insertions(+), 27 deletions(-)
diff --git a/src/lib/elementary/elm_code_widget.c b/src/lib/elementary/elm_code_widget.c
index c5a3846633..f408e7a2fc 100644
--- a/src/lib/elementary/elm_code_widget.c
+++ b/src/lib/elementary/elm_code_widget.c
@@ -479,7 +479,8 @@ _elm_code_widget_fill_line(Elm_Code_Widget *widget, Elm_Code_Widget_Data *pd, El
_elm_code_widget_fill_selection(widget, line, cells, gutter, w);
_elm_code_widget_fill_cursor(widget, line->number, gutter, w);
- if (line->number < elm_code_file_lines_get(line->file))
+ if (line->number < elm_code_file_lines_get(line->file) &&
+ (length + (unsigned int) gutter) < w)
_elm_code_widget_fill_whitespace(widget, '\n', &cells[length + gutter]);
evas_object_textgrid_update_add(grid, 0, 0, w, 1);
@@ -556,21 +557,10 @@ _elm_code_widget_fill_line_empty(Elm_Code_Widget *widget, Elm_Code_Widget_Data *
static void
_elm_code_widget_cursor_selection_set(Elm_Code_Widget *widget, Elm_Code_Widget_Data *pd)
{
- unsigned int end_line, end_col;
-
- end_line = pd->selection->end_line;
- end_col = pd->selection->end_col;
-
if (pd->selection->type == ELM_CODE_WIDGET_SELECTION_KEYBOARD)
return;
- if ((pd->selection->start_line == pd->selection->end_line && pd->selection->end_col > pd->selection->start_col) ||
- (pd->selection->start_line < pd->selection->end_line))
- {
- end_col++;
- }
-
- elm_code_widget_cursor_position_set(widget, end_line, end_col);
+ elm_code_widget_cursor_position_set(widget, pd->selection->end_line, pd->selection->end_col);
}
static void
@@ -745,7 +735,7 @@ _elm_code_widget_selection_clear_cb(void *data, const Efl_Event *event EINA_UNUS
widget = (Elm_Code_Widget *)data;
- _elm_code_widget_fill(widget);
+ _elm_code_widget_refresh(widget, NULL);
}
static void
@@ -1282,7 +1272,7 @@ _elm_code_widget_mouse_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj
if (!pd->selection)
if (col > 0 && row <= elm_code_file_lines_get(pd->code->file))
- elm_code_widget_selection_start(widget, row, col);
+ elm_code_widget_selection_start(widget, pd->cursor_line, pd->cursor_col);
_elm_code_widget_selection_type_set(widget, ELM_CODE_WIDGET_SELECTION_MOUSE);
_elm_code_widget_selection_in_progress_set(widget, EINA_TRUE);
diff --git a/src/lib/elementary/elm_code_widget_selection.c b/src/lib/elementary/elm_code_widget_selection.c
index 674f466c33..9e3970f2df 100644
--- a/src/lib/elementary/elm_code_widget_selection.c
+++ b/src/lib/elementary/elm_code_widget_selection.c
@@ -38,6 +38,46 @@ _elm_code_widget_selection_limit(Evas_Object *widget EINA_UNUSED, Elm_Code_Widge
*col = width + 1;
}
+static Eina_Bool
+_elm_code_widget_selection_position_leq(unsigned int line, unsigned int col,
+ unsigned int other_line, unsigned int other_col)
+{
+ return (line < other_line) || (line == other_line && col <= other_col);
+}
+
+static void
+_elm_code_widget_selection_position_prev(Evas_Object *widget, Elm_Code_Widget_Data *pd,
+ unsigned int line, unsigned int col,
+ unsigned int *prev_line, unsigned int *prev_col)
+{
+ Elm_Code_Line *line_obj;
+
+ if (col > 1)
+ {
+ *prev_line = line;
+ *prev_col = col - 1;
+ return;
+ }
+
+ if (line <= 1)
+ {
+ *prev_line = 1;
+ *prev_col = 0;
+ return;
+ }
+
+ *prev_line = line - 1;
+ line_obj = elm_code_file_line_get(pd->code->file, *prev_line);
+ if (!line_obj)
+ {
+ *prev_line = 1;
+ *prev_col = 0;
+ return;
+ }
+
+ *prev_col = elm_code_widget_line_text_column_width_get(widget, line_obj) + 1;
+}
+
EAPI void
elm_code_widget_selection_start(Evas_Object *widget,
unsigned int line, unsigned int col)
@@ -119,6 +159,7 @@ elm_code_widget_selection_normalized_get(Evas_Object *widget)
Elm_Code_Widget_Data *pd;
Elm_Code_Widget_Selection_Data *selection;
Eina_Bool reverse;
+ unsigned int start_line, start_col, end_line, end_col;
pd = efl_data_scope_get(widget, ELM_CODE_WIDGET_CLASS);
selection = _elm_code_widget_selection_new();
@@ -131,24 +172,52 @@ elm_code_widget_selection_normalized_get(Evas_Object *widget)
return selection;
}
- if (pd->selection->start_line == pd->selection->end_line)
- reverse = pd->selection->start_col > pd->selection->end_col;
+ if (pd->selection->type == ELM_CODE_WIDGET_SELECTION_MOUSE)
+ {
+ if (_elm_code_widget_selection_position_leq(pd->selection->start_line, pd->selection->start_col,
+ pd->selection->end_line, pd->selection->end_col))
+ {
+ selection->start_line = pd->selection->start_line;
+ selection->start_col = pd->selection->start_col;
+ _elm_code_widget_selection_position_prev(widget, pd,
+ pd->selection->end_line, pd->selection->end_col,
+ &selection->end_line, &selection->end_col);
+ }
+ else
+ {
+ selection->start_line = pd->selection->end_line;
+ selection->start_col = pd->selection->end_col;
+ _elm_code_widget_selection_position_prev(widget, pd,
+ pd->selection->start_line, pd->selection->start_col,
+ &selection->end_line, &selection->end_col);
+ }
+
+ return selection;
+ }
+
+ start_line = pd->selection->start_line;
+ start_col = pd->selection->start_col;
+ end_line = pd->selection->end_line;
+ end_col = pd->selection->end_col;
+
+ if (start_line == end_line)
+ reverse = start_col > end_col;
else
- reverse = pd->selection->start_line > pd->selection->end_line;
+ reverse = start_line > end_line;
if (reverse)
{
- selection->start_line = pd->selection->end_line;
- selection->start_col = pd->selection->end_col;
- selection->end_line = pd->selection->start_line;
- selection->end_col = pd->selection->start_col;
+ selection->start_line = end_line;
+ selection->start_col = end_col;
+ selection->end_line = start_line;
+ selection->end_col = start_col;
}
else
{
- selection->start_line = pd->selection->start_line;
- selection->start_col = pd->selection->start_col;
- selection->end_line = pd->selection->end_line;
- selection->end_col = pd->selection->end_col;
+ selection->start_line = start_line;
+ selection->start_col = start_col;
+ selection->end_line = end_line;
+ selection->end_col = end_col;
}
return selection;
@@ -515,4 +584,3 @@ _elm_code_widget_selection_type_set(Evas_Object *widget, Elm_Code_Widget_Selecti
pd->selection->type = type;
}
-
diff --git a/src/tests/elementary/elm_code_test_widget_selection.c b/src/tests/elementary/elm_code_test_widget_selection.c
index 76ed16d6d9..29452add26 100644
--- a/src/tests/elementary/elm_code_test_widget_selection.c
+++ b/src/tests/elementary/elm_code_test_widget_selection.c
@@ -109,6 +109,38 @@ EFL_START_TEST(elm_code_test_widget_selection_text_get)
}
EFL_END_TEST
+EFL_START_TEST(elm_code_test_widget_selection_text_get_mouse_singleline)
+{
+ Elm_Code *code;
+ Elm_Code_File *file;
+ Elm_Code_Widget *widget;
+ Elm_Code_Widget_Data *pd;
+ Evas_Object *win;
+ char *selection;
+
+ char *args[] = { "exe" };
+ elm_init(1, args);
+ code = elm_code_create();
+ file = elm_code_file_new(code);
+ elm_code_file_line_append(file, "test", 4, NULL);
+
+ win = win_add(NULL, "entry", ELM_WIN_BASIC);
+ widget = elm_code_widget_add(win, code);
+ pd = efl_data_scope_get(widget, ELM_CODE_WIDGET_CLASS);
+
+ elm_code_widget_selection_start(widget, 1, 2);
+ pd->selection->type = ELM_CODE_WIDGET_SELECTION_MOUSE;
+ elm_code_widget_selection_end(widget, 1, 4);
+
+ selection = elm_code_widget_selection_text_get(widget);
+ ck_assert_str_eq("es", selection);
+ free(selection);
+
+ elm_code_free(code);
+ elm_shutdown();
+}
+EFL_END_TEST
+
EFL_START_TEST(elm_code_test_widget_selection_reverse_text_get)
{
Elm_Code *code;
@@ -143,6 +175,39 @@ EFL_START_TEST(elm_code_test_widget_selection_reverse_text_get)
}
EFL_END_TEST
+EFL_START_TEST(elm_code_test_widget_selection_text_get_mouse_twoline)
+{
+ Elm_Code *code;
+ Elm_Code_File *file;
+ Elm_Code_Widget *widget;
+ Elm_Code_Widget_Data *pd;
+ Evas_Object *win;
+ char *selection;
+
+ char *args[] = { "exe" };
+ elm_init(1, args);
+ code = elm_code_create();
+ file = elm_code_file_new(code);
+ elm_code_file_line_append(file, "test", 4, NULL);
+ elm_code_file_line_append(file, "test", 4, NULL);
+
+ win = win_add(NULL, "entry", ELM_WIN_BASIC);
+ widget = elm_code_widget_add(win, code);
+ pd = efl_data_scope_get(widget, ELM_CODE_WIDGET_CLASS);
+
+ elm_code_widget_selection_start(widget, 1, 3);
+ pd->selection->type = ELM_CODE_WIDGET_SELECTION_MOUSE;
+ elm_code_widget_selection_end(widget, 2, 1);
+
+ selection = elm_code_widget_selection_text_get(widget);
+ ck_assert_str_eq("st", selection);
+ free(selection);
+
+ elm_code_free(code);
+ elm_shutdown();
+}
+EFL_END_TEST
+
EFL_START_TEST(elm_code_test_widget_selection_text_get_twoline)
{
Elm_Code *code;
@@ -700,7 +765,9 @@ void elm_code_test_widget_selection(TCase *tc)
tcase_add_test(tc, elm_code_test_widget_selection_set);
tcase_add_test(tc, elm_code_test_widget_selection_normalized_get);
tcase_add_test(tc, elm_code_test_widget_selection_text_get);
+ tcase_add_test(tc, elm_code_test_widget_selection_text_get_mouse_singleline);
tcase_add_test(tc, elm_code_test_widget_selection_reverse_text_get);
+ tcase_add_test(tc, elm_code_test_widget_selection_text_get_mouse_twoline);
tcase_add_test(tc, elm_code_test_widget_selection_text_get_twoline);
tcase_add_test(tc, elm_code_test_widget_selection_reverse_text_get_twoline);
tcase_add_test(tc, elm_code_test_widget_selection_text_get_multiline);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.