Merge branch 'press' into 'master'
layout: Improve press handling See merge request Librem5/squeekboard!330
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,
 | 
			
		||||
    /// and the actions submitted with them.
 | 
			
		||||
    pub fn get_id(keystate: &Rc<RefCell<KeyState>>) -> KeyStateId {
 | 
			
		||||
 | 
			
		||||
@ -26,10 +26,10 @@ use std::vec::Vec;
 | 
			
		||||
 | 
			
		||||
use ::action::Action;
 | 
			
		||||
use ::drawing;
 | 
			
		||||
use ::keyboard::{ KeyState, PressType };
 | 
			
		||||
use ::keyboard::KeyState;
 | 
			
		||||
use ::logging;
 | 
			
		||||
use ::manager;
 | 
			
		||||
use ::submission::{ Submission, Timestamp };
 | 
			
		||||
use ::submission::{ Submission, SubmitData, Timestamp };
 | 
			
		||||
use ::util::find_max_double;
 | 
			
		||||
 | 
			
		||||
// Traits
 | 
			
		||||
@ -916,9 +916,38 @@ mod seat {
 | 
			
		||||
                "Key {:?} was already pressed", rckey,
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        let mut key = rckey.borrow_mut();
 | 
			
		||||
        submission.handle_press(&key, KeyState::get_id(rckey), time);
 | 
			
		||||
        key.pressed = PressType::Pressed;
 | 
			
		||||
        let key: KeyState = {
 | 
			
		||||
            RefCell::borrow(rckey).clone()
 | 
			
		||||
        };
 | 
			
		||||
        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(
 | 
			
		||||
@ -1006,6 +1035,7 @@ mod test {
 | 
			
		||||
    use super::*;
 | 
			
		||||
 | 
			
		||||
    use std::ffi::CString;
 | 
			
		||||
    use ::keyboard::PressType;
 | 
			
		||||
 | 
			
		||||
    pub fn make_state() -> Rc<RefCell<::keyboard::KeyState>> {
 | 
			
		||||
        Rc::new(RefCell::new(::keyboard::KeyState {
 | 
			
		||||
 | 
			
		||||
@ -17,11 +17,11 @@
 | 
			
		||||
 * and those events SHOULD NOT cause any lost events.
 | 
			
		||||
 * */
 | 
			
		||||
 
 | 
			
		||||
use ::action::Action;
 | 
			
		||||
use std::ffi::CString;
 | 
			
		||||
 
 | 
			
		||||
use ::imservice;
 | 
			
		||||
use ::imservice::IMService;
 | 
			
		||||
use ::keyboard::{ KeyCode, KeyState, KeyStateId, PressType };
 | 
			
		||||
use ::logging;
 | 
			
		||||
use ::keyboard::{ KeyCode, KeyStateId, PressType };
 | 
			
		||||
use ::vkeyboard::VirtualKeyboard;
 | 
			
		||||
 | 
			
		||||
/// Gathers stuff defined in C or called by C
 | 
			
		||||
@ -109,59 +109,66 @@ pub struct Submission {
 | 
			
		||||
    pressed: Vec<(KeyStateId, SubmittedAction)>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub enum SubmitData<'a> {
 | 
			
		||||
    Text(&'a CString),
 | 
			
		||||
    Erase,
 | 
			
		||||
    Keycodes,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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,
 | 
			
		||||
        key_id: KeyStateId,
 | 
			
		||||
        data: SubmitData,
 | 
			
		||||
        keycodes: &Vec<KeyCode>,
 | 
			
		||||
        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 {
 | 
			
		||||
            Some(imservice) => {
 | 
			
		||||
                enum Outcome {
 | 
			
		||||
                    Submitted(Result<(), imservice::SubmitError>),
 | 
			
		||||
                    NotSubmitted,
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                let submit_outcome = match data {
 | 
			
		||||
                    SubmitData::Text(text) => {
 | 
			
		||||
                        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 {
 | 
			
		||||
            true => SubmittedAction::IMService,
 | 
			
		||||
            false => {
 | 
			
		||||
                self.virtual_keyboard.switch(
 | 
			
		||||
                    &key.keycodes,
 | 
			
		||||
                    keycodes,
 | 
			
		||||
                    PressType::Pressed,
 | 
			
		||||
                    time,
 | 
			
		||||
                );
 | 
			
		||||
                SubmittedAction::VirtualKeyboard(key.keycodes.clone())
 | 
			
		||||
                SubmittedAction::VirtualKeyboard(keycodes.clone())
 | 
			
		||||
            },
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user