input_method: Use for erasing

This commit is contained in:
Dorota Czaplejewicz
2020-01-23 15:39:40 +00:00
parent 42cb73cd8c
commit 585ed5e97d
21 changed files with 101 additions and 33 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -37,5 +37,7 @@ pub enum Action {
/// The key events this symbol submits when submitting text is not possible /// The key events this symbol submits when submitting text is not possible
keys: Vec<KeySym>, keys: Vec<KeySym>,
}, },
/// Erase a position behind the cursor
Erase,
ShowPreferences, ShowPreferences,
} }

View File

@ -15,6 +15,7 @@ use std::vec::Vec;
use xkbcommon::xkb; use xkbcommon::xkb;
use ::action;
use ::keyboard::{ use ::keyboard::{
KeyState, PressType, KeyState, PressType,
generate_keymap, generate_keycodes, FormattingError generate_keymap, generate_keycodes, FormattingError
@ -259,6 +260,9 @@ enum Action {
SetView(String), SetView(String),
#[serde(rename="show_prefs")] #[serde(rename="show_prefs")]
ShowPrefs, ShowPrefs,
/// Remove last character
#[serde(rename="erase")]
Erase,
} }
#[derive(Debug, Clone, Deserialize, PartialEq)] #[derive(Debug, Clone, Deserialize, PartialEq)]
@ -381,6 +385,10 @@ impl Layout {
) )
}).collect() }).collect()
}, },
action::Action::Erase => vec![
*keymap.get("BackSpace")
.expect(&format!("BackSpace missing from keymap")),
],
_ => Vec::new(), _ => Vec::new(),
}; };
( (
@ -547,6 +555,7 @@ fn create_action<H: WarningHandler>(
SubmitData::Action( SubmitData::Action(
Action::ShowPrefs Action::ShowPrefs
) => ::action::Action::ShowPreferences, ) => ::action::Action::ShowPreferences,
SubmitData::Action(Action::Erase) => action::Action::Erase,
SubmitData::Keysym(keysym) => ::action::Action::Submit { SubmitData::Keysym(keysym) => ::action::Action::Submit {
text: None, text: None,
keys: vec!(::action::KeySym( keys: vec!(::action::KeySym(
@ -581,7 +590,7 @@ fn create_action<H: WarningHandler>(
false => format!("U{:04X}", codepoint as u32), false => format!("U{:04X}", codepoint as u32),
}) })
}).collect(), }).collect(),
} },
} }
} }

View File

