Implemented X11 KeyDown/KeyUp events and reduced code duplication
authorthefiddler <stapostol@gmail.com>
Wed, 25 Dec 2013 10:46:02 +0000 (11:46 +0100)
committerthefiddler <stapostol@gmail.com>
Wed, 25 Dec 2013 10:46:02 +0000 (11:46 +0100)
Source/OpenTK/Platform/X11/X11GLNative.cs
Source/OpenTK/Platform/X11/X11Input.cs

index 1246042..eb61139 100644 (file)
@@ -59,6 +59,7 @@ namespace OpenTK.Platform.X11
 
         // Legacy input support
         X11Input driver;
+        KeyboardDevice keyboard;
         MouseDevice mouse;
 
         // Window manager hints for fullscreen windows.
@@ -119,6 +120,8 @@ namespace OpenTK.Platform.X11
         readonly byte[] ascii = new byte[16];
         readonly char[] chars = new char[16];
         readonly KeyPressEventArgs KPEventArgs = new KeyPressEventArgs('\0');
+        readonly KeyboardKeyEventArgs KeyDownEventArgs = new KeyboardKeyEventArgs();
+        readonly KeyboardKeyEventArgs KeyUpEventArgs = new KeyboardKeyEventArgs();
 
         readonly IntPtr EmptyCursor;
 
@@ -209,6 +212,7 @@ namespace OpenTK.Platform.X11
             RefreshWindowBounds(ref e);
 
             driver = new X11Input(window);
+            keyboard = driver.Keyboard[0];
             mouse = driver.Mouse[0];
 
             EmptyCursor = CreateEmptyCursor(window);
@@ -256,7 +260,7 @@ namespace OpenTK.Platform.X11
         #endregion
 
         #region Private Members
-        
+
         #region private void RegisterAtoms()
 
         /// <summary>
@@ -795,32 +799,50 @@ namespace OpenTK.Platform.X11
                         break;
 
                     case XEventName.KeyPress:
-                        driver.ProcessEvent(ref e);
-                        int status = 0;
-                        status = Functions.XLookupString(ref e.KeyEvent, ascii, ascii.Length, null, IntPtr.Zero);
-                        Encoding.Default.GetChars(ascii, 0, status, chars, 0);
-
-                        EventHandler<KeyPressEventArgs> key_press = KeyPress;
-                        if (key_press != null)
+                    case XEventName.KeyRelease:
+                        bool pressed = e.type == XEventName.KeyPress;
+                        Key key;
+                        if (driver.TranslateKey(ref e.KeyEvent, out key))
                         {
-                            for (int i = 0; i < status; i++)
+                            if (pressed)
                             {
-                                if (!Char.IsControl(chars[i]))
+                                // Raise KeyDown event
+                                KeyDownEventArgs.Key = key;
+                                KeyDownEventArgs.ScanCode = (uint)e.KeyEvent.keycode;
+                                KeyDown(this, KeyDownEventArgs);
+                            }
+                            else
+                            {
+                                // Raise KeyUp event
+                                KeyUpEventArgs.Key = key;
+                                KeyUpEventArgs.ScanCode = (uint)e.KeyEvent.keycode;
+                                KeyUp(this, KeyDownEventArgs);
+                            }
+
+                            // Update legacy GameWindow.Keyboard API:
+                            keyboard.SetKey(key, (uint)e.KeyEvent.keycode, pressed);
+
+                            if (pressed)
+                            {
+                                // Translate XKeyPress to characters and
+                                // raise KeyPress events
+                                int status = 0;
+                                status = Functions.XLookupString(
+                                    ref e.KeyEvent, ascii, ascii.Length, null, IntPtr.Zero);
+                                Encoding.Default.GetChars(ascii, 0, status, chars, 0);
+    
+                                for (int i = 0; i < status; i++)
                                 {
-                                    KPEventArgs.KeyChar = chars[i];
-                                    key_press(this, KPEventArgs);
+                                    if (!Char.IsControl(chars[i]))
+                                    {
+                                        KPEventArgs.KeyChar = chars[i];
+                                        KeyPress(this, KPEventArgs);
+                                    }
                                 }
                             }
                         }
                         break;
 
-                    case XEventName.KeyRelease:
-                        // Todo: raise KeyPress event. Use code from
-                        // http://anonsvn.mono-project.com/viewvc/trunk/mcs/class/Managed.Windows.Forms/System.Windows.Forms/X11Keyboard.cs?view=markup
-                        
-                        driver.ProcessEvent(ref e);
-                        break;
-                        
                     case XEventName.MotionNotify:
                     {
                         // Try to detect and ignore events from XWarpPointer, below.
index a9193a4..6f3bab0 100644 (file)
@@ -148,29 +148,38 @@ namespace OpenTK.Platform.X11
 #endif
         #endregion
 
+        #region TranslateKey
+
+        internal bool TranslateKey(ref XKeyEvent e, out Key key)
+        {
+            XKey keysym = (XKey)API.LookupKeysym(ref e, 0);
+            XKey keysym2 = (XKey)API.LookupKeysym(ref e, 1);
+            key = Key.Unknown;
+
+            if (keymap.ContainsKey(keysym))
+            {
+                key = keymap[keysym];
+            }
+            else if (keymap.ContainsKey(keysym2))
+            {
+                key = keymap[keysym2];
+            }
+            else
+            {
+                Debug.Print("KeyCode {0} (Keysym: {1}, {2}) not mapped.", e.keycode, (XKey)keysym, (XKey)keysym2);
+            }
+
+            return key != Key.Unknown;
+        }
+
+        #endregion
+
         #region internal void ProcessEvent(ref XEvent e)
 
         internal void ProcessEvent(ref XEvent e)
         {
             switch (e.type)
             {
-                case XEventName.KeyPress:
-                case XEventName.KeyRelease:
-                    bool pressed = e.type == XEventName.KeyPress;
-                    XKey keysym = (XKey)API.LookupKeysym(ref e.KeyEvent, 0);
-                    XKey keysym2 = (XKey)API.LookupKeysym(ref e.KeyEvent, 1);
-                    Key key = Key.Unknown;
-
-                    if (keymap.ContainsKey(keysym))
-                        key = keymap[keysym];
-                    else if (keymap.ContainsKey(keysym2))
-                        key = keymap[keysym2];
-                    else
-                        Debug.Print("KeyCode {0} (Keysym: {1}, {2}) not mapped.", e.KeyEvent.keycode, (XKey)keysym, (XKey)keysym2);
-
-                    keyboard.SetKey(key, (uint)e.KeyEvent.keycode, pressed);
-                    break;
-
                 case XEventName.ButtonPress:
                     if (e.ButtonEvent.button == 1) mouse[OpenTK.Input.MouseButton.Left] = true;
                     else if (e.ButtonEvent.button == 2) mouse[OpenTK.Input.MouseButton.Middle] = true;