mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
input: report mouse drag events also when the pointer is outside the grid
As long as the mouse button was *pressed* while the pointer was inside the grid, we want to keep reporting motion events until the button is released. Even when the pointer moves outside the grid (but in this case, the reported coordinates are bounded by the grid size). This patch also tries to improve multi-button handling (i.e. multiple buttons pressed at the same time), and the events we report to the client for these, in the following ways: * Motion events now report the *initial* button. That is, if you start a drag operation with the LEFT button, then press RIGHT (before releasing LEFT), keep reporting LEFT in the motion events. * Mouse release events are reported for *any* button, as long as the pointer is *inside* the grid, *or*, the button released was the button used to start a drag operation. The last point is important; if we have reported a button press followed by motion events (i.e. a drag operation), we need to report the button release, *even* if the pointer is outside the grid. Note that the client may receive unbalanced button press/release events in the following ways if the user pressed one, and then a second button *inside* the grid, then releases the *first* button (possibly outside the grid), and finally releases the *second* button *outside* the grid. In this case, both buttons will report press events. The first button will report a release event since it is the initial button in the drag operation. However, we don’t track the fact that the second button is being pressed, and thus if it is released outside the grid, it wont generate a release event.
This commit is contained in:
parent
975e70dae1
commit
a1a0b489ee
3 changed files with 40 additions and 4 deletions
|
|
@ -123,6 +123,8 @@ means foot can be PGO:d in e.g. sandboxed build scripts. See
|
||||||
(https://codeberg.org/dnkl/foot/issues/233).
|
(https://codeberg.org/dnkl/foot/issues/233).
|
||||||
* `\E[s`+`\E[u` (save/restore cursor) now saves and restores
|
* `\E[s`+`\E[u` (save/restore cursor) now saves and restores
|
||||||
attributes and charset configuration, just like `\E7`+`\E8`.
|
attributes and charset configuration, just like `\E7`+`\E8`.
|
||||||
|
* Report mouse motion events to the client application also while
|
||||||
|
dragging the cursor outside the grid.
|
||||||
|
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
|
||||||
30
input.c
30
input.c
|
|
@ -1250,7 +1250,7 @@ wl_pointer_leave(void *data, struct wl_pointer *wl_pointer,
|
||||||
/* Reset mouse state */
|
/* Reset mouse state */
|
||||||
seat->mouse.x = seat->mouse.y = 0;
|
seat->mouse.x = seat->mouse.y = 0;
|
||||||
seat->mouse.col = seat->mouse.row = 0;
|
seat->mouse.col = seat->mouse.row = 0;
|
||||||
seat->mouse.button = seat->mouse.last_button = seat->mouse.count = 0;
|
seat->mouse.button = seat->mouse.last_button = seat->mouse.button_for_motion_events = seat->mouse.count = 0;
|
||||||
seat->mouse.consumed = false;
|
seat->mouse.consumed = false;
|
||||||
memset(&seat->mouse.last_time, 0, sizeof(seat->mouse.last_time));
|
memset(&seat->mouse.last_time, 0, sizeof(seat->mouse.last_time));
|
||||||
seat->mouse.axis_aggregated = 0.0;
|
seat->mouse.axis_aggregated = 0.0;
|
||||||
|
|
@ -1383,6 +1383,16 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer,
|
||||||
selection_row = seat->mouse.row;
|
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 (seat->mouse.button_for_motion_events > 0) {
|
||||||
|
seat->mouse.col = selection_col;
|
||||||
|
seat->mouse.row = selection_row;
|
||||||
|
}
|
||||||
|
|
||||||
assert(seat->mouse.col == -1 || (seat->mouse.col >= 0 && seat->mouse.col < term->cols));
|
assert(seat->mouse.col == -1 || (seat->mouse.col >= 0 && seat->mouse.col < term->cols));
|
||||||
assert(seat->mouse.row == -1 || (seat->mouse.row >= 0 && seat->mouse.row < term->rows));
|
assert(seat->mouse.row == -1 || (seat->mouse.row >= 0 && seat->mouse.row < term->rows));
|
||||||
|
|
||||||
|
|
@ -1440,13 +1450,18 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer,
|
||||||
/* Send mouse event to client application */
|
/* Send mouse event to client application */
|
||||||
if (!seat->mouse.consumed &&
|
if (!seat->mouse.consumed &&
|
||||||
!term_mouse_grabbed(term, seat) &&
|
!term_mouse_grabbed(term, seat) &&
|
||||||
cursor_is_on_new_cell && cursor_is_on_grid)
|
cursor_is_on_new_cell &&
|
||||||
|
(seat->mouse.button_for_motion_events > 0 ||
|
||||||
|
(seat->mouse.button == 0 && cursor_is_on_grid)))
|
||||||
{
|
{
|
||||||
assert(seat->mouse.col < term->cols);
|
assert(seat->mouse.col < term->cols);
|
||||||
assert(seat->mouse.row < term->rows);
|
assert(seat->mouse.row < term->rows);
|
||||||
|
|
||||||
term_mouse_motion(
|
term_mouse_motion(
|
||||||
term, seat->mouse.button, seat->mouse.row, seat->mouse.col,
|
term,
|
||||||
|
(seat->mouse.button_for_motion_events > 0
|
||||||
|
? seat->mouse.button_for_motion_events : 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);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -1702,6 +1717,9 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
|
||||||
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);
|
||||||
|
|
||||||
|
if (seat->mouse.button_for_motion_events == 0)
|
||||||
|
seat->mouse.button_for_motion_events = button;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1711,11 +1729,15 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
|
||||||
|
|
||||||
if (!seat->mouse.consumed &&
|
if (!seat->mouse.consumed &&
|
||||||
!term_mouse_grabbed(term, seat) &&
|
!term_mouse_grabbed(term, seat) &&
|
||||||
cursor_is_on_grid)
|
((cursor_is_on_grid && seat->mouse.button_for_motion_events > 0) ||
|
||||||
|
seat->mouse.button_for_motion_events == button))
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
|
||||||
|
if (seat->mouse.button_for_motion_events == button)
|
||||||
|
seat->mouse.button_for_motion_events = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
seat->mouse.consumed = false;
|
seat->mouse.consumed = false;
|
||||||
|
|
|
||||||
12
wayland.h
12
wayland.h
|
|
@ -202,6 +202,18 @@ struct seat {
|
||||||
int col;
|
int col;
|
||||||
int row;
|
int row;
|
||||||
int button;
|
int button;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Button to send in motion events to the client. This is
|
||||||
|
* always the *first* button pressed on the grid. If multiple
|
||||||
|
* buttons are pressed, the first button is still the one used
|
||||||
|
* in motion events.
|
||||||
|
*
|
||||||
|
* A non-zero value of this *also* indicates that the client
|
||||||
|
* should receive events even if the pointer is outside the
|
||||||
|
* grid.
|
||||||
|
*/
|
||||||
|
int button_for_motion_events;
|
||||||
bool consumed; /* True if a button press was consumed - i.e. if a binding claimed it */
|
bool consumed; /* True if a button press was consumed - i.e. if a binding claimed it */
|
||||||
|
|
||||||
int count;
|
int count;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue