Merge branch 'scancodes'

Conflicts:
	Source/OpenTK/OpenTK.csproj
	Source/OpenTK/Platform/Windows/WinFactory.cs
This commit is contained in:
Stefanos A 2013-10-11 01:05:55 +02:00
commit 73e3614338
7 changed files with 378 additions and 532 deletions

View file

@ -261,6 +261,8 @@ namespace OpenTK.Input
KeypadPlus = KeypadAdd, KeypadPlus = KeypadAdd,
/// <summary>The keypad decimal key.</summary> /// <summary>The keypad decimal key.</summary>
KeypadDecimal, KeypadDecimal,
/// <summary>The keypad period key (equivalent to KeypadDecimal).</summary>
KeypadPeriod = KeypadDecimal,
/// <summary>The keypad enter key.</summary> /// <summary>The keypad enter key.</summary>
KeypadEnter, KeypadEnter,
@ -343,6 +345,8 @@ namespace OpenTK.Input
// Symbols // Symbols
/// <summary>The tilde key.</summary> /// <summary>The tilde key.</summary>
Tilde, Tilde,
/// <summary>The grave key (equivaent to Tilde).</summary>
Grave = Tilde,
/// <summary>The minus key.</summary> /// <summary>The minus key.</summary>
Minus, Minus,
//Equal, //Equal,
@ -368,6 +372,8 @@ namespace OpenTK.Input
Slash, Slash,
/// <summary>The backslash key.</summary> /// <summary>The backslash key.</summary>
BackSlash, BackSlash,
/// <summary>The secondary backslash key.</summary>
NonUSBackSlash,
/// <summary>Indicates the last available keyboard key.</summary> /// <summary>Indicates the last available keyboard key.</summary>
LastKey LastKey
} }

View file

@ -332,9 +332,6 @@
<Compile Include="Platform\Windows\WinKeyMap.cs"> <Compile Include="Platform\Windows\WinKeyMap.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="Platform\Windows\WMInput.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\Windows\WinGLNative.cs"> <Compile Include="Platform\Windows\WinGLNative.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
@ -809,4 +806,4 @@
</PostBuildEvent> </PostBuildEvent>
</PropertyGroup> </PropertyGroup>
<ItemGroup /> <ItemGroup />
</Project> </Project>

View file

@ -1,209 +0,0 @@
#region License
//
// The Open Toolkit Library License
//
// Copyright (c) 2006 - 2010 the Open Toolkit library.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#endregion
using System;
using System.Collections.Generic;
using System.Diagnostics;
#if !MINIMAL
using System.Drawing;
#endif
using System.Threading;
using System.Text;
using OpenTK.Input;
namespace OpenTK.Platform.Windows
{
// Input driver for legacy (pre XP) Windows platforms.
// Supports a single mouse and keyboard through async input.
// Supports multiple joysticks through WinMM.
sealed class WMInput : IInputDriver2, IMouseDriver2, IKeyboardDriver2/*, IGamePadDriver*/ //HACK uncomment and implement
{
#region Fields
readonly object MouseLock = new object();
readonly object KeyboardLock = new object();
readonly WinMMJoystick gamepad_driver = new WinMMJoystick();
readonly WinKeyMap KeyMap = new WinKeyMap();
KeyboardState keyboard = new KeyboardState();
MouseState mouse = new MouseState();
bool disposed;
#endregion
#region Constructor
public WMInput()
: base()
{
Debug.WriteLine("Using WMInput.");
}
#endregion
#region Private Members
void UpdateKeyboard()
{
for (byte i = 0; i < byte.MaxValue; i++)
{
bool pressed = (Functions.GetAsyncKeyState((VirtualKeys)i) >> 8) != 0;
Key key;
KeyMap.TryGetValue((VirtualKeys)i,out key);
keyboard.SetKeyState(key, i, pressed);
}
}
void UpdateMouse()
{
POINT p = new POINT();
Functions.GetCursorPos(ref p);
mouse.X = p.X;
mouse.Y = p.Y;
// Note: we cannot poll the mouse wheel
mouse[MouseButton.Left] = (Functions.GetAsyncKeyState(VirtualKeys.LBUTTON) >> 8) != 0;
mouse[MouseButton.Middle] = (Functions.GetAsyncKeyState(VirtualKeys.RBUTTON) >> 8) != 0;
mouse[MouseButton.Right] = (Functions.GetAsyncKeyState(VirtualKeys.MBUTTON) >> 8) != 0;
mouse[MouseButton.Button1] = (Functions.GetAsyncKeyState(VirtualKeys.XBUTTON1) >> 8) != 0;
mouse[MouseButton.Button2] = (Functions.GetAsyncKeyState(VirtualKeys.XBUTTON2) >> 8) != 0;
}
#endregion
#region IInputDriver2 Members
public IKeyboardDriver2 KeyboardDriver
{
get { return this; }
}
public IMouseDriver2 MouseDriver
{
get { return this; }
}
public IGamePadDriver GamePadDriver
{
get { return null; } //HACK return this when implemented.
}
#endregion
#region IMouseDriver2 Members
public MouseState GetState()
{
lock (MouseLock)
{
UpdateMouse();
return mouse;
}
}
public MouseState GetState(int index)
{
lock (MouseLock)
{
UpdateMouse();
if (index == 0)
return mouse;
else
return new MouseState();
}
}
public void SetPosition(double x, double y)
{
Functions.SetCursorPos((int)x, (int)y);
}
#endregion
#region IKeyboardDriver2 Members
KeyboardState IKeyboardDriver2.GetState()
{
lock (KeyboardLock)
{
UpdateKeyboard();
return keyboard;
}
}
KeyboardState IKeyboardDriver2.GetState(int index)
{
lock (KeyboardLock)
{
UpdateKeyboard();
if (index == 0)
return keyboard;
else
return new KeyboardState();
}
}
string IKeyboardDriver2.GetDeviceName(int index)
{
return "Default Windows Keyboard";
}
#endregion
#region IDisposable Members
void Dispose(bool manual)
{
if (!disposed)
{
if (manual)
{
// Todo: implement this
}
else
{
Debug.Print("{0} leaked, did you forget to call Dispose()?", GetType());
}
disposed = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~WMInput()
{
Dispose(false);
}
#endregion
}
}

View file

@ -1,159 +1,158 @@
#region License #region License
// //
// The Open Toolkit Library License // The Open Toolkit Library License
// //
// Copyright (c) 2006 - 2009 the Open Toolkit library. // Copyright (c) 2006 - 2009 the Open Toolkit library.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights to // in the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do // the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions: // so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in all // The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software. // copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// //
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Text; using System.Text;
namespace OpenTK.Platform.Windows namespace OpenTK.Platform.Windows
{ {
using Graphics; using Graphics;
using OpenTK.Input; using OpenTK.Input;
class WinFactory : IPlatformFactory class WinFactory : IPlatformFactory
{ {
bool disposed; bool disposed;
readonly object SyncRoot = new object(); readonly object SyncRoot = new object();
IInputDriver2 inputDriver; IInputDriver2 inputDriver;
public WinFactory() public WinFactory()
{ {
if (System.Environment.OSVersion.Version.Major >= 6) if (System.Environment.OSVersion.Version.Major <= 4)
{ {
// Enable high-dpi support throw new PlatformNotSupportedException("OpenTK requires Windows XP or higher");
// Only available on Windows Vista and higher }
bool result = Functions.SetProcessDPIAware();
Debug.Print("SetProcessDPIAware() returned {0}", result); if (System.Environment.OSVersion.Version.Major >= 6)
} {
} // Enable high-dpi support
// Only available on Windows Vista and higher
#region IPlatformFactory Members bool result = Functions.SetProcessDPIAware();
Debug.Print("SetProcessDPIAware() returned {0}", result);
public virtual INativeWindow CreateNativeWindow(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice device) }
{ }
return new WinGLNative(x, y, width, height, title, options, device);
} #region IPlatformFactory Members
public virtual IDisplayDeviceDriver CreateDisplayDeviceDriver() public virtual INativeWindow CreateNativeWindow(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice device)
{ {
return new WinDisplayDeviceDriver(); return new WinGLNative(x, y, width, height, title, options, device);
} }
public virtual IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags) public virtual IDisplayDeviceDriver CreateDisplayDeviceDriver()
{ {
return new WinGLContext(mode, (WinWindowInfo)window, shareContext, major, minor, flags); return new WinDisplayDeviceDriver();
} }
public virtual IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags) public virtual IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags)
{ {
return new WinGLContext(handle, (WinWindowInfo)window, shareContext, major, minor, flags); return new WinGLContext(mode, (WinWindowInfo)window, shareContext, major, minor, flags);
} }
public virtual GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext() public virtual IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags)
{ {
return (GraphicsContext.GetCurrentContextDelegate)delegate return new WinGLContext(handle, (WinWindowInfo)window, shareContext, major, minor, flags);
{ }
return new ContextHandle(Wgl.GetCurrentContext());
}; public virtual GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext()
} {
return (GraphicsContext.GetCurrentContextDelegate)delegate
public virtual IGraphicsMode CreateGraphicsMode() {
{ return new ContextHandle(Wgl.GetCurrentContext());
return new WinGraphicsMode(); };
} }
public virtual OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver() public virtual IGraphicsMode CreateGraphicsMode()
{ {
return InputDriver.KeyboardDriver; return new WinGraphicsMode();
} }
public virtual OpenTK.Input.IMouseDriver2 CreateMouseDriver() public virtual OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver()
{ {
return InputDriver.MouseDriver; return InputDriver.KeyboardDriver;
} }
public virtual OpenTK.Input.IGamePadDriver CreateGamePadDriver() public virtual OpenTK.Input.IMouseDriver2 CreateMouseDriver()
{ {
return InputDriver.GamePadDriver; return InputDriver.MouseDriver;
} }
#endregion public virtual OpenTK.Input.IGamePadDriver CreateGamePadDriver()
{
IInputDriver2 InputDriver return InputDriver.GamePadDriver;
{ }
get
{ #endregion
lock (SyncRoot)
{ IInputDriver2 InputDriver
if (inputDriver == null) {
{ get
// If Windows version is NT5 or higher, we are able to use raw input. {
if (System.Environment.OSVersion.Version.Major > 5 || lock (SyncRoot)
(System.Environment.OSVersion.Version.Major == 5 && {
System.Environment.OSVersion.Version.Minor > 0)) if (inputDriver == null)
inputDriver = new WinRawInput(); {
else inputDriver = new WinRawInput();
inputDriver = new WMInput(); }
} return inputDriver;
return inputDriver; }
} }
} }
}
#region IDisposable Members
#region IDisposable Members
void Dispose(bool manual)
void Dispose(bool manual) {
{ if (!disposed)
if (!disposed) {
{ if (manual)
if (manual) {
{ InputDriver.Dispose();
InputDriver.Dispose(); }
} else
else {
{ Debug.Print("{0} leaked, did you forget to call Dispose()?", GetType());
Debug.Print("{0} leaked, did you forget to call Dispose()?", GetType()); }
} disposed = true;
disposed = true; }
} }
}
public void Dispose()
public void Dispose() {
{ Dispose(true);
Dispose(true); GC.SuppressFinalize(this);
GC.SuppressFinalize(this); }
}
~WinFactory()
~WinFactory() {
{ Dispose(false);
Dispose(false); }
}
#endregion
#endregion }
} }
}

View file

@ -375,64 +375,16 @@ namespace OpenTK.Platform.Windows
// In this case, both keys will be reported as pressed. // In this case, both keys will be reported as pressed.
bool extended = (lParam.ToInt64() & ExtendedBit) != 0; bool extended = (lParam.ToInt64() & ExtendedBit) != 0;
uint scancode = (uint)((lParam.ToInt64() >> 16) & 0xFF); short scancode = (short)((lParam.ToInt64() >> 16) & 0xFF);
Key key = Key.Unknown; VirtualKeys vkey = (VirtualKeys)wParam;
switch ((VirtualKeys)wParam) bool is_valid;
Key key = KeyMap.TranslateKey(scancode, vkey, extended, false, out is_valid);
if (is_valid)
{ {
case VirtualKeys.SHIFT: keyboard.SetKey(key, (byte)scancode, pressed);
// The behavior of this key is very strange. Unlike Control and Alt, there is no extended bit
// to distinguish between left and right keys. Moreover, pressing both keys and releasing one
// may result in both keys being held down (but not always).
// The only reliable way to solve this was reported by BlueMonkMN at the forums: we should
// check the scancodes. It looks like GLFW does the same thing, so it should be reliable.
// Note: we release both keys when either shift is released.
// Otherwise, the state of one key might be stuck to pressed.
if (ShiftRightScanCode != 0 && pressed)
{
if (scancode == ShiftRightScanCode)
key = Input.Key.ShiftRight;
else
key = Input.Key.ShiftLeft;
}
else
{
// Windows 9x and NT4.0 or key release event.
keyboard.SetKey(Input.Key.ShiftLeft, ShiftLeftScanCode, pressed);
keyboard.SetKey(Input.Key.ShiftRight, ShiftRightScanCode, pressed);
}
break;
case VirtualKeys.CONTROL:
if (extended)
key = Input.Key.ControlRight;
else
key = Input.Key.ControlLeft;
break;
case VirtualKeys.MENU:
if (extended)
key = Input.Key.AltRight;
else
key = Input.Key.AltLeft;
break;
case VirtualKeys.RETURN:
if (extended)
key = Key.KeypadEnter;
else
key = Key.Enter;
break;
default:
if (!KeyMap.ContainsKey((VirtualKeys)wParam))
Debug.Print("Virtual key {0} ({1}) not mapped.", (VirtualKeys)wParam, (long)lParam);
else
key = KeyMap[(VirtualKeys)wParam];
break;
} }
keyboard.SetKey(key, scancode, pressed);
return IntPtr.Zero; return IntPtr.Zero;
case WindowMessage.SYSCHAR: case WindowMessage.SYSCHAR:

View file

@ -27,96 +27,214 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using OpenTK.Input; using OpenTK.Input;
namespace OpenTK.Platform.Windows namespace OpenTK.Platform.Windows
{ {
class WinKeyMap : Dictionary<VirtualKeys, Input.Key> class WinKeyMap
{ {
/// <summary> readonly Dictionary<int, Key> ScanMap = new Dictionary<int, Key>();
/// Initializes the map between VirtualKeys and OpenTK.Key
/// </summary>
public WinKeyMap() public WinKeyMap()
{ {
this.Add(VirtualKeys.ESCAPE, Key.Escape); // 0 - 15
Append(Key.Unknown);
Append(Key.Escape);
// Function keys for (int i = 0; i < 9; i++)
for (int i = 0; i < 24; i++) Append(Key.Number1 + i);
Append(Key.Number0);
Append(Key.Minus);
Append(Key.Plus);
Append(Key.BackSpace);
Append(Key.Tab);
// 16-31
Append(Key.Q);
Append(Key.W);
Append(Key.E);
Append(Key.R);
Append(Key.T);
Append(Key.Y);
Append(Key.U);
Append(Key.I);
Append(Key.O);
Append(Key.P);
Append(Key.BracketLeft);
Append(Key.BracketRight);
Append(Key.Enter);
Append(Key.ControlLeft);
Append(Key.A);
Append(Key.S);
// 32 - 47
Append(Key.D);
Append(Key.F);
Append(Key.G);
Append(Key.H);
Append(Key.J);
Append(Key.K);
Append(Key.L);
Append(Key.Semicolon);
Append(Key.Quote);
Append(Key.Grave);
Append(Key.ShiftLeft);
Append(Key.BackSlash);
Append(Key.Z);
Append(Key.X);
Append(Key.C);
Append(Key.V);
// 48 - 63
Append(Key.B);
Append(Key.N);
Append(Key.M);
Append(Key.Comma);
Append(Key.Period);
Append(Key.Slash);
Append(Key.ShiftRight);
Append(Key.PrintScreen);
Append(Key.AltLeft);
Append(Key.Space);
Append(Key.CapsLock);
Append(Key.F1);
Append(Key.F2);
Append(Key.F3);
Append(Key.F4);
Append(Key.F5);
// 64 - 79
Append(Key.F6);
Append(Key.F7);
Append(Key.F8);
Append(Key.F9);
Append(Key.F10);
Append(Key.NumLock);
Append(Key.ScrollLock);
Append(Key.Home);
Append(Key.Up);
Append(Key.PageUp);
Append(Key.KeypadMinus);
Append(Key.Left);
Append(Key.Keypad5);
Append(Key.Right);
Append(Key.KeypadPlus);
Append(Key.End);
// 80 - 95
Append(Key.Down);
Append(Key.PageDown);
Append(Key.Insert);
Append(Key.Delete);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.NonUSBackSlash);
Append(Key.F11);
Append(Key.F12);
Append(Key.Pause);
Append(Key.Unknown);
Append(Key.WinLeft);
Append(Key.WinRight);
Append(Key.Menu);
Append(Key.Unknown);
Append(Key.Unknown);
// 96 - 111
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.F13);
Append(Key.F14);
Append(Key.F15);
Append(Key.F16);
Append(Key.F17);
Append(Key.F18);
Append(Key.F19);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
// 112 - 127
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
}
void Append(Key key)
{
ScanMap.Add(ScanMap.Count, key);
}
public Key TranslateKey(short scancode, VirtualKeys vkey, bool extended0, bool extended1, out bool is_valid)
{
is_valid = true;
Key key;
ScanMap.TryGetValue(scancode, out key);
if (!extended0)
{ {
this.Add((VirtualKeys)((int)VirtualKeys.F1 + i), Key.F1 + i); switch (key)
{
case Key.Insert: key = Key.Keypad0; break;
case Key.End: key = Key.Keypad1; break;
case Key.Down: key = Key.Keypad2; break;
case Key.PageDown: key = Key.Keypad3; break;
case Key.Left: key = Key.Keypad4; break;
case Key.Right: key = Key.Keypad6; break;
case Key.Home: key = Key.Keypad7; break;
case Key.Up: key = Key.Keypad8; break;
case Key.PageUp: key = Key.Keypad9; break;
case Key.PrintScreen: key = Key.KeypadMultiply; break;
case Key.Delete: key = Key.KeypadDecimal; break;
case Key.NumLock:
if (vkey == VirtualKeys.Last)
is_valid = false;
else if (vkey == VirtualKeys.PAUSE)
key = Key.Pause;
break;
}
}
else
{
switch (key)
{
case Key.Enter: key = Key.KeypadEnter; break;
case Key.AltLeft: key = Key.AltRight; break;
case Key.AltRight: key = Key.AltLeft; break;
case Key.ControlLeft: key = Key.ControlRight; break;
case Key.ControlRight: key = Key.ControlLeft; break;
case Key.ShiftLeft: is_valid = false; break;
}
} }
// Number keys (0-9) if (extended1)
for (int i = 0; i <= 9; i++)
{ {
this.Add((VirtualKeys)(0x30 + i), Key.Number0 + i); switch (key)
{
case Key.ControlLeft: key = Key.Pause; break;
}
} }
// Letters (A-Z) return key;
for (int i = 0; i < 26; i++)
{
this.Add((VirtualKeys)(0x41 + i), Key.A + i);
}
this.Add(VirtualKeys.TAB, Key.Tab);
this.Add(VirtualKeys.CAPITAL, Key.CapsLock);
this.Add(VirtualKeys.LCONTROL, Key.ControlLeft);
this.Add(VirtualKeys.LSHIFT, Key.ShiftLeft);
this.Add(VirtualKeys.LWIN, Key.WinLeft);
this.Add(VirtualKeys.LMENU, Key.AltLeft);
this.Add(VirtualKeys.SPACE, Key.Space);
this.Add(VirtualKeys.RMENU, Key.AltRight);
this.Add(VirtualKeys.RWIN, Key.WinRight);
this.Add(VirtualKeys.APPS, Key.Menu);
this.Add(VirtualKeys.RCONTROL, Key.ControlRight);
this.Add(VirtualKeys.RSHIFT, Key.ShiftRight);
this.Add(VirtualKeys.RETURN, Key.Enter);
this.Add(VirtualKeys.BACK, Key.BackSpace);
this.Add(VirtualKeys.OEM_1, Key.Semicolon); // Varies by keyboard, ;: on Win2K/US
this.Add(VirtualKeys.OEM_2, Key.Slash); // Varies by keyboard, /? on Win2K/US
this.Add(VirtualKeys.OEM_3, Key.Tilde); // Varies by keyboard, `~ on Win2K/US
this.Add(VirtualKeys.OEM_4, Key.BracketLeft); // Varies by keyboard, [{ on Win2K/US
this.Add(VirtualKeys.OEM_5, Key.BackSlash); // Varies by keyboard, \| on Win2K/US
this.Add(VirtualKeys.OEM_6, Key.BracketRight); // Varies by keyboard, ]} on Win2K/US
this.Add(VirtualKeys.OEM_7, Key.Quote); // Varies by keyboard, '" on Win2K/US
this.Add(VirtualKeys.OEM_PLUS, Key.Plus); // Invariant: +
this.Add(VirtualKeys.OEM_COMMA, Key.Comma); // Invariant: ,
this.Add(VirtualKeys.OEM_MINUS, Key.Minus); // Invariant: -
this.Add(VirtualKeys.OEM_PERIOD, Key.Period); // Invariant: .
this.Add(VirtualKeys.HOME, Key.Home);
this.Add(VirtualKeys.END, Key.End);
this.Add(VirtualKeys.DELETE, Key.Delete);
this.Add(VirtualKeys.PRIOR, Key.PageUp);
this.Add(VirtualKeys.NEXT, Key.PageDown);
this.Add(VirtualKeys.PRINT, Key.PrintScreen);
this.Add(VirtualKeys.PAUSE, Key.Pause);
this.Add(VirtualKeys.NUMLOCK, Key.NumLock);
this.Add(VirtualKeys.SCROLL, Key.ScrollLock);
this.Add(VirtualKeys.SNAPSHOT, Key.PrintScreen);
this.Add(VirtualKeys.CLEAR, Key.Clear);
this.Add(VirtualKeys.INSERT, Key.Insert);
this.Add(VirtualKeys.SLEEP, Key.Sleep);
// Keypad
for (int i = 0; i <= 9; i++)
{
this.Add((VirtualKeys)((int)VirtualKeys.NUMPAD0 + i), Key.Keypad0 + i);
}
this.Add(VirtualKeys.DECIMAL, Key.KeypadDecimal);
this.Add(VirtualKeys.ADD, Key.KeypadAdd);
this.Add(VirtualKeys.SUBTRACT, Key.KeypadSubtract);
this.Add(VirtualKeys.DIVIDE, Key.KeypadDivide);
this.Add(VirtualKeys.MULTIPLY, Key.KeypadMultiply);
// Navigation
this.Add(VirtualKeys.UP, Key.Up);
this.Add(VirtualKeys.DOWN, Key.Down);
this.Add(VirtualKeys.LEFT, Key.Left);
this.Add(VirtualKeys.RIGHT, Key.Right);
} }
} }
} }

View file

@ -157,6 +157,13 @@ namespace OpenTK.Platform.Windows
bool pressed = bool pressed =
rin.Data.Keyboard.Message == (int)WindowMessage.KEYDOWN || rin.Data.Keyboard.Message == (int)WindowMessage.KEYDOWN ||
rin.Data.Keyboard.Message == (int)WindowMessage.SYSKEYDOWN; rin.Data.Keyboard.Message == (int)WindowMessage.SYSKEYDOWN;
var scancode = rin.Data.Keyboard.MakeCode;
var vkey = rin.Data.Keyboard.VKey;
bool extended0 = (int)(rin.Data.Keyboard.Flags & RawInputKeyboardDataFlags.E0) != 0;
bool extended1 = (int)(rin.Data.Keyboard.Flags & RawInputKeyboardDataFlags.E1) != 0;
bool is_valid = true;
ContextHandle handle = new ContextHandle(rin.Header.Device); ContextHandle handle = new ContextHandle(rin.Header.Device);
KeyboardState keyboard; KeyboardState keyboard;
@ -175,36 +182,12 @@ namespace OpenTK.Platform.Windows
int keyboard_handle = rawids.ContainsKey(handle) ? rawids[handle] : 0; int keyboard_handle = rawids.ContainsKey(handle) ? rawids[handle] : 0;
keyboard = keyboards[keyboard_handle]; keyboard = keyboards[keyboard_handle];
// Generic control, shift, alt keys may be sent instead of left/right. Key key = KeyMap.TranslateKey(scancode, vkey, extended0, extended1, out is_valid);
// It seems you have to explicitly register left/right events.
switch (rin.Data.Keyboard.VKey) if (is_valid)
{ {
case VirtualKeys.SHIFT: keyboard.SetKeyState(key, (byte)scancode, pressed);
keyboard.SetKeyState(Key.ShiftLeft, (byte)WinGLNative.ShiftLeftScanCode, pressed); processed = true;
keyboard.SetKeyState(Key.ShiftRight, (byte)WinGLNative.ShiftRightScanCode, pressed);
processed = true;
break;
case VirtualKeys.CONTROL:
keyboard.SetKeyState(Key.ControlLeft, (byte)WinGLNative.ControlLeftScanCode, pressed);
keyboard.SetKeyState(Key.ControlRight, (byte)WinGLNative.ControlRightScanCode, pressed);
processed = true;
break;
case VirtualKeys.MENU:
keyboard.SetKeyState(Key.AltLeft, (byte)WinGLNative.AltLeftScanCode, pressed);
keyboard.SetKeyState(Key.AltRight, (byte)WinGLNative.AltRightScanCode, pressed);
processed = true;
break;
default:
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;
} }
lock (UpdateLock) lock (UpdateLock)