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:
@ -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 {
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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",
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let was_committed_as_text = match (&mut self.imservice, &key.action) {
|
let submit_outcome = match data {
|
||||||
(Some(imservice), Action::Submit { text: Some(text), keys: _ }) => {
|
SubmitData::Text(text) => {
|
||||||
let submit_result = imservice.commit_string(text)
|
Outcome::Submitted(imservice.commit_string(text))
|
||||||
.and_then(|_| imservice.commit());
|
},
|
||||||
match submit_result {
|
SubmitData::Erase => {
|
||||||
Ok(()) => true,
|
/* Delete_surrounding_text takes byte offsets,
|
||||||
Err(imservice::SubmitError::NotActive) => false,
|
* 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,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/* Delete_surrounding_text takes byte offsets,
|
_ => false,
|
||||||
* 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())
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user