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.
This commit is contained in:
Daniel Eklöf 2020-08-07 19:55:02 +02:00
parent 158722b642
commit 721ca80abe
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 22 additions and 9 deletions

View file

@ -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

29
input.c
View file

@ -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);