From 721ca80abe13d47a232a41452780a3c1bb03b862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 7 Aug 2020 19:55:02 +0200 Subject: [PATCH] input: motion: do selection update even if cursor is outside the grid Previously, the selection was only updated when the mouse cursor was inside the grid. This makes it difficult to e.g. do large selections fast, since you often end up moving the cursor outside the grid, or outside the terminal window even. Now, we update the selection regardless of *where* the cursor is. This is done by bounding the row/col we pass to 'selection_update()' to the grid, while still setting the seat's row/col to -1 when the cursor is outside the grid, to ensure the xcursor etc are set correctly. Care must also be taken to *not* pass any motion events to a mouse grabbing client, when the cursor is outside the grid. Closes #70. --- CHANGELOG.md | 2 ++ input.c | 29 ++++++++++++++++++++--------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9edbf1b..d6408bf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,8 @@ text. * Compilation errors in 32-bit builds. * Mouse cursor style of top and left margins. +* Selection is now **updated** when the cursor moves outside the grid + (https://codeberg.org/dnkl/foot/issues/70). ### Security diff --git a/input.c b/input.c index 161af06b..cd23fd80 100644 --- a/input.c +++ b/input.c @@ -1204,8 +1204,6 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, break; case TERM_SURF_GRID: { - term_xcursor_update_for_seat(term, seat); - int col = x >= term->margins.left ? (x - term->margins.left) / term->cell_width : -1; int row = y >= term->margins.top ? (y - term->margins.top) / term->cell_height : -1; @@ -1215,22 +1213,35 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, seat->mouse.col = col >= 0 && col < term->cols ? col : -1; seat->mouse.row = row >= 0 && row < term->rows ? row : -1; - if (seat->mouse.col < 0 || seat->mouse.row < 0) - break; + term_xcursor_update_for_seat(term, seat); - bool update_selection = seat->mouse.button == BTN_LEFT || seat->mouse.button == BTN_RIGHT; + /* Update selection even if cursor is outside the grid, + * including outside the terminal bounds */ + int selection_col = max(0, min(col, term->cols - 1)); + int selection_row = max(0, min(row, term->rows - 1)); + + bool update_selection = + seat->mouse.button == BTN_LEFT || seat->mouse.button == BTN_RIGHT; bool update_selection_early = term->selection.end.row == -1; if (update_selection && update_selection_early) - selection_update(term, seat->mouse.col, seat->mouse.row); + selection_update(term, selection_col, selection_row); - if (old_col == seat->mouse.col && old_row == seat->mouse.row) + if (old_col == seat->mouse.col && old_row == seat->mouse.row) { + /* Cursor hasn't moved to a new cell since last motion event */ break; + } if (update_selection && !update_selection_early) - selection_update(term, seat->mouse.col, seat->mouse.row); + selection_update(term, selection_col, selection_row); + + if (!term_mouse_grabbed(term, seat) && + seat->mouse.col >= 0 && + seat->mouse.row >= 0) + { + assert(seat->mouse.col < term->cols); + assert(seat->mouse.row < term->rows); - if (!term_mouse_grabbed(term, seat)) { term_mouse_motion( term, seat->mouse.button, seat->mouse.row, seat->mouse.col, seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl);