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.

Reply via email to