Index: Source/OpenTK/Platform/Windows/WinGLNative.cs
===================================================================
--- Source/OpenTK/Platform/Windows/WinGLNative.cs (revision 3125)
+++ Source/OpenTK/Platform/Windows/WinGLNative.cs (working copy)
@@ -89,7 +89,13 @@
IList<KeyboardDevice> keyboards = new List<KeyboardDevice>(1);
IList<MouseDevice> mice = new List<MouseDevice>(1);
const long ExtendedBit = 1 << 24; // Used to distinguish left and right control, alt and enter keys.
- static readonly uint ShiftRightScanCode = Functions.MapVirtualKey(VirtualKeys.RSHIFT, 0); // Used to distinguish left and right shift keys.
+
+ public static readonly uint ShiftLeftScanCode = Functions.MapVirtualKey(VirtualKeys.LSHIFT, 0);
+ public static readonly uint ShiftRightScanCode = Functions.MapVirtualKey(VirtualKeys.RSHIFT, 0);
+ public static readonly uint ControlLeftScanCode = Functions.MapVirtualKey(VirtualKeys.LCONTROL, 0);
+ public static readonly uint ControlRightScanCode = Functions.MapVirtualKey(VirtualKeys.RCONTROL, 0);
+ public static readonly uint AltLeftScanCode = Functions.MapVirtualKey(VirtualKeys.LMENU, 0);
+ public static readonly uint AltRightScanCode = Functions.MapVirtualKey(VirtualKeys.RMENU, 0);
KeyPressEventArgs key_press = new KeyPressEventArgs((char)0);
@@ -369,6 +375,8 @@
// In this case, both keys will be reported as pressed.
bool extended = (lParam.ToInt64() & ExtendedBit) != 0;
+ uint scancode = (uint)((lParam.ToInt64() >> 16) & 0xFF);
+ Key key = Key.Unknown;
switch ((VirtualKeys)wParam)
{
case VirtualKeys.SHIFT:
@@ -382,56 +390,51 @@
// Otherwise, the state of one key might be stuck to pressed.
if (ShiftRightScanCode != 0 && pressed)
{
- unchecked
- {
- if (((lParam.ToInt64() >> 16) & 0xFF) == ShiftRightScanCode)
- keyboard[Input.Key.ShiftRight] = pressed;
- else
- keyboard[Input.Key.ShiftLeft] = pressed;
- }
+ if (scancode == ShiftRightScanCode)
+ key = Input.Key.ShiftRight;
+ else
+ key = Input.Key.ShiftLeft;
}
else
{
// Windows 9x and NT4.0 or key release event.
- keyboard[Input.Key.ShiftLeft] = keyboard[Input.Key.ShiftRight] = pressed;
+ keyboard.SetKey(Input.Key.ShiftLeft, ShiftLeftScanCode, pressed);
+ keyboard.SetKey(Input.Key.ShiftRight, ShiftRightScanCode, pressed);
}
- return IntPtr.Zero;
+ break;
case VirtualKeys.CONTROL:
if (extended)
- keyboard[Input.Key.ControlRight] = pressed;
+ key = Input.Key.ControlRight;
else
- keyboard[Input.Key.ControlLeft] = pressed;
- return IntPtr.Zero;
+ key = Input.Key.ControlLeft;
+ break;
case VirtualKeys.MENU:
if (extended)
- keyboard[Input.Key.AltRight] = pressed;
+ key = Input.Key.AltRight;
else
- keyboard[Input.Key.AltLeft] = pressed;
- return IntPtr.Zero;
+ key = Input.Key.AltLeft;
+ break;
case VirtualKeys.RETURN:
if (extended)
- keyboard[Key.KeypadEnter] = pressed;
+ key = Key.KeypadEnter;
else
- keyboard[Key.Enter] = pressed;
- return IntPtr.Zero;
+ key = Key.Enter;
+ break;
default:
if (!KeyMap.ContainsKey((VirtualKeys)wParam))
- {
Debug.Print("Virtual key {0} ({1}) not mapped.", (VirtualKeys)wParam, (long)lParam);
- break;
- }
else
- {
- keyboard[KeyMap[(VirtualKeys)wParam]] = pressed;
- }
- return IntPtr.Zero;
+ key = KeyMap[(VirtualKeys)wParam];
+ break;
}
- break;
+ keyboard.SetKey(key, scancode, pressed);
+ return IntPtr.Zero;
+
case WindowMessage.SYSCHAR:
return IntPtr.Zero;
Index: Source/OpenTK/Platform/Windows/WMInput.cs
===================================================================
--- Source/OpenTK/Platform/Windows/WMInput.cs (revision 3125)
+++ Source/OpenTK/Platform/Windows/WMInput.cs (working copy)
@@ -70,14 +70,12 @@
void UpdateKeyboard()
{
- for (int i = 0; i < 256; i++)
+ for (byte i = 0; i < byte.MaxValue; i++)
{
- VirtualKeys key = (VirtualKeys)i;
- bool pressed = (Functions.GetAsyncKeyState(key) >> 8) != 0;
- if (KeyMap.ContainsKey(key))
- {
- keyboard[KeyMap[key]] = pressed;
- }
+ bool pressed = (Functions.GetAsyncKeyState((VirtualKeys)i) >> 8) != 0;
+ Key key;
+ KeyMap.TryGetValue((VirtualKeys)i,out key);
+ keyboard.SetKeyState(key, i, pressed);
}
}
Index: Source/OpenTK/Platform/Windows/WinRawKeyboard.cs
===================================================================
--- Source/OpenTK/Platform/Windows/WinRawKeyboard.cs (revision 3125)
+++ Source/OpenTK/Platform/Windows/WinRawKeyboard.cs (working copy)
@@ -171,31 +171,30 @@
switch (rin.Data.Keyboard.VKey)
{
case VirtualKeys.SHIFT:
- keyboard[Input.Key.ShiftLeft] = keyboard[Input.Key.ShiftRight] = pressed;
+ keyboard.SetKeyState(Key.ShiftLeft, (byte)WinGLNative.ShiftLeftScanCode, pressed);
+ keyboard.SetKeyState(Key.ShiftRight, (byte)WinGLNative.ShiftRightScanCode, pressed);
processed = true;
break;
case VirtualKeys.CONTROL:
- keyboard[Input.Key.ControlLeft] = keyboard[Input.Key.ControlRight] = pressed;
+ keyboard.SetKeyState(Key.ControlLeft, (byte)WinGLNative.ControlLeftScanCode, pressed);
+ keyboard.SetKeyState(Key.ControlRight, (byte)WinGLNative.ControlRightScanCode, pressed);
processed = true;
break;
case VirtualKeys.MENU:
- keyboard[Input.Key.AltLeft] = keyboard[Input.Key.AltRight] = pressed;
+ keyboard.SetKeyState(Key.AltLeft, (byte)WinGLNative.AltLeftScanCode, pressed);
+ keyboard.SetKeyState(Key.AltRight, (byte)WinGLNative.AltRightScanCode, pressed);
processed = true;
break;
default:
- if (!KeyMap.ContainsKey(rin.Data.Keyboard.VKey))
- {
- Debug.Print("Virtual key {0} ({1}) not mapped.",
- rin.Data.Keyboard.VKey, (int)rin.Data.Keyboard.VKey);
- }
- else
- {
- keyboard[KeyMap[rin.Data.Keyboard.VKey]] = pressed;
- processed = true;
- }
+ Key key;
+ KeyMap.TryGetValue(rin.Data.Keyboard.VKey, out key);
+ if (key == Key.Unknown)
+ Debug.Print("Virtual key {0} ({1}) not mapped.", rin.Data.Keyboard.VKey, (int)rin.Data.Keyboard.VKey);
+ keyboard.SetKeyState(key, BitConverter.GetBytes(rin.Data.Keyboard.MakeCode)[0], pressed);
+ processed = true;
break;
}
Index: Source/OpenTK/Platform/MacOS/HIDInput.cs
===================================================================
--- Source/OpenTK/Platform/MacOS/HIDInput.cs (revision 3125)
+++ Source/OpenTK/Platform/MacOS/HIDInput.cs (working copy)
@@ -250,18 +250,13 @@
HIDPage page = NativeMethods.IOHIDElementGetUsagePage(elem);
int usage = NativeMethods.IOHIDElementGetUsage(elem);
- switch (page)
+ switch (page)
{
case HIDPage.GenericDesktop:
case HIDPage.KeyboardOrKeypad:
- int raw = (int)usage;
- if (raw >= RawKeyMap.Length || raw < 0)
- {
- Debug.Print("[Warning] Key {0} not mapped.", raw);
- return state;
- }
- Key key = RawKeyMap[raw];
- state[key] = v_int != 0;
+ if (usage >= RawKeyMap.Length || usage < 0)
+ Debug.Print("[Warning] Key {0} not mapped.", usage);
+ state.SetKeyState(RawKeyMap[usage], (byte)usage, v_int != 0);
break;
}
Index: Source/OpenTK/Platform/MacOS/CarbonGLNative.cs
===================================================================
--- Source/OpenTK/Platform/MacOS/CarbonGLNative.cs (revision 3125)
+++ Source/OpenTK/Platform/MacOS/CarbonGLNative.cs (working copy)
@@ -368,6 +368,7 @@
break;
}
+ OpenTK.Input.Key key;
switch (evt.KeyboardEventKind)
{
case KeyboardEventKind.RawKeyRepeat:
@@ -376,25 +377,15 @@
break;
case KeyboardEventKind.RawKeyDown:
- {
- OpenTK.Input.Key key;
- if (Keymap.TryGetValue(code, out key))
- {
- InputDriver.Keyboard[0][key] = true;
- OnKeyPress(mKeyPressArgs);
- }
+ Keymap.TryGetValue(code, out key);
+ InputDriver.Keyboard[0].SetKey(key, (uint)code, true);
+ OnKeyPress(mKeyPressArgs);
return OSStatus.NoError;
- }
case KeyboardEventKind.RawKeyUp:
- {
- OpenTK.Input.Key key;
- if (Keymap.TryGetValue(code, out key))
- {
- InputDriver.Keyboard[0][key] = false;
- }
+ Keymap.TryGetValue(code, out key);
+ InputDriver.Keyboard[0].SetKey(key, (uint)code, false);
return OSStatus.NoError;
- }
case KeyboardEventKind.RawKeyModifiersChanged:
ProcessModifierKey(inEvent);
@@ -614,21 +605,21 @@
Debug.Print("Modifiers Changed: {0}", modifiers);
Input.KeyboardDevice keyboard = InputDriver.Keyboard[0];
-
+
if (keyboard[OpenTK.Input.Key.AltLeft] ^ option)
- keyboard[OpenTK.Input.Key.AltLeft] = option;
+ keyboard.SetKey(OpenTK.Input.Key.AltLeft, (uint)MacOSKeyModifiers.Option, option);
if (keyboard[OpenTK.Input.Key.ShiftLeft] ^ shift)
- keyboard[OpenTK.Input.Key.ShiftLeft] = shift;
+ keyboard.SetKey(OpenTK.Input.Key.ShiftLeft, (uint)MacOSKeyModifiers.Shift, shift);
if (keyboard[OpenTK.Input.Key.WinLeft] ^ command)
- keyboard[OpenTK.Input.Key.WinLeft] = command;
+ keyboard.SetKey(OpenTK.Input.Key.WinLeft, (uint)MacOSKeyModifiers.Command, command);
if (keyboard[OpenTK.Input.Key.ControlLeft] ^ control)
- keyboard[OpenTK.Input.Key.ControlLeft] = control;
+ keyboard.SetKey(OpenTK.Input.Key.ControlLeft, (uint)MacOSKeyModifiers.Control, control);
if (keyboard[OpenTK.Input.Key.CapsLock] ^ caps)
- keyboard[OpenTK.Input.Key.CapsLock] = caps;
+ keyboard.SetKey(OpenTK.Input.Key.CapsLock, (uint)MacOSKeyModifiers.CapsLock, caps);
}
Index: Source/OpenTK/Platform/X11/X11Input.cs
===================================================================
--- Source/OpenTK/Platform/X11/X11Input.cs (revision 3125)
+++ Source/OpenTK/Platform/X11/X11Input.cs (working copy)
@@ -157,20 +157,22 @@
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;
- IntPtr keysym = API.LookupKeysym(ref e.KeyEvent, 0);
- IntPtr keysym2 = API.LookupKeysym(ref e.KeyEvent, 1);
-
- if (keymap.ContainsKey((XKey)keysym))
- keyboard[keymap[(XKey)keysym]] = pressed;
- else if (keymap.ContainsKey((XKey)keysym2))
- keyboard[keymap[(XKey)keysym2]] = pressed;
+ 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;
+ 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 == 3) mouse[OpenTK.Input.MouseButton.Right] = true;
else if (e.ButtonEvent.button == 4) mouse.Wheel++;
@@ -190,7 +192,7 @@
break;
case XEventName.ButtonRelease:
- if (e.ButtonEvent.button == 1) mouse[OpenTK.Input.MouseButton.Left] = false;
+ if (e.ButtonEvent.button == 1) mouse[OpenTK.Input.MouseButton.Left] = false;
else if (e.ButtonEvent.button == 2) mouse[OpenTK.Input.MouseButton.Middle] = false;
else if (e.ButtonEvent.button == 3) mouse[OpenTK.Input.MouseButton.Right] = false;
else if (e.ButtonEvent.button == 6) mouse[OpenTK.Input.MouseButton.Button1] = false;
Index: Source/OpenTK/Input/KeyboardDevice.cs
===================================================================
--- Source/OpenTK/Input/KeyboardDevice.cs (revision 3125)
+++ Source/OpenTK/Input/KeyboardDevice.cs (working copy)
@@ -22,6 +22,7 @@
{
//private IKeyboard keyboard;
private bool[] keys = new bool[Enum.GetValues(typeof(Key)).Length];
+ private bool[] scancodes = new bool[256];
private string description;
private int numKeys, numFKeys, numLeds;
private IntPtr devID;
@@ -44,24 +45,16 @@
public bool this[Key key]
{
get { return keys[(int)key]; }
- internal set
- {
- if (keys[(int)key] != value || KeyRepeat)
- {
- keys[(int)key] = value;
+ }
- if (value && KeyDown != null)
- {
- args.Key = key;
- KeyDown(this, args);
- }
- else if (!value && KeyUp != null)
- {
- args.Key = key;
- KeyUp(this, args);
- }
- }
- }
+ /// <summary>
+ /// Gets a value indicating the status of the specified Key.
+ /// </summary>
+ /// <param name="scancode">The scancode to check.</param>
+ /// <returns>True if the scancode is pressed, false otherwise.</returns>
+ public bool this[uint scancode]
+ {
+ get { return scancodes[scancode]; }
}
/// <summary>
@@ -197,12 +190,34 @@
internal void ClearKeys()
{
for (int i = 0; i < keys.Length; i++)
- if (this[(Key)i]) // Make sure KeyUp events are *not* raised for keys that are up, even if key repeat is on.
- this[(Key)i] = false;
+ keys[i] = false;
+ for (uint i = 0; i < scancodes.Length; i++)
+ scancodes[i] = false;
}
#endregion
+ internal void SetKey(Key key, uint scancode, bool state)
+ {
+ if (keys[(int)key] != state || KeyRepeat)
+ {
+ keys[(int)key] = scancodes[scancode] = state;
+
+ if (state && KeyDown != null)
+ {
+ args.Key = key;
+ args.ScanCode = scancode;
+ KeyDown(this, args);
+ }
+ else if (!state && KeyUp != null)
+ {
+ args.Key = key;
+ args.ScanCode = scancode;
+ KeyUp(this, args);
+ }
+ }
+ }
+
#endregion
}
}
\ No newline at end of file
Index: Source/OpenTK/Input/KeyboardKeyEventArgs.cs
===================================================================
--- Source/OpenTK/Input/KeyboardKeyEventArgs.cs (revision 3125)
+++ Source/OpenTK/Input/KeyboardKeyEventArgs.cs (working copy)
@@ -46,6 +46,7 @@
#region Fields
Key key;
+ uint scancode;
#endregion
@@ -63,6 +64,7 @@
public KeyboardKeyEventArgs(KeyboardKeyEventArgs args)
{
Key = args.Key;
+ ScanCode = args.ScanCode;
}
#endregion
@@ -77,6 +79,14 @@
get { return key; }
internal set { key = value; }
}
+ /// <summary>
+ /// Gets the scancode which generated this event.
+ /// </summary>
+ public uint ScanCode
+ {
+ get { return scancode; }
+ internal set { scancode = value; }
+ }
#endregion
}
Index: Source/OpenTK/Input/KeyboardState.cs
===================================================================
--- Source/OpenTK/Input/KeyboardState.cs (revision 3125)
+++ Source/OpenTK/Input/KeyboardState.cs (working copy)
@@ -43,6 +43,7 @@
const int NumInts = ((int)Key.LastKey + IntSize - 1) / IntSize;
// The following line triggers bogus CS0214 in gmcs 2.0.1, sigh...
unsafe fixed int Keys[NumInts];
+ unsafe fixed int Codes[256];
bool is_connected;
#endregion
@@ -58,16 +59,20 @@
public bool this[Key key]
{
get { return IsKeyDown(key); }
- internal set
- {
- if (value)
- EnableBit((int)key);
- else
- DisableBit((int)key);
- }
}
/// <summary>
+ /// Gets a <see cref="System.Boolean"/> indicating whether the specified
+ /// <see cref="OpenTK.Input.Key"/> is pressed.
+ /// </summary>
+ /// <param name="key">The <see cref="OpenTK.Input.Key"/> to check.</param>
+ /// <returns>True if key is pressed; false otherwise.</returns>
+ public bool this[short code]
+ {
+ get { return IsKeyDown(code); }
+ }
+
+ /// <summary>
/// Gets a <see cref="System.Boolean"/> indicating whether this key is down.
/// </summary>
/// <param name="key">The <see cref="OpenTK.Input.Key"/> to check.</param>
@@ -77,6 +82,15 @@
}
/// <summary>
+ /// Gets a <see cref="System.Boolean"/> indicating whether this scan code is down.
+ /// </summary>
+ /// <param name="code">The scan code to check.</param>
+ public bool IsKeyDown(short code)
+ {
+ return ReadBit(code,true);
+ }
+
+ /// <summary>
/// Gets a <see cref="System.Boolean"/> indicating whether this key is up.
/// </summary>
/// <param name="key">The <see cref="OpenTK.Input.Key"/> to check.</param>
@@ -86,6 +100,15 @@
}
/// <summary>
+ /// Gets a <see cref="System.Boolean"/> indicating whether this scan code is down.
+ /// </summary>
+ /// <param name="code">The scan code to check.</param>
+ public bool IsKeyUp(short code)
+ {
+ return !ReadBit(code,true);
+ }
+
+ /// <summary>
/// Gets a <see cref="System.Boolean"/> indicating whether this keyboard
/// is connected.
/// </summary>
@@ -187,48 +210,62 @@
#region Internal Members
- internal bool ReadBit(int offset)
+ internal void SetKeyState(Key key, byte code, bool down)
{
- ValidateOffset(offset);
+ if (down)
+ {
+ EnableBit((int)key);
+ EnableBit(code,true);
+ }
+ else
+ {
+ DisableBit((int)key);
+ DisableBit(code, true);
+ }
+ }
+ internal bool ReadBit(int offset, bool ScanCode = false)
+ {
+ ValidateOffset(offset, ScanCode);
+
int int_offset = offset / 32;
int bit_offset = offset % 32;
unsafe
{
- fixed (int* k = Keys)
- {
- return (*(k + int_offset) & (1 << bit_offset)) != 0u;
- }
+ if (ScanCode)
+ fixed (int* c = Codes) { return (*(c + int_offset) & (1 << bit_offset)) != 0u; }
+ else
+ fixed (int* k = Keys) { return (*(k + int_offset) & (1 << bit_offset)) != 0u; }
}
}
- internal void EnableBit(int offset)
+ internal void EnableBit(int offset, bool ScanCode = false)
{
- ValidateOffset(offset);
+ ValidateOffset(offset, ScanCode);
int int_offset = offset / 32;
int bit_offset = offset % 32;
unsafe
{
- fixed (int* k = Keys)
- {
- *(k + int_offset) |= 1 << bit_offset;
- }
+ if (ScanCode)
+ fixed (int* c = Codes) { *(c + int_offset) |= 1 << bit_offset; }
+ else
+ fixed (int* k = Keys) { *(k + int_offset) |= 1 << bit_offset; }
}
}
- internal void DisableBit(int offset)
+ internal void DisableBit(int offset, bool ScanCode = false)
{
- ValidateOffset(offset);
+ ValidateOffset(offset, ScanCode);
int int_offset = offset / 32;
int bit_offset = offset % 32;
unsafe
{
- fixed (int* k = Keys)
- {
- *(k + int_offset) &= ~(1 << bit_offset);
- }
+ if (ScanCode)
+ fixed (int* c = Codes) { *(c + int_offset) &= ~(1 << bit_offset); }
+ else
+ fixed (int* k = Keys) { *(k + int_offset) &= ~(1 << bit_offset); }
}
}
@@ -242,6 +279,12 @@
for (int i = 0; i < NumInts; i++)
*(k1 + i) |= *(k2 + i);
}
+ int* c2 = other.Codes;
+ fixed (int* c1 = Codes)
+ {
+ for (int i = 0; i < short.MaxValue; i++)
+ *(c1 + i) |= *(c2 + i);
+ }
}
IsConnected |= other.IsConnected;
}
@@ -250,9 +293,9 @@
#region Private Members
- static void ValidateOffset(int offset)
+ static void ValidateOffset(int offset, bool ScanCode)
{
- if (offset < 0 || offset >= NumInts * IntSize)
+ if (offset < 0 || offset >= (ScanCode ? 256 : NumInts * IntSize))
throw new ArgumentOutOfRangeException("offset");
}