diff --git a/src/keyboard.rs b/src/keyboard.rs
index cbdaa00740f7a7ae9a6f4e015c33a05cdf19a304..e1a3a32514024b6cd5657e1db0c07be1b2a1c8c6 100644
--- a/src/keyboard.rs
+++ b/src/keyboard.rs
@@ -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 {
diff --git a/src/layout.rs b/src/layout.rs
index ec601b66b384443c488a802c52c4a0a8b91e0184..ae554d5a06aa92e205a7666d2fa7e2481e90ede4 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -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 {
diff --git a/src/submission.rs b/src/submission.rs
index 9ea969b2007b9059d150911b1ae065989b579f7b..e681b2e33337a2c4c973f1ec8306ee72c24e5ee7 100644
--- a/src/submission.rs
+++ b/src/submission.rs
@@ -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,
+                };
 
-        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,
+                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,
-             * 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,
+            _ => 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())
             },
         };