From fc336a76bfa158c972a6303ce638359343260fad Mon Sep 17 00:00:00 2001 From: Nathan Lilienthal Date: Thu, 1 Oct 2020 22:07:09 -0400 Subject: [PATCH] Fix incorrect modifiers state on startup Fixes #1563. --- CHANGELOG.md | 1 + .../linux/x11/event_processor.rs | 54 ++++++++++++------- 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fc06c8f..f151fcfb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,7 @@ - On Wayland, disable maximize button for non-resizable window. - On Wayland, added support for `set_ime_position`. - On Wayland, fix crash on startup since GNOME 3.37.90. +- On X11, fix incorrect modifiers state on startup. # 0.22.2 (2020-05-16) diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 976c17b6..ab87d76d 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -20,6 +20,9 @@ use crate::{ event_loop::EventLoopWindowTarget as RootELW, }; +/// The X11 documentation states: "Keycodes lie in the inclusive range [8,255]". +const KEYCODE_OFFSET: u8 = 8; + pub(super) struct EventProcessor { pub(super) dnd: Dnd, pub(super) ime_receiver: ImeReceiver, @@ -565,7 +568,7 @@ impl EventProcessor { // When a compose sequence or IME pre-edit is finished, it ends in a KeyPress with // a keycode of 0. if keycode != 0 { - let scancode = keycode - 8; + let scancode = keycode - KEYCODE_OFFSET as u32; let keysym = wt.xconn.lookup_keysym(xkev); let virtual_keycode = events::keysym_to_element(keysym as c_uint); @@ -921,9 +924,12 @@ impl EventProcessor { }); // Issue key press events for all pressed keys - self.handle_pressed_keys( + Self::handle_pressed_keys( + &wt, window_id, ElementState::Pressed, + &self.mod_keymap, + &mut self.device_mod_state, &mut callback, ); } @@ -942,9 +948,12 @@ impl EventProcessor { let window_id = mkwid(xev.event); // Issue key release events for all pressed keys - self.handle_pressed_keys( + Self::handle_pressed_keys( + &wt, window_id, ElementState::Released, + &self.mod_keymap, + &mut self.device_mod_state, &mut callback, ); @@ -1081,10 +1090,10 @@ impl EventProcessor { let device_id = mkdid(xev.sourceid); let keycode = xev.detail; - if keycode < 8 { + let scancode = keycode - KEYCODE_OFFSET as i32; + if scancode < 0 { return; } - let scancode = (keycode - 8) as u32; let keysym = wt.xconn.keycode_to_keysym(keycode as ffi::KeyCode); let virtual_keycode = events::keysym_to_element(keysym as c_uint); let modifiers = self.device_mod_state.modifiers(); @@ -1093,7 +1102,7 @@ impl EventProcessor { callback(Event::DeviceEvent { device_id, event: DeviceEvent::Key(KeyboardInput { - scancode, + scancode: scancode as u32, virtual_keycode, state, modifiers, @@ -1221,30 +1230,37 @@ impl EventProcessor { } fn handle_pressed_keys( - &self, + wt: &super::EventLoopWindowTarget, window_id: crate::window::WindowId, state: ElementState, + mod_keymap: &ModifierKeymap, + device_mod_state: &mut ModifierKeyState, callback: &mut F, ) where F: FnMut(Event<'_, T>), { - let wt = get_xtarget(&self.target); - let device_id = mkdid(util::VIRTUAL_CORE_KEYBOARD); - let modifiers = self.device_mod_state.modifiers(); + let modifiers = device_mod_state.modifiers(); - // Get the set of keys currently pressed and apply Key events to each - let keys = wt.xconn.query_keymap(); - - for keycode in &keys { - if keycode < 8 { - continue; - } - - let scancode = (keycode - 8) as u32; + // Update modifiers state and emit key events based on which keys are currently pressed. + for keycode in wt + .xconn + .query_keymap() + .into_iter() + .filter(|k| *k >= KEYCODE_OFFSET) + { + let scancode = (keycode - KEYCODE_OFFSET) as u32; let keysym = wt.xconn.keycode_to_keysym(keycode); let virtual_keycode = events::keysym_to_element(keysym as c_uint); + if let Some(modifier) = mod_keymap.get_modifier(keycode as ffi::KeyCode) { + device_mod_state.key_event( + ElementState::Pressed, + keycode as ffi::KeyCode, + modifier, + ); + } + #[allow(deprecated)] callback(Event::WindowEvent { window_id,