mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-23 22:01:31 +11:00
On X11, avoid false positive key repeats
Instead of a single `bool` indicating that a key press has occured and no key has been released since then, we store the scancode of the last pressed key (if it is a key that repeats when held). This fixes a bug where pressing a new key while one is already held down will be flagged as a repeat even though it is obviously not a repeat.
This commit is contained in:
parent
bca57ed0b4
commit
bd890e69aa
|
@ -8,6 +8,8 @@ And please only add new entries to the top of this list, right below the `# Unre
|
||||||
|
|
||||||
# Unreleased
|
# Unreleased
|
||||||
|
|
||||||
|
- On X11, fix false positive flagging of key repeats when pressing different keys with no release
|
||||||
|
between presses.
|
||||||
- Implement `PartialOrd` and `Ord` for `KeyCode` and `NativeKeyCode`.
|
- Implement `PartialOrd` and `Ord` for `KeyCode` and `NativeKeyCode`.
|
||||||
|
|
||||||
# 0.29.0-beta.0
|
# 0.29.0-beta.0
|
||||||
|
|
|
@ -354,7 +354,6 @@ impl KbdState {
|
||||||
self.post_init(state, keymap);
|
self.post_init(state, keymap);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "wayland")]
|
|
||||||
pub fn key_repeats(&mut self, keycode: ffi::xkb_keycode_t) -> bool {
|
pub fn key_repeats(&mut self, keycode: ffi::xkb_keycode_t) -> bool {
|
||||||
unsafe { (XKBH.xkb_keymap_key_repeats)(self.xkb_keymap, keycode) == 1 }
|
unsafe { (XKBH.xkb_keymap_key_repeats)(self.xkb_keymap, keycode) == 1 }
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,11 @@ pub(super) struct EventProcessor<T: 'static> {
|
||||||
pub(super) kb_state: KbdState,
|
pub(super) kb_state: KbdState,
|
||||||
// Number of touch events currently in progress
|
// Number of touch events currently in progress
|
||||||
pub(super) num_touch: u32,
|
pub(super) num_touch: u32,
|
||||||
// Whether we've got a key release for the key press.
|
// This is the last pressed key that is repeatable (if it hasn't been
|
||||||
pub(super) got_key_release: bool,
|
// released).
|
||||||
|
//
|
||||||
|
// Used to detect key repeats.
|
||||||
|
pub(super) held_key_press: Option<u32>,
|
||||||
pub(super) first_touch: Option<u64>,
|
pub(super) first_touch: Option<u64>,
|
||||||
// Currently focused window belonging to this process
|
// Currently focused window belonging to this process
|
||||||
pub(super) active_window: Option<ffi::Window>,
|
pub(super) active_window: Option<ffi::Window>,
|
||||||
|
@ -548,13 +551,39 @@ impl<T: 'static> EventProcessor<T> {
|
||||||
let device_id = mkdid(util::VIRTUAL_CORE_KEYBOARD);
|
let device_id = mkdid(util::VIRTUAL_CORE_KEYBOARD);
|
||||||
|
|
||||||
let keycode = xkev.keycode as _;
|
let keycode = xkev.keycode as _;
|
||||||
let repeat = ty == ffi::KeyPress && !self.got_key_release;
|
|
||||||
// Update state after the repeat setting.
|
// Update state to track key repeats and determine whether this key was a repeat.
|
||||||
|
//
|
||||||
|
// Note, when a key is held before focusing on this window the first
|
||||||
|
// (non-synthetic) event will not be flagged as a repeat (also note that the
|
||||||
|
// synthetic press event that is generated before this when the window gains focus
|
||||||
|
// will also not be flagged as a repeat).
|
||||||
|
//
|
||||||
|
// Only keys that can repeat should change the held_key_press state since a
|
||||||
|
// continuously held repeatable key may continue repeating after the press of a
|
||||||
|
// non-repeatable key.
|
||||||
|
let repeat = if self.kb_state.key_repeats(keycode) {
|
||||||
|
let is_latest_held = self.held_key_press == Some(keycode);
|
||||||
|
|
||||||
|
if ty == ffi::KeyPress {
|
||||||
|
self.held_key_press = Some(keycode);
|
||||||
|
is_latest_held
|
||||||
|
} else {
|
||||||
|
// Check that the released key is the latest repeatable key that has been
|
||||||
|
// pressed, since repeats will continue for the latest key press if a
|
||||||
|
// different previously pressed key is released.
|
||||||
|
if is_latest_held {
|
||||||
|
self.held_key_press = None;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
let state = if ty == ffi::KeyPress {
|
let state = if ty == ffi::KeyPress {
|
||||||
self.got_key_release = false;
|
|
||||||
ElementState::Pressed
|
ElementState::Pressed
|
||||||
} else {
|
} else {
|
||||||
self.got_key_release = true;
|
|
||||||
ElementState::Released
|
ElementState::Released
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -926,6 +955,9 @@ impl<T: 'static> EventProcessor<T> {
|
||||||
&mut self.kb_state,
|
&mut self.kb_state,
|
||||||
&mut callback,
|
&mut callback,
|
||||||
);
|
);
|
||||||
|
// Clear this so detecting key repeats is consistently handled when the
|
||||||
|
// window regains focus.
|
||||||
|
self.held_key_press = None;
|
||||||
|
|
||||||
callback(Event::WindowEvent {
|
callback(Event::WindowEvent {
|
||||||
window_id,
|
window_id,
|
||||||
|
|
|
@ -289,10 +289,10 @@ impl<T: 'static> EventLoop<T> {
|
||||||
xkbext,
|
xkbext,
|
||||||
kb_state,
|
kb_state,
|
||||||
num_touch: 0,
|
num_touch: 0,
|
||||||
|
held_key_press: None,
|
||||||
first_touch: None,
|
first_touch: None,
|
||||||
active_window: None,
|
active_window: None,
|
||||||
is_composing: false,
|
is_composing: false,
|
||||||
got_key_release: true,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Register for device hotplug events
|
// Register for device hotplug events
|
||||||
|
|
Loading…
Reference in a new issue