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",
 | 
					                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())
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user