diff --git a/docs/changelog.rst b/docs/changelog.rst index 0cc79e734..ea9506dcb 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -9,6 +9,10 @@ To update |kitty|, :doc:`follow the instructions `. - Add a new :ref:`action-toggle_layout` action to easily zoom/unzoom a window +- When right clicking to extend a selection, move the nearest selection + boundary rather than the end of the selection. To restore previous behavior + use ``mouse_map right press ungrabbed mouse_selection move-end``. + - Fix a bug in the implementation of the synchronized updates escape code that could cause incorrect parsing if either the pending buffer capacity or the pending timeout were exceeded (:iss:`3779`) diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index 43073ba6b..97f45a577 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -17,6 +17,7 @@ MOUSE_SELECTION_NORMAL: int MOUSE_SELECTION_WORD: int MOUSE_SELECTION_RECTANGLE: int MOUSE_SELECTION_LINE_FROM_POINT: int +MOUSE_SELECTION_MOVE_END: int KITTY_VCS_REV: str NO_CLOSE_REQUESTED: int IMPERATIVE_CLOSE_REQUESTED: int diff --git a/kitty/mouse.c b/kitty/mouse.c index 5447040b9..0bbbc6a98 100644 --- a/kitty/mouse.c +++ b/kitty/mouse.c @@ -281,11 +281,11 @@ drag_scroll(Window *w, OSWindow *frame) { } static inline void -extend_selection(Window *w, bool ended) { +extend_selection(Window *w, bool ended, bool extend_nearest) { Screen *screen = w->render_data.screen; if (screen_has_selection(screen)) { screen_update_selection(screen, w->mouse_pos.cell_x, w->mouse_pos.cell_y, w->mouse_pos.in_left_half_of_cell, - (SelectionUpdate){.ended=ended, .set_as_nearest_extend=true}); + (SelectionUpdate){.ended=ended, .set_as_nearest_extend=extend_nearest}); } } @@ -590,6 +590,7 @@ typedef enum MouseSelectionType { MOUSE_SELECTION_WORD, MOUSE_SELECTION_LINE, MOUSE_SELECTION_LINE_FROM_POINT, + MOUSE_SELECTION_MOVE_END, } MouseSelectionType; @@ -621,7 +622,10 @@ mouse_selection(Window *w, int code, int button) { if (screen_selection_range_for_line(screen, w->mouse_pos.cell_y, &start, &end) && end > w->mouse_pos.cell_x) S(EXTEND_LINE_FROM_POINT); break; case MOUSE_SELECTION_EXTEND: - extend_selection(w, false); + extend_selection(w, false, true); + break; + case MOUSE_SELECTION_MOVE_END: + extend_selection(w, false, false); break; } set_mouse_cursor_when_dragging(); @@ -863,6 +867,7 @@ init_mouse(PyObject *module) { PyModule_AddIntMacro(module, MOUSE_SELECTION_WORD); PyModule_AddIntMacro(module, MOUSE_SELECTION_LINE); PyModule_AddIntMacro(module, MOUSE_SELECTION_LINE_FROM_POINT); + PyModule_AddIntMacro(module, MOUSE_SELECTION_MOVE_END); if (PyModule_AddFunctions(module, module_methods) != 0) return false; return true; } diff --git a/kitty/options/definition.py b/kitty/options/definition.py index 472969aad..73154de20 100644 --- a/kitty/options/definition.py +++ b/kitty/options/definition.py @@ -548,6 +548,7 @@ mma('Select line from point', mma('Extend the current selection', 'extend_selection right press ungrabbed mouse_selection extend', + long_text='If you want only the end of the selection to be moved instead of the nearest boundary, use move-end instead of extend.' ) mma('Paste from the primary selection even when grabbed', diff --git a/kitty/options/utils.py b/kitty/options/utils.py index 1dd67ecec..06aca5fff 100644 --- a/kitty/options/utils.py +++ b/kitty/options/utils.py @@ -341,6 +341,7 @@ def mouse_selection(func: str, rest: str) -> FuncArgsType: cmap = { 'normal': defines.MOUSE_SELECTION_NORMAL, 'extend': defines.MOUSE_SELECTION_EXTEND, + 'move-end': defines.MOUSE_SELECTION_MOVE_END, 'rectangle': defines.MOUSE_SELECTION_RECTANGLE, 'word': defines.MOUSE_SELECTION_WORD, 'line': defines.MOUSE_SELECTION_LINE,