diff --git a/docs/changelog.rst b/docs/changelog.rst index ecd31a49f..4e5befd0e 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -66,6 +66,8 @@ Detailed list of changes - kitten @ send-key: Fix some keys being sent in kitty keyboard protocol encoding when not using socket for remote control +- Dont clear selections on erase in screen commands unless the erased region intersects a selection (:iss:`7408`) + 0.34.1 [2024-04-19] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/kitty/screen.c b/kitty/screen.c index 1dfd99ac7..6f97f1152 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -542,6 +542,23 @@ selection_has_screen_line(const Selections *selections, const int y) { return false; } +static bool +selection_intersects_screen_lines(const Selections *selections, int a, int b) { + if (a > b) SWAP(a, b); + for (size_t i = 0; i < selections->count; i++) { + const Selection *s = selections->items + i; + if (!is_selection_empty(s)) { + int start = (int)s->start.y - s->start_scrolled_by; + int end = (int)s->end.y - s->end_scrolled_by; + int top = MIN(start, end); + int bottom = MAX(start, end); + if ((top <= a && bottom >= a) || (top >= a && top <= b)) return true; + } + } + return false; +} + + static void init_text_loop_line(Screen *self, text_loop_state *s) { if (self->modes.mIRM) { @@ -1968,7 +1985,7 @@ screen_erase_in_display(Screen *self, unsigned int how, bool private) { } } else linebuf_clear_lines(self->linebuf, self->cursor, a, b); self->is_dirty = true; - clear_selection(&self->selections); + if (selection_intersects_screen_lines(&self->selections, a, b)) clear_selection(&self->selections); } if (how < 2) { screen_erase_in_line(self, how, private);