Implemented X11 KeyDown/KeyUp events and reduced code duplication

This commit is contained in:
thefiddler 2013-12-25 11:46:02 +01:00
parent ffdf881cea
commit 4d27b6ee55
2 changed files with 67 additions and 36 deletions

View file

@ -59,6 +59,7 @@ namespace OpenTK.Platform.X11
// Legacy input support // Legacy input support
X11Input driver; X11Input driver;
KeyboardDevice keyboard;
MouseDevice mouse; MouseDevice mouse;
// Window manager hints for fullscreen windows. // Window manager hints for fullscreen windows.
@ -119,6 +120,8 @@ namespace OpenTK.Platform.X11
readonly byte[] ascii = new byte[16]; readonly byte[] ascii = new byte[16];
readonly char[] chars = new char[16]; readonly char[] chars = new char[16];
readonly KeyPressEventArgs KPEventArgs = new KeyPressEventArgs('\0'); readonly KeyPressEventArgs KPEventArgs = new KeyPressEventArgs('\0');
readonly KeyboardKeyEventArgs KeyDownEventArgs = new KeyboardKeyEventArgs();
readonly KeyboardKeyEventArgs KeyUpEventArgs = new KeyboardKeyEventArgs();
readonly IntPtr EmptyCursor; readonly IntPtr EmptyCursor;
@ -209,6 +212,7 @@ namespace OpenTK.Platform.X11
RefreshWindowBounds(ref e); RefreshWindowBounds(ref e);
driver = new X11Input(window); driver = new X11Input(window);
keyboard = driver.Keyboard[0];
mouse = driver.Mouse[0]; mouse = driver.Mouse[0];
EmptyCursor = CreateEmptyCursor(window); EmptyCursor = CreateEmptyCursor(window);
@ -256,7 +260,7 @@ namespace OpenTK.Platform.X11
#endregion #endregion
#region Private Members #region Private Members
#region private void RegisterAtoms() #region private void RegisterAtoms()
/// <summary> /// <summary>
@ -795,32 +799,50 @@ namespace OpenTK.Platform.X11
break; break;
case XEventName.KeyPress: case XEventName.KeyPress:
driver.ProcessEvent(ref e); case XEventName.KeyRelease:
int status = 0; bool pressed = e.type == XEventName.KeyPress;
status = Functions.XLookupString(ref e.KeyEvent, ascii, ascii.Length, null, IntPtr.Zero); Key key;
Encoding.Default.GetChars(ascii, 0, status, chars, 0); if (driver.TranslateKey(ref e.KeyEvent, out key))
EventHandler<KeyPressEventArgs> key_press = KeyPress;
if (key_press != null)
{ {
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]; if (!Char.IsControl(chars[i]))
key_press(this, KPEventArgs); {
KPEventArgs.KeyChar = chars[i];
KeyPress(this, KPEventArgs);
}
} }
} }
} }
break; 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: case XEventName.MotionNotify:
{ {
// Try to detect and ignore events from XWarpPointer, below. // Try to detect and ignore events from XWarpPointer, below.

View file

@ -148,29 +148,38 @@ namespace OpenTK.Platform.X11
#endif #endif
#endregion #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) #region internal void ProcessEvent(ref XEvent e)
internal void ProcessEvent(ref XEvent e) internal void ProcessEvent(ref XEvent e)
{ {
switch (e.type) 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: case XEventName.ButtonPress:
if (e.ButtonEvent.button == 1) mouse[OpenTK.Input.MouseButton.Left] = true; if (e.ButtonEvent.button == 1) mouse[OpenTK.Input.MouseButton.Left] = true;
else if (e.ButtonEvent.button == 2) mouse[OpenTK.Input.MouseButton.Middle] = true; else if (e.ButtonEvent.button == 2) mouse[OpenTK.Input.MouseButton.Middle] = true;