diff --git a/include/osgViewer/api/X11/GraphicsWindowX11 b/include/osgViewer/api/X11/GraphicsWindowX11 index 6c3e69555..c4015af86 100644 --- a/include/osgViewer/api/X11/GraphicsWindowX11 +++ b/include/osgViewer/api/X11/GraphicsWindowX11 @@ -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 _mouseCursorMap; diff --git a/src/osgViewer/GraphicsWindowX11.cpp b/src/osgViewer/GraphicsWindowX11.cpp index 46e418874..34d462c31 100644 --- a/src/osgViewer/GraphicsWindowX11.cpp +++ b/src/osgViewer/GraphicsWindowX11.cpp @@ -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"<(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 {