action: refresh keyboard focus when running actions with modifiers

Now that 2f8afb2 and 98bf316 are reverted, let's introduce another
approach to prevent firefox to show its menu bar with Alt-* keybinds.

In this commit, wl_keyboard.leave and wl_keyboard.enter events are sent to
the client after a action is invoked if the compositor has sent
key-release events of modifier keys. This prevents Firefox from showing
its menu bar with Alt-* keybinds, while making sure applications like
Blender see release events for modifier keys and their key state never get
stuck.
This commit is contained in:
tokyo4j 2024-12-23 02:17:39 +09:00
parent bf9a2eeb62
commit d29ee5eba3
4 changed files with 36 additions and 9 deletions

View file

@ -1301,4 +1301,18 @@ actions_run(struct view *activator, struct server *server,
" This is a BUG. Please report.", action->type);
}
}
/*
* We send wl_keyboard.{leave,enter} to the clint when we have sent
* key-press events to it since the last wl_keyboard.leave event.
* This prevents firefox to show its menu bar when a keybind with
* Alt key is executed.
*/
struct seat *seat = &server->seat;
if (seat->modifier_press_sent) {
struct wlr_surface *focused_surface =
seat->seat->keyboard_state.focused_surface;
seat_focus_surface(seat, NULL);
seat_focus_surface(seat, focused_surface);
}
}

View file

@ -503,12 +503,10 @@ miss_shift_toggle:
static enum lab_key_handled
handle_compositor_keybindings(struct keyboard *keyboard,
struct wlr_keyboard_key_event *event)
struct keyinfo *keyinfo, struct wlr_keyboard_key_event *event)
{
struct seat *seat = keyboard->base.seat;
struct server *server = seat->server;
struct wlr_keyboard *wlr_keyboard = keyboard->wlr_keyboard;
struct keyinfo keyinfo = get_keyinfo(wlr_keyboard, event->keycode);
bool locked = seat->server->session_lock_manager->locked;
key_state_set_pressed(event->keycode,
@ -529,7 +527,7 @@ handle_compositor_keybindings(struct keyboard *keyboard,
}
/* Catch C-A-F1 to C-A-F12 to change tty */
if (handle_change_vt_key(server, keyboard, &keyinfo.translated)) {
if (handle_change_vt_key(server, keyboard, &keyinfo->translated)) {
key_state_store_pressed_key_as_bound(event->keycode);
return LAB_KEY_HANDLED_TRUE_AND_VT_CHANGED;
}
@ -542,13 +540,13 @@ handle_compositor_keybindings(struct keyboard *keyboard,
if (!locked) {
if (server->input_mode == LAB_INPUT_STATE_MENU) {
key_state_store_pressed_key_as_bound(event->keycode);
handle_menu_keys(server, &keyinfo.translated);
handle_menu_keys(server, &keyinfo->translated);
return true;
}
if (server->osd_state.cycle_view) {
key_state_store_pressed_key_as_bound(event->keycode);
handle_cycle_view_key(server, &keyinfo);
handle_cycle_view_key(server, keyinfo);
return true;
}
}
@ -556,7 +554,7 @@ handle_compositor_keybindings(struct keyboard *keyboard,
/*
* Handle compositor keybinds
*/
cur_keybind = match_keybinding(server, &keyinfo, keyboard->is_virtual);
cur_keybind = match_keybinding(server, keyinfo, keyboard->is_virtual);
if (cur_keybind && (!locked || cur_keybind->allow_when_locked)) {
/*
* Update key-state before action_run() because the action
@ -585,8 +583,10 @@ handle_keybind_repeat(void *data)
.keycode = keyboard->keybind_repeat_keycode,
.state = WL_KEYBOARD_KEY_STATE_PRESSED
};
struct keyinfo keyinfo =
get_keyinfo(keyboard->wlr_keyboard, event.keycode);
handle_compositor_keybindings(keyboard, &event);
handle_compositor_keybindings(keyboard, &keyinfo, &event);
int next_repeat_ms = 1000 / keyboard->keybind_repeat_rate;
wl_event_source_timer_update(keyboard->keybind_repeat,
next_repeat_ms);
@ -629,13 +629,15 @@ keyboard_key_notify(struct wl_listener *listener, void *data)
struct seat *seat = keyboard->base.seat;
struct wlr_keyboard_key_event *event = data;
struct wlr_seat *wlr_seat = seat->seat;
struct keyinfo keyinfo = get_keyinfo(keyboard->wlr_keyboard, event->keycode);
idle_manager_notify_activity(seat->seat);
/* any new press/release cancels current keybind repeat */
keyboard_cancel_keybind_repeat(keyboard);
enum lab_key_handled handled =
handle_compositor_keybindings(keyboard, event);
handle_compositor_keybindings(keyboard, &keyinfo, event);
if (handled == LAB_KEY_HANDLED_TRUE_AND_VT_CHANGED) {
return;
@ -655,6 +657,7 @@ keyboard_key_notify(struct wl_listener *listener, void *data)
wlr_seat_set_keyboard(wlr_seat, keyboard->wlr_keyboard);
wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec,
event->keycode, event->state);
seat->modifier_press_sent |= keyinfo.is_modifier;
}
}

View file

@ -668,6 +668,8 @@ seat_focus(struct seat *seat, struct wlr_surface *surface, bool is_lock_surface)
return;
}
seat->modifier_press_sent = false;
if (!surface) {
wlr_seat_keyboard_notify_clear_focus(seat->seat);
input_method_relay_set_focus(seat->input_method_relay, NULL);