miniquad
miniquad copied to clipboard
Linux keyboard event handling gives char and down events in reverse order to Windows and Mac
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 bykey_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.