From 4d27b6ee558897e3861a519553fcc3b8da9b32ea Mon Sep 17 00:00:00 2001 From: thefiddler <stapostol@gmail.com> Date: Wed, 25 Dec 2013 11:46:02 +0100 Subject: [PATCH] Implemented X11 KeyDown/KeyUp events and reduced code duplication --- Source/OpenTK/Platform/X11/X11GLNative.cs | 60 ++++++++++++++++------- Source/OpenTK/Platform/X11/X11Input.cs | 43 +++++++++------- 2 files changed, 67 insertions(+), 36 deletions(-) diff --git a/Source/OpenTK/Platform/X11/X11GLNative.cs b/Source/OpenTK/Platform/X11/X11GLNative.cs index 12460425..eb611394 100644 --- a/Source/OpenTK/Platform/X11/X11GLNative.cs +++ b/Source/OpenTK/Platform/X11/X11GLNative.cs @@ -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. diff --git a/Source/OpenTK/Platform/X11/X11Input.cs b/Source/OpenTK/Platform/X11/X11Input.cs index a9193a40..6f3bab0b 100644 --- a/Source/OpenTK/Platform/X11/X11Input.cs +++ b/Source/OpenTK/Platform/X11/X11Input.cs @@ -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;