input_method: Use for erasing
This commit is contained in:
@ -45,7 +45,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: "erase"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "special"
|
||||
|
||||
@ -45,7 +45,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: "erase"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "special"
|
||||
|
||||
@ -46,7 +46,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: "erase"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "altline"
|
||||
|
||||
@ -44,7 +44,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: "erase"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "default"
|
||||
|
||||
@ -39,7 +39,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: "erase"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "altline"
|
||||
|
||||
@ -46,7 +46,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: "erase"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "default"
|
||||
|
||||
@ -195,7 +195,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "wide"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: erase
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
|
||||
@ -195,7 +195,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "wide"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: erase
|
||||
Return:
|
||||
outline: "wide"
|
||||
icon: "key-enter"
|
||||
|
||||
@ -39,7 +39,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: erase
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "altline"
|
||||
|
||||
@ -16,7 +16,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: erase
|
||||
space:
|
||||
outline: spaceline
|
||||
text: " "
|
||||
|
||||
@ -39,7 +39,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: erase
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "altline"
|
||||
|
||||
@ -45,7 +45,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: erase
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "special"
|
||||
|
||||
@ -39,9 +39,9 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: erase
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
action: show_prefs
|
||||
outline: "special"
|
||||
icon: "keyboard-mode-symbolic"
|
||||
show_numbers:
|
||||
|
||||
@ -39,7 +39,7 @@ buttons:
|
||||
BackSpace:
|
||||
outline: "altline"
|
||||
icon: "edit-clear-symbolic"
|
||||
keysym: "BackSpace"
|
||||
action: "erase"
|
||||
preferences:
|
||||
action: "show_prefs"
|
||||
outline: "special"
|
||||
|
||||
@ -37,5 +37,7 @@ pub enum Action {
|
||||
/// The key events this symbol submits when submitting text is not possible
|
||||
keys: Vec<KeySym>,
|
||||
},
|
||||
/// Erase a position behind the cursor
|
||||
Erase,
|
||||
ShowPreferences,
|
||||
}
|
||||
|
||||
11
src/data.rs
11
src/data.rs
@ -15,6 +15,7 @@ use std::vec::Vec;
|
||||
|
||||
use xkbcommon::xkb;
|
||||
|
||||
use ::action;
|
||||
use ::keyboard::{
|
||||
KeyState, PressType,
|
||||
generate_keymap, generate_keycodes, FormattingError
|
||||
@ -259,6 +260,9 @@ enum Action {
|
||||
SetView(String),
|
||||
#[serde(rename="show_prefs")]
|
||||
ShowPrefs,
|
||||
/// Remove last character
|
||||
#[serde(rename="erase")]
|
||||
Erase,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq)]
|
||||
@ -381,6 +385,10 @@ impl Layout {
|
||||
)
|
||||
}).collect()
|
||||
},
|
||||
action::Action::Erase => vec![
|
||||
*keymap.get("BackSpace")
|
||||
.expect(&format!("BackSpace missing from keymap")),
|
||||
],
|
||||
_ => Vec::new(),
|
||||
};
|
||||
(
|
||||
@ -547,6 +555,7 @@ fn create_action<H: WarningHandler>(
|
||||
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(
|
||||
@ -581,7 +590,7 @@ fn create_action<H: WarningHandler>(
|
||||
false => format!("U{:04X}", codepoint as u32),
|
||||
})
|
||||
}).collect(),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
@ -35,6 +35,7 @@ pub mod c {
|
||||
#[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);
|
||||
@ -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> {
|
||||
match self.current.active {
|
||||
true => {
|
||||
|
||||
@ -79,9 +79,10 @@ 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())
|
||||
sorted(key_names.into_iter().chain(special_keysyms))
|
||||
.map(|name| String::from(name))
|
||||
.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(
|
||||
keystates: &HashMap::<String, KeyState>
|
||||
) -> Result<String, FormattingError> {
|
||||
@ -123,17 +127,32 @@ pub fn generate_keymap(
|
||||
)?;
|
||||
|
||||
for (name, state) in keystates.iter() {
|
||||
if let Action::Submit { text: _, keys } = &state.action {
|
||||
if let 0 = keys.len() { eprintln!("Key {} has no keysyms", name); };
|
||||
for (named_keysym, keycode) in keys.iter().zip(&state.keycodes) {
|
||||
match &state.action {
|
||||
Action::Submit { text: _, keys } => {
|
||||
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!(
|
||||
buf,
|
||||
"
|
||||
<{}> = {};",
|
||||
named_keysym.0,
|
||||
keycode,
|
||||
<BackSpace> = {};",
|
||||
keycodes.next().expect("Erase key has no keycode"),
|
||||
)?;
|
||||
}
|
||||
if let Some(_) = keycodes.next() {
|
||||
eprintln!("BUG: Erase key has multiple keycodes");
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,7 +164,9 @@ pub fn generate_keymap(
|
||||
xkb_symbols \"squeekboard\" {{
|
||||
|
||||
name[Group1] = \"Letters\";
|
||||
name[Group2] = \"Numbers/Symbols\";"
|
||||
name[Group2] = \"Numbers/Symbols\";
|
||||
|
||||
key <BackSpace> {{ [ BackSpace ] }};"
|
||||
)?;
|
||||
|
||||
for (name, state) in keystates.iter() {
|
||||
|
||||
@ -887,7 +887,9 @@ mod seat {
|
||||
|
||||
// process changes
|
||||
match action {
|
||||
Action::Submit { text: _, keys: _ } => {
|
||||
Action::Submit { text: _, keys: _ }
|
||||
| Action::Erase
|
||||
=> {
|
||||
unstick_locks(layout).apply();
|
||||
submission.handle_release(KeyState::get_id(rckey), time);
|
||||
},
|
||||
|
||||
@ -116,16 +116,18 @@ impl Submission {
|
||||
key: &KeyState, key_id: KeyStateId,
|
||||
time: Timestamp,
|
||||
) {
|
||||
let key_string = match &key.action {
|
||||
Action::Submit { text, keys: _ } => text,
|
||||
match &key.action {
|
||||
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;
|
||||
},
|
||||
};
|
||||
|
||||
let text_was_committed = match (&mut self.imservice, key_string) {
|
||||
(Some(imservice), Some(text)) => {
|
||||
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 {
|
||||
@ -133,10 +135,18 @@ impl Submission {
|
||||
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,
|
||||
};
|
||||
|
||||
let submit_action = match text_was_committed {
|
||||
let submit_action = match was_committed_as_text {
|
||||
true => SubmittedAction::IMService,
|
||||
false => {
|
||||
self.virtual_keyboard.switch(
|
||||
|
||||
Reference in New Issue
Block a user