At the moment there's no guarantee that for a key that triggered a key-press
event before there will ever be the matching key-release event later. This
is a problem for applications like FlightGear: here pressing the b-key, for
example, applies the brakes on the landing gear until the key is reported
released. If there's never a release, then the brakes remain stuck, until
one pressed/released b again. But how could the release event possibly get
lost? Consider this:

  1.  b down       -> 'b' press event
  2.  Shift down   -> shift modifier set
  3.  b up         -> 'B' release event  (but 'B' was never reported pressed!)
  4.  Shift up     -> shift modifier unset


Well, letters aren't really a *big* problem. We hack around that by checking
for an a-release if maybe 'A' or Ctrl-a was reported pressed before, or for
an A-release if maybe 'a' or Ctrl-a ... etc.


But what about this case:

  1. \ down         -> '\' press event
  2. Shift down
  3. \ up           -> '|' release event --  '\' remains stuck!!
  4. Shift up

We can't hack around that, because it depends on the keyboard layout whether
\ and | are on the same key. This information is lost for the OSG client and
can't be retrieved in a cross-platform way. That's OSG's job.


One way to fix that would be to store all reported symbols for press events per
physical key, and to make sure that the same symbol will be reported for the
release, even if that means to inject an artificial release. This works here
in my local build. (The attached patch is not meant to be applied -- I'd make
some more cleanup before. All usage of _keyMap could then be removed, too.)

Any comments on that? Windows and Mac maintainers would have to implement the
same solution, which is the main reason for the RFC. Otherwise I would just
have submitted the patch. And I can only remove the hack in FlightGear, once
all platforms work correctly.

(Should EventTime for the generated release event differ from the press event,
e.g. by subtracting a very small time?)

m.
Index: include/osgViewer/api/X11/GraphicsWindowX11
===================================================================
--- include/osgViewer/api/X11/GraphicsWindowX11	(revision 10305)
+++ include/osgViewer/api/X11/GraphicsWindowX11	(working copy)
@@ -52,6 +52,8 @@
         {
             _traits = traits;
             memset(_keyMap, 0, 32);
+            for (int i = 0; i < sizeof(_lastKey) / sizeof(int); i++)
+                _lastKey[i] = -1;
 
             init();
             
@@ -195,6 +197,7 @@
         int             _modifierState;
         int             _numLockMask;
 
+        int             _lastKey[256];
         char            _keyMap[32];
         std::map<MouseCursor,Cursor> _mouseCursorMap;
 };
Index: src/osgViewer/GraphicsWindowX11.cpp
===================================================================
--- src/osgViewer/GraphicsWindowX11.cpp	(revision 10305)
+++ src/osgViewer/GraphicsWindowX11.cpp	(working copy)
@@ -1246,10 +1246,16 @@
                 eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
 
                 _modifierState = ev.xkey.state;
-                keyMapSetKey(_keyMap, ev.xkey.keycode);
                 int keySymbol = 0;
                 adaptKey(ev.xkey, keySymbol);
 
+                int lastKey = _lastKey[ev.xkey.keycode];
+                if (lastKey != -1 && lastKey != keySymbol)
+                    getEventQueue()->keyRelease(lastKey, eventTime);
+
+                _lastKey[ev.xkey.keycode] = keySymbol;
+
+                keyMapSetKey(_keyMap, ev.xkey.keycode);
                 getEventQueue()->keyPress(keySymbol, eventTime);
                 break;
             }
@@ -1280,6 +1286,11 @@
                 keyMapClearKey(_keyMap, ev.xkey.keycode);
                 int keySymbol = 0;
                 adaptKey(ev.xkey, keySymbol);
+
+                if (_lastKey[ev.xkey.keycode] != -1) {
+                    keySymbol = _lastKey[ev.xkey.keycode];
+                    _lastKey[ev.xkey.keycode] = -1;
+                }
                 
                 getEventQueue()->keyRelease(keySymbol, eventTime);
                 break;
_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to