diff --git a/src/core/layout.rs b/src/core/layout.rs index 2d551b7..894b833 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 Layout); + let layout = &mut *(data as *mut LayoutFile); 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 Layout); + let layout = &mut *(data as *mut LayoutFile); let name = CStr::from_ptr(c_name) .to_str().expect("layout: XML element name must be UTF-8"); @@ -493,16 +493,6 @@ impl Key { } } -pub struct Layout { - rows: Vec>, - width: f64, - height: f64, - row_width: f64, - in_row: u32, - - text_supp: bool, -} - const KEYSYMS: [(&str, Keysym, &str); 21] = [ ("\\#", Keysym::numbersign, "#"), ("\\?", Keysym::question, "?"), @@ -527,48 +517,15 @@ const KEYSYMS: [(&str, Keysym, &str); 21] = [ ("up", Keysym::Up, "↑"), ]; -impl Layout { - pub fn is_keysym_modifier(modifier: usize) -> bool - { - match modifier { - MOD_FN => true, - _ => false, - } - } - - /* - * Check if the modifier can be emitted as a key event. - * - * Modifiers that modify the key values (e.g. the Fn key and any accents) - * should usually not be emitted as key events to applications, and their - * only purpose is to modify the key values. The Meta modifier should also - * be inhibited from emitting a key event, because its purpose is to make - * every key value emit a key press. - */ - pub fn is_pressable_modifier(modifier: usize) -> bool - { - !Self::is_keysym_modifier(modifier) && modifier != MOD_META - } - - pub fn is_label_modifier(modifier: usize) -> bool - { - // Shift does not change the keysym used for input, but changes the - // rendered keysym. - Self::is_keysym_modifier(modifier) || modifier == MOD_SHIFT - } - - pub fn modifier_keysym(modifier: usize) -> Keysym - { - match modifier { - MOD_SHIFT => Keysym::Shift_L, - MOD_CTRL => Keysym::Control_L, - MOD_ALT => Keysym::Alt_L, - MOD_FN => Keysym::XF86_Fn, - MOD_META => Keysym::Meta_L, - _ => Keysym::NoSymbol, - } - } +struct LayoutFile { + rows: Vec>, + width: f64, + height: f64, + row_width: f64, + in_row: u32, +} +impl LayoutFile { fn get_keysym_by_name(name: &str) -> KeyValue { if let Ok(idx) = KEYSYMS.binary_search_by_key(&name, |&(k, _, _)| k) { @@ -651,29 +608,20 @@ impl Layout { } } - pub fn load(cfg: &Configuration) -> Result + fn load>(path: P) -> Result { - let mut layout = Layout { + let mut layout = LayoutFile { rows: Vec::new(), width: 0.0, height: 0.0, row_width: 0.0, in_row: 0, - text_supp: false, }; - let dir = Path::new("/usr/share/unfettered-keyboard/layouts"); - let mut vec = Vec::new(); - let path = dir.join(cfg.layout()); let mut file = File::open(path)?; file.read_to_end(&mut vec)?; - let mut vec2 = Vec::new(); - let path = dir.join("bottom_row.xml"); - let mut file = File::open(path)?; - file.read_to_end(&mut vec2)?; - unsafe { let parser = expat::XML_ParserCreate(ptr::null()); if ptr::eq(parser, ptr::null_mut()) { @@ -681,7 +629,7 @@ impl Layout { } expat::XML_SetElementHandler(parser, Some(start_elem), Some(end_elem)); - expat::XML_SetUserData(parser, &mut layout as *mut Layout as *mut c_void); + expat::XML_SetUserData(parser, &mut layout as *mut Self as *mut c_void); let status = expat::XML_Parse(parser, vec.as_ptr() as *const c_char, vec.len() as i32, 1); @@ -689,21 +637,101 @@ impl Layout { return Err(Error::new(ErrorKind::InvalidData, "Could not parse XML")); } - expat::XML_ParserReset(parser, ptr::null()); - expat::XML_SetElementHandler(parser, Some(start_elem), Some(end_elem)); - expat::XML_SetUserData(parser, &mut layout as *mut Layout as *mut c_void); - - let status = expat::XML_Parse(parser, vec2.as_ptr() as *const c_char, - vec2.len() as i32, 1); - if status != expat::XML_Status_XML_STATUS_OK { - return Err(Error::new(ErrorKind::InvalidData, "Could not parse XML")); - } - expat::XML_ParserFree(parser); }; Ok(layout) } +} + +pub struct Layout { + rows: Vec>, + width: f64, + height: f64, + text_supp: bool, +} + +impl Layout { + pub fn is_keysym_modifier(modifier: usize) -> bool + { + match modifier { + MOD_FN => true, + _ => false, + } + } + + /* + * Check if the modifier can be emitted as a key event. + * + * Modifiers that modify the key values (e.g. the Fn key and any accents) + * should usually not be emitted as key events to applications, and their + * only purpose is to modify the key values. The Meta modifier should also + * be inhibited from emitting a key event, because its purpose is to make + * every key value emit a key press. + */ + pub fn is_pressable_modifier(modifier: usize) -> bool + { + !Self::is_keysym_modifier(modifier) && modifier != MOD_META + } + + pub fn is_label_modifier(modifier: usize) -> bool + { + // Shift does not change the keysym used for input, but changes the + // rendered keysym. + Self::is_keysym_modifier(modifier) || modifier == MOD_SHIFT + } + + pub fn modifier_keysym(modifier: usize) -> Keysym + { + match modifier { + MOD_SHIFT => Keysym::Shift_L, + MOD_CTRL => Keysym::Control_L, + MOD_ALT => Keysym::Alt_L, + MOD_FN => Keysym::XF86_Fn, + MOD_META => Keysym::Meta_L, + _ => Keysym::NoSymbol, + } + } + + pub fn load(cfg: &Configuration) -> Result + { + let dir = Path::new("/usr/share/unfettered-keyboard/layouts"); + + let path = dir.join(cfg.layout()); + let main_layout = LayoutFile::load(path)?; + + let mut layout = Layout { + rows: main_layout.rows, + width: main_layout.width, + height: main_layout.height, + text_supp: false, + }; + + let path = dir.join("bottom_row.xml"); + let bottom_row = LayoutFile::load(path)?; + + let old_height = layout.height; + layout.height += bottom_row.height; + + layout.rows.reserve(bottom_row.rows.len()); + for row in bottom_row.rows { + let mut new_row = Vec::with_capacity(row.len()); + + for key in row { + new_row.push(Key { + parts: key.parts, + x1: key.x1, + y1: old_height + key.y1, + x2: key.x2, + y2: old_height + key.y2, + }); + } + + layout.rows.push(new_row); + } + + Ok(layout) + } #[inline(always)] pub fn width(&self) -> f64