layout: Improve press handling

Makes it more similar to release handling, removes some redundant checks.

This makes it easier to integrate modifiers in the future.
This commit is contained in:
Dorota Czaplejewicz
2020-02-05 12:25:46 +00:00
parent da1f480f7a
commit cb802cfb50
3 changed files with 89 additions and 44 deletions

View File

@ -46,6 +46,14 @@ impl KeyState {
} }
} }
#[must_use]
pub fn into_pressed(self) -> KeyState {
KeyState {
pressed: PressType::Pressed,
..self
}
}
/// KeyStates instances are the unique identifiers of pressed keys, /// KeyStates instances are the unique identifiers of pressed keys,
/// and the actions submitted with them. /// and the actions submitted with them.
pub fn get_id(keystate: &Rc<RefCell<KeyState>>) -> KeyStateId { pub fn get_id(keystate: &Rc<RefCell<KeyState>>) -> KeyStateId {

View File

@ -26,10 +26,10 @@ use std::vec::Vec;
use ::action::Action; use ::action::Action;
use ::drawing; use ::drawing;
use ::keyboard::{ KeyState, PressType }; use ::keyboard::KeyState;
use ::logging; use ::logging;
use ::manager; use ::manager;
use ::submission::{ Submission, Timestamp }; use ::submission::{ Submission, SubmitData, Timestamp };
use ::util::find_max_double; use ::util::find_max_double;
// Traits // Traits
@ -916,9 +916,38 @@ mod seat {
"Key {:?} was already pressed", rckey, "Key {:?} was already pressed", rckey,
); );
} }
let mut key = rckey.borrow_mut(); let key: KeyState = {
submission.handle_press(&key, KeyState::get_id(rckey), time); RefCell::borrow(rckey).clone()
key.pressed = PressType::Pressed; };
let action = key.action.clone();
match action {
Action::Submit {
text: Some(text),
keys: _,
} => submission.handle_press(
KeyState::get_id(rckey),
SubmitData::Text(&text),
&key.keycodes,
time,
),
Action::Submit {
text: None,
keys: _,
} => submission.handle_press(
KeyState::get_id(rckey),
SubmitData::Keycodes,
&key.keycodes,
time,
),
Action::Erase => submission.handle_press(
KeyState::get_id(rckey),
SubmitData::Erase,
&key.keycodes,
time,
),
_ => {},
};
RefCell::replace(rckey, key.into_pressed());
} }
pub fn handle_release_key( pub fn handle_release_key(
@ -1006,6 +1035,7 @@ mod test {
use super::*; use super::*;
use std::ffi::CString; use std::ffi::CString;
use ::keyboard::PressType;
pub fn make_state() -> Rc<RefCell<::keyboard::KeyState>> { pub fn make_state() -> Rc<RefCell<::keyboard::KeyState>> {
Rc::new(RefCell::new(::keyboard::KeyState { Rc::new(RefCell::new(::keyboard::KeyState {

View File

@ -17,11 +17,11 @@
* and those events SHOULD NOT cause any lost events. * and those events SHOULD NOT cause any lost events.
* */ * */
use ::action::Action; use std::ffi::CString;
use ::imservice; use ::imservice;
use ::imservice::IMService; use ::imservice::IMService;
use ::keyboard::{ KeyCode, KeyState, KeyStateId, PressType }; use ::keyboard::{ KeyCode, KeyStateId, PressType };
use ::logging;
use ::vkeyboard::VirtualKeyboard; use ::vkeyboard::VirtualKeyboard;
/// Gathers stuff defined in C or called by C /// Gathers stuff defined in C or called by C
@ -109,59 +109,66 @@ pub struct Submission {
pressed: Vec<(KeyStateId, SubmittedAction)>, pressed: Vec<(KeyStateId, SubmittedAction)>,
} }
pub enum SubmitData<'a> {
Text(&'a CString),
Erase,
Keycodes,
}
impl Submission { impl Submission {
/// Sends a submit text event if possible; /// Sends a submit text event if possible;
/// otherwise sends key press and makes a note of it /// otherwise sends key press and makes a note of it
pub fn handle_press( pub fn handle_press(
&mut self, &mut self,
key: &KeyState, key_id: KeyStateId, key_id: KeyStateId,
data: SubmitData,
keycodes: &Vec<KeyCode>,
time: Timestamp, time: Timestamp,
) { ) {
match &key.action { let was_committed_as_text = match &mut self.imservice {
Action::Submit { text: _, keys: _ } Some(imservice) => {
| Action::Erase enum Outcome {
=> (), Submitted(Result<(), imservice::SubmitError>),
_ => { NotSubmitted,
log_print!( };
logging::Level::Bug,
"Submitted key with action other than Submit or Erase", let submit_outcome = match data {
); SubmitData::Text(text) => {
return; Outcome::Submitted(imservice.commit_string(text))
},
SubmitData::Erase => {
/* Delete_surrounding_text takes byte offsets,
* so cannot work without get_surrounding_text.
* This is a bug in the protocol.
*/
// imservice.delete_surrounding_text(1, 0),
Outcome::NotSubmitted
},
SubmitData::Keycodes => Outcome::NotSubmitted,
};
match submit_outcome {
Outcome::Submitted(result) => {
match result.and_then(|()| imservice.commit()) {
Ok(()) => true,
Err(imservice::SubmitError::NotActive) => false,
}
},
Outcome::NotSubmitted => false,
}
}, },
_ => false,
}; };
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 { let submit_action = match was_committed_as_text {
true => SubmittedAction::IMService, true => SubmittedAction::IMService,
false => { false => {
self.virtual_keyboard.switch( self.virtual_keyboard.switch(
&key.keycodes, keycodes,
PressType::Pressed, PressType::Pressed,
time, time,
); );
SubmittedAction::VirtualKeyboard(key.keycodes.clone()) SubmittedAction::VirtualKeyboard(keycodes.clone())
}, },
}; };