From f8da14eed5a4cf2826ba96ca9ff5f3b8ef83b78a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 2 Feb 2021 09:51:22 +0100 Subject: [PATCH 1/4] term: term_mouse_grabbed: return true if mouse tracking is disabled --- terminal.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/terminal.c b/terminal.c index 6f8130fa..7b0ba599 100644 --- a/terminal.c +++ b/terminal.c @@ -2431,9 +2431,10 @@ term_mouse_grabbed(const struct terminal *term, struct seat *seat) /* * Mouse is grabbed by us, regardless of whether mouse tracking has been enabled or not. */ - return seat->kbd_focus == term && - seat->kbd.shift && - !seat->kbd.alt && /*!seat->kbd.ctrl &&*/ !seat->kbd.meta; + return term->mouse_tracking == MOUSE_NONE || + (seat->kbd_focus == term && + seat->kbd.shift && + !seat->kbd.alt && /*!seat->kbd.ctrl &&*/ !seat->kbd.meta); } void From d6b1dbf8d9e9e9e87fd9d1a930f52a9cf1b7d404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 2 Feb 2021 09:52:05 +0100 Subject: [PATCH 2/4] =?UTF-8?q?input:=20don=E2=80=99t=20execute=20mouse=20?= =?UTF-8?q?bindings=20when=20the=20application=20is=20grabbing=20the=20mou?= =?UTF-8?q?se?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the application is grabbing the mouse, we require ‘shift’ to be pressed to be able to use foot’s mouse bindings. Otherwise the mouse event is sent to the application. This wasn’t being enforced consistently; each and every mouse **only** action was checking the mouse grab state, but e.g. *primary paste* (which can be used as both a key binding and a mouse binding) was not. The fix is actually quite simple: don’t even try to execute *any* mouse bindings when the application is grabbing the mouse (unless shift is pressed). This fixes an issue where e.g. middle mouse button events (using the default mouse bindings) were never seen by any mouse grabbing client applications. --- input.c | 172 +++++++++++++++++++++++++------------------------------- 1 file changed, 76 insertions(+), 96 deletions(-) diff --git a/input.c b/input.c index 5042edb5..8052e265 100644 --- a/input.c +++ b/input.c @@ -82,8 +82,6 @@ execute_binding(struct seat *seat, struct terminal *term, enum bind_action_normal action, char *const *pipe_argv, uint32_t serial) { - const bool cursor_is_on_grid = seat->mouse.col >= 0 && seat->mouse.row >= 0; - switch (action) { case BIND_ACTION_NONE: return true; @@ -274,33 +272,22 @@ execute_binding(struct seat *seat, struct terminal *term, } case BIND_ACTION_SELECT_BEGIN: - if (selection_enabled(term, seat) && cursor_is_on_grid) { - selection_start( - term, seat->mouse.col, seat->mouse.row, SELECTION_CHAR_WISE, false); - return true; - } - return false; + selection_start( + term, seat->mouse.col, seat->mouse.row, SELECTION_CHAR_WISE, false); + return true; case BIND_ACTION_SELECT_BEGIN_BLOCK: - if (selection_enabled(term, seat) && cursor_is_on_grid) { - selection_start( - term, seat->mouse.col, seat->mouse.row, SELECTION_BLOCK, false); - return true; - } - return false; + selection_start( + term, seat->mouse.col, seat->mouse.row, SELECTION_BLOCK, false); + return true; case BIND_ACTION_SELECT_EXTEND: - if (selection_enabled(term, seat) && cursor_is_on_grid) { - selection_extend( - seat, term, seat->mouse.col, seat->mouse.row, term->selection.kind); - return true; - } - return false; + selection_extend( + seat, term, seat->mouse.col, seat->mouse.row, term->selection.kind); + return true; case BIND_ACTION_SELECT_EXTEND_CHAR_WISE: - if (selection_enabled(term, seat) && cursor_is_on_grid && - term->selection.kind != SELECTION_BLOCK) - { + if (term->selection.kind != SELECTION_BLOCK) { selection_extend( seat, term, seat->mouse.col, seat->mouse.row, SELECTION_CHAR_WISE); return true; @@ -308,28 +295,19 @@ execute_binding(struct seat *seat, struct terminal *term, return false; case BIND_ACTION_SELECT_WORD: - if (selection_enabled(term, seat) && cursor_is_on_grid) { - selection_start( - term, seat->mouse.col, seat->mouse.row, SELECTION_WORD_WISE, false); - return true; - } - return false; + selection_start( + term, seat->mouse.col, seat->mouse.row, SELECTION_WORD_WISE, false); + return true; case BIND_ACTION_SELECT_WORD_WS: - if (selection_enabled(term, seat) && cursor_is_on_grid) { - selection_start( - term, seat->mouse.col, seat->mouse.row, SELECTION_WORD_WISE, true); - return true; - } - return false; + selection_start( + term, seat->mouse.col, seat->mouse.row, SELECTION_WORD_WISE, true); + return true; case BIND_ACTION_SELECT_ROW: - if (selection_enabled(term, seat) && cursor_is_on_grid) { - selection_start( - term, seat->mouse.col, seat->mouse.row, SELECTION_LINE_WISE, false); - return true; - } - return false; + selection_start( + term, seat->mouse.col, seat->mouse.row, SELECTION_LINE_WISE, false); + return true; case BIND_ACTION_COUNT: xassert(false); @@ -1707,77 +1685,79 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, case WL_POINTER_BUTTON_STATE_PRESSED: { bool consumed = false; - if (seat->wl_keyboard != NULL && seat->kbd.xkb_state != NULL) { - /* Seat has keyboard - use mouse bindings *with* modifiers */ + if (cursor_is_on_grid && term_mouse_grabbed(term, seat)) { + if (seat->wl_keyboard != NULL && seat->kbd.xkb_state != NULL) { + /* Seat has keyboard - use mouse bindings *with* modifiers */ - xkb_mod_mask_t mods = xkb_state_serialize_mods( - seat->kbd.xkb_state, XKB_STATE_MODS_DEPRESSED); + xkb_mod_mask_t mods = xkb_state_serialize_mods( + seat->kbd.xkb_state, XKB_STATE_MODS_DEPRESSED); - /* Ignore Shift when matching modifiers, since it is - * used to enable selection in mouse grabbing client - * applications */ - mods &= ~(1 << seat->kbd.mod_shift); + /* Ignore Shift when matching modifiers, since it is + * used to enable selection in mouse grabbing client + * applications */ + mods &= ~(1 << seat->kbd.mod_shift); - const struct mouse_binding *match = NULL; + const struct mouse_binding *match = NULL; - tll_foreach(seat->mouse.bindings, it) { - const struct mouse_binding *binding = &it->item; + tll_foreach(seat->mouse.bindings, it) { + const struct mouse_binding *binding = &it->item; - if (binding->button != button) { - /* Wrong button */ - continue; + if (binding->button != button) { + /* Wrong button */ + continue; + } + + if (binding->mods != mods) { + /* Modifier mismatch */ + continue; + } + + if (binding->count > seat->mouse.count) { + /* Not correct click count */ + continue; + } + + if (match == NULL || binding->count > match->count) + match = binding; } - if (binding->mods != mods) { - /* Modifier mismatch */ - continue; + if (match != NULL) { + consumed = execute_binding( + seat, term, match->action, match->pipe_argv, serial); } - - if (binding->count > seat->mouse.count) { - /* Not correct click count */ - continue; - } - - if (match == NULL || binding->count > match->count) - match = binding; } - if (match != NULL) { - consumed = execute_binding( - seat, term, match->action, match->pipe_argv, serial); - } - } + else { + /* Seat does NOT have a keyboard - use mouse bindings *without* modifiers */ + const struct config_mouse_binding *match = NULL; - else { - /* Seat does NOT have a keyboard - use mouse bindings *without* modifiers */ - const struct config_mouse_binding *match = NULL; + tll_foreach(seat->wayl->conf->bindings.mouse, it) { + const struct config_mouse_binding *binding = &it->item; - tll_foreach(seat->wayl->conf->bindings.mouse, it) { - const struct config_mouse_binding *binding = &it->item; + if (binding->button != button) { + /* Wrong button */ + continue; + } - if (binding->button != button) { - /* Wrong button */ - continue; + if (binding->count > seat->mouse.count) { + /* Incorrect click count */ + continue; + } + + const struct config_key_modifiers no_mods = {0}; + if (memcmp(&binding->modifiers, &no_mods, sizeof(no_mods)) != 0) { + /* Binding has modifiers */ + continue; + } + + if (match == NULL || binding->count > match->count) + match = binding; } - if (binding->count > seat->mouse.count) { - /* Incorrect click count */ - continue; + if (match != NULL) { + consumed = execute_binding( + seat, term, match->action, match->pipe.argv, serial); } - - const struct config_key_modifiers no_mods = {0}; - if (memcmp(&binding->modifiers, &no_mods, sizeof(no_mods)) != 0) { - /* Binding has modifiers */ - continue; - } - - if (match == NULL || binding->count > match->count) - match = binding; - } - - if (match != NULL) { - consumed = execute_binding( - seat, term, match->action, match->pipe.argv, serial); } } From eff8481cdc6c37407faaa3167ea6f6897b12f544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 2 Feb 2021 09:52:22 +0100 Subject: [PATCH 3/4] selection: remove selection_enabled() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Its name did not reflect its semantics. Since it was only used in a single place, “inline” it there, and get rid of it. --- selection.c | 10 ---------- selection.h | 1 - terminal.c | 5 ++++- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/selection.c b/selection.c index e9c3fce6..90c6c392 100644 --- a/selection.c +++ b/selection.c @@ -33,16 +33,6 @@ static const char *const mime_type_map[] = { [DATA_OFFER_MIME_URI_LIST] = "text/uri-list", }; -bool -selection_enabled(const struct terminal *term, struct seat *seat) -{ - return - seat->mouse.col >= 0 && seat->mouse.row >= 0 && - (term->mouse_tracking == MOUSE_NONE || - term_mouse_grabbed(term, seat) || - term->is_searching); -} - bool selection_on_rows(const struct terminal *term, int row_start, int row_end) { diff --git a/selection.h b/selection.h index aa027d3e..241ec262 100644 --- a/selection.h +++ b/selection.h @@ -8,7 +8,6 @@ extern const struct wl_data_device_listener data_device_listener; extern const struct zwp_primary_selection_device_v1_listener primary_selection_device_listener; -bool selection_enabled(const struct terminal *term, struct seat *seat); void selection_start( struct terminal *term, int col, int row, enum selection_kind new_kind, bool spaces_only); diff --git a/terminal.c b/terminal.c index 7b0ba599..701313cc 100644 --- a/terminal.c +++ b/terminal.c @@ -2570,7 +2570,10 @@ term_xcursor_update_for_seat(struct terminal *term, struct seat *seat) const char *xcursor = seat->pointer.hidden ? XCURSOR_HIDDEN : term->is_searching ? XCURSOR_LEFT_PTR - : selection_enabled(term, seat) ? XCURSOR_TEXT + : (seat->mouse.col >= 0 && + seat->mouse.row >= 0 && + term_mouse_grabbed(term, seat)) ? XCURSOR_TEXT + : term->is_searching ? XCURSOR_TEXT : XCURSOR_LEFT_PTR; render_xcursor_set(seat, term, xcursor); From 5a2e44e24eae95cb6d346434043543abaf3e93a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 2 Feb 2021 09:53:24 +0100 Subject: [PATCH 4/4] changelog: some mouse events never being sent to the client application --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f15380c4..3bed2a4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,6 +73,13 @@ ### Fixed + +* Some mouse bindings (_primary paste_, for example) did not require + `shift` to be pressed while used in a mouse grabbing + application. This meant the mouse event was never seen by the + application. + + ### Security ### Contributors