diff --git a/src/Input/input.cxx b/src/Input/input.cxx
index ca38a2d37..704b25be8 100644
--- a/src/Input/input.cxx
+++ b/src/Input/input.cxx
@@ -108,7 +108,8 @@ getModAlt ()
 ////////////////////////////////////////////////////////////////////////
 
 
-FGInput::FGInput ()
+FGInput::FGInput () :
+    _key_event(fgGetNode("/devices/status/keyboard/event", true))
 {
     if (default_input == 0)
         default_input = this;
@@ -150,6 +151,13 @@ FGInput::bind ()
   fgTie("/devices/status/keyboard/shift", getModShift);
   fgTie("/devices/status/keyboard/ctrl", getModCtrl);
   fgTie("/devices/status/keyboard/alt", getModAlt);
+
+  _key_event->tie("key", SGRawValuePointer<int>(&_key_code));
+  _key_event->tie("pressed", SGRawValuePointer<bool>(&_key_pressed));
+  _key_event->tie("modifier", SGRawValuePointer<int>(&_key_modifiers));
+  _key_event->tie("modifier/shift", SGRawValuePointer<bool>(&_key_shift));
+  _key_event->tie("modifier/ctrl", SGRawValuePointer<bool>(&_key_ctrl));
+  _key_event->tie("modifier/alt", SGRawValuePointer<bool>(&_key_alt));
 }
 
 void
@@ -158,6 +166,13 @@ FGInput::unbind ()
   fgUntie("/devices/status/keyboard/shift");
   fgUntie("/devices/status/keyboard/ctrl");
   fgUntie("/devices/status/keyboard/alt");
+
+  _key_event->untie("key");
+  _key_event->untie("pressed");
+  _key_event->untie("modifier");
+  _key_event->untie("modifier/shift");
+  _key_event->untie("modifier/ctrl");
+  _key_event->untie("modifier/alt");
 }
 
 void 
@@ -204,6 +219,16 @@ FGInput::doKey (int k, int modifiers, int x, int y)
     return;
   }
 
+  _key_code = k;
+  _key_modifiers = modifiers & ~KEYMOD_RELEASED;
+  _key_pressed = bool(!(modifiers & KEYMOD_RELEASED));
+  _key_shift = bool(modifiers & KEYMOD_SHIFT);
+  _key_ctrl = bool(modifiers & KEYMOD_CTRL);
+  _key_alt = bool(modifiers & KEYMOD_ALT);
+  _key_event->fireValueChanged();
+  if (!_key_code)
+      return;
+
   button &b = _key_bindings[k];
 
                                 // Key pressed.
@@ -227,23 +252,6 @@ FGInput::doKey (int k, int modifiers, int x, int y)
       for (unsigned int i = 0; i < bindings.size(); i++)
         bindings[i]->fire();
       b.last_state = 0;
-    } else {
-      if (k >= 1 && k <= 26) {
-        if (_key_bindings[k + '@'].last_state)
-          doKey(k + '@', KEYMOD_RELEASED, x, y);
-        if (_key_bindings[k + '`'].last_state)
-          doKey(k + '`', KEYMOD_RELEASED, x, y);
-      } else if (k >= 'A' && k <= 'Z') {
-        if (_key_bindings[k - '@'].last_state)
-          doKey(k - '@', KEYMOD_RELEASED, x, y);
-        if (_key_bindings[tolower(k)].last_state)
-          doKey(tolower(k), KEYMOD_RELEASED, x, y);
-      } else if (k >= 'a' && k <= 'z') {
-        if (_key_bindings[k - '`'].last_state)
-          doKey(k - '`', KEYMOD_RELEASED, x, y);
-        if (_key_bindings[toupper(k)].last_state)
-          doKey(toupper(k), KEYMOD_RELEASED, x, y);
-      }
     }
   }
 }
diff --git a/src/Input/input.hxx b/src/Input/input.hxx
index a9dd5303f..3b3803e9f 100644
--- a/src/Input/input.hxx
+++ b/src/Input/input.hxx
@@ -328,6 +328,17 @@ private:
    * List of currently pressed mouse button events
    */
   std::map<int, std::list<SGSharedPtr<SGPickCallback> > > _activePickCallbacks;
