From 45c7cd3f7472b11d50622b10867a329b4d8e2451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 18 Jul 2024 08:08:44 +0200 Subject: [PATCH] input: allow mouse selections to start inside the margins Before this, margins were special cased: * The mouse cursor was always a pointer, and never an I-beam (thus signaling selections cannot be made). * The internal mouse coords where set to -1 when the cursor was inside the margins, causing: - text selections from being made - mouse events being passed to mouse grabbing applications In particular, even with a one-pixel margin, making selections was unnecessarily hard in e.g. fullscreen mode, where you'd expect to be able to throw the cursor into the corner of the screen and then start a selection. With this patch, the cursor is treated as if it was in the first/last column/row, when inside the margin(s). An unintended side-effect of this, initially, was that auto-scrolling selections where way too easy to trigger, since part of its logic is checking if the cursor is inside the margins. That problem has been reduced by two things: * auto-scrolling does not occur unless a selection has been started. That is, just holding down the mouse in the margins and moving up/down doesn't cause scrolling. You have to first select at least one cell in the visible viewport. * A selection isn't fully started (i.e. a cell is actually selected) unless the cursor is inside the actual grid, and *not* in the margins. What does the last point mean? We now allow a selection to be _started_ when clicking in the margin. What this means internally is we set a start coordinate for a selection, but *not* and end coordinate. At this point, we don't have an actual selection. Nothing is selected, and no cells are highlighted, graphically. This happens when we set an end coordinate. Without the last bullet point, that would happen as soon as the cursor was _moved_, even if still inside the margins. Now, we require the cursor to leave the margins and touch an actual cell before we set an end coordinate. Closes #1702 --- CHANGELOG.md | 3 ++ input.c | 82 +++++++++++++++++----------------------------------- terminal.c | 5 +--- 3 files changed, 31 insertions(+), 59 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce993718..dfa2b9ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -106,10 +106,13 @@ ([#1763][1763]). * Replaced the old catppuccin theme with updated flavored themes pulled from [catppuccin/foot](https://github.com/catppuccin/foot) +* Mouse selections can now be started inside the margins + ([#1702][1702]). [1701]: https://codeberg.org/dnkl/foot/issues/1701 [1761]: https://codeberg.org/dnkl/foot/issues/1761 [1763]: https://codeberg.org/dnkl/foot/issues/1763 +[1702]: https://codeberg.org/dnkl/foot/issues/1702 ### Deprecated diff --git a/input.c b/input.c index 68cb9314..dc588f75 100644 --- a/input.c +++ b/input.c @@ -1860,14 +1860,17 @@ mouse_coord_pixel_to_cell(struct seat *seat, const struct terminal *term, * if the cursor is outside the grid. I.e. if it is inside the * margins. */ - - if (x < term->margins.left || x >= term->width - term->margins.right) - seat->mouse.col = -1; + if (x < term->margins.left) + seat->mouse.col = 0; + else if (x >= term->width - term->margins.right) + seat->mouse.col = term->cols - 1; else seat->mouse.col = (x - term->margins.left) / term->cell_width; - if (y < term->margins.top || y >= term->height - term->margins.bottom) - seat->mouse.row = -1; + if (y < term->margins.top) + seat->mouse.row = 0; + else if (y >= term->height - term->margins.bottom) + seat->mouse.row = term->rows - 1; else seat->mouse.row = (y - term->margins.top) / term->cell_height; } @@ -2127,49 +2130,10 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, int old_col = seat->mouse.col; int old_row = seat->mouse.row; - /* - * While the seat's mouse coordinates must always be on the - * grid, or -1, we allow updating the selection even when the - * mouse is outside the grid (could also be outside the - * terminal window). - */ - int selection_col; - int selection_row; + mouse_coord_pixel_to_cell(seat, term, seat->mouse.x, seat->mouse.y); - if (x < term->margins.left) { - seat->mouse.col = -1; - selection_col = 0; - } else if (x >= term->width - term->margins.right) { - seat->mouse.col = -1; - selection_col = term->cols - 1; - } else { - seat->mouse.col = (x - term->margins.left) / term->cell_width; - selection_col = seat->mouse.col; - } - - if (y < term->margins.top) { - seat->mouse.row = -1; - selection_row = 0; - } else if (y >= term->height - term->margins.bottom) { - seat->mouse.row = -1; - selection_row = term->rows - 1; - } else { - seat->mouse.row = (y - term->margins.top) / term->cell_height; - selection_row = seat->mouse.row; - } - - /* - * If client is receiving events (because the button was - * pressed while the cursor was inside the grid area), then - * make sure it receives valid coordinates. - */ - if (send_to_client) { - seat->mouse.col = selection_col; - seat->mouse.row = selection_row; - } - - xassert(seat->mouse.col == -1 || (seat->mouse.col >= 0 && seat->mouse.col < term->cols)); - xassert(seat->mouse.row == -1 || (seat->mouse.row >= 0 && seat->mouse.row < term->rows)); + xassert(seat->mouse.col >= 0 && seat->mouse.col < term->cols); + xassert(seat->mouse.row >= 0 && seat->mouse.row < term->rows); /* Cursor has moved to a different cell since last time */ bool cursor_is_on_new_cell @@ -2186,9 +2150,13 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, const bool cursor_is_on_grid = seat->mouse.col >= 0 && seat->mouse.row >= 0; enum selection_scroll_direction auto_scroll_direction - = y < term->margins.top ? SELECTION_SCROLL_UP - : y > term->height - term->margins.bottom ? SELECTION_SCROLL_DOWN - : SELECTION_SCROLL_NOT; + = term->selection.coords.end.row < 0 + ? SELECTION_SCROLL_NOT + : y < term->margins.top + ? SELECTION_SCROLL_UP + : y > term->height - term->margins.bottom + ? SELECTION_SCROLL_DOWN + : SELECTION_SCROLL_NOT; if (auto_scroll_direction == SELECTION_SCROLL_NOT) selection_stop_scroll_timer(term); @@ -2220,14 +2188,18 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, selection_start_scroll_timer( term, 400000000 / (divisor > 0 ? divisor : 1), - auto_scroll_direction, selection_col); + auto_scroll_direction, seat->mouse.col); } - if (term->selection.ongoing && ( - cursor_is_on_new_cell || - term->selection.coords.end.row < 0)) + if (term->selection.ongoing && + (cursor_is_on_new_cell || + (term->selection.coords.end.row < 0 && + seat->mouse.x >= term->margins.left && + seat->mouse.x < term->width - term->margins.right && + seat->mouse.y >= term->margins.top && + seat->mouse.y < term->height - term->margins.bottom))) { - selection_update(term, selection_col, selection_row); + selection_update(term, seat->mouse.col, seat->mouse.row); } } diff --git a/terminal.c b/terminal.c index e1da77f5..35cfe8aa 100644 --- a/terminal.c +++ b/terminal.c @@ -3451,10 +3451,7 @@ term_xcursor_update_for_seat(struct terminal *term, struct seat *seat) shape = CURSOR_SHAPE_CUSTOM; } - else if (seat->mouse.col >= 0 && - seat->mouse.row >= 0 && - term_mouse_grabbed(term, seat)) - { + else if (term_mouse_grabbed(term, seat)) { shape = CURSOR_SHAPE_TEXT; }