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
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.

View 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;