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