From c1f35731e0a98344b605d5b07caa77c2f00e3791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 12:31:13 +0200 Subject: [PATCH] input: margins are not selectable * Fix col/row calculation in pointer-enter event; we did not take the margins into account. * seat->mouse.col,row are now set to -1 if the cursor is inside the margins. That is, col/row are only ever valid when the mouse is actually over the grid, and not in the margins. * Use regular 'left-ptr' mouse cursor when mouse is inside the margins, to not make the user think he/she can start a selection. Besides making things clearer, this also fixes a crash that occurred if you started a selection in e.g. the right margin. --- CHANGELOG.md | 6 ++++++ input.c | 40 ++++++++++++++++++++++++++-------------- selection.c | 7 ++++--- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea392a60..22da9175 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,11 +32,17 @@ outside it. * Scrollback search to focus match, that requires a viewport change, roughly in the center of the screen. +* Mouse cursor is now always a `left_ptr` when inside the margins, to + indicate it is not possible to start a selection. ### Deprecated ### Removed ### Fixed + +* Crash when starting a selection inside the margins. + + ### Security diff --git a/input.c b/input.c index 442cd322..4dd8cf39 100644 --- a/input.c +++ b/input.c @@ -1023,11 +1023,16 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, int y = wl_fixed_to_int(surface_y) * term->scale; switch ((term->active_surface = term_surface_kind(term, surface))) { - case TERM_SURF_GRID: - seat->mouse.col = x / term->cell_width; - seat->mouse.row = y / term->cell_height; + case TERM_SURF_GRID: { + int col = (x - term->margins.left) / term->cell_width; + int row = (y - term->margins.top) / term->cell_height; + + seat->mouse.col = col >= 0 && col < term->cols ? col : -1; + seat->mouse.row = row >= 0 && row < term->rows ? row : -1; + term_xcursor_update(term); break; + } case TERM_SURF_SEARCH: case TERM_SURF_TITLE: @@ -1165,26 +1170,31 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, break; case TERM_SURF_GRID: { + term_xcursor_update(term); + int col = (x - term->margins.left) / term->cell_width; int row = (y - term->margins.top) / term->cell_height; - if (col < 0 || row < 0 || col >= term->cols || row >= term->rows) - return; + int old_col = seat->mouse.col; + int old_row = seat->mouse.row; + + 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; bool update_selection = seat->mouse.button == BTN_LEFT; bool update_selection_early = term->selection.end.row == -1; if (update_selection && update_selection_early) - selection_update(term, col, row); + selection_update(term, seat->mouse.col, seat->mouse.row); - if (col == seat->mouse.col && row == seat->mouse.row) + if (old_col == seat->mouse.col && old_row == seat->mouse.row) break; - seat->mouse.col = col; - seat->mouse.row = row; - if (update_selection && !update_selection_early) - selection_update(term, col, row); + selection_update(term, seat->mouse.col, seat->mouse.row); if (!term_mouse_grabbed(term, seat)) { term_mouse_motion( @@ -1360,9 +1370,11 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, if (selection_enabled(term, seat)) { switch (seat->mouse.count) { case 1: - selection_start( - term, seat->mouse.col, seat->mouse.row, - seat->kbd.ctrl ? SELECTION_BLOCK : SELECTION_NORMAL); + if (seat->mouse.col >= 0 && seat->mouse.row >= 0) { + selection_start( + term, seat->mouse.col, seat->mouse.row, + seat->kbd.ctrl ? SELECTION_BLOCK : SELECTION_NORMAL); + } break; case 2: diff --git a/selection.c b/selection.c index d5add464..3b8c1969 100644 --- a/selection.c +++ b/selection.c @@ -25,9 +25,10 @@ bool selection_enabled(const struct terminal *term, struct seat *seat) { return - term->mouse_tracking == MOUSE_NONE || - term_mouse_grabbed(term, seat) || - term->is_searching; + seat->mouse.col >= 0 && seat->mouse.row >= 0 && + (term->mouse_tracking == MOUSE_NONE || + term_mouse_grabbed(term, seat) || + term->is_searching); } bool