keymap: Generate from symbol map, not layout

This commit is contained in:
Dorota Czaplejewicz
2020-09-28 17:52:00 +00:00
parent 8e2e8b0f5f
commit 44e06bc0dc
2 changed files with 24 additions and 62 deletions

View File

@ -382,7 +382,7 @@ impl Layout {
)
)}).collect();
let keymap: HashMap<String, u32> = generate_keycodes(
let symbolmap: HashMap<String, u32> = generate_keycodes(
button_actions.iter()
.filter_map(|(_name, action)| {
match action {
@ -399,20 +399,20 @@ impl Layout {
let button_states = button_actions.into_iter().map(|(name, action)| {
let keycodes = match &action {
::action::Action::Submit { text: _, keys } => {
keys.iter().map(|named_keycode| {
*keymap.get(named_keycode.0.as_str())
keys.iter().map(|named_keysym| {
*symbolmap.get(named_keysym.0.as_str())
.expect(
format!(
"keycode {} in key {} missing from keymap",
named_keycode.0,
"keysym {} in key {} missing from symbol map",
named_keysym.0,
name
).as_str()
)
}).collect()
},
action::Action::Erase => vec![
*keymap.get("BackSpace")
.expect(&format!("BackSpace missing from keymap")),
*symbolmap.get("BackSpace")
.expect(&format!("BackSpace missing from symbol map")),
],
_ => Vec::new(),
};
@ -430,8 +430,7 @@ impl Layout {
button_states
);
// TODO: generate from symbols
let keymap_str = match generate_keymap(&button_states) {
let keymap_str = match generate_keymap(symbolmap) {
Err(e) => { return (Err(e), warning_handler) },
Ok(v) => v,
};

View File

@ -9,7 +9,6 @@ use std::rc::Rc;
use std::string::FromUtf8Error;
use ::action::Action;
use ::logging;
// Traits
use std::io::Write;
@ -125,11 +124,9 @@ impl From<io::Error> for FormattingError {
}
/// Generates a de-facto single level keymap.
// TODO: don't rely on keys and their order,
// but rather on what keysyms and keycodes are in use.
// Iterating actions makes it hard to deduplicate keysyms.
/// Key codes must not repeat and must remain between 9 and 255.
pub fn generate_keymap(
keystates: &HashMap::<String, KeyState>
symbolmap: HashMap::<String, KeyCode>,
) -> Result<String, FormattingError> {
let mut buf: Vec<u8> = Vec::new();
writeln!(
@ -138,15 +135,14 @@ pub fn generate_keymap(
xkb_keycodes \"squeekboard\" {{
minimum = 8;
maximum = 999;"
maximum = 255;"
)?;
// Not all layouts fit in 255 characters... so bump the limit to 999.
// Xorg can only consume up to 255, so this may not work in Xwayland.
// Xorg can only consume up to 255 keys, so this may not work in Xwayland.
// Two possible solutions:
// - use levels to cram multiple characters into one key
// - swap layouts on key presses
for keycode in 9..999 {
for keycode in symbolmap.values() {
write!(
buf,
"
@ -165,40 +161,15 @@ pub fn generate_keymap(
"
)?;
for (_name, state) in keystates.iter() {
match &state.action{
Action::Submit { text: _, keys } => {
for (named_keysym, keycode) in keys.iter().zip(&state.keycodes) {
for (name, keycode) in symbolmap.iter() {
write!(
buf,
"
key <I{}> {{ [ {} ] }};",
key <I{}> {{ [ {} ] }};",
keycode,
named_keysym.0,
name,
)?;
}
},
Action::Erase => {
let mut keycodes = state.keycodes.iter();
write!(
buf,
"
key <I{}> {{ [ BackSpace ] }};",
keycodes.next().expect("Erase key has no keycode"),
)?;
if let Some(_) = keycodes.next() {
log_print!(
logging::Level::Bug,
"Erase key has multiple keycodes",
);
}
},
Action::SetView(_) => {},
Action::LockView{ .. } => {},
Action::ApplyModifier(_) => {},
Action::ShowPreferences => {},
}
}
writeln!(
buf,
@ -247,21 +218,13 @@ mod tests {
use xkbcommon::xkb;
use ::action::KeySym;
#[test]
fn test_keymap_multi() {
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
let keymap_str = generate_keymap(&hashmap!{
"ac".into() => KeyState {
action: Action::Submit {
text: None,
keys: vec!(KeySym("a".into()), KeySym("c".into())),
},
keycodes: vec!(9, 10),
pressed: PressType::Released,
},
let keymap_str = generate_keymap(hashmap!{
"a".into() => 9,
"c".into() => 10,
}).unwrap();
let keymap = xkb::Keymap::new_from_string(