@ -55,6 +55,11 @@ eek_input_method_commit_string(struct zwp_input_method_v2 *zwp_input_method_v2,
zwp_input_method_v2_commit_string(zwp_input_method_v2, 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 void
eek_input_method_commit(struct zwp_input_method_v2 *zwp_input_method_v2, uint32_t serial) eek_input_method_commit(struct zwp_input_method_v2 *zwp_input_method_v2, uint32_t serial)
{ {

View File

@ -35,6 +35,7 @@ pub mod c {
#[allow(improper_ctypes)] // IMService will never be dereferenced in C #[allow(improper_ctypes)] // IMService will never be dereferenced in C
pub fn imservice_connect_listeners(im: *mut InputMethod, imservice: *const IMService); 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_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); 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 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_show_keyboard(imservice: *const UIManager);
@ -375,6 +376,24 @@ impl IMService {
} }
} }
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> { pub fn commit(&mut self) -> Result<(), SubmitError> {
match self.current.active { match self.current.active {
true => { true => {

View File

@ -79,9 +79,10 @@ fn sorted<'a, I: Iterator<Item=&'a str>>(
pub fn generate_keycodes<'a, C: IntoIterator<Item=&'a str>>( pub fn generate_keycodes<'a, C: IntoIterator<Item=&'a str>>(
key_names: C key_names: C
) -> HashMap<String, u32> { ) -> HashMap<String, u32> {
let special_keysyms = ["BackSpace", "Return"].iter().map(|&s| s);
HashMap::from_iter( HashMap::from_iter(
// sort to remove a source of indeterminism in keycode assignment // sort to remove a source of indeterminism in keycode assignment
sorted(key_names.into_iter()) sorted(key_names.into_iter().chain(special_keysyms))
.map(|name| String::from(name)) .map(|name| String::from(name))
.zip(9..) .zip(9..)
) )
@ -108,7 +109,10 @@ impl From<io::Error> for FormattingError {
} }
} }
/// Generates a de-facto single level keymap. TODO: actually drop second level /// 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.
pub fn generate_keymap( pub fn generate_keymap(
keystates: &HashMap::<String, KeyState> keystates: &HashMap::<String, KeyState>
) -> Result<String, FormattingError> { ) -> Result<String, FormattingError> {
@ -123,17 +127,32 @@ pub fn generate_keymap(
)?; )?;
for (name, state) in keystates.iter() { for (name, state) in keystates.iter() {
if let Action::Submit { text: _, keys } = &state.action { match &state.action {
if let 0 = keys.len() { eprintln!("Key {} has no keysyms", name); }; Action::Submit { text: _, keys } => {
for (named_keysym, keycode) in keys.iter().zip(&state.keycodes) { if let 0 = keys.len() { eprintln!("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();
write!( write!(
buf, buf,
" "
<{}> = {};", <BackSpace> = {};",
named_keysym.0, keycodes.next().expect("Erase key has no keycode"),
keycode,
)?; )?;
} if let Some(_) = keycodes.next() {
eprintln!("BUG: Erase key has multiple keycodes");
}
},
_ => {},
} }
} }
@ -145,7 +164,9 @@ pub fn generate_keymap(
xkb_symbols \"squeekboard\" {{ xkb_symbols \"squeekboard\" {{
name[Group1] = \"Letters\"; name[Group1] = \"Letters\";
name[Group2] = \"Numbers/Symbols\";" name[Group2] = \"Numbers/Symbols\";
key <BackSpace> {{ [ BackSpace ] }};"
)?; )?;
for (name, state) in keystates.iter() { for (name, state) in keystates.iter() {

View File

@ -887,7 +887,9 @@ mod seat {
// process changes // process changes
match action { match action {
Action::Submit { text: _, keys: _ } => { Action::Submit { text: _, keys: _ }
| Action::Erase
=> {
unstick_locks(layout).apply(); unstick_locks(layout).apply();
submission.handle_release(KeyState::get_id(rckey), time); submission.handle_release(KeyState::get_id(rckey), time);
}, },

View File

@ -116,16 +116,18 @@ impl Submission {
key: &KeyState, key_id: KeyStateId, key: &KeyState, key_id: KeyStateId,
time: Timestamp, time: Timestamp,
) { ) {
let key_string = match &key.action { match &key.action {
Action::Submit { text, keys: _ } => text, Action::Submit { text: _, keys: _ }
| Action::Erase
=> (),
_ => { _ => {
eprintln!("BUG: Submitted key with action other than Submit"); eprintln!("BUG: Submitted key with action other than Submit or Erase");
return; return;
}, },
}; };
let text_was_committed = match (&mut self.imservice, key_string) { let was_committed_as_text = match (&mut self.imservice, &key.action) {
(Some(imservice), Some(text)) => { (Some(imservice), Action::Submit { text: Some(text), keys: _ }) => {
let submit_result = imservice.commit_string(text) let submit_result = imservice.commit_string(text)
.and_then(|_| imservice.commit()); .and_then(|_| imservice.commit());
match submit_result { match submit_result {
@ -133,10 +135,18 @@ impl Submission {
Err(imservice::SubmitError::NotActive) => false, Err(imservice::SubmitError::NotActive) => false,
} }
}, },
(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, (_, _) => false,
}; };
let submit_action = match text_was_committed { let submit_action = match was_committed_as_text {
true => SubmittedAction::IMService, true => SubmittedAction::IMService,
false => { false => {
self.virtual_keyboard.switch( self.virtual_keyboard.switch(