config: fix parsing of XF86ScreenSaver key

Closes #1969
This commit is contained in:
elivance
2025-10-24 04:23:13 +01:00
committed by Ivan Molodetskikh
parent b3245b81a6
commit 4310c20c32
+54 -2
View File
@@ -9,7 +9,7 @@ use niri_ipc::{
ColumnDisplay, LayoutSwitchTarget, PositionChange, SizeChange, WorkspaceReferenceArg,
};
use smithay::input::keyboard::keysyms::KEY_NoSymbol;
use smithay::input::keyboard::xkb::{keysym_from_name, KEYSYM_CASE_INSENSITIVE};
use smithay::input::keyboard::xkb::{keysym_from_name, KEYSYM_CASE_INSENSITIVE, KEYSYM_NO_FLAGS};
use smithay::input::keyboard::Keysym;
use crate::utils::{expect_only_children, MergeWith};
@@ -984,7 +984,34 @@ impl FromStr for Key {
} else if key.eq_ignore_ascii_case("TouchpadScrollRight") {
Trigger::TouchpadScrollRight
} else {
let keysym = keysym_from_name(key, KEYSYM_CASE_INSENSITIVE);
let mut keysym = keysym_from_name(key, KEYSYM_CASE_INSENSITIVE);
// The keyboard event handling code can receive either
// XF86ScreenSaver or XF86Screensaver, because there is no
// case mapping defined between these keysyms. If we just
// use the case-insensitive version of keysym_from_name it
// is not possible to bind the uppercase version, because the
// case-insensitive match prefers the lowercase version when
// there is a choice.
//
// Therefore, when we match this key with the initial
// case-insensitive match we try a further case-sensitive match
// (so that either key can be bound). If that fails, we change
// to the uppercase version because:
//
// - A comment in xkb_keysym_from_name (in libxkbcommon) tells us that the uppercase
// version is the "best" of the two. [0]
// - The xkbcommon crate only has a constant for ScreenSaver. [1]
//
// [0]: https://github.com/xkbcommon/libxkbcommon/blob/45a118d5325b051343b4b174f60c1434196fa7d4/src/keysym.c#L276
// [1]: https://docs.rs/xkbcommon/latest/xkbcommon/xkb/keysyms/index.html#:~:text=KEY%5FXF86ScreenSaver
//
// See https://github.com/YaLTeR/niri/issues/1969
if keysym == Keysym::XF86_Screensaver {
keysym = keysym_from_name(key, KEYSYM_NO_FLAGS);
if keysym.raw() == KEY_NoSymbol {
keysym = Keysym::XF86_ScreenSaver;
}
}
if keysym.raw() == KEY_NoSymbol {
return Err(miette!("invalid key: {key}"));
}
@@ -999,6 +1026,31 @@ impl FromStr for Key {
mod tests {
use super::*;
#[test]
fn parse_xf86_screensaver() {
assert_eq!(
"XF86ScreenSaver".parse::<Key>().unwrap(),
Key {
trigger: Trigger::Keysym(Keysym::XF86_ScreenSaver),
modifiers: Modifiers::empty(),
},
);
assert_eq!(
"XF86Screensaver".parse::<Key>().unwrap(),
Key {
trigger: Trigger::Keysym(Keysym::XF86_Screensaver),
modifiers: Modifiers::empty(),
}
);
assert_eq!(
"xf86screensaver".parse::<Key>().unwrap(),
Key {
trigger: Trigger::Keysym(Keysym::XF86_ScreenSaver),
modifiers: Modifiers::empty(),
}
);
}
#[test]
fn parse_iso_level_shifts() {
assert_eq!(