diff --git a/src/core/layout.rs b/src/core/layout.rs index 2dd2506..a0ee67b 100644 --- a/src/core/layout.rs +++ b/src/core/layout.rs @@ -25,7 +25,7 @@ unsafe extern "C" fn start_elem(data: *mut c_void, c_name: *const expat::XML_Char, c_attrs: *mut *const expat::XML_Char) { - let layout = &mut *(data as *mut LayoutFile); + let layout = &mut *(data as *mut LayoutLoader); let name = CStr::from_ptr(c_name) .to_str().expect("layout: XML element name must be UTF-8"); @@ -45,7 +45,7 @@ unsafe extern "C" fn start_elem(data: *mut c_void, unsafe extern "C" fn end_elem(data: *mut c_void, c_name: *const expat::XML_Char) { - let layout = &mut *(data as *mut LayoutFile); + let layout = &mut *(data as *mut LayoutLoader); let name = CStr::from_ptr(c_name) .to_str().expect("layout: XML element name must be UTF-8"); @@ -448,6 +448,7 @@ const KEYSYMS: [(&str, Keysym, &str); 24] = [ ("\\?", Keysym::question, "?"), ("\\@", Keysym::at, "@"), ("\\\\", Keysym::backslash, "\\"), + ("alt", Keysym::Alt_L, "Alt"), ("backspace", Keysym::BackSpace, "⌫"), ("ctrl", Keysym::Control_L, "Ctrl"), ("delete", Keysym::Delete, "⌦"), @@ -458,8 +459,7 @@ const KEYSYMS: [(&str, Keysym, &str); 24] = [ ("f12_placeholder", Keysym::F12, "F12"), ("fn", Keysym::XF86_Fn, "Fn"), ("left", Keysym::Left, "←"), - ("loc alt", Keysym::Alt_L, "Alt"), - ("loc meta", Keysym::Meta_L, "Meta"), + ("meta", Keysym::Meta_L, "Meta"), ("right", Keysym::Right, "→"), ("shift", Keysym::Shift_L, "⇧"), ("space", Keysym::space, " "), @@ -476,13 +476,28 @@ struct LayoutFile { has_bottom_row: bool, width: f64, height: f64, +} + +struct LayoutLoader<'a> { + file: LayoutFile, + extra_keys: &'a Vec, row_width: f64, in_row: u32, } -impl LayoutFile { - fn get_keysym_by_name(name: &str) -> KeyValue +impl<'a> LayoutLoader<'a> { + fn get_keysym_by_name(extra_keys: &Vec, name: &str) -> KeyValue { + let name = if name.starts_with("loc ") { + if extra_keys.binary_search_by_key(&&name[4..], |k| k).is_ok() { + &name[4..] + } else { + return KeyValue::from(Keysym::NoSymbol, "") + } + } else { + name + }; + if let Ok(idx) = KEYSYMS.binary_search_by_key(&name, |&(k, _, _)| k) { return KeyValue::from(KEYSYMS[idx].1, KEYSYMS[idx].2); } @@ -513,25 +528,25 @@ impl LayoutFile { self.row_width = x2; let key = Key::new( - x1, self.height, x2, self.height + 1.0, - Self::get_keysym_by_name(attrs.get("key0").unwrap_or(&"")), - Self::get_keysym_by_name(attrs.get("key1").unwrap_or(&"")), - Self::get_keysym_by_name(attrs.get("key2").unwrap_or(&"")), - Self::get_keysym_by_name(attrs.get("key3").unwrap_or(&"")), - Self::get_keysym_by_name(attrs.get("key4").unwrap_or(&"")), - Self::get_keysym_by_name(attrs.get("key5").unwrap_or(&"")), - Self::get_keysym_by_name(attrs.get("key6").unwrap_or(&"")), - Self::get_keysym_by_name(attrs.get("key7").unwrap_or(&"")), - Self::get_keysym_by_name(attrs.get("key8").unwrap_or(&"")) + x1, self.file.height, x2, self.file.height + 1.0, + Self::get_keysym_by_name(&self.extra_keys, attrs.get("key0").unwrap_or(&"")), + Self::get_keysym_by_name(&self.extra_keys, attrs.get("key1").unwrap_or(&"")), + Self::get_keysym_by_name(&self.extra_keys, attrs.get("key2").unwrap_or(&"")), + Self::get_keysym_by_name(&self.extra_keys, attrs.get("key3").unwrap_or(&"")), + Self::get_keysym_by_name(&self.extra_keys, attrs.get("key4").unwrap_or(&"")), + Self::get_keysym_by_name(&self.extra_keys, attrs.get("key5").unwrap_or(&"")), + Self::get_keysym_by_name(&self.extra_keys, attrs.get("key6").unwrap_or(&"")), + Self::get_keysym_by_name(&self.extra_keys, attrs.get("key7").unwrap_or(&"")), + Self::get_keysym_by_name(&self.extra_keys, attrs.get("key8").unwrap_or(&"")) ); - let idx = self.rows.len() - 1; - self.rows[idx].push(key); + let idx = self.file.rows.len() - 1; + self.file.rows[idx].push(key); } fn start_row(&mut self) { - self.rows.push(Vec::new()); + self.file.rows.push(Vec::new()); self.in_row += 1; self.row_width = 0.0; } @@ -539,7 +554,7 @@ impl LayoutFile { fn start_keyboard(&mut self, attrs: &HashMap<&str, &str>) { if *attrs.get("bottom_row").unwrap_or(&"") == "false" { - self.has_bottom_row = false; + self.file.has_bottom_row = false; } } @@ -558,11 +573,11 @@ impl LayoutFile { { self.in_row -= 1; - if self.row_width > self.width { - self.width = self.row_width; + if self.row_width > self.file.width { + self.file.width = self.row_width; } - self.height += 1.0; + self.file.height += 1.0; } fn end_elem(&mut self, name: &str) @@ -572,13 +587,16 @@ impl LayoutFile { } } - fn load>(path: P) -> Result + fn load>(path: P, extra_keys: &'a Vec) -> Result { - let mut layout = LayoutFile { - rows: Vec::new(), - has_bottom_row: true, - width: 0.0, - height: 0.0, + let mut layout = LayoutLoader { + file: LayoutFile { + rows: Vec::new(), + has_bottom_row: true, + width: 0.0, + height: 0.0, + }, + extra_keys, row_width: 0.0, in_row: 0, }; @@ -605,7 +623,7 @@ impl LayoutFile { expat::XML_ParserFree(parser); }; - Ok(layout) + Ok(layout.file) } } @@ -694,19 +712,20 @@ impl Layout { pub fn load(cfg: &Configuration) -> Result { + let extra_keys = cfg.extra_keys(); let dir = Path::new("/usr/share/unfettered-keyboard/layouts"); let path = dir.join(cfg.layout()); - let main_layout = LayoutFile::load(path)?; + let main_layout = LayoutLoader::load(path, extra_keys)?; let path = dir.join("numeric.xml"); - let numeric = LayoutFile::load(path)?; + let numeric = LayoutLoader::load(path, extra_keys)?; let path = dir.join("greekmath.xml"); - let greekmath = LayoutFile::load(path)?; + let greekmath = LayoutLoader::load(path, extra_keys)?; let path = dir.join("bottom_row.xml"); - let bottom_row = LayoutFile::load(path)?; + let bottom_row = LayoutLoader::load(path, extra_keys)?; let mut layout = Layout { main_layout,