Commit 8e654346 authored by Dorota Czaplejewicz's avatar Dorota Czaplejewicz
Browse files

keysyms: Derive from Unicode labels

parent 015ba79f
......@@ -10,6 +10,11 @@ name = "dtoa"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "linked-hash-map"
version = "0.5.2"
......@@ -20,6 +25,15 @@ name = "maplit"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memmap"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "proc-macro2"
version = "1.0.2"
......@@ -44,6 +58,7 @@ dependencies = [
"maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)",
"xkbcommon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
......@@ -90,6 +105,34 @@ name = "unicode-xid"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "xkbcommon"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "yaml-rust"
version = "0.4.3"
......@@ -101,8 +144,10 @@ dependencies = [
[metadata]
"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
"checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e"
"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
"checksum proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "175a40b9cf564ce9bf050654633dbf339978706b8ead1a907bb970b63185dd95"
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f"
......@@ -110,4 +155,8 @@ dependencies = [
"checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582"
"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum xkbcommon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fda0ea5f7ddabd51deeeda7799bee06274112f577da7dd3d954b8eda731b2fce"
"checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d"
......@@ -7,6 +7,7 @@ bitflags = "1.1"
maplit = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.8"
xkbcommon = { version = "0.4", features = ["wayland"] }
[lib]
name = "rs"
......
......@@ -11,6 +11,8 @@ use std::path::PathBuf;
use std::rc::Rc;
use std::vec::Vec;
use xkbcommon::xkb;
use ::keyboard::{
KeyState,
generate_keymap, generate_keycodes, FormattingError
......@@ -358,6 +360,39 @@ fn create_symbol(
}
}
fn keysym_valid(name: &str) -> bool {
xkb::keysym_from_name(name, xkb::KEYSYM_NO_FLAGS) != xkb::KEY_NoSymbol
}
let keysym = match &symbol_meta.action {
Some(_) => None,
None => Some(match &symbol_meta.keysym {
Some(keysym) => match keysym_valid(keysym.as_str()) {
true => keysym.clone(),
false => {
eprintln!("Keysym name invalid: {}", keysym);
"space".into() // placeholder
},
},
None => match keysym_valid(name) {
true => String::from(name),
false => match name.chars().count() {
1 => format!("U{:04X}", name.chars().next().unwrap() as u32),
// If the name is longer than 1 char,
// then it's not a single Unicode char,
// but was trying to be an identifier
_ => {
eprintln!(
"Could not derive a valid keysym for key {}",
name
);
"space".into() // placeholder
}
},
},
}),
};
match &symbol_meta.action {
Some(Action::SetView(view_name)) => ::symbol::Symbol {
action: ::symbol::Action::SetLevel(
......@@ -374,11 +409,18 @@ fn create_symbol(
),
},
},
_ => ::symbol::Symbol {
Some(Action::ShowPrefs) => ::symbol::Symbol {
action: ::symbol::Action::Submit {
text: None,
keys: Vec::new(),
},
},
None => ::symbol::Symbol {
action: ::symbol::Action::Submit {
text: None,
// TODO: derive keysym name & value from button name
keys: vec!(),
keys: vec!(
::symbol::KeySym(keysym.unwrap()),
),
},
},
}
......@@ -523,6 +565,36 @@ mod tests {
}
}
#[test]
fn test_layout_punctuation() {
let out = Layout::from_yaml_stream(PathBuf::from("tests/layout_key1.yaml"))
.unwrap()
.build()
.unwrap();
assert_eq!(
out.views["base"]
.rows[0]
.buttons[0]
.label,
::layout::Label::Text(CString::new("test").unwrap())
);
}
#[test]
fn test_layout_unicode() {
let out = Layout::from_yaml_stream(PathBuf::from("tests/layout_key2.yaml"))
.unwrap()
.build()
.unwrap();
assert_eq!(
out.views["base"]
.rows[0]
.buttons[0]
.label,
::layout::Label::Text(CString::new("test").unwrap())
);
}
#[test]
fn parsing_fallback() {
assert!(load_layout_from_resource(FALLBACK_LAYOUT_NAME)
......@@ -530,4 +602,39 @@ mod tests {
.is_ok()
);
}
#[test]
fn unicode_keysym() {
let keysym = xkb::keysym_from_name(
format!("U{:X}", "å".chars().next().unwrap() as u32).as_str(),
xkb::KEYSYM_NO_FLAGS,
);
let keysym = xkb::keysym_to_utf8(keysym);
assert_eq!(keysym, \0");
}
#[test]
fn test_key_unicode() {
assert_eq!(
create_symbol(
&hashmap!{
".".into() => ButtonMeta {
icon: None,
keysym: None,
action: None,
label: Some("test".into()),
outline: None,
}
},
".",
Vec::new()
),
::symbol::Symbol {
action: ::symbol::Action::Submit {
text: None,
keys: vec!(::symbol::KeySym("U002E".into())),
},
}
);
}
}
......@@ -177,7 +177,6 @@ impl From<io::Error> for FormattingError {
}
/// Generates a de-facto single level keymap. TODO: actually drop second level
/// TODO: take in keysym->keycode mapping
pub fn generate_keymap(
keystates: &HashMap::<String, Rc<RefCell<KeyState>>>
) -> Result<String, FormattingError> {
......@@ -192,14 +191,24 @@ pub fn generate_keymap(
)?;
for (name, state) in keystates.iter() {
if let Some(keycode) = state.borrow().keycode {
write!(
buf,
"
let state = state.borrow();
if let ::symbol::Action::Submit { text: _, keys } = &state.symbol.action {
match keys.len() {
0 => eprintln!("Key {} has no keysyms", name),
a => {
// TODO: don't ignore any keysyms
if a > 1 {
eprintln!("Key {} multiple keysyms", name);
}
write!(
buf,
"
<{}> = {};",
name,
keycode
)?;
keys[0].0,
state.keycode.unwrap()
)?;
},
};
}
}
......@@ -215,13 +224,15 @@ pub fn generate_keymap(
)?;
for (name, state) in keystates.iter() {
if let Some(_) = state.borrow().keycode {
write!(
buf,
"
if let ::symbol::Action::Submit { text: _, keys } = &state.borrow().symbol.action {
if let Some(keysym) = keys.iter().next() {
write!(
buf,
"
key <{}> {{ [ {0} ] }};",
name,
)?;
keysym.0,
)?;
}
}
}
writeln!(
......
......@@ -546,7 +546,7 @@ pub struct Size {
pub height: f64,
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq)]
pub enum Label {
/// Text used to display the symbol
Text(CString),
......
......@@ -3,6 +3,7 @@ extern crate bitflags;
#[macro_use]
extern crate maplit;
extern crate serde;
extern crate xkbcommon;
mod data;
pub mod float_ord;
......
......@@ -2,37 +2,22 @@
use std::ffi::CString;
/// Just defines some int->identifier mappings for convenience
#[derive(Debug, Clone)]
pub enum KeySym {
Unknown = 0,
Shift = 0xffe1,
}
impl KeySym {
pub fn from_u32(num: u32) -> KeySym {
match num {
0xffe1 => KeySym::Shift,
_ => KeySym::Unknown,
}
}
}
#[derive(Debug, Clone)]
pub struct XKeySym(pub u32);
/// Name of the keysym
#[derive(Debug, Clone, PartialEq)]
pub struct KeySym(pub String);
/// Use to switch layouts
type Level = String;
/// Use to send modified keypresses
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq)]
pub enum Modifier {
Control,
Alt,
}
/// Action to perform on the keypress and, in reverse, on keyrelease
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq)]
pub enum Action {
/// Switch to this view
SetLevel(Level),
......@@ -49,12 +34,12 @@ pub enum Action {
/// Text to submit with input-method
text: Option<CString>,
/// The key events this symbol submits when submitting text is not possible
keys: Vec<XKeySym>,
keys: Vec<KeySym>,
},
}
/// Contains a static description of a particular key's actions
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq)]
pub struct Symbol {
/// The action that this key performs
pub action: Action,
......
---
# punctuation
bounds:
x: 0
y: 0
width: 0
height: 0
views:
base:
- "."
outlines:
default:
corner_radius: 1
bounds: { x: 0, y: 0, width: 0, height: 0 }
buttons:
".":
label: "test"
---
# punctuation
bounds:
x: 0
y: 0
width: 0
height: 0
views:
base:
- "å"
outlines:
default:
corner_radius: 1
bounds: { x: 0, y: 0, width: 0, height: 0 }
buttons:
å:
label: "test"
......@@ -46,6 +46,7 @@ test_check_xkb (void)
xkb_context_unref(context);
if (!keymap) {
printf("%s", keymap_str);
g_error("Bad keymap");
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment