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

m.
Index: include/osgViewer/api/X11/GraphicsWindowX11
===================================================================
--- include/osgViewer/api/X11/GraphicsWindowX11	(revision 7974)
+++ include/osgViewer/api/X11/GraphicsWindowX11	(working copy)
@@ -47,7 +47,8 @@
             _realized(false),
             _timeOfLastCheckEvents(-1.0),
             _lastEventType(0),
-            _lockMask(0)
+            _modifierState(0),
+            _numLockMask(0)
         {
             _traits = traits;
             memset(_keyMap, 0, 32);
@@ -164,9 +165,10 @@
         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 @@
 
         double          _timeOfLastCheckEvents;
         int             _lastEventType;
-        int             _lockMask;
+        int             _modifierState;
+        int             _numLockMask;
 
         char            _keyMap[32];
         std::map<MouseCursor,Cursor> _mouseCursorMap;
Index: src/osgViewer/GraphicsWindowX11.cpp
===================================================================
--- src/osgViewer/GraphicsWindowX11.cpp	(revision 7974)
+++ src/osgViewer/GraphicsWindowX11.cpp	(working copy)
@@ -715,6 +715,7 @@
 
     XFlush( _eventDisplay );
     XSync( _eventDisplay, 0 );
+    rescanModifierMapping();
 
     return true;
 }
@@ -1017,8 +1018,8 @@
 
             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 @@
 
                 char modMap[32];
                 getModifierMap(modMap);
-                syncCapsLock();
+                syncLocks();
 
                 // release normal (non-modifier) keys
                 for (unsigned int key = 8; key < 256; key++)
@@ -1062,6 +1063,11 @@
                 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 @@
                 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 @@
                     }
                 }
 #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 @@
     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::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
 {

Attachment: x11numlock.tar.gz
Description: application/tgz

_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Reply via email to