mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
input: workaround GNOME issue with pointer button events
Under certain circumstances, GNOME will send multiple pointer button press events, without any release or leave events in between. This trips up our button tracking. Workaround, by replacing the existing state for the pressed button with the new state. Previously, debug builds would assert (and thus crash), while release builds would have multiple states for the same button, causing (probably) issues like the title bar not being usable (as in, cannot be dragged, buttons not working etc). Hopefully closes #709
This commit is contained in:
parent
4853bcd139
commit
e553e1076c
2 changed files with 63 additions and 45 deletions
102
input.c
102
input.c
|
|
@ -1694,50 +1694,6 @@ fdm_csd_move(struct fdm *fdm, int fd, int events, void *data)
|
|||
|
||||
struct wl_window *win = seat->mouse_focus->window;
|
||||
|
||||
/*
|
||||
* Workaround GNOME bug
|
||||
*
|
||||
* Dragging the window, then stopping the drag (releasing the
|
||||
* mouse button), *without* moving the mouse, and then clicking
|
||||
* twice, waiting for the CSD timer, and finally clicking once
|
||||
* more, results in the following sequence (keyboard and other
|
||||
* irrelevant events filtered out, unless they’re needed to prove
|
||||
* a point):
|
||||
*
|
||||
* dbg: input.c:1551: cancelling drag timer, moving window
|
||||
* dbg: input.c:759: keyboard_leave: keyboard=0x607000003580, serial=873, surface=0x6070000036d0
|
||||
* dbg: input.c:1432: seat0: pointer-leave: pointer=0x607000003660, serial=874, surface = 0x6070000396e0, old-moused = 0x622000006100
|
||||
*
|
||||
* --> drag stopped here
|
||||
*
|
||||
* --> LMB clicked first time after the drag (generates the enter event on *release*, but no button events)
|
||||
* dbg: input.c:1360: pointer-enter: pointer=0x607000003660, serial=876, surface = 0x6070000396e0, new-moused = 0x622000006100
|
||||
*
|
||||
* --> LMB clicked, and held until the timer times out, second time after the drag
|
||||
* dbg: input.c:1712: BUTTON: pointer=0x607000003660, serial=877, button=110, state=1
|
||||
* dbg: input.c:1806: starting move timer
|
||||
* dbg: input.c:1692: move timer timed out
|
||||
* dbg: input.c:759: keyboard_leave: keyboard=0x607000003580, serial=878, surface=0x6070000036d0
|
||||
*
|
||||
* --> NOTE: ^^ no pointer leave event this time, only the keyboard leave
|
||||
*
|
||||
* --> LMB clicked one last time
|
||||
* dbg: input.c:697: seat0: keyboard_enter: keyboard=0x607000003580, serial=879, surface=0x6070000036d0
|
||||
* dbg: input.c:1712: BUTTON: pointer=0x607000003660, serial=880, button=110, state=1
|
||||
* err: input.c:1741: BUG in wl_pointer_button(): assertion failed: 'it->item.button != button'
|
||||
*
|
||||
* What are we seeing?
|
||||
*
|
||||
* - GNOME does *not* send a pointer *enter* event after the drag
|
||||
* has stopped
|
||||
* - The second drag does *not* generate a pointer *leave* event
|
||||
* - The missing leave event means we’re still tracking LMB as
|
||||
* being held down in our seat struct.
|
||||
* - This leads to an assert (debug builds) when LMB is clicked
|
||||
* again (seat’s button list already contains LMB).
|
||||
*/
|
||||
tll_free(seat->mouse.buttons);
|
||||
|
||||
win->csd.move_timeout_fd = -1;
|
||||
xdg_toplevel_move(win->xdg_toplevel, seat->wl_seat, win->csd.serial);
|
||||
return true;
|
||||
|
|
@ -1774,6 +1730,62 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
|
|||
} else
|
||||
seat->mouse.count = 1;
|
||||
|
||||
/*
|
||||
* Workaround GNOME bug
|
||||
*
|
||||
* Dragging the window, then stopping the drag (releasing the
|
||||
* mouse button), *without* moving the mouse, and then
|
||||
* clicking twice, waiting for the CSD timer, and finally
|
||||
* clicking once more, results in the following sequence
|
||||
* (keyboard and other irrelevant events filtered out, unless
|
||||
* they’re needed to prove a point):
|
||||
*
|
||||
* dbg: input.c:1551: cancelling drag timer, moving window
|
||||
* dbg: input.c:759: keyboard_leave: keyboard=0x607000003580, serial=873, surface=0x6070000036d0
|
||||
* dbg: input.c:1432: seat0: pointer-leave: pointer=0x607000003660, serial=874, surface = 0x6070000396e0, old-moused = 0x622000006100
|
||||
*
|
||||
* --> drag stopped here
|
||||
*
|
||||
* --> LMB clicked first time after the drag (generates the
|
||||
* enter event on *release*, but no button events)
|
||||
* dbg: input.c:1360: pointer-enter: pointer=0x607000003660, serial=876, surface = 0x6070000396e0, new-moused = 0x622000006100
|
||||
*
|
||||
* --> LMB clicked, and held until the timer times out, second
|
||||
* time after the drag
|
||||
* dbg: input.c:1712: BUTTON: pointer=0x607000003660, serial=877, button=110, state=1
|
||||
* dbg: input.c:1806: starting move timer
|
||||
* dbg: input.c:1692: move timer timed out
|
||||
* dbg: input.c:759: keyboard_leave: keyboard=0x607000003580, serial=878, surface=0x6070000036d0
|
||||
*
|
||||
* --> NOTE: ^^ no pointer leave event this time, only the
|
||||
* keyboard leave
|
||||
*
|
||||
* --> LMB clicked one last time
|
||||
* dbg: input.c:697: seat0: keyboard_enter: keyboard=0x607000003580, serial=879, surface=0x6070000036d0
|
||||
* dbg: input.c:1712: BUTTON: pointer=0x607000003660, serial=880, button=110, state=1
|
||||
* err: input.c:1741: BUG in wl_pointer_button(): assertion failed: 'it->item.button != button'
|
||||
*
|
||||
* What are we seeing?
|
||||
*
|
||||
* - GNOME does *not* send a pointer *enter* event after the drag
|
||||
* has stopped
|
||||
* - The second drag does *not* generate a pointer *leave* event
|
||||
* - The missing leave event means we’re still tracking LMB as
|
||||
* being held down in our seat struct.
|
||||
* - This leads to an assert (debug builds) when LMB is clicked
|
||||
* again (seat’s button list already contains LMB).
|
||||
*
|
||||
* Note: I’ve also observed variants of the above
|
||||
*/
|
||||
tll_foreach(seat->mouse.buttons, it) {
|
||||
if (it->item.button == button) {
|
||||
LOG_WARN("multiple button press events for button %d "
|
||||
"(compositor bug?)", button);
|
||||
tll_remove(seat->mouse.buttons, it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_DEBUG)
|
||||
tll_foreach(seat->mouse.buttons, it)
|
||||
xassert(it->item.button != button);
|
||||
|
|
@ -1817,7 +1829,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
|
|||
* 4. Release mouse button
|
||||
* 5. BAM!
|
||||
*/
|
||||
LOG_WARN("stray button release event");
|
||||
LOG_WARN("stray button release event (compositor bug?)");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue