Merge remote-tracking branch 'origin/ScanCodeKeyboardBranch'

This commit is contained in:
Tom Edwards 2013-02-17 14:58:16 +00:00
commit 6c35e8ef24
11 changed files with 283 additions and 218 deletions

View file

@ -52,6 +52,7 @@ namespace Examples
// The ExampleBrowser works pretty poorly on some platforms, so you may want to start examples directly.
// for example: Examples.Tutorial.T12_GLSL_Parallax.Main ();
// Examples.Tutorial.T10_GLSL_Cube.Main ();
Examples.Tests.BasicMouseInput.Main ();
using (Form browser = new ExampleBrowser())
{

View file

@ -25,7 +25,7 @@ namespace Examples.Tests
{
public BasicMouseInput()
: base(800, 600, GraphicsMode.Default)
: base(800, 600)
{ }
protected override void OnLoad(EventArgs e)
@ -42,6 +42,8 @@ namespace Examples.Tests
protected override void OnUpdateFrame(FrameEventArgs e)
{
base.OnUpdateFrame(e);
// Here's the big test!
if(OpenTK.Input.Mouse.GetState()[MouseButton.Left]){
Console.WriteLine("The left mouse button is down!");
@ -66,7 +68,7 @@ namespace Examples.Tests
protected override void OnRenderFrame(FrameEventArgs e)
{
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.Clear(ClearBufferMask.ColorBufferBit);
SwapBuffers();
}
@ -78,7 +80,8 @@ namespace Examples.Tests
// Get the title and category of this example using reflection.
ExampleAttribute info = ((ExampleAttribute)example.GetType().GetCustomAttributes(false)[0]);
example.Title = String.Format("OpenTK | {0} {1}: {2}", info.Category, info.Difficulty, info.Title);
example.Run(30.0, 0.0);
example.Run(30.0);
}
}

View file

@ -22,6 +22,7 @@ namespace OpenTK.Input
{
//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 @@ namespace OpenTK.Input
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 @@ namespace OpenTK.Input
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
}
}

View file

@ -46,6 +46,7 @@ namespace OpenTK.Input
#region Fields
Key key;
uint scancode;
#endregion
@ -63,6 +64,7 @@ namespace OpenTK.Input
public KeyboardKeyEventArgs(KeyboardKeyEventArgs args)
{
Key = args.Key;
ScanCode = args.ScanCode;
}
#endregion
@ -78,6 +80,16 @@ namespace OpenTK.Input
internal set { key = value; }
}
/// <summary>
/// Gets the scancode which generated this event.
/// </summary>
public uint ScanCode
{
get { return scancode; }
internal set { scancode = value; }
}
#endregion
}
}

View file

@ -43,6 +43,7 @@ namespace OpenTK.Input
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,13 +59,17 @@ namespace OpenTK.Input
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>
@ -76,6 +81,15 @@ namespace OpenTK.Input
return ReadBit((int)key);
}
/// <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>
@ -85,6 +99,15 @@ namespace OpenTK.Input
return !ReadBit((int)key);
}
/// <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.
@ -187,48 +210,62 @@ namespace OpenTK.Input
#region Internal Members
internal bool ReadBit(int offset)
internal void SetKeyState(Key key, byte code, bool down)
{
ValidateOffset(offset);
int int_offset = offset / 32;
int bit_offset = offset % 32;
unsafe
if (down)
{
fixed (int* k = Keys)
{
return (*(k + int_offset) & (1 << bit_offset)) != 0u;
}
EnableBit((int)key);
EnableBit(code,true);
}
else
{
DisableBit((int)key);
DisableBit(code, true);
}
}
internal void EnableBit(int offset)
internal bool ReadBit(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) { return (*(c + int_offset) & (1 << bit_offset)) != 0u; }
else
fixed (int* k = Keys) { return (*(k + int_offset) & (1 << bit_offset)) != 0u; }
}
}
internal void DisableBit(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, bool ScanCode = false)
{
ValidateOffset(offset, ScanCode);
int int_offset = offset / 32;
int bit_offset = offset % 32;
unsafe
{
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 @@ namespace OpenTK.Input
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 @@ namespace OpenTK.Input
#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");
}

View file

@ -368,6 +368,7 @@ namespace OpenTK.Platform.MacOS
break;
}
OpenTK.Input.Key key;
switch (evt.KeyboardEventKind)
{
case KeyboardEventKind.RawKeyRepeat:
@ -376,25 +377,15 @@ namespace OpenTK.Platform.MacOS
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);
@ -616,19 +607,19 @@ namespace OpenTK.Platform.MacOS
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);
}

View file

@ -263,14 +263,12 @@ namespace OpenTK.Platform.MacOS
{
case HIDPage.GenericDesktop:
case HIDPage.KeyboardOrKeypad:
int raw = (int) usage;
if (raw >= RawKeyMap.Length)
if (usage >= RawKeyMap.Length)
{
Debug.Print("[Warning] Key {0} not mapped.", raw);
Debug.Print("[Warning] Key {0} not mapped.", usage);
return state;
}
Key key = RawKeyMap[raw];
state[key] = v_int != 0;
state.SetKeyState(RawKeyMap[usage], (byte)usage, v_int != 0);
break;
}

View file

@ -70,14 +70,12 @@ namespace OpenTK.Platform.Windows
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);
}
}

View file

@ -89,7 +89,13 @@ namespace OpenTK.Platform.Windows
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 @@ namespace OpenTK.Platform.Windows
// 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,55 +390,50 @@ namespace OpenTK.Platform.Windows
// 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;

View file

@ -180,31 +180,30 @@ namespace OpenTK.Platform.Windows
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;
}

View file

@ -157,20 +157,22 @@ namespace OpenTK.Platform.X11
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 @@ namespace OpenTK.Platform.X11
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;