core: layout: handle extra "loc " keys

This commit is contained in:
Richard Acayan 2024-11-07 18:43:39 -05:00
parent d9956baffa
commit 67f6538a8b
No known key found for this signature in database
GPG key ID: 0346F4894879DB73

View file

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