wayland: don't dispatch modifier key events (#9027)

Modifier keys are dispatched as events on wayland, unlike macos. This
prevents pending bindings from matching, because something like e.g. `g
shift-e` is received by the key matcher as `g shift shift-e`.
This commit is contained in:
Rom Grk 2024-03-07 15:42:48 -05:00 committed by GitHub
parent 27518f4280
commit 9068911eb4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -41,9 +41,9 @@ use crate::platform::linux::wayland::window::{WaylandDecorationState, WaylandWin
use crate::platform::{LinuxPlatformInner, PlatformWindow}; use crate::platform::{LinuxPlatformInner, PlatformWindow};
use crate::{ use crate::{
platform::linux::wayland::window::WaylandWindowState, AnyWindowHandle, CursorStyle, DisplayId, platform::linux::wayland::window::WaylandWindowState, AnyWindowHandle, CursorStyle, DisplayId,
KeyDownEvent, KeyUpEvent, Keystroke, Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent, KeyDownEvent, KeyUpEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton,
MouseUpEvent, NavigationDirection, Pixels, PlatformDisplay, PlatformInput, Point, ScrollDelta, MouseDownEvent, MouseMoveEvent, MouseUpEvent, NavigationDirection, Pixels, PlatformDisplay,
ScrollWheelEvent, TouchPhase, WindowOptions, PlatformInput, Point, ScrollDelta, ScrollWheelEvent, TouchPhase, WindowOptions,
}; };
/// Used to convert evdev scancode to xkb scancode /// Used to convert evdev scancode to xkb scancode
@ -681,6 +681,7 @@ impl Dispatch<wl_keyboard::WlKeyboard, ()> for WaylandClientState {
let Some(focused_window) = focused_window else { let Some(focused_window) = focused_window else {
return; return;
}; };
let focused_window = focused_window.clone();
let keymap_state = state.keymap_state.as_ref().unwrap(); let keymap_state = state.keymap_state.as_ref().unwrap();
let keycode = Keycode::from(key + MIN_KEYCODE); let keycode = Keycode::from(key + MIN_KEYCODE);
@ -688,12 +689,20 @@ impl Dispatch<wl_keyboard::WlKeyboard, ()> for WaylandClientState {
match key_state { match key_state {
wl_keyboard::KeyState::Pressed => { wl_keyboard::KeyState::Pressed => {
let input = PlatformInput::KeyDown(KeyDownEvent { let input = if keysym.is_modifier_key() {
keystroke: Keystroke::from_xkb(keymap_state, state.modifiers, keycode), PlatformInput::ModifiersChanged(ModifiersChangedEvent {
is_held: false, // todo(linux) modifiers: state.modifiers,
}); })
} else {
focused_window.handle_input(input.clone()); PlatformInput::KeyDown(KeyDownEvent {
keystroke: Keystroke::from_xkb(
keymap_state,
state.modifiers,
keycode,
),
is_held: false, // todo(linux)
})
};
if !keysym.is_modifier_key() { if !keysym.is_modifier_key() {
state.repeat.current_id += 1; state.repeat.current_id += 1;
@ -706,6 +715,7 @@ impl Dispatch<wl_keyboard::WlKeyboard, ()> for WaylandClientState {
let timer = Timer::from_duration(delay); let timer = Timer::from_duration(delay);
let state_ = Rc::clone(&this.client_state_inner); let state_ = Rc::clone(&this.client_state_inner);
let input_ = input.clone();
state state
.loop_handle .loop_handle
.insert_source(timer, move |event, _metadata, shared_data| { .insert_source(timer, move |event, _metadata, shared_data| {
@ -723,21 +733,39 @@ impl Dispatch<wl_keyboard::WlKeyboard, ()> for WaylandClientState {
drop(state_); drop(state_);
focused_window.handle_input(input.clone()); focused_window.handle_input(input_.clone());
TimeoutAction::ToDuration(Duration::from_secs(1) / rate) TimeoutAction::ToDuration(Duration::from_secs(1) / rate)
}) })
.unwrap(); .unwrap();
} }
drop(state);
focused_window.handle_input(input);
} }
wl_keyboard::KeyState::Released => { wl_keyboard::KeyState::Released => {
focused_window.handle_input(PlatformInput::KeyUp(KeyUpEvent { let input = if keysym.is_modifier_key() {
keystroke: Keystroke::from_xkb(keymap_state, state.modifiers, keycode), PlatformInput::ModifiersChanged(ModifiersChangedEvent {
})); modifiers: state.modifiers,
})
} else {
PlatformInput::KeyUp(KeyUpEvent {
keystroke: Keystroke::from_xkb(
keymap_state,
state.modifiers,
keycode,
),
})
};
if !keysym.is_modifier_key() { if !keysym.is_modifier_key() {
state.repeat.current_keysym = None; state.repeat.current_keysym = None;
} }
drop(state);
focused_window.handle_input(input);
} }
_ => {} _ => {}
} }