From Melchior Franz, "In KDE I switch desktops with Super-Tab, and occasionally I

get an excess Tab key report when switching back to an OSG
application (usually FlightGear :-). Although KDE has consumed
the Tab, it's sometimes still in the XKeymapEvent's key_vector,
and followed by a Tab KeyRelease event.

Avoid this artifact by
- asking for a "fresh" keymap (via XQueryKeymap()), rather than
 using the unreliable(?) XKeymapEvent's key_vector, and by
- flushing all key events on focus-in (to avoid the KeyRelease)

After Super-press, Tab-press, Super-release, Tab-release (note
the wrong release order!) I still get an extra Tab event. But
this is not surprising and not exactly wrong either. Also it's
hard to avoid, as we can't see what happened to the keyboard
before we regained focus.

Files changed:
 src/osgViewer/GraphicsWindowX11.cpp
 include/osgViewer/api/X11/GraphicsWindowX11"
This commit is contained in:
Robert Osfield 2008-05-08 16:45:59 +00:00
parent 4345382316
commit 9e6c3a7628
2 changed files with 15 additions and 3 deletions

View File

@ -169,6 +169,7 @@ class OSGVIEWER_EXPORT GraphicsWindowX11 : public osgViewer::GraphicsWindow
void getModifierMap(char* keymap) const; void getModifierMap(char* keymap) const;
int getModifierMask() const; int getModifierMask() const;
void syncLocks(); void syncLocks();
void flushKeyEvents();
bool _valid; bool _valid;
Display* _display; Display* _display;

View File

@ -993,6 +993,7 @@ void GraphicsWindowX11::checkEvents()
case FocusIn : case FocusIn :
osg::notify(osg::INFO)<<"FocusIn event received"<<std::endl; osg::notify(osg::INFO)<<"FocusIn event received"<<std::endl;
flushKeyEvents();
break; break;
case UnmapNotify : case UnmapNotify :
@ -1038,12 +1039,15 @@ void GraphicsWindowX11::checkEvents()
getModifierMap(modMap); getModifierMap(modMap);
syncLocks(); syncLocks();
char keyMap[32];
XQueryKeymap(_eventDisplay, keyMap);
// release normal (non-modifier) keys // release normal (non-modifier) keys
for (unsigned int key = 8; key < 256; key++) for (unsigned int key = 8; key < 256; key++)
{ {
bool isModifier = keyMapGetKey(modMap, key); bool isModifier = keyMapGetKey(modMap, key);
if (isModifier) continue; if (isModifier) continue;
bool isPressed = keyMapGetKey(ev.xkeymap.key_vector, key); bool isPressed = keyMapGetKey(keyMap, key);
if (!isPressed) forceKey(key, eventTime, false); if (!isPressed) forceKey(key, eventTime, false);
} }
@ -1052,7 +1056,7 @@ void GraphicsWindowX11::checkEvents()
{ {
bool isModifier = keyMapGetKey(modMap, key); bool isModifier = keyMapGetKey(modMap, key);
if (!isModifier) continue; if (!isModifier) continue;
bool isPressed = keyMapGetKey(ev.xkeymap.key_vector, key); bool isPressed = keyMapGetKey(keyMap, key);
forceKey(key, eventTime, isPressed); forceKey(key, eventTime, isPressed);
} }
@ -1061,7 +1065,7 @@ void GraphicsWindowX11::checkEvents()
{ {
bool isModifier = keyMapGetKey(modMap, key); bool isModifier = keyMapGetKey(modMap, key);
if (isModifier) continue; if (isModifier) continue;
bool isPressed = keyMapGetKey(ev.xkeymap.key_vector, key); bool isPressed = keyMapGetKey(keyMap, key);
if (isPressed) forceKey(key, eventTime, true); if (isPressed) forceKey(key, eventTime, true);
} }
break; break;
@ -1385,6 +1389,13 @@ void GraphicsWindowX11::rescanModifierMapping()
} }
} }
void GraphicsWindowX11::flushKeyEvents()
{
XEvent e;
while (XCheckMaskEvent(_eventDisplay, KeyPressMask|KeyReleaseMask, &e))
continue;
}
// Returns char[32] keymap with bits for every modifier key set. // Returns char[32] keymap with bits for every modifier key set.
void GraphicsWindowX11::getModifierMap(char* keymap) const void GraphicsWindowX11::getModifierMap(char* keymap) const
{ {