Merge branch 'selection-improvements' into master

Closes #70
This commit is contained in:
Daniel Eklöf 2020-08-08 10:19:04 +02:00
commit e391658d72
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 84 additions and 32 deletions

View file

@ -54,6 +54,9 @@
* Incorrect multi-column character spacer insertion when reflowing * Incorrect multi-column character spacer insertion when reflowing
text. text.
* Compilation errors in 32-bit builds. * Compilation errors in 32-bit builds.
* Mouse cursor style in top and left margins.
* Selection is now **updated** when the cursor moves outside the grid
(https://codeberg.org/dnkl/foot/issues/70).
### Security ### Security

113
input.c
View file

@ -1049,11 +1049,21 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer,
switch ((term->active_surface = term_surface_kind(term, surface))) { switch ((term->active_surface = term_surface_kind(term, surface))) {
case TERM_SURF_GRID: { case TERM_SURF_GRID: {
int col = (x - term->margins.left) / term->cell_width; /*
int row = (y - term->margins.top) / term->cell_height; * Translate x,y pixel coordinate to a cell coordinate, or -1
* if the cursor is outside the grid. I.e. if it is inside the
* margins.
*/
seat->mouse.col = col >= 0 && col < term->cols ? col : -1; if (x < term->margins.left || x >= term->width - term->margins.right)
seat->mouse.row = row >= 0 && row < term->rows ? row : -1; seat->mouse.col = -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;
else
seat->mouse.row = (y - term->margins.top) / term->cell_height;
term_xcursor_update_for_seat(term, seat); term_xcursor_update_for_seat(term, seat);
break; break;
@ -1200,33 +1210,65 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer,
break; break;
case TERM_SURF_GRID: { case TERM_SURF_GRID: {
term_xcursor_update_for_seat(term, seat);
int col = (x - term->margins.left) / term->cell_width;
int row = (y - term->margins.top) / term->cell_height;
int old_col = seat->mouse.col; int old_col = seat->mouse.col;
int old_row = seat->mouse.row; 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; * 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;
if (seat->mouse.col < 0 || seat->mouse.row < 0) if (x < term->margins.left) {
break; 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;
}
bool update_selection = seat->mouse.button == BTN_LEFT || seat->mouse.button == BTN_RIGHT; if (y < term->margins.top) {
bool update_selection_early = term->selection.end.row == -1; 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 (update_selection && update_selection_early) assert(seat->mouse.col == -1 || (seat->mouse.col >= 0 && seat->mouse.col < term->cols));
selection_update(term, seat->mouse.col, seat->mouse.row); assert(seat->mouse.row == -1 || (seat->mouse.row >= 0 && seat->mouse.row < term->rows));
if (old_col == seat->mouse.col && old_row == seat->mouse.row) term_xcursor_update_for_seat(term, seat);
break;
if (update_selection && !update_selection_early) /* Cursor has moved to a different cell since last time */
selection_update(term, seat->mouse.col, seat->mouse.row); bool cursor_is_on_new_cell
= old_col != seat->mouse.col || old_row != seat->mouse.row;
/* Cursor is inside the grid, i.e. *not* in the margins */
bool cursor_is_on_grid = seat->mouse.col >= 0 && seat->mouse.row >= 0;
/* Update selection */
if (seat->mouse.button == BTN_LEFT || seat->mouse.button == BTN_RIGHT) {
if (cursor_is_on_new_cell || term->selection.end.row < 0)
selection_update(term, selection_col, selection_row);
}
/* Send mouse event to client application */
if (!term_mouse_grabbed(term, seat) &&
cursor_is_on_new_cell && cursor_is_on_grid)
{
assert(seat->mouse.col < term->cols);
assert(seat->mouse.row < term->rows);
if (!term_mouse_grabbed(term, seat)) {
term_mouse_motion( term_mouse_motion(
term, seat->mouse.button, seat->mouse.row, seat->mouse.col, term, seat->mouse.button, seat->mouse.row, seat->mouse.col,
seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl); seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl);
@ -1395,19 +1437,19 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
case TERM_SURF_GRID: { case TERM_SURF_GRID: {
search_cancel(term); search_cancel(term);
bool cursor_is_on_grid = seat->mouse.col >= 0 && seat->mouse.row >= 0;
switch (state) { switch (state) {
case WL_POINTER_BUTTON_STATE_PRESSED: { case WL_POINTER_BUTTON_STATE_PRESSED: {
if (button == BTN_LEFT && seat->mouse.count <= 3) { if (button == BTN_LEFT && seat->mouse.count <= 3) {
selection_cancel(term); selection_cancel(term);
if (selection_enabled(term, seat)) { if (selection_enabled(term, seat) && cursor_is_on_grid) {
switch (seat->mouse.count) { switch (seat->mouse.count) {
case 1: case 1:
if (seat->mouse.col >= 0 && seat->mouse.row >= 0) { selection_start(
selection_start( term, seat->mouse.col, seat->mouse.row,
term, seat->mouse.col, seat->mouse.row, seat->kbd.ctrl ? SELECTION_BLOCK : SELECTION_NORMAL);
seat->kbd.ctrl ? SELECTION_BLOCK : SELECTION_NORMAL);
}
break; break;
case 2: case 2:
@ -1424,7 +1466,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
} }
else if (button == BTN_RIGHT && seat->mouse.count == 1) { else if (button == BTN_RIGHT && seat->mouse.count == 1) {
if (selection_enabled(term, seat)) { if (selection_enabled(term, seat) && cursor_is_on_grid) {
selection_extend( selection_extend(
seat, term, seat->mouse.col, seat->mouse.row, serial); seat, term, seat->mouse.col, seat->mouse.row, serial);
} }
@ -1449,7 +1491,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
} }
} }
if (!term_mouse_grabbed(term, seat)) { if (!term_mouse_grabbed(term, seat) && cursor_is_on_grid) {
term_mouse_down( term_mouse_down(
term, button, seat->mouse.row, seat->mouse.col, term, button, seat->mouse.row, seat->mouse.col,
seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl); seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl);
@ -1461,7 +1503,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
if (button == BTN_LEFT && term->selection.end.col != -1) if (button == BTN_LEFT && term->selection.end.col != -1)
selection_finalize(seat, term, serial); selection_finalize(seat, term, serial);
if (!term_mouse_grabbed(term, seat)) { if (!term_mouse_grabbed(term, seat) && cursor_is_on_grid) {
term_mouse_up( term_mouse_up(
term, button, seat->mouse.row, seat->mouse.col, term, button, seat->mouse.row, seat->mouse.col,
seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl); seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl);
@ -1513,16 +1555,23 @@ mouse_scroll(struct seat *seat, int amount)
keyboard_key(seat, NULL, seat->kbd.serial, 0, key - 8, XKB_KEY_DOWN); keyboard_key(seat, NULL, seat->kbd.serial, 0, key - 8, XKB_KEY_DOWN);
keyboard_key(seat, NULL, seat->kbd.serial, 0, key - 8, XKB_KEY_UP); keyboard_key(seat, NULL, seat->kbd.serial, 0, key - 8, XKB_KEY_UP);
} else { } else {
if (!term_mouse_grabbed(term, seat)) { 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);
for (int i = 0; i < amount; i++) { for (int i = 0; i < amount; i++) {
term_mouse_down( term_mouse_down(
term, button, seat->mouse.row, seat->mouse.col, term, button, seat->mouse.row, seat->mouse.col,
seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl); seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl);
} }
term_mouse_up( term_mouse_up(
term, button, seat->mouse.row, seat->mouse.col, term, button, seat->mouse.row, seat->mouse.col,
seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl); seat->kbd.shift, seat->kbd.alt, seat->kbd.ctrl);
} }
scrollback(term, amount); scrollback(term, amount);
} }
} }