keymaps: Use multiple key maps, each within the limit of what Xorg can accept.
Key maps are switched on key press whenever needed.
This commit is contained in:
72
src/tests.rs
72
src/tests.rs
@ -40,21 +40,29 @@ pub fn check_layout_file(path: &str) {
|
||||
)
|
||||
}
|
||||
|
||||
fn check_sym_presence(
|
||||
state: &xkb::State,
|
||||
sym_name: &str,
|
||||
handler: &mut dyn logging::Handler,
|
||||
) {
|
||||
fn check_sym_in_keymap(state: &xkb::State, sym_name: &str) -> bool {
|
||||
let sym = xkb::keysym_from_name(sym_name, xkb::KEYSYM_NO_FLAGS);
|
||||
if sym == xkb::KEY_NoSymbol {
|
||||
panic!(format!("Entered invalid keysym: {}", sym_name));
|
||||
}
|
||||
let map = state.get_keymap();
|
||||
let range = map.min_keycode()..=map.max_keycode();
|
||||
let found = range.flat_map(|code| state.key_get_syms(code))
|
||||
range.flat_map(|code| state.key_get_syms(code))
|
||||
.find(|s| **s == sym)
|
||||
.is_some();
|
||||
if !found {
|
||||
.is_some()
|
||||
}
|
||||
|
||||
fn check_sym_presence(
|
||||
states: &[xkb::State],
|
||||
sym_name: &str,
|
||||
handler: &mut dyn logging::Handler,
|
||||
) {
|
||||
let found = states.iter()
|
||||
.position(|state| {
|
||||
check_sym_in_keymap(&state, sym_name)
|
||||
});
|
||||
|
||||
if let None = found {
|
||||
handler.handle(
|
||||
logging::Level::Surprise,
|
||||
&format!("There's no way to input the keysym {} on this layout", sym_name),
|
||||
@ -71,26 +79,27 @@ fn check_layout(layout: Layout, allow_missing_return: bool) {
|
||||
}
|
||||
|
||||
let layout = layout.expect("layout broken");
|
||||
|
||||
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
|
||||
|
||||
let keymap_str = layout.keymap_str
|
||||
.clone()
|
||||
.into_string().expect("Failed to decode keymap string");
|
||||
|
||||
let keymap = xkb::Keymap::new_from_string(
|
||||
&context,
|
||||
keymap_str.clone(),
|
||||
xkb::KEYMAP_FORMAT_TEXT_V1,
|
||||
xkb::KEYMAP_COMPILE_NO_FLAGS,
|
||||
).expect("Failed to create keymap");
|
||||
let xkb_states: Vec<xkb::State> = layout.keymaps.iter()
|
||||
.map(|keymap_str| {
|
||||
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
|
||||
let keymap_str = keymap_str
|
||||
.clone()
|
||||
.into_string().expect("Failed to decode keymap string");
|
||||
let keymap = xkb::Keymap::new_from_string(
|
||||
&context,
|
||||
keymap_str.clone(),
|
||||
xkb::KEYMAP_FORMAT_TEXT_V1,
|
||||
xkb::KEYMAP_COMPILE_NO_FLAGS,
|
||||
).expect("Failed to create keymap");
|
||||
xkb::State::new(&keymap)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let state = xkb::State::new(&keymap);
|
||||
|
||||
check_sym_presence(&state, "BackSpace", &mut handler);
|
||||
check_sym_presence(&xkb_states, "BackSpace", &mut handler);
|
||||
let mut printer = logging::Print;
|
||||
check_sym_presence(
|
||||
&state,
|
||||
&xkb_states,
|
||||
"Return",
|
||||
if allow_missing_return { &mut printer }
|
||||
else { &mut handler },
|
||||
@ -102,10 +111,19 @@ fn check_layout(layout: Layout, allow_missing_return: bool) {
|
||||
for (_x, button) in row.get_buttons() {
|
||||
let keystate = button.state.borrow();
|
||||
for keycode in &keystate.keycodes {
|
||||
match state.key_get_one_sym(*keycode) {
|
||||
match xkb_states[keycode.keymap_idx].key_get_one_sym(keycode.code) {
|
||||
xkb::KEY_NoSymbol => {
|
||||
eprintln!("{}", keymap_str);
|
||||
panic!("Keysym {} on key {:?} can't be resolved", keycode, button.name);
|
||||
eprintln!(
|
||||
"keymap {}: {}",
|
||||
keycode.keymap_idx,
|
||||
layout.keymaps[keycode.keymap_idx].to_str().unwrap(),
|
||||
);
|
||||
panic!(
|
||||
"Keysym for code {:?} on key {} ({:?}) can't be resolved",
|
||||
keycode,
|
||||
button.name.to_string_lossy(),
|
||||
button.name,
|
||||
);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user