Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linux keyboard event handling gives char and down events in reverse order to Windows and Mac #417

Open
caspark opened this issue Feb 2, 2024 · 0 comments

Comments

@caspark
Copy link

caspark commented Feb 2, 2024

Summary

On Linux, char and key down events are issued in that order, whereas Mac and Windows issue them as key down first and char second. This inconsistency causes bugs downstream, such as breaking egui-miniquad's copy and cut operations on Linux.

Details

Linux code looks like this currently:

let keycode = (*event).xkey.keycode as libc::c_int;
let key = keycodes::translate_key(&mut self.libx11, self.display, keycode);
let repeat = self.repeated_keycodes[(keycode & 0xff) as usize];
self.repeated_keycodes[(keycode & 0xff) as usize] = true;
let mods = keycodes::translate_mod((*event).xkey.state as libc::c_int);
let mut keysym: KeySym = 0;
(self.libx11.XLookupString)(
    &mut (*event).xkey,
    std::ptr::null_mut(),
    0 as libc::c_int,
    &mut keysym,
    std::ptr::null_mut(),
);
let chr = keycodes::keysym_to_unicode(keysym);
if chr > 0 {
    if let Some(chr) = std::char::from_u32(chr as u32) {
        event_handler.char_event(chr, mods, repeat);
    }
}
event_handler.key_down_event(key, mods, repeat);

In other words, the char_event callback is called before the key_down_event callback. Meanwhile:

  • MacOS explicitly calls char_event followed by key_down_event
  • Windows will receive the WM_CHAR message before the WM_KEYDOWN message (based on MSDN docs), so it will also match the MacOS ordering
  • (I don't know about iOS and Android)

Impact

This inconsistency seems to be a cause of a bug in egui-miniquad for me: it is coded to ignore char events if the ctrl modifier is pressed, but the modifier state is only updated when the keydown event is received. So if I copy or cut some text on Linux, then the char event is received first and egui-miniquad has not yet recorded that ctrl is held down, which means that the char event is passed on to egui and the selection is replaced with x or c.

Obviously this could be fixed in egui-miniquad by also updating its modifier state in the char handler too (and this is how I am working around it currently), but if all platforms are able to emit keydown events before char events (i.e. we guarantee that ordering as part of the miniquad API) then that won't be necessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant