From Melchoir Franz, "osgViewer toggled the NumLock state correctly when pressing the NumLock
key, but it didn't pick up the initial state. So, if NumLock was on for the OS at startup (LED on), it was still off for OSG. And the first keypress turned the LED off, and NumLock on for OSG. The attached fix picks up the state on every FocusIn, just like it was done in the last commits for CapsLock. The difference is, that the NumLock mask isn't standardized (e.g. 0x10 for Linux, and 0x80 for AIX), so we have to do a reverse lookup (::rescanModifierMapping()). Note that I could not reproduce the problem on my system, but someone else confirmed it twice on his, and the patch fixed it for him. Changed files: ./include/osgViewer/api/X11/GraphicsWindowX11 ./src/osgViewer/GraphicsWindowX11.cpp "
This commit is contained in:
parent
01de26e678
commit
f5f29a03c1
@ -47,7 +47,8 @@ class OSGVIEWER_EXPORT GraphicsWindowX11 : public osgViewer::GraphicsWindow
|
||||
_realized(false),
|
||||
_timeOfLastCheckEvents(-1.0),
|
||||
_lastEventType(0),
|
||||
_lockMask(0)
|
||||
_modifierState(0),
|
||||
_numLockMask(0)
|
||||
{
|
||||
_traits = traits;
|
||||
memset(_keyMap, 0, 32);
|
||||
@ -164,9 +165,10 @@ class OSGVIEWER_EXPORT GraphicsWindowX11 : public osgViewer::GraphicsWindow
|
||||
void transformMouseXY(float& x, float& y);
|
||||
void adaptKey(XKeyEvent& keyevent, int& keySymbol);
|
||||
void forceKey(int key, double time, bool state);
|
||||
void rescanModifierMapping();
|
||||
void getModifierMap(char* keymap) const;
|
||||
int getModifierMask() const;
|
||||
void syncCapsLock();
|
||||
void syncLocks();
|
||||
|
||||
bool _valid;
|
||||
Display* _display;
|
||||
@ -186,7 +188,8 @@ class OSGVIEWER_EXPORT GraphicsWindowX11 : public osgViewer::GraphicsWindow
|
||||
|
||||
double _timeOfLastCheckEvents;
|
||||
int _lastEventType;
|
||||
int _lockMask;
|
||||
int _modifierState;
|
||||
int _numLockMask;
|
||||
|
||||
char _keyMap[32];
|
||||
std::map<MouseCursor,Cursor> _mouseCursorMap;
|
||||
|
@ -715,6 +715,7 @@ bool GraphicsWindowX11::createWindow()
|
||||
|
||||
XFlush( _eventDisplay );
|
||||
XSync( _eventDisplay, 0 );
|
||||
rescanModifierMapping();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1017,8 +1018,8 @@ void GraphicsWindowX11::checkEvents()
|
||||
|
||||
case EnterNotify :
|
||||
osg::notify(osg::INFO)<<"EnterNotify event received"<<std::endl;
|
||||
_lockMask = ev.xcrossing.state & LockMask;
|
||||
syncCapsLock();
|
||||
_modifierState = ev.xcrossing.state;
|
||||
syncLocks();
|
||||
break;
|
||||
|
||||
case KeymapNotify :
|
||||
@ -1031,7 +1032,7 @@ void GraphicsWindowX11::checkEvents()
|
||||
|
||||
char modMap[32];
|
||||
getModifierMap(modMap);
|
||||
syncCapsLock();
|
||||
syncLocks();
|
||||
|
||||
// release normal (non-modifier) keys
|
||||
for (unsigned int key = 8; key < 256; key++)
|
||||
@ -1062,6 +1063,11 @@ void GraphicsWindowX11::checkEvents()
|
||||
break;
|
||||
}
|
||||
|
||||
case MappingNotify :
|
||||
osg::notify(osg::INFO)<<"MappingNotify event received"<<std::endl;
|
||||
if (ev.xmapping.request == MappingModifier) rescanModifierMapping();
|
||||
break;
|
||||
|
||||
case MotionNotify :
|
||||
{
|
||||
if (firstEventTime==0) firstEventTime = ev.xmotion.time;
|
||||
@ -1177,7 +1183,7 @@ void GraphicsWindowX11::checkEvents()
|
||||
Time relativeTime = ev.xmotion.time - firstEventTime;
|
||||
eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
|
||||
|
||||
_lockMask = ev.xkey.state & LockMask;
|
||||
_modifierState = ev.xkey.state;
|
||||
keyMapSetKey(_keyMap, ev.xkey.keycode);
|
||||
int keySymbol = 0;
|
||||
adaptKey(ev.xkey, keySymbol);
|
||||
@ -1208,7 +1214,7 @@ void GraphicsWindowX11::checkEvents()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
_lockMask = ev.xkey.state & LockMask;
|
||||
_modifierState = ev.xkey.state;
|
||||
keyMapClearKey(_keyMap, ev.xkey.keycode);
|
||||
int keySymbol = 0;
|
||||
adaptKey(ev.xkey, keySymbol);
|
||||
@ -1321,7 +1327,7 @@ void GraphicsWindowX11::forceKey(int key, double time, bool state)
|
||||
event.y = 0;
|
||||
event.x_root = 0;
|
||||
event.y_root = 0;
|
||||
event.state = getModifierMask() | _lockMask;
|
||||
event.state = getModifierMask() | (_modifierState & (LockMask | _numLockMask));
|
||||
event.keycode = key;
|
||||
event.same_screen = True;
|
||||
|
||||
@ -1342,20 +1348,39 @@ void GraphicsWindowX11::forceKey(int key, double time, bool state)
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsWindowX11::syncCapsLock()
|
||||
void GraphicsWindowX11::syncLocks()
|
||||
{
|
||||
unsigned int mask = getEventQueue()->getCurrentEventState()->getModKeyMask();
|
||||
if (_lockMask)
|
||||
{
|
||||
|
||||
if (_modifierState & LockMask)
|
||||
mask |= osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask &= ~osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK;
|
||||
}
|
||||
|
||||
if (_modifierState & _numLockMask)
|
||||
mask |= osgGA::GUIEventAdapter::MODKEY_NUM_LOCK;
|
||||
else
|
||||
mask &= ~osgGA::GUIEventAdapter::MODKEY_NUM_LOCK;
|
||||
|
||||
getEventQueue()->getCurrentEventState()->setModKeyMask(mask);
|
||||
}
|
||||
|
||||
void GraphicsWindowX11::rescanModifierMapping()
|
||||
{
|
||||
XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay);
|
||||
KeyCode *m = mkm->modifiermap;
|
||||
KeyCode numlock = XKeysymToKeycode(_eventDisplay, XK_Num_Lock);
|
||||
_numLockMask = 0;
|
||||
for (int i = 0; i < mkm->max_keypermod * 8; i++, m++)
|
||||
{
|
||||
if (*m == numlock)
|
||||
{
|
||||
_numLockMask = 1 << (i / mkm->max_keypermod);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns char[32] keymap with bits for every modifier key set.
|
||||
void GraphicsWindowX11::getModifierMap(char* keymap) const
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user