Compare commits

..

1 Commits

Author SHA1 Message Date
1488aa97f3 Release 1.8.1 "Corona"
- Landscape layout doesn't crash
- CSS font is actually taken into account
- Failed start due to dbus is now communicated
- Better log messages
- Fixed Enter in numbers layout
- More consistent terminal layout
- Proper font sizes in terminal layout
2020-01-31 10:08:59 +00:00
36 changed files with 196 additions and 741 deletions

14
Cargo.lock generated
View File

@ -2,10 +2,10 @@
# It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.7.8"
version = "0.7.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -254,7 +254,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "2.3.2"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -317,8 +317,8 @@ name = "regex"
version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"aho-corasick 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
@ -457,7 +457,7 @@ dependencies = [
]
[metadata]
"checksum aho-corasick 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "743ad5a418686aad3b87fd14c43badd828cf26e214a00f92a384291cf22e1811"
"checksum aho-corasick 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5f56c476256dc249def911d6f7580b5fc7e875895b5d7ee88f5d602208035744"
"checksum atk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7017e53393e713212aed7aea336b6553be4927f58c37070a56c2fe3d107e489"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum cairo-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd940f0d609699e343ef71c4af5f66423afbf30d666f796dabd8fd15229cf5b6"
@ -481,7 +481,7 @@ dependencies = [
"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
"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 memchr 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53445de381a1f436797497c61d851644d0e8e88e6140f22872ad33a704933978"
"checksum memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223"
"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
"checksum pango 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c2cb169402a3eb1ba034a7cc7d95b8b1c106e9be5ba4be79a5a93dc1a2795f4"
"checksum pango-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6eb49268e69dd0c1da5d3001a61aac08e2e9d2bfbe4ae4b19b9963c998f6453"

View File

@ -45,7 +45,7 @@ buttons:
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
action: "erase"
keysym: "BackSpace"
preferences:
action: "show_prefs"
outline: "special"

View File

@ -45,7 +45,7 @@ buttons:
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
action: "erase"
keysym: "BackSpace"
preferences:
action: "show_prefs"
outline: "special"

View File

@ -46,7 +46,7 @@ buttons:
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
action: "erase"
keysym: "BackSpace"
preferences:
action: "show_prefs"
outline: "altline"

View File

@ -1,80 +1,16 @@
---
outlines:
default: { width: 52, height: 52 }
altline: { width: 40, height: 52 }
narrow: { width: 22, height: 52 }
altline: { width: 52, height: 52 }
views:
base:
- "😀 😁 😅 😂 😊 😇 🙃"
- "😍 😘 😋 😜 😎 🥳 😔"
- "😢 😭 😡 😱 🤔 😬 🙄"
- "preferences blank 1 2 3 4 5 6 blank BackSpace"
two:
- "🤩 🤨 🤓 😴 🤢 🤮 😈"
- "💩 🙌 👏 👍 👎 👌 👋"
- "💪 🖕 🙏 💋 🤦‍♀️ 🤷‍♀️ 💃"
- "preferences blank 1 2 3 4 5 6 blank BackSpace"
three:
- "🐶 🐱 🐯 🙈 🐴 🦄 🌳"
- "🍀 🌹 💫 ⭐️ ✨ 💥 🔥"
- "🌈 ☀️ 🌤 🌧 ⛄️ ☂️ 🌊"
- "preferences blank 1 2 3 4 5 6 blank BackSpace"
four:
- "🍎 🍓 🍑 🍍 🍆 🥑 🥦"
- "🍕 🎂 🍫 🍿 🍻 🍾 🍽"
- "⚽️ 🏀 🏓 🏆 🎹 🎸 🎯"
- "preferences blank 1 2 3 4 5 6 blank BackSpace"
five:
- "🚗 🚌 🚲 🚄 🚂 ✈️ 🛰"
- "🚀 🛸 🚁 🚦 🏝 🏔 ⛺️"
- "🏠 🏢 🏥 🏛 🛤 🌅 🎇"
- "preferences blank 1 2 3 4 5 6 blank BackSpace"
six:
- "⌚️ 📱 💻 🖥 🖨 🕹 ✉️"
- "📞 ☎️ ⏰ ⏳ 📈 📉 📌"
- "🎁 ❤️ 💕 💯 ✅ ❎ 📢"
- "preferences blank 1 2 3 4 5 6 blank BackSpace"
- "preferences 🤨 🤓 😴 🤢 🤮 😈"
buttons:
1:
action:
set_view: "base"
outline: "altline"
label: "1"
2:
action:
set_view: "two"
outline: "altline"
label: "2"
3:
action:
set_view: "three"
outline: "altline"
label: "3"
4:
action:
set_view: "four"
outline: "altline"
label: "4"
5:
action:
set_view: "five"
outline: "altline"
label: "5"
6:
action:
set_view: "six"
outline: "altline"
label: "6"
preferences:
action: "show_prefs"
outline: "altline"
icon: "keyboard-mode-symbolic"
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
keysym: BackSpace
blank:
outline: "narrow"
text: ""

View File

@ -44,7 +44,7 @@ buttons:
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
action: "erase"
keysym: "BackSpace"
preferences:
action: "show_prefs"
outline: "default"

View File

@ -39,7 +39,7 @@ buttons:
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
action: "erase"
keysym: "BackSpace"
preferences:
action: "show_prefs"
outline: "altline"

View File

@ -46,7 +46,7 @@ buttons:
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
action: "erase"
keysym: "BackSpace"
preferences:
action: "show_prefs"
outline: "default"

View File

@ -195,7 +195,7 @@ buttons:
BackSpace:
outline: "wide"
icon: "edit-clear-symbolic"
action: erase
keysym: "BackSpace"
Return:
outline: "wide"
icon: "key-enter"

View File

@ -195,7 +195,7 @@ buttons:
BackSpace:
outline: "wide"
icon: "edit-clear-symbolic"
action: erase
keysym: "BackSpace"
Return:
outline: "wide"
icon: "key-enter"

View File

@ -39,7 +39,7 @@ buttons:
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
action: erase
keysym: "BackSpace"
preferences:
action: "show_prefs"
outline: "altline"

View File

@ -16,7 +16,7 @@ buttons:
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
action: erase
keysym: "BackSpace"
space:
outline: spaceline
text: " "

View File

@ -1,110 +0,0 @@
---
outlines:
default: { width: 35.33, height: 52 }
altline: { width: 52.67, height: 52 }
wide: { width: 59, height: 52 }
spaceline: { width: 140, height: 52 }
special: { width: 44, height: 52 }
views:
base:
- "q w e r t y u i o p"
- "a s d f g h j k l"
- "Shift_L z x c v b n m BackSpace"
- "show_numbers preferences space show_accents Return"
upper:
- "Q W E R T Y U I O P"
- "A S D F G H J K L"
- "Shift_L Z X C V B N M BackSpace"
- "show_numbers preferences space show_upper_accents Return"
numbers:
- "1 2 3 4 5 6 7 8 9 0"
- "@ # $ % & - _ + ( )"
- "show_symbols , \" ' colon ; ! ? BackSpace"
- "show_letters preferences space period Return"
symbols:
- "~ ` | · √ π τ ÷ × ¶"
- "© ® £ € ¥ ^ ° * { }"
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
- "show_letters preferences space period Return"
accents:
- "q w ę r t y u i ó p"
- "ą ś d f g h j k ł"
- "accents_show_upper ż ź ć v b ń m BackSpace"
- "show_numbers preferences space show_accents Return"
upper_accents:
- "Q W Ę R T Y U I Ó P"
- "Ą Ś D F G H J K Ł"
- "accents_show_upper Ż Ź Ć V B Ń M BackSpace"
- "show_numbers preferences space show_upper_accents Return"
buttons:
Shift_L:
action:
locking:
lock_view: "upper"
unlock_view: "base"
outline: "altline"
icon: "key-shift"
accents_show_upper:
action:
locking:
lock_view: "upper_accents"
unlock_view: "accents"
outline: "altline"
icon: "key-shift"
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
keysym: "BackSpace"
preferences:
action: "show_prefs"
outline: "special"
icon: "keyboard-mode-symbolic"
show_numbers:
action:
set_view: "numbers"
outline: "wide"
label: "123"
show_numbers_from_symbols:
action:
set_view: "numbers"
outline: "altline"
label: "123"
show_letters:
action:
set_view: "base"
outline: "wide"
label: "ABC"
show_symbols:
action:
set_view: "symbols"
outline: "altline"
label: "*/="
show_accents:
action:
locking:
lock_view: "accents"
unlock_view: "base"
outline: "altline"
label: "ąę"
show_upper_accents:
action:
locking:
lock_view: "upper_accents"
unlock_view: "upper"
outline: "altline"
label: "ĄĘ"
period:
outline: "altline"
text: "."
space:
outline: "spaceline"
text: " "
Return:
outline: "wide"
icon: "key-enter"
keysym: "Return"
colon:
text: ":"

View File

@ -1,102 +0,0 @@
---
outlines:
default: { width: 54, height: 42 }
altline: { width: 81, height: 42 }
wide: { width: 100, height: 42 }
spaceline: { width: 206, height: 42 }
special: { width: 54, height: 42 }
views:
base:
- "q w e r t y u i o p"
- "a s d f g h j k l"
- "Shift_L z x c v b n m BackSpace"
- "show_numbers preferences space show_accents Return"
upper:
- "Q W E R T Y U I O P"
- "A S D F G H J K L"
- "Shift_L Z X C V B N M BackSpace"
- "show_numbers preferences space show_upper_accents Return"
numbers:
- "1 2 3 4 5 6 7 8 9 0"
- "@ # $ % & - _ + ( )"
- "show_symbols , \" ' colon ; ! ? BackSpace"
- "show_letters preferences space period Return"
symbols:
- "~ ` | · √ π τ ÷ × ¶"
- "© ® £ € ¥ ^ ° * { }"
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
- "show_letters preferences space period Return"
accents:
- "q w ę r t y u i ó p"
- "ą ś d f g h j k ł"
- "Shift_L ż ź ć v b ń m BackSpace"
- "show_numbers preferences space show_accents Return"
upper_accents:
- "Q W Ę R T Y U I Ó P"
- "Ą Ś D F G H J K Ł"
- "Shift_L Ż Ź Ć V B Ń M BackSpace"
- "show_numbers preferences space show_upper_accents Return"
buttons:
Shift_L:
action:
locking:
lock_view: "upper"
unlock_view: "base"
outline: "altline"
icon: "key-shift"
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
keysym: "BackSpace"
preferences:
action: "show_prefs"
outline: "special"
icon: "keyboard-mode-symbolic"
show_numbers:
action:
set_view: "numbers"
outline: "wide"
label: "123"
show_numbers_from_symbols:
action:
set_view: "numbers"
outline: "altline"
label: "123"
show_letters:
action:
set_view: "base"
outline: "wide"
label: "ABC"
show_symbols:
action:
set_view: "symbols"
outline: "altline"
label: "*/="
show_accents:
action:
locking:
lock_view: "accents"
unlock_view: "base"
outline: "altline"
label: "ąę"
show_upper_accents:
action:
locking:
lock_view: "upper_accents"
unlock_view: "upper"
outline: "altline"
label: "ĄĘ"
period:
outline: "altline"
text: "."
space:
outline: "spaceline"
text: " "
Return:
outline: "wide"
icon: "key-enter"
keysym: "Return"
colon:
text: ":"

View File

@ -39,7 +39,7 @@ buttons:
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
action: erase
keysym: "BackSpace"
preferences:
action: "show_prefs"
outline: "altline"

View File

@ -20,13 +20,13 @@ views:
- "show_numbers preferences space show_actions Return"
numbers:
- "1 2 3 4 5 6 7 8 9 0"
- "* # $ / & - _ + ( )"
- "@ # $ % & - _ + ( )"
- "show_symbols , \" ' colon ; ! ? BackSpace"
- "show_letters preferences space period Return"
symbols:
- "~ ` | · √ π τ ÷ × ¶"
- "© ® £ € ¥ ^ ° @ { }"
- "show_numbers_from_symbols \\ % < > = [ ] BackSpace"
- "© ® £ € ¥ ^ ° * { }"
- "show_numbers_from_symbols \\ / < > = [ ] BackSpace"
- "show_letters preferences space period Return"
actions:
- "F1 F2 F3 F4 F5 F6"
@ -45,7 +45,7 @@ buttons:
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
action: erase
keysym: "BackSpace"
preferences:
action: "show_prefs"
outline: "special"
@ -69,14 +69,14 @@ buttons:
action:
set_view: "symbols"
outline: "altline"
label: "τ=\\"
label: "*/="
show_actions:
action:
set_view: "actions"
outline: "altline"
label: ">_"
period:
outline: "altline"
outline: "special"
text: "."
space:
outline: "spaceline"

View File

@ -39,9 +39,9 @@ buttons:
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
action: erase
keysym: "BackSpace"
preferences:
action: show_prefs
action: "show_prefs"
outline: "special"
icon: "keyboard-mode-symbolic"
show_numbers:

View File

@ -39,7 +39,7 @@ buttons:
BackSpace:
outline: "altline"
icon: "edit-clear-symbolic"
action: "erase"
keysym: "BackSpace"
preferences:
action: "show_prefs"
outline: "special"

View File

@ -0,0 +1,8 @@
us Englisch (US)
de Deutsch
el Griechisch
es Spanisch
it Italienisch
jp+kana Japanisch (Kana)
no Norwegisch

View File

@ -1,2 +1,10 @@
emoji Emoji
terminal Terminal
us English (US)
de German
el Greek
es Spanish
fi Finnish
it Italian
jp+kana Japanese (kana)
no Norwegian
se Swedish

View File

@ -0,0 +1,8 @@
us 英語 (US)
de ドイツ語
el ギリシャ語
es スペイン語
it イタリア語
jp+kana 日本語 (かな)
nb ノルウェー語

View File

@ -1,2 +1,9 @@
emoji emoji
terminal terminal
us angielski (USA)
de niemiecki
el grecki
es hiszpański
fi fiński
it włoski
jp+kana japoński (kana)
no norweski
se szwedzki

37
debian/changelog vendored
View File

@ -1,40 +1,3 @@
squeekboard (1.9.0) amber-phone; urgency=medium
[ Dorota Czaplejewicz ]
* imservice: Add commit_string method
* submission: Handle submitting strings
* input_method: Use for erasing
* logging: Use in merged functions
* translations: Remove redundant ones
* translations: Translate builtin layouts
* greek: Rename to gr which is used by gnome settings
[ Sebastian Krzyszkowiak ]
* layouts: Add Polish layouts
[ Dorota Czaplejewicz ]
* locks: Draw based on current view
* locking: Lock keys statelessly
* layouts: Better accented uppercase in PL
* emoji: Add more choices
* row: Eliminate angle
* layout: Center views relative to each other and the layout bounds
* drawing: Generalized foreach_visible_button
* variant: Fix double-free
* variant: Fix leak
* keyboard_layout: Fix leak
* layout: Improve scoping of locked variable
* terminal: Make */ easier to reach
[ Sebastian Krzyszkowiak ]
* layouts: terminal: Use altline outline for dot key
[ Dorota Czaplejewicz ]
* text input: Disable erasing
* cargo: Update deps
-- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm> Wed, 19 Feb 2020 14:32:39 +0000
squeekboard (1.8.1) amber-phone; urgency=medium
[ Dorota Czaplejewicz ]

View File

@ -116,7 +116,6 @@ settings_get_layout(GSettings *settings, char **type, char **layout)
GVariant *inputs = g_settings_get_value(settings, "sources");
// current layout is always first
g_variant_get_child(inputs, 0, "(ss)", type, layout);
g_variant_unref(inputs);
}
void
@ -140,11 +139,9 @@ eekboard_context_service_update_layout(EekboardContextService *context, enum squ
switch (priv->purpose) {
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NUMBER:
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE:
g_free(keyboard_layout);
keyboard_layout = g_strdup("number");
break;
case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL:
g_free(keyboard_layout);
keyboard_layout = g_strdup("terminal");
break;
default:

View File

@ -31,29 +31,10 @@ pub enum Action {
SetModifier(Modifier),
/// Submit some text
Submit {
/// Text to submit with input-method.
/// If None, then keys are to be submitted instead.
/// Text to submit with input-method
text: Option<CString>,
/// The key events this symbol submits when submitting text is not possible
keys: Vec<KeySym>,
},
/// Erase a position behind the cursor
Erase,
ShowPreferences,
}
impl Action {
pub fn is_locked(&self, view_name: &str) -> bool {
match self {
Action::LockView { lock, unlock: _ } => lock == view_name,
_ => false,
}
}
pub fn is_active(&self, view_name: &str) -> bool {
match self {
Action::SetView(view) => view == view_name,
Action::LockView { lock, unlock: _ } => lock == view_name,
_ => false,
}
}
}

View File

@ -15,7 +15,6 @@ use std::vec::Vec;
use xkbcommon::xkb;
use ::action;
use ::keyboard::{
KeyState, PressType,
generate_keymap, generate_keycodes, FormattingError
@ -265,9 +264,6 @@ enum Action {
SetView(String),
#[serde(rename="show_prefs")]
ShowPrefs,
/// Remove last character
#[serde(rename="erase")]
Erase,
}
#[derive(Debug, Clone, Deserialize, PartialEq)]
@ -390,16 +386,13 @@ impl Layout {
)
}).collect()
},
action::Action::Erase => vec![
*keymap.get("BackSpace")
.expect(&format!("BackSpace missing from keymap")),
],
_ => Vec::new(),
};
(
name.into(),
KeyState {
pressed: PressType::Released,
locked: false,
keycodes,
action,
}
@ -424,8 +417,8 @@ impl Layout {
)}
);
let views: Vec<_> = self.views.iter()
.map(|(name, view)| {
let views = HashMap::from_iter(
self.views.iter().map(|(name, view)| {
let rows = view.iter().map(|row| {
let buttons = row.split_ascii_whitespace()
.map(|name| {
@ -439,7 +432,8 @@ impl Layout {
&mut warning_handler,
))
});
layout::Row {
::layout::Row {
angle: 0,
buttons: add_offsets(
buttons,
|button| button.size.width,
@ -452,25 +446,8 @@ impl Layout {
name.clone(),
layout::View::new(rows)
)
}).collect();
// Center views on the same point.
let views = {
let total_size = layout::View::calculate_super_size(
views.iter().map(|(_name, view)| view).collect()
);
HashMap::from_iter(views.into_iter().map(|(name, view)| (
name,
(
layout::c::Point {
x: (total_size.width - view.get_width()) / 2.0,
y: (total_size.height - view.get_height()) / 2.0,
},
view,
),
)))
};
})
);
(
Ok(::layout::LayoutData {
@ -581,7 +558,6 @@ fn create_action<H: logging::Handler>(
SubmitData::Action(
Action::ShowPrefs
) => ::action::Action::ShowPreferences,
SubmitData::Action(Action::Erase) => action::Action::Erase,
SubmitData::Keysym(keysym) => ::action::Action::Submit {
text: None,
keys: vec!(::action::KeySym(
@ -613,7 +589,7 @@ fn create_action<H: logging::Handler>(
false => format!("U{:04X}", codepoint as u32),
})
}).collect(),
},
}
}
}
@ -767,7 +743,7 @@ mod tests {
.build(ProblemPanic).0
.unwrap();
assert_eq!(
out.views["base"].1
out.views["base"]
.get_rows()[0].1
.buttons[0].1
.label,
@ -782,7 +758,7 @@ mod tests {
.build(ProblemPanic).0
.unwrap();
assert_eq!(
out.views["base"].1
out.views["base"]
.get_rows()[0].1
.buttons[0].1
.label,
@ -798,7 +774,7 @@ mod tests {
.build(ProblemPanic).0
.unwrap();
assert_eq!(
out.views["base"].1
out.views["base"]
.get_rows()[0].1
.buttons[0].1
.state.borrow()

View File

@ -37,7 +37,6 @@ mod c {
);
}
/// Draws all buttons that are not in the base state
#[no_mangle]
pub extern "C"
fn squeek_layout_draw_all_changed(
@ -48,18 +47,20 @@ mod c {
let layout = unsafe { &mut *layout };
let cr = unsafe { cairo::Context::from_raw_none(cr) };
layout.foreach_visible_button(|offset, button| {
let state = RefCell::borrow(&button.state).clone();
let locked = state.action.is_active(&layout.current_view);
if state.pressed == keyboard::PressType::Pressed || locked {
render_button_at_position(
renderer, &cr,
offset,
button.as_ref(),
state.pressed, locked,
);
let view = layout.get_current_view();
for (row_offset, row) in &view.get_rows() {
for (x_offset, button) in &row.buttons {
let state = RefCell::borrow(&button.state).clone();
if state.pressed == keyboard::PressType::Pressed || state.locked {
render_button_at_position(
renderer, &cr,
row_offset + Point { x: *x_offset, y: 0.0 },
button.as_ref(),
state.pressed, state.locked,
);
}
}
})
}
}
#[no_mangle]
@ -71,15 +72,17 @@ mod c {
) {
let layout = unsafe { &mut *layout };
let cr = unsafe { cairo::Context::from_raw_none(cr) };
layout.foreach_visible_button(|offset, button| {
render_button_at_position(
renderer, &cr,
offset,
button.as_ref(),
keyboard::PressType::Released, false,
);
})
let view = layout.get_current_view();
for (row_offset, row) in &view.get_rows() {
for (x_offset, button) in &row.buttons {
render_button_at_position(
renderer, &cr,
row_offset + Point { x: *x_offset, y: 0.0 },
button.as_ref(),
keyboard::PressType::Released, false,
);
}
}
}
}

View File

@ -49,23 +49,6 @@ void imservice_connect_listeners(struct zwp_input_method_v2 *im, struct imservic
zwp_input_method_v2_add_listener(im, &input_method_listener, imservice);
}
void
eek_input_method_commit_string(struct zwp_input_method_v2 *zwp_input_method_v2, const char *text)
{
zwp_input_method_v2_commit_string(zwp_input_method_v2, text);
}
void
eek_input_method_delete_surrounding_text(struct zwp_input_method_v2 *zwp_input_method_v2, uint32_t before_length, uint32_t after_length) {
zwp_input_method_v2_delete_surrounding_text(zwp_input_method_v2, before_length, after_length);
};
void
eek_input_method_commit(struct zwp_input_method_v2 *zwp_input_method_v2, uint32_t serial)
{
zwp_input_method_v2_commit(zwp_input_method_v2, serial);
}
/// Declared explicitly because _destroy is inline,
/// making it unavailable in Rust
void imservice_destroy_im(struct zwp_input_method_v2 *im) {

View File

@ -1,8 +1,3 @@
/*! Manages zwp_input_method_v2 protocol.
*
* Library module.
*/
use std::boxed::Box;
use std::ffi::CString;
use std::fmt;
@ -37,9 +32,6 @@ pub mod c {
fn imservice_destroy_im(im: *mut c::InputMethod);
#[allow(improper_ctypes)] // IMService will never be dereferenced in C
pub fn imservice_connect_listeners(im: *mut InputMethod, imservice: *const IMService);
pub fn eek_input_method_commit_string(im: *mut InputMethod, text: *const c_char);
pub fn eek_input_method_delete_surrounding_text(im: *mut InputMethod, before: u32, after: u32);
pub fn eek_input_method_commit(im: *mut InputMethod, serial: u32);
fn eekboard_context_service_set_hint_purpose(state: *const StateManager, hint: u32, purpose: u32);
fn server_context_service_show_keyboard(imservice: *const UIManager);
fn server_context_service_hide_keyboard(imservice: *const UIManager);
@ -336,7 +328,7 @@ impl Default for IMProtocolState {
pub struct IMService {
/// Owned reference (still created and destroyed in C)
pub im: *mut c::InputMethod,
pub im: *const c::InputMethod,
/// Unowned reference. Be careful, it's shared with C at large
state_manager: *const c::StateManager,
/// Unowned reference. Be careful, it's shared with C at large
@ -348,11 +340,6 @@ pub struct IMService {
serial: Wrapping<u32>,
}
pub enum SubmitError {
/// The input method had not been activated
NotActive,
}
impl IMService {
pub fn new(
im: *mut c::InputMethod,
@ -377,51 +364,4 @@ impl IMService {
}
imservice
}
pub fn commit_string(&self, text: &CString) -> Result<(), SubmitError> {
match self.current.active {
true => {
unsafe {
c::eek_input_method_commit_string(self.im, text.as_ptr())
}
Ok(())
},
false => Err(SubmitError::NotActive),
}
}
pub fn delete_surrounding_text(
&self,
before: u32, after: u32,
) -> Result<(), SubmitError> {
match self.current.active {
true => {
unsafe {
c::eek_input_method_delete_surrounding_text(
self.im,
before, after,
)
}
Ok(())
},
false => Err(SubmitError::NotActive),
}
}
pub fn commit(&mut self) -> Result<(), SubmitError> {
match self.current.active {
true => {
unsafe {
c::eek_input_method_commit(self.im, self.serial.0)
}
self.serial += Wrapping(1u32);
Ok(())
},
false => Err(SubmitError::NotActive),
}
}
pub fn is_active(&self) -> bool {
self.current.active
}
}

View File

@ -1,17 +1,14 @@
/*! State of the emulated keyboard and keys.
* Regards the keyboard as if it was composed of switches. */
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt;
use std::io;
use std::rc::Rc;
use std::string::FromUtf8Error;
use ::action::Action;
use ::logging;
// Traits
use std::io::Write;
use std::iter::{ FromIterator, IntoIterator };
@ -23,14 +20,10 @@ pub enum PressType {
pub type KeyCode = u32;
/// When the submitted actions of keys need to be tracked,
/// they need a stable, comparable ID
#[derive(PartialEq)]
pub struct KeyStateId(*const KeyState);
#[derive(Debug, Clone)]
pub struct KeyState {
pub pressed: PressType,
pub locked: bool,
/// A cache of raw keycodes derived from Action::Sumbit given a keymap
pub keycodes: Vec<KeyCode>,
/// Static description of what the key does when pressed or released
@ -38,6 +31,17 @@ pub struct KeyState {
}
impl KeyState {
#[must_use]
pub fn into_activated(self) -> KeyState {
match self.action {
Action::LockView { lock: _, unlock: _ } => KeyState {
locked: self.locked ^ true,
..self
},
_ => self,
}
}
#[must_use]
pub fn into_released(self) -> KeyState {
KeyState {
@ -45,12 +49,6 @@ impl KeyState {
..self
}
}
/// KeyStates instances are the unique identifiers of pressed keys,
/// and the actions submitted with them.
pub fn get_id(keystate: &Rc<RefCell<KeyState>>) -> KeyStateId {
KeyStateId(keystate.as_ptr() as *const KeyState)
}
}
/// Sorts an iterator by converting it to a Vector and back
@ -68,10 +66,9 @@ fn sorted<'a, I: Iterator<Item=&'a str>>(
pub fn generate_keycodes<'a, C: IntoIterator<Item=&'a str>>(
key_names: C
) -> HashMap<String, u32> {
let special_keysyms = ["BackSpace", "Return"].iter().map(|&s| s);
HashMap::from_iter(
// sort to remove a source of indeterminism in keycode assignment
sorted(key_names.into_iter().chain(special_keysyms))
sorted(key_names.into_iter())
.map(|name| String::from(name))
.zip(9..)
)
@ -98,10 +95,7 @@ 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.
/// Generates a de-facto single level keymap. TODO: actually drop second level
pub fn generate_keymap(
keystates: &HashMap::<String, KeyState>
) -> Result<String, FormattingError> {
@ -116,40 +110,22 @@ pub fn generate_keymap(
)?;
for (name, state) in keystates.iter() {
match &state.action {
Action::Submit { text: _, keys } => {
if let 0 = keys.len() {
log_print!(
logging::Level::Warning,
"Key {} has no keysyms", name,
);
};
for (named_keysym, keycode) in keys.iter().zip(&state.keycodes) {
write!(
buf,
"
<{}> = {};",
named_keysym.0,
keycode,
)?;
}
},
Action::Erase => {
let mut keycodes = state.keycodes.iter();
if let Action::Submit { text: _, keys } = &state.action {
if let 0 = keys.len() {
log_print!(
logging::Level::Warning,
"Key {} has no keysyms", name,
);
};
for (named_keysym, keycode) in keys.iter().zip(&state.keycodes) {
write!(
buf,
"
<BackSpace> = {};",
keycodes.next().expect("Erase key has no keycode"),
<{}> = {};",
named_keysym.0,
keycode,
)?;
if let Some(_) = keycodes.next() {
log_print!(
logging::Level::Bug,
"Erase key has multiple keycodes",
);
}
},
_ => {},
}
}
}
@ -161,9 +137,7 @@ pub fn generate_keymap(
xkb_symbols \"squeekboard\" {{
name[Group1] = \"Letters\";
name[Group2] = \"Numbers/Symbols\";
key <BackSpace> {{ [ BackSpace ] }};"
name[Group2] = \"Numbers/Symbols\";"
)?;
for (name, state) in keystates.iter() {
@ -221,6 +195,7 @@ mod tests {
keys: vec!(KeySym("a".into()), KeySym("c".into())),
},
keycodes: vec!(9, 10),
locked: false,
pressed: PressType::Released,
},
}).unwrap();

View File

@ -329,8 +329,11 @@ pub mod c {
Point { x: x_widget, y: y_widget }
);
let state = layout.find_button_by_position(point)
.map(|place| place.button.state.clone());
let state = {
let view = layout.get_current_view();
view.find_button_by_position(point)
.map(|place| place.button.state.clone())
};
if let Some(state) = state {
seat::handle_press_key(
@ -371,7 +374,8 @@ pub mod c {
let pressed = layout.pressed_keys.clone();
let button_info = {
let place = layout.find_button_by_position(point);
let view = layout.get_current_view();
let place = view.find_button_by_position(point);
place.map(|place| {(
place.button.state.clone(),
place.button.clone(),
@ -482,6 +486,8 @@ pub struct Button {
pub struct Row {
/// Buttons together with their offset from the left
pub buttons: Vec<(f64, Box<Button>)>,
/// Angle is not really used anywhere...
pub angle: i32,
}
impl Row {
@ -548,14 +554,14 @@ impl View {
})
}
pub fn get_width(&self) -> f64 {
fn get_width(&self) -> f64 {
// No need to call `get_rows()`,
// as the biggest row is the most far reaching in both directions
// because they are all centered.
find_max_double(self.rows.iter(), |(_offset, row)| row.get_width())
}
pub fn get_height(&self) -> f64 {
fn get_height(&self) -> f64 {
self.rows.iter().next_back()
.map(|(y_offset, row)| row.get_height() + y_offset)
.unwrap_or(0.0)
@ -572,21 +578,6 @@ impl View {
row,
)}).collect()
}
/// Returns a size which contains all the views
/// if they are all centered on the same point.
pub fn calculate_super_size(views: Vec<&View>) -> Size {
Size {
height: find_max_double(
views.iter(),
|view| view.get_height(),
),
width: find_max_double(
views.iter(),
|view| view.get_width(),
),
}
}
}
/// The physical characteristic of layout for the purpose of styling
@ -614,8 +605,7 @@ pub struct Layout {
// Views own the actual buttons which have state
// Maybe they should own UI only,
// and keys should be owned by a dedicated non-UI-State?
/// Point is the offset within the layout
pub views: HashMap<String, (c::Point, View)>,
pub views: HashMap<String, View>,
// Non-UI stuff
/// xkb keymap applicable to the contained keys. Unchangeable
@ -629,12 +619,12 @@ pub struct Layout {
// When the list tracks actual location,
// it becomes possible to place popovers and other UI accurately.
pub pressed_keys: HashSet<::util::Pointer<RefCell<KeyState>>>,
pub locked_keys: HashSet<::util::Pointer<RefCell<KeyState>>>,
}
/// A builder structure for picking up layout data from storage
pub struct LayoutData {
/// Point is the offset within layout
pub views: HashMap<String, (c::Point, View)>,
pub views: HashMap<String, View>,
pub keymap_str: CString,
pub margins: Margins,
}
@ -660,17 +650,13 @@ impl Layout {
views: data.views,
keymap_str: data.keymap_str,
pressed_keys: HashSet::new(),
locked_keys: HashSet::new(),
margins: data.margins,
}
}
pub fn get_current_view_position(&self) -> &(c::Point, View) {
&self.views
.get(&self.current_view).expect("Selected nonexistent view")
}
pub fn get_current_view(&self) -> &View {
&self.views.get(&self.current_view).expect("Selected nonexistent view").1
self.views.get(&self.current_view).expect("Selected nonexistent view")
}
fn set_view(&mut self, view: String) -> Result<(), NoSuchView> {
@ -684,9 +670,16 @@ impl Layout {
/// Calculates size without margins
fn calculate_inner_size(&self) -> Size {
View::calculate_super_size(
self.views.iter().map(|(_, (_offset, v))| v).collect()
)
Size {
height: find_max_double(
self.views.iter(),
|(_name, view)| view.get_height(),
),
width: find_max_double(
self.views.iter(),
|(_name, view)| view.get_width(),
),
}
}
/// Size including margins
@ -721,42 +714,6 @@ impl Layout {
scale: 1.0,
})
}
fn find_button_by_position(&self, point: c::Point) -> Option<ButtonPlace> {
let (offset, layout) = self.get_current_view_position();
layout.find_button_by_position(point - offset)
}
pub fn foreach_visible_button<F>(&self, mut f: F)
where F: FnMut(c::Point, &Box<Button>)
{
let (view_offset, view) = self.get_current_view_position();
for (row_offset, row) in &view.get_rows() {
for (x_offset, button) in &row.buttons {
let offset = view_offset
+ row_offset.clone()
+ c::Point { x: *x_offset, y: 0.0 };
f(offset, button);
}
}
}
pub fn get_locked_keys(&self) -> Vec<Rc<RefCell<KeyState>>> {
let mut out = Vec::new();
let view = self.get_current_view();
for (_, row) in &view.get_rows() {
for (_, button) in &row.buttons {
let locked = {
let state = RefCell::borrow(&button.state).clone();
state.action.is_locked(&self.current_view)
};
if locked {
out.push(button.state.clone());
}
}
}
out
}
}
mod procedures {
@ -808,6 +765,7 @@ mod procedures {
let row = Row {
buttons: vec!((0.1, button)),
angle: 0,
};
let view = View {
@ -883,9 +841,9 @@ mod seat {
#[must_use]
fn unstick_locks(layout: &mut Layout) -> ViewChange {
let mut new_view = None;
for key in layout.get_locked_keys().clone() {
for key in layout.locked_keys.clone() {
let key: &Rc<RefCell<KeyState>> = key.borrow();
let key = RefCell::borrow(key);
let mut key = RefCell::borrow_mut(key);
match &key.action {
Action::LockView { lock: _, unlock: view } => {
new_view = Some(view.clone());
@ -896,6 +854,7 @@ mod seat {
a,
),
};
key.locked = false;
}
ViewChange {
@ -917,7 +876,11 @@ mod seat {
);
}
let mut key = rckey.borrow_mut();
submission.handle_press(&key, KeyState::get_id(rckey), time);
submission.virtual_keyboard.switch(
&key.keycodes,
PressType::Pressed,
time,
);
key.pressed = PressType::Pressed;
}
@ -936,25 +899,32 @@ mod seat {
// update
let key = key.into_released();
let key = match action {
Action::LockView { lock: _, unlock: _ } => key.into_activated(),
_ => key,
};
// process changes
match action {
Action::Submit { text: _, keys: _ }
| Action::Erase
=> {
Action::Submit { text: _, keys: _ } => {
unstick_locks(layout).apply();
submission.handle_release(KeyState::get_id(rckey), time);
submission.virtual_keyboard.switch(
&key.keycodes,
PressType::Released,
time,
);
},
Action::SetView(view) => {
try_set_view(layout, view)
},
Action::LockView { lock, unlock } => {
let gets_locked = !key.action.is_locked(&layout.current_view);
// The button that triggered this will be in the right state
// due to commit at the end.
unstick_locks(layout)
// It doesn't matter what the resulting view should be,
// it's getting changed anyway.
.choose_view(
match gets_locked {
match key.locked {
true => lock.clone(),
false => unlock.clone(),
}
@ -996,6 +966,11 @@ mod seat {
let pointer = ::util::Pointer(rckey.clone());
// Apply state changes
layout.pressed_keys.remove(&pointer);
if key.locked {
layout.locked_keys.insert(pointer);
} else {
layout.locked_keys.remove(&pointer);
}
// Commit activated button state changes
RefCell::replace(rckey, key);
}
@ -1010,6 +985,7 @@ mod test {
pub fn make_state() -> Rc<RefCell<::keyboard::KeyState>> {
Rc::new(RefCell::new(::keyboard::KeyState {
pressed: PressType::Released,
locked: false,
keycodes: Vec::new(),
action: Action::SetView("default".into()),
}))
@ -1036,6 +1012,7 @@ mod test {
(
0.0,
Row {
angle: 0,
buttons: vec![(
0.0,
Box::new(Button {
@ -1048,6 +1025,7 @@ mod test {
(
10.0,
Row {
angle: 0,
buttons: vec![(
0.0,
Box::new(Button {
@ -1071,6 +1049,7 @@ mod test {
(
0.0,
Row {
angle: 0,
buttons: vec![(
0.0,
Box::new(Button {
@ -1085,6 +1064,7 @@ mod test {
current_view: String::new(),
keymap_str: CString::new("").unwrap(),
kind: ArrangementKind::Base,
locked_keys: HashSet::new(),
pressed_keys: HashSet::new(),
// Lots of bottom margin
margins: Margins {
@ -1094,7 +1074,7 @@ mod test {
bottom: 1.0,
},
views: hashmap! {
String::new() => (c::Point { x: 0.0, y: 0.0 }, view),
String::new() => view,
},
};
assert_eq!(

View File

@ -91,11 +91,6 @@ mod variants {
unsafe {
let ret = glib_sys::g_variant_builder_end(builder);
glib_sys::g_variant_builder_unref(builder);
// HACK: This is to prevent C taking ownership
// of "floating" Variants,
// where Rust gets to keep a stale reference
// and crash when trying to drop it.
glib_sys::g_variant_ref_sink(ret);
glib::Variant::from_glib_full(ret)
}
}
@ -146,7 +141,7 @@ fn set_layout(kind: String, name: String) {
.chain(inputs).collect();
settings.set_value(
"sources",
&variants::ArrayPairString(inputs).to_variant(),
&variants::ArrayPairString(inputs).to_variant()
);
settings.apply();
}

View File

@ -16,16 +16,14 @@ const KEYBOARDS: &[(*const str, *const str)] = &[
("us_wide", include_str!("../data/keyboards/us_wide.yaml")),
("de", include_str!("../data/keyboards/de.yaml")),
("de_wide", include_str!("../data/keyboards/de_wide.yaml")),
("el", include_str!("../data/keyboards/el.yaml")),
("es", include_str!("../data/keyboards/es.yaml")),
("fi", include_str!("../data/keyboards/fi.yaml")),
("gr", include_str!("../data/keyboards/gr.yaml")),
("it", include_str!("../data/keyboards/it.yaml")),
("jp+kana", include_str!("../data/keyboards/jp+kana.yaml")),
("jp+kana_wide", include_str!("../data/keyboards/jp+kana_wide.yaml")),
("no", include_str!("../data/keyboards/no.yaml")),
("number", include_str!("../data/keyboards/number.yaml")),
("pl", include_str!("../data/keyboards/pl.yaml")),
("pl_wide", include_str!("../data/keyboards/pl_wide.yaml")),
("se", include_str!("../data/keyboards/se.yaml")),
// layout+overlay
("terminal", include_str!("../data/keyboards/terminal.yaml")),

View File

@ -16,12 +16,8 @@
* The text-input interface may be enabled and disabled at arbitrary times,
* and those events SHOULD NOT cause any lost events.
* */
use ::action::Action;
use ::imservice;
use ::imservice::IMService;
use ::keyboard::{ KeyCode, KeyState, KeyStateId, PressType };
use ::logging;
use ::vkeyboard::VirtualKeyboard;
/// Gathers stuff defined in C or called by C
@ -61,7 +57,6 @@ pub mod c {
Submission {
imservice,
virtual_keyboard: VirtualKeyboard(vk),
pressed: Vec::new(),
}
))
}
@ -97,94 +92,9 @@ pub mod c {
#[derive(Clone, Copy)]
pub struct Timestamp(pub u32);
enum SubmittedAction {
/// A collection of keycodes that were pressed
VirtualKeyboard(Vec<KeyCode>),
IMService,
}
pub struct Submission {
// used by C callbacks internally, TODO: make use with virtual keyboard
#[allow(dead_code)]
imservice: Option<Box<IMService>>,
virtual_keyboard: VirtualKeyboard,
pressed: Vec<(KeyStateId, SubmittedAction)>,
}
impl Submission {
/// Sends a submit text event if possible;
/// otherwise sends key press and makes a note of it
pub fn handle_press(
&mut self,
key: &KeyState, key_id: KeyStateId,
time: Timestamp,
) {
match &key.action {
Action::Submit { text: _, keys: _ }
| Action::Erase
=> (),
_ => {
log_print!(
logging::Level::Bug,
"Submitted key with action other than Submit or Erase",
);
return;
},
};
let was_committed_as_text = match (&mut self.imservice, &key.action) {
(Some(imservice), Action::Submit { text: Some(text), keys: _ }) => {
let submit_result = imservice.commit_string(text)
.and_then(|_| imservice.commit());
match submit_result {
Ok(()) => true,
Err(imservice::SubmitError::NotActive) => false,
}
},
/* Delete_surrounding_text takes byte offsets,
* so cannot work without get_surrounding_text.
* This is a bug in the protocol.
(Some(imservice), Action::Erase) => {
let submit_result = imservice.delete_surrounding_text(1, 0)
.and_then(|_| imservice.commit());
match submit_result {
Ok(()) => true,
Err(imservice::SubmitError::NotActive) => false,
}
}*/
(_, _) => false,
};
let submit_action = match was_committed_as_text {
true => SubmittedAction::IMService,
false => {
self.virtual_keyboard.switch(
&key.keycodes,
PressType::Pressed,
time,
);
SubmittedAction::VirtualKeyboard(key.keycodes.clone())
},
};
self.pressed.push((key_id, submit_action));
}
pub fn handle_release(&mut self, key_id: KeyStateId, time: Timestamp) {
let index = self.pressed.iter().position(|(id, _)| *id == key_id);
if let Some(index) = index {
let (_id, action) = self.pressed.remove(index);
match action {
// string already sent, nothing to do
SubmittedAction::IMService => {},
// no matter if the imservice got activated,
// keys must be released
SubmittedAction::VirtualKeyboard(keycodes) => {
self.virtual_keyboard.switch(
&keycodes,
PressType::Released,
time,
)
},
}
};
}
pub virtual_keyboard: VirtualKeyboard,
}

View File

@ -60,7 +60,7 @@ fn check_layout(layout: Layout) {
let state = xkb::State::new(&keymap);
// "Press" each button with keysyms
for (_pos, view) in layout.views.values() {
for view in layout.views.values() {
for (_y, row) in &view.get_rows() {
for (_x, button) in &row.buttons {
let keystate = button.state.borrow();

View File

@ -50,14 +50,13 @@ endforeach
foreach layout : [
'us', 'us_wide',
'de', 'de_wide',
'el',
'es',
'fi',
'gr',
'it',
'jp+kana','jp+kana_wide',
'no',
'number',
'pl', 'pl_wide',
'se',
'terminal',