Skip to content
This repository has been archived by the owner on Sep 22, 2024. It is now read-only.

Commit

Permalink
Fix incorrect modifiers state on startup
Browse files Browse the repository at this point in the history
  • Loading branch information
nixpulvis authored Oct 2, 2020
1 parent b9f3d33 commit fc336a7
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 20 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
56 changes: 36 additions & 20 deletions src/platform_impl/linux/x11/event_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T: 'static> {
pub(super) dnd: Dnd,
pub(super) ime_receiver: ImeReceiver,
Expand Down Expand Up @@ -565,7 +568,7 @@ impl<T: 'static> EventProcessor<T> {
// 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);

Expand Down Expand Up @@ -921,9 +924,12 @@ impl<T: 'static> EventProcessor<T> {
});

// 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,
);
}
Expand All @@ -942,9 +948,12 @@ impl<T: 'static> EventProcessor<T> {
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,
);

Expand Down Expand Up @@ -1081,10 +1090,10 @@ impl<T: 'static> EventProcessor<T> {

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();
Expand All @@ -1093,7 +1102,7 @@ impl<T: 'static> EventProcessor<T> {
callback(Event::DeviceEvent {
device_id,
event: DeviceEvent::Key(KeyboardInput {
scancode,
scancode: scancode as u32,
virtual_keycode,
state,
modifiers,
Expand Down Expand Up @@ -1221,30 +1230,37 @@ impl<T: 'static> EventProcessor<T> {
}

fn handle_pressed_keys<F>(
&self,
wt: &super::EventLoopWindowTarget<T>,
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();

// 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;
let modifiers = device_mod_state.modifiers();

// 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,
Expand Down

0 comments on commit fc336a7

Please sign in to comment.