From a21bf1b4d98c97fd8f408241fcbc35079e812c82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 4 Aug 2021 17:27:34 +0200 Subject: [PATCH] input: workaround GNOME messing up pointer leave/enter after moving window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GNOME doesn’t send pointer enter after finishing a window move. In subsequent move operations, it is also possible to make it skip sending pointer leave when starting the move operations. This caused foot to assert in debug builds, and add the same button multiple times to the list of buttons currently being pressed. --- input.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/input.c b/input.c index c7077e0d..6711e11e 100644 --- a/input.c +++ b/input.c @@ -1019,12 +1019,12 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, #if defined(_DEBUG) && defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG char sym_name[100]; xkb_keysym_get_name(sym, sym_name, sizeof(sym_name)); -#endif LOG_DBG("%s (%u/0x%x): seat=%s, term=%p, serial=%u, " "mods=0x%08x, consumed=0x%08x, repeats=%d", sym_name, sym, sym, seat->name, (void *)term, serial, mods, consumed, should_repeat); +#endif /* * User configurable bindings @@ -1360,6 +1360,8 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, LOG_DBG("pointer-enter: pointer=%p, serial=%u, surface = %p, new-moused = %p", (void *)wl_pointer, serial, (void *)surface, (void *)term); + xassert(tll_length(seat->mouse.buttons) == 0); + /* Scale may have changed */ wayl_reload_xcursor_theme(seat, term->scale); @@ -1691,6 +1693,50 @@ 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 follwing 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;