+
+  /**
+   * Key listener interface.
+   */
+  SGPropertyNode_ptr _key_event;
+  int  _key_code;
+  int  _key_modifiers;
+  bool _key_pressed;
+  bool _key_ctrl;
+  bool _key_alt;
+  bool _key_shift;
 };
 
 #endif // _INPUT_HXX
diff --git a/src/Main/FGManipulator.cxx b/src/Main/FGManipulator.cxx
index 058641981..bf6935de4 100644
--- a/src/Main/FGManipulator.cxx
+++ b/src/Main/FGManipulator.cxx
@@ -276,5 +276,24 @@ void FGManipulator::handleKey(const osgGA::GUIEventAdapter& ea, int& key,
     currentModifiers = modifiers;
     if (eventType == osgGA::GUIEventAdapter::KEYUP)
 	modifiers |= KEYMOD_RELEASED;
+
+    // Release the letter key, for which the keypress was reported
+    if (key >= 0 && key < int(sizeof(release_keys))) {
+        if (modifiers & KEYMOD_RELEASED) {
+            key = release_keys[key];
+        } else {
+            release_keys[key] = key;
+            if (key >= 1 && key <= 26) {
+                release_keys[key + '@'] = key;
+                release_keys[key + '`'] = key;
+            } else if (key >= 'A' && key <= 'Z') {
+                release_keys[key - '@'] = key;
+                release_keys[tolower(key)] = key;
+            } else if (key >= 'a' && key <= 'z') {
+                release_keys[key - '`'] = key;
+                release_keys[toupper(key)] = key;
+            }
+        }
+    }
 }
 
diff --git a/src/Main/FGManipulator.hxx b/src/Main/FGManipulator.hxx
index 4ad190d19..edfcd9f3d 100644
--- a/src/Main/FGManipulator.hxx
+++ b/src/Main/FGManipulator.hxx
@@ -139,5 +139,6 @@ protected:
     bool mouseWarped;
     // workaround for osgViewer double scroll events
     bool scrollButtonPressed;
+    int release_keys[128];
 };
 #endif
diff --git a/src/Main/fg_os.cxx b/src/Main/fg_os.cxx
index a9fcf86c9..acff231dc 100644
--- a/src/Main/fg_os.cxx
+++ b/src/Main/fg_os.cxx
@@ -105,15 +105,28 @@ static void GLUTspecialkey(int k, int x, int y)
     callKeyHandler(256 + k, fgGetKeyModifiers(), x, y);
 }
 
+static unsigned char release_keys[256];
+
 static void GLUTkeyup(unsigned char k, int x, int y)
 {
     GlutModifiers = glutGetModifiers();
-    callKeyHandler(k, fgGetKeyModifiers() | KEYMOD_RELEASED, x, y);
+    callKeyHandler(release_keys[k], fgGetKeyModifiers() | KEYMOD_RELEASED, x, y);
 }
 
 static void GLUTkey(unsigned char k, int x, int y)
 {
     GlutModifiers = glutGetModifiers();
+    release_keys[k] = k;
+    if (k >= 1 && k <= 26) {
+        release_keys[k + '@'] = k;
+        release_keys[k + '`'] = k;
+    } else if (k >= 'A' && k <= 'Z') {
+        release_keys[k - '@'] = k;
+        release_keys[tolower(k)] = k;
+    } else if (k >= 'a' && k <= 'z') {
+        release_keys[k - '`'] = k;
+        release_keys[toupper(k)] = k;
+    }
     callKeyHandler(k, fgGetKeyModifiers(), x, y);
 }
 
diff --git a/src/Main/fg_os_sdl.cxx b/src/Main/fg_os_sdl.cxx
index 791783207..81f2e4c5a 100644
--- a/src/Main/fg_os_sdl.cxx
+++ b/src/Main/fg_os_sdl.cxx
@@ -184,10 +184,8 @@ static void handleKey(int key, int raw, int keyup)
 
     if(modmask == 0 && KeyHandler) {
         if (keymod & KEYMOD_RELEASED) {
-            if (keys[raw].mod) {
-                key = keys[raw].unicode;
-                keys[raw].mod = 0;
-            }
+            key = keys[raw].unicode;
+
         } else {
             keys[raw].mod = keymod;
             keys[raw].unicode = key;