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");
}
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/MacOS/HIDInput.cs
===================================================================
--- Source/OpenTK/Platform/MacOS/HIDInput.cs (revision 3125)
+++ Source/OpenTK/Platform/MacOS/HIDInput.cs (working copy)
@@ -1,937 +1,932 @@
-#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;
-using System.Runtime.InteropServices;
-using OpenTK.Input;
-
-namespace OpenTK.Platform.MacOS
-{
- using Carbon;
- using CFAllocatorRef = System.IntPtr;
- using CFDictionaryRef = System.IntPtr;
- using CFIndex = System.IntPtr;
- using CFRunLoop = System.IntPtr;
- using CFString = System.IntPtr;
- using CFStringRef = System.IntPtr; // Here used interchangeably with the CFString
- using CFTypeRef = System.IntPtr;
- using IOHIDDeviceRef = System.IntPtr;
- using IOHIDElementRef = System.IntPtr;
- using IOHIDManagerRef = System.IntPtr;
- using IOHIDValueRef = System.IntPtr;
- using IOOptionBits = System.IntPtr;
- using IOReturn = System.IntPtr;
-
- // Requires Mac OS X 10.5 or higher.
- // Todo: create a driver for older installations. Maybe use CGGetLastMouseDelta for that?
- class HIDInput : IInputDriver2, IMouseDriver2, IKeyboardDriver2
- {
- #region Fields
-
- readonly IOHIDManagerRef hidmanager;
-
- readonly Dictionary<IntPtr, MouseState> MouseDevices =
- new Dictionary<IntPtr, MouseState>(new IntPtrEqualityComparer());
- readonly Dictionary<int, IntPtr> MouseIndexToDevice =
- new Dictionary<int, IntPtr>();
- readonly Dictionary<IntPtr, KeyboardState> KeyboardDevices =
- new Dictionary<IntPtr, KeyboardState>(new IntPtrEqualityComparer());
- readonly Dictionary<int, IntPtr> KeyboardIndexToDevice =
- new Dictionary<int, IntPtr>();
-
- readonly CFRunLoop RunLoop = CF.CFRunLoopGetMain();
- readonly CFString InputLoopMode = CF.RunLoopModeDefault;
- readonly CFDictionary DeviceTypes = new CFDictionary();
-
- readonly NativeMethods.IOHIDDeviceCallback HandleDeviceAdded;
- readonly NativeMethods.IOHIDDeviceCallback HandleDeviceRemoved;
- readonly NativeMethods.IOHIDValueCallback HandleDeviceValueReceived;
-
- #endregion
-
- #region Constructors
-
- public HIDInput()
- {
- Debug.Print("Using HIDInput.");
-
- HandleDeviceAdded = DeviceAdded;
- HandleDeviceRemoved = DeviceRemoved;
- HandleDeviceValueReceived = DeviceValueReceived;
-
- hidmanager = CreateHIDManager();
- RegisterHIDCallbacks(hidmanager);
- }
-
- #endregion
-
- #region Private Members
-
- IOHIDManagerRef CreateHIDManager()
- {
- return NativeMethods.IOHIDManagerCreate(IntPtr.Zero, IntPtr.Zero);
- }
-
- // Registers callbacks for device addition and removal. These callbacks
- // are called when we run the loop in CheckDevicesMode
- void RegisterHIDCallbacks(IOHIDManagerRef hidmanager)
- {
- NativeMethods.IOHIDManagerRegisterDeviceMatchingCallback(
- hidmanager, HandleDeviceAdded, IntPtr.Zero);
- NativeMethods.IOHIDManagerRegisterDeviceRemovalCallback(
- hidmanager, HandleDeviceRemoved, IntPtr.Zero);
- NativeMethods.IOHIDManagerScheduleWithRunLoop(hidmanager,
- RunLoop, InputLoopMode);
-
- NativeMethods.IOHIDManagerSetDeviceMatching(hidmanager, DeviceTypes.Ref);
- NativeMethods.IOHIDManagerOpen(hidmanager, IOOptionBits.Zero);
-
- OpenTK.Platform.MacOS.Carbon.CF.CFRunLoopRunInMode(InputLoopMode, 0.0, true);
- }
-
- void DeviceAdded(IntPtr context, IOReturn res, IntPtr sender, IOHIDDeviceRef device)
- {
- if (NativeMethods.IOHIDDeviceOpen(device, IOOptionBits.Zero) == IOReturn.Zero)
- {
- if (NativeMethods.IOHIDDeviceConformsTo(device,
- HIDPage.GenericDesktop, (int)HIDUsageGD.Mouse))
- {
- if (!MouseDevices.ContainsKey(device))
- {
- Debug.Print("Mouse device {0} discovered", device);
- MouseState state = new MouseState();
- state.IsConnected = true;
- MouseIndexToDevice.Add(MouseDevices.Count, device);
- MouseDevices.Add(device, state);
- }
- else
- {
- Debug.Print("Mouse device {0} reconnected", device);
- MouseState state = MouseDevices[device];
- state.IsConnected = true;
- MouseDevices[device] = state;
- }
- }
-
- if (NativeMethods.IOHIDDeviceConformsTo(device,
- HIDPage.GenericDesktop, (int)HIDUsageGD.Keyboard))
- {
- if (!KeyboardDevices.ContainsKey(device))
- {
- Debug.Print("Keyboard device {0} discovered", device);
- KeyboardState state = new KeyboardState();
- state.IsConnected = true;
- KeyboardIndexToDevice.Add(KeyboardDevices.Count, device);
- KeyboardDevices.Add(device, state);
- }
- else
- {
- Debug.Print("Keyboard device {0} reconnected", device);
- KeyboardState state = KeyboardDevices[device];
- state.IsConnected = true;
- KeyboardDevices[device] = state;
- }
- }
-
- NativeMethods.IOHIDDeviceRegisterInputValueCallback(device,
- HandleDeviceValueReceived, IntPtr.Zero);
- NativeMethods.IOHIDDeviceScheduleWithRunLoop(device, RunLoop, InputLoopMode);
- }
- }
-
- void DeviceRemoved(IntPtr context, IOReturn res, IntPtr sender, IOHIDDeviceRef device)
- {
- if (NativeMethods.IOHIDDeviceConformsTo(device, HIDPage.GenericDesktop, (int)HIDUsageGD.Mouse) &&
- MouseDevices.ContainsKey(device))
- {
- Debug.Print("Mouse device {0} disconnected", device);
-
- // Keep the device in case it comes back later on
- MouseState state = MouseDevices[device];
- state.IsConnected = false;
- MouseDevices[device] = state;
- }
-
- if (NativeMethods.IOHIDDeviceConformsTo(device, HIDPage.GenericDesktop, (int)HIDUsageGD.Keyboard) &&
- KeyboardDevices.ContainsKey(device))
- {
- Debug.Print("Keyboard device {0} disconnected", device);
-
- // Keep the device in case it comes back later on
- KeyboardState state = KeyboardDevices[device];
- state.IsConnected = false;
- KeyboardDevices[device] = state;
- }
-
- NativeMethods.IOHIDDeviceRegisterInputValueCallback(device, null, IntPtr.Zero);
- NativeMethods.IOHIDDeviceUnscheduleWithRunLoop(device, RunLoop, InputLoopMode);
- }
-
- void DeviceValueReceived(IntPtr context, IOReturn res, IntPtr sender, IOHIDValueRef val)
- {
- MouseState mouse;
- KeyboardState keyboard;
- if (MouseDevices.TryGetValue(sender, out mouse))
- {
- MouseDevices[sender] = UpdateMouse(mouse, val);
- }
- else if (KeyboardDevices.TryGetValue(sender, out keyboard))
- {
- KeyboardDevices[sender] = UpdateKeyboard(keyboard, val);
- }
- }
-
- static MouseState UpdateMouse(MouseState state, IOHIDValueRef val)
- {
- IOHIDElementRef elem = NativeMethods.IOHIDValueGetElement(val);
- int v_int = NativeMethods.IOHIDValueGetIntegerValue(val).ToInt32();
- //double v_physical = NativeMethods.IOHIDValueGetScaledValue(val, IOHIDValueScaleType.Physical);
- //double v_calbrated = NativeMethods.IOHIDValueGetScaledValue(val, IOHIDValueScaleType.Calibrated);
- HIDPage page = NativeMethods.IOHIDElementGetUsagePage(elem);
- int usage = NativeMethods.IOHIDElementGetUsage(elem);
-
- switch (page)
- {
- case HIDPage.GenericDesktop:
- switch ((HIDUsageGD)usage)
- {
- case HIDUsageGD.X:
- state.X += v_int;
- break;
-
- case HIDUsageGD.Y:
- state.Y += v_int;
- break;
-
- case HIDUsageGD.Wheel:
- state.WheelPrecise += v_int;
- break;
- }
- break;
-
- case HIDPage.Button:
- state[OpenTK.Input.MouseButton.Left + usage - 1] = v_int == 1;
- break;
- }
-
- return state;
- }
-
- static KeyboardState UpdateKeyboard(KeyboardState state, IOHIDValueRef val)
- {
- IOHIDElementRef elem = NativeMethods.IOHIDValueGetElement(val);
- int v_int = NativeMethods.IOHIDValueGetIntegerValue(val).ToInt32();
- HIDPage page = NativeMethods.IOHIDElementGetUsagePage(elem);
- int usage = NativeMethods.IOHIDElementGetUsage(elem);
-
- 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;
- break;
- }
-
- return state;
- }
-
- #endregion
-
- #region IInputDriver2 Members
-
- public IMouseDriver2 MouseDriver { get { return this; } }
- public IKeyboardDriver2 KeyboardDriver { get { return this; } }
- public IGamePadDriver GamePadDriver { get { throw new NotImplementedException(); } }
-
- #endregion
-
- #region IMouseDriver2 Members
-
- MouseState IMouseDriver2.GetState()
- {
- MouseState master = new MouseState();
- foreach (KeyValuePair<IntPtr, MouseState> item in MouseDevices)
- {
- master.MergeBits(item.Value);
- }
-
- return master;
- }
-
- MouseState IMouseDriver2.GetState(int index)
- {
- IntPtr device;
- if (MouseIndexToDevice.TryGetValue(index, out device))
- {
- return MouseDevices[device];
- }
-
- return new MouseState();
- }
-
- void IMouseDriver2.SetPosition(double x, double y)
- {
- CG.SetLocalEventsSuppressionInterval(0.0);
- CG.WarpMouseCursorPosition(new Carbon.HIPoint(x, y));
- }
-
- #endregion
-
- #region IKeyboardDriver2
-
- KeyboardState IKeyboardDriver2.GetState()
- {
- KeyboardState master = new KeyboardState();
- foreach (KeyValuePair<IntPtr, KeyboardState> item in KeyboardDevices)
- {
- master.MergeBits(item.Value);
- }
-
- return master;
- }
-
- KeyboardState IKeyboardDriver2.GetState(int index)
- {
- IntPtr device;
- if (KeyboardIndexToDevice.TryGetValue(index, out device))
- {
- return KeyboardDevices[device];
- }
-
- return new KeyboardState();
- }
-
- string IKeyboardDriver2.GetDeviceName(int index)
- {
- IntPtr device;
- if (KeyboardIndexToDevice.TryGetValue(index, out device))
- {
- IntPtr vendor_id = NativeMethods.IOHIDDeviceGetProperty(device, NativeMethods.IOHIDVendorIDKey);
- IntPtr product_id = NativeMethods.IOHIDDeviceGetProperty(device, NativeMethods.IOHIDProductIDKey);
- // Todo: find out the real vendor/product name from the relevant ids.
- return String.Format("{0}:{1}", vendor_id, product_id);
- }
- return String.Empty;
- }
-
- #endregion
-
- #region NativeMethods
-
- class NativeMethods
- {
- const string hid = "/System/Library/Frameworks/IOKit.framework/Versions/Current/IOKit";
-
- public static readonly CFString IOHIDVendorIDKey = CF.CFSTR("VendorID");
- public static readonly CFString IOHIDVendorIDSourceKey = CF.CFSTR("VendorIDSource");
- public static readonly CFString IOHIDProductIDKey = CF.CFSTR("ProductID");
- public static readonly CFString IOHIDVersionNumberKey = CF.CFSTR("VersionNumber");
- public static readonly CFString IOHIDManufacturerKey = CF.CFSTR("Manufacturer");
- public static readonly CFString IOHIDProductKey = CF.CFSTR("Product");
- public static readonly CFString IOHIDDeviceUsageKey = CF.CFSTR("DeviceUsage");
- public static readonly CFString IOHIDDeviceUsagePageKey = CF.CFSTR("DeviceUsagePage");
- public static readonly CFString IOHIDDeviceUsagePairsKey = CF.CFSTR("DeviceUsagePairs");
-
- [DllImport(hid)]
- public static extern IOHIDManagerRef IOHIDManagerCreate(
- CFAllocatorRef allocator, IOOptionBits options) ;
-
- // This routine will be called when a new (matching) device is connected.
- [DllImport(hid)]
- public static extern void IOHIDManagerRegisterDeviceMatchingCallback(
- IOHIDManagerRef inIOHIDManagerRef,
- IOHIDDeviceCallback inIOHIDDeviceCallback,
- IntPtr inContext);
-
- // This routine will be called when a (matching) device is disconnected.
- [DllImport(hid)]
- public static extern void IOHIDManagerRegisterDeviceRemovalCallback(
- IOHIDManagerRef inIOHIDManagerRef,
- IOHIDDeviceCallback inIOHIDDeviceCallback,
- IntPtr inContext);
-
- [DllImport(hid)]
- public static extern void IOHIDManagerScheduleWithRunLoop(
- IOHIDManagerRef inIOHIDManagerRef,
- CFRunLoop inCFRunLoop,
- CFString inCFRunLoopMode);
-
- [DllImport(hid)]
- public static extern void IOHIDManagerSetDeviceMatching(
- IOHIDManagerRef manager,
- CFDictionaryRef matching) ;
-
- [DllImport(hid)]
- public static extern IOReturn IOHIDManagerOpen(
- IOHIDManagerRef manager,
- IOOptionBits options) ;
-
- [DllImport(hid)]
- public static extern IOReturn IOHIDDeviceOpen(
- IOHIDDeviceRef manager,
- IOOptionBits opts);
-
- [DllImport(hid)]
- public static extern CFTypeRef IOHIDDeviceGetProperty(
- IOHIDDeviceRef device,
- CFStringRef key);
-
- [DllImport(hid)]
- public static extern bool IOHIDDeviceConformsTo(
- IOHIDDeviceRef inIOHIDDeviceRef, // IOHIDDeviceRef for the HID device
- HIDPage inUsagePage, // the usage page to test conformance with
- int inUsage); // the usage to test conformance with
-
- [DllImport(hid)]
- public static extern void IOHIDDeviceRegisterInputValueCallback(
- IOHIDDeviceRef device,
- IOHIDValueCallback callback,
- IntPtr context);
-
- [DllImport(hid)]
- public static extern void IOHIDDeviceScheduleWithRunLoop(
- IOHIDDeviceRef device,
- CFRunLoop inCFRunLoop,
- CFString inCFRunLoopMode);
-
- [DllImport(hid)]
- public static extern void IOHIDDeviceUnscheduleWithRunLoop(
- IOHIDDeviceRef device,
- CFRunLoop inCFRunLoop,
- CFString inCFRunLoopMode);
-
- [DllImport(hid)]
- public static extern IOHIDElementRef IOHIDValueGetElement(IOHIDValueRef @value);
-
- [DllImport(hid)]
- public static extern CFIndex IOHIDValueGetIntegerValue(IOHIDValueRef @value);
-
- [DllImport(hid)]
- public static extern double IOHIDValueGetScaledValue(
- IOHIDValueRef @value,
- IOHIDValueScaleType type) ;
-
- [DllImport(hid)]
- public static extern int IOHIDElementGetUsage(IOHIDElementRef elem);
-
- [DllImport(hid)]
- public static extern HIDPage IOHIDElementGetUsagePage(IOHIDElementRef elem);
-
- public delegate void IOHIDDeviceCallback(IntPtr ctx, IOReturn res, IntPtr sender, IOHIDDeviceRef device);
- public delegate void IOHIDValueCallback(IntPtr ctx, IOReturn res, IntPtr sender, IOHIDValueRef val);
- }
-
- enum IOHIDValueScaleType
- {
- Physical, // [device min, device max]
- Calibrated // [-1, +1]
- }
-
- enum HIDPage
- {
- Undefined = 0x00,
- GenericDesktop = 0x01,
- Simulation = 0x02,
- VR = 0x03,
- Sport = 0x04,
- Game = 0x05,
- /* Reserved 0x06 */
- KeyboardOrKeypad = 0x07, /* USB Device Class Definition for Human Interface Devices (HID). Note: the usage type for all key codes is Selector (Sel). */
- LEDs = 0x08,
- Button = 0x09,
- Ordinal = 0x0A,
- Telephony = 0x0B,
- Consumer = 0x0C,
- Digitizer = 0x0D,
- /* Reserved 0x0E */
- PID = 0x0F, /* USB Physical Interface Device definitions for force feedback and related devices. */
- Unicode = 0x10,
- /* Reserved 0x11 - 0x13 */
- AlphanumericDisplay = 0x14,
- /* Reserved 0x15 - 0x7F */
- /* Monitor 0x80 - 0x83 USB Device Class Definition for Monitor Devices */
- /* Power 0x84 - 0x87 USB Device Class Definition for Power Devices */
- PowerDevice = 0x84, /* Power Device Page */
- BatterySystem = 0x85, /* Battery System Page */
- /* Reserved 0x88 - 0x8B */
- BarCodeScanner = 0x8C, /* (Point of Sale) USB Device Class Definition for Bar Code Scanner Devices */
- WeighingDevice = 0x8D, /* (Point of Sale) USB Device Class Definition for Weighing Devices */
- Scale = 0x8D, /* (Point of Sale) USB Device Class Definition for Scale Devices */
- MagneticStripeReader = 0x8E,
- /* ReservedPointofSalepages 0x8F */
- CameraControl = 0x90, /* USB Device Class Definition for Image Class Devices */
- Arcade = 0x91, /* OAAF Definitions for arcade and coinop related Devices */
- /* Reserved 0x92 - 0xFEFF */
- /* VendorDefined 0xFF00 - 0xFFFF */
- VendorDefinedStart = 0xFF00
- }
-
- // Generic desktop usage
- enum HIDUsageGD
- {
- Pointer = 0x01, /* Physical Collection */
- Mouse = 0x02, /* Application Collection */
- /* 0x03 Reserved */
- Joystick = 0x04, /* Application Collection */
- GamePad = 0x05, /* Application Collection */
- Keyboard = 0x06, /* Application Collection */
- Keypad = 0x07, /* Application Collection */
- MultiAxisController = 0x08, /* Application Collection */
- /* 0x09 - 0x2F Reserved */
- X = 0x30, /* Dynamic Value */
- Y = 0x31, /* Dynamic Value */
- Z = 0x32, /* Dynamic Value */
- Rx = 0x33, /* Dynamic Value */
- Ry = 0x34, /* Dynamic Value */
- Rz = 0x35, /* Dynamic Value */
- Slider = 0x36, /* Dynamic Value */
- Dial = 0x37, /* Dynamic Value */
- Wheel = 0x38, /* Dynamic Value */
- Hatswitch = 0x39, /* Dynamic Value */
- CountedBuffer = 0x3A, /* Logical Collection */
- ByteCount = 0x3B, /* Dynamic Value */
- MotionWakeup = 0x3C, /* One-Shot Control */
- Start = 0x3D, /* On/Off Control */
- Select = 0x3E, /* On/Off Control */
- /* 0x3F Reserved */
- Vx = 0x40, /* Dynamic Value */
- Vy = 0x41, /* Dynamic Value */
- Vz = 0x42, /* Dynamic Value */
- Vbrx = 0x43, /* Dynamic Value */
- Vbry = 0x44, /* Dynamic Value */
- Vbrz = 0x45, /* Dynamic Value */
- Vno = 0x46, /* Dynamic Value */
- /* 0x47 - 0x7F Reserved */
- SystemControl = 0x80, /* Application Collection */
- SystemPowerDown = 0x81, /* One-Shot Control */
- SystemSleep = 0x82, /* One-Shot Control */
- SystemWakeUp = 0x83, /* One-Shot Control */
- SystemContextMenu = 0x84, /* One-Shot Control */
- SystemMainMenu = 0x85, /* One-Shot Control */
- SystemAppMenu = 0x86, /* One-Shot Control */
- SystemMenuHelp = 0x87, /* One-Shot Control */
- SystemMenuExit = 0x88, /* One-Shot Control */
- SystemMenu = 0x89, /* Selector */
- SystemMenuRight = 0x8A, /* Re-Trigger Control */
- SystemMenuLeft = 0x8B, /* Re-Trigger Control */
- SystemMenuUp = 0x8C, /* Re-Trigger Control */
- SystemMenuDown = 0x8D, /* Re-Trigger Control */
- /* 0x8E - 0x8F Reserved */
- DPadUp = 0x90, /* On/Off Control */
- DPadDown = 0x91, /* On/Off Control */
- DPadRight = 0x92, /* On/Off Control */
- DPadLeft = 0x93, /* On/Off Control */
- /* 0x94 - 0xFFFF Reserved */
- Reserved = 0xFFFF
- }
-
- enum HIDButton
- {
- Button_1 = 0x01, /* (primary/trigger) */
- Button_2 = 0x02, /* (secondary) */
- Button_3 = 0x03, /* (tertiary) */
- Button_4 = 0x04, /* 4th button */
- /* ... */
- Button_65535 = 0xFFFF
- }
-
- enum HIDKey
- {
- ErrorRollOver = 0x01, /* ErrorRollOver */
- POSTFail = 0x02, /* POSTFail */
- ErrorUndefined = 0x03, /* ErrorUndefined */
- A = 0x04, /* a or A */
- B = 0x05, /* b or B */
- C = 0x06, /* c or C */
- D = 0x07, /* d or D */
- E = 0x08, /* e or E */
- F = 0x09, /* f or F */
- G = 0x0A, /* g or G */
- H = 0x0B, /* h or H */
- I = 0x0C, /* i or I */
- J = 0x0D, /* j or J */
- K = 0x0E, /* k or K */
- L = 0x0F, /* l or L */
- M = 0x10, /* m or M */
- N = 0x11, /* n or N */
- O = 0x12, /* o or O */
- P = 0x13, /* p or P */
- Q = 0x14, /* q or Q */
- R = 0x15, /* r or R */
- S = 0x16, /* s or S */
- T = 0x17, /* t or T */
- U = 0x18, /* u or U */
- V = 0x19, /* v or V */
- W = 0x1A, /* w or W */
- X = 0x1B, /* x or X */
- Y = 0x1C, /* y or Y */
- Z = 0x1D, /* z or Z */
- Number1 = 0x1E, /* 1 or ! */
- Number2 = 0x1F, /* 2 or @ */
- Number3 = 0x20, /* 3 or # */
- Number4 = 0x21, /* 4 or $ */
- Number5 = 0x22, /* 5 or % */
- Number6 = 0x23, /* 6 or ^ */
- Number7 = 0x24, /* 7 or & */
- Number8 = 0x25, /* 8 or * */
- Number9 = 0x26, /* 9 or ( */
- Number0 = 0x27, /* 0 or ) */
- ReturnOrEnter = 0x28, /* Return (Enter) */
- Escape = 0x29, /* Escape */
- DeleteOrBackspace = 0x2A, /* Delete (Backspace) */
- Tab = 0x2B, /* Tab */
- Spacebar = 0x2C, /* Spacebar */
- Hyphen = 0x2D, /* - or _ */
- EqualSign = 0x2E, /* = or + */
- OpenBracket = 0x2F, /* [ or { */
- CloseBracket = 0x30, /* ] or } */
- Backslash = 0x31, /* \ or | */
- NonUSPound = 0x32, /* Non-US # or _ */
- Semicolon = 0x33, /* ; or : */
- Quote = 0x34, /* ' or " */
- GraveAccentAndTilde = 0x35, /* Grave Accent and Tilde */
- Comma = 0x36, /* , or < */
- Period = 0x37, /* . or > */
- Slash = 0x38, /* / or ? */
- CapsLock = 0x39, /* Caps Lock */
- F1 = 0x3A, /* F1 */
- F2 = 0x3B, /* F2 */
- F3 = 0x3C, /* F3 */
- F4 = 0x3D, /* F4 */
- F5 = 0x3E, /* F5 */
- F6 = 0x3F, /* F6 */
- F7 = 0x40, /* F7 */
- F8 = 0x41, /* F8 */
- F9 = 0x42, /* F9 */
- F10 = 0x43, /* F10 */
- F11 = 0x44, /* F11 */
- F12 = 0x45, /* F12 */
- PrintScreen = 0x46, /* Print Screen */
- ScrollLock = 0x47, /* Scroll Lock */
- Pause = 0x48, /* Pause */
- Insert = 0x49, /* Insert */
- Home = 0x4A, /* Home */
- PageUp = 0x4B, /* Page Up */
- DeleteForward = 0x4C, /* Delete Forward */
- End = 0x4D, /* End */
- PageDown = 0x4E, /* Page Down */
- RightArrow = 0x4F, /* Right Arrow */
- LeftArrow = 0x50, /* Left Arrow */
- DownArrow = 0x51, /* Down Arrow */
- UpArrow = 0x52, /* Up Arrow */
- KeypadNumLock = 0x53, /* Keypad NumLock or Clear */
- KeypadSlash = 0x54, /* Keypad / */
- KeypadAsterisk = 0x55, /* Keypad * */
- KeypadHyphen = 0x56, /* Keypad - */
- KeypadPlus = 0x57, /* Keypad + */
- KeypadEnter = 0x58, /* Keypad Enter */
- Keypad1 = 0x59, /* Keypad 1 or End */
- Keypad2 = 0x5A, /* Keypad 2 or Down Arrow */
- Keypad3 = 0x5B, /* Keypad 3 or Page Down */
- Keypad4 = 0x5C, /* Keypad 4 or Left Arrow */
- Keypad5 = 0x5D, /* Keypad 5 */
- Keypad6 = 0x5E, /* Keypad 6 or Right Arrow */
- Keypad7 = 0x5F, /* Keypad 7 or Home */
- Keypad8 = 0x60, /* Keypad 8 or Up Arrow */
- Keypad9 = 0x61, /* Keypad 9 or Page Up */
- Keypad0 = 0x62, /* Keypad 0 or Insert */
- KeypadPeriod = 0x63, /* Keypad . or Delete */
- NonUSBackslash = 0x64, /* Non-US \ or | */
- Application = 0x65, /* Application */
- Power = 0x66, /* Power */
- KeypadEqualSign = 0x67, /* Keypad = */
- F13 = 0x68, /* F13 */
- F14 = 0x69, /* F14 */
- F15 = 0x6A, /* F15 */
- F16 = 0x6B, /* F16 */
- F17 = 0x6C, /* F17 */
- F18 = 0x6D, /* F18 */
- F19 = 0x6E, /* F19 */
- F20 = 0x6F, /* F20 */
- F21 = 0x70, /* F21 */
- F22 = 0x71, /* F22 */
- F23 = 0x72, /* F23 */
- F24 = 0x73, /* F24 */
- Execute = 0x74, /* Execute */
- Help = 0x75, /* Help */
- Menu = 0x76, /* Menu */
- Select = 0x77, /* Select */
- Stop = 0x78, /* Stop */
- Again = 0x79, /* Again */
- Undo = 0x7A, /* Undo */
- Cut = 0x7B, /* Cut */
- Copy = 0x7C, /* Copy */
- Paste = 0x7D, /* Paste */
- Find = 0x7E, /* Find */
- Mute = 0x7F, /* Mute */
- VolumeUp = 0x80, /* Volume Up */
- VolumeDown = 0x81, /* Volume Down */
- LockingCapsLock = 0x82, /* Locking Caps Lock */
- LockingNumLock = 0x83, /* Locking Num Lock */
- LockingScrollLock = 0x84, /* Locking Scroll Lock */
- KeypadComma = 0x85, /* Keypad Comma */
- KeypadEqualSignAS400 = 0x86, /* Keypad Equal Sign for AS/400 */
- International1 = 0x87, /* International1 */
- International2 = 0x88, /* International2 */
- International3 = 0x89, /* International3 */
- International4 = 0x8A, /* International4 */
- International5 = 0x8B, /* International5 */
- International6 = 0x8C, /* International6 */
- International7 = 0x8D, /* International7 */
- International8 = 0x8E, /* International8 */
- International9 = 0x8F, /* International9 */
- LANG1 = 0x90, /* LANG1 */
- LANG2 = 0x91, /* LANG2 */
- LANG3 = 0x92, /* LANG3 */
- LANG4 = 0x93, /* LANG4 */
- LANG5 = 0x94, /* LANG5 */
- LANG6 = 0x95, /* LANG6 */
- LANG7 = 0x96, /* LANG7 */
- LANG8 = 0x97, /* LANG8 */
- LANG9 = 0x98, /* LANG9 */
- AlternateErase = 0x99, /* AlternateErase */
- SysReqOrAttention = 0x9A, /* SysReq/Attention */
- Cancel = 0x9B, /* Cancel */
- Clear = 0x9C, /* Clear */
- Prior = 0x9D, /* Prior */
- Return = 0x9E, /* Return */
- Separator = 0x9F, /* Separator */
- Out = 0xA0, /* Out */
- Oper = 0xA1, /* Oper */
- ClearOrAgain = 0xA2, /* Clear/Again */
- CrSelOrProps = 0xA3, /* CrSel/Props */
- ExSel = 0xA4, /* ExSel */
- /* 0xA5-0xDF Reserved */
- LeftControl = 0xE0, /* Left Control */
- LeftShift = 0xE1, /* Left Shift */
- LeftAlt = 0xE2, /* Left Alt */
- LeftGUI = 0xE3, /* Left GUI */
- RightControl = 0xE4, /* Right Control */
- RightShift = 0xE5, /* Right Shift */
- RightAlt = 0xE6, /* Right Alt */
- RightGUI = 0xE7, /* Right GUI */
- /* 0xE8-0xFFFF Reserved */
- //_Reserved = 0xFFFF
- }
-
- // Maps HIDKey to OpenTK.Input.Key.
- static readonly Key[] RawKeyMap = new Key[]
- {
- Key.Unknown,
- Key.Unknown, /* ErrorRollOver */
- Key.Unknown, /* POSTFail */
- Key.Unknown, /* ErrorUndefined */
- Key.A, /* a or A */
- Key.B, /* b or B */
- Key.C, /* c or C */
- Key.D, /* d or D */
- Key.E, /* e or E */
- Key.F, /* f or F */
- Key.G, /* g or G */
- Key.H, /* h or H */
- Key.I, /* i or I */
- Key.J, /* j or J */
- Key.K, /* k or K */
- Key.L, /* l or L */
- Key.M, /* m or M */
- Key.N, /* n or N */
- Key.O, /* o or O */
- Key.P, /* p or P */
- Key.Q, /* q or Q */
- Key.R, /* r or R */
- Key.S, /* s or S */
- Key.T, /* t or T */
- Key.U, /* u or U */
- Key.V, /* v or V */
- Key.W, /* w or W */
- Key.X, /* x or X */
- Key.Y, /* y or Y */
- Key.Z, /* z or Z */
- Key.Number1, /* 1 or ! */
- Key.Number2, /* 2 or @ */
- Key.Number3, /* 3 or # */
- Key.Number4, /* 4 or $ */
- Key.Number5, /* 5 or % */
- Key.Number6, /* 6 or ^ */
- Key.Number7, /* 7 or & */
- Key.Number8, /* 8 or * */
- Key.Number9, /* 9 or ( */
- Key.Number0, /* 0 or ) */
- Key.Enter, /* Return (Enter) */
- Key.Escape, /* Escape */
- Key.BackSpace, /* Delete (Backspace) */
- Key.Tab, /* Tab */
- Key.Space, /* Spacebar */
- Key.Minus, /* - or _ */
- Key.Plus, /* = or + */
- Key.BracketLeft, /* [ or { */
- Key.BracketRight, /* ] or } */
- Key.BackSlash, /* \ or | */
- Key.Minus, /* Non-US # or _ */
- Key.Semicolon, /* ; or : */
- Key.Quote, /* ' or " */
- Key.Tilde, /* Grave Accent and Tilde */
- Key.Comma, /* , or < */
- Key.Period, /* . or > */
- Key.Slash, /* / or ? */
- Key.CapsLock, /* Caps Lock */
- Key.F1, /* F1 */
- Key.F2, /* F2 */
- Key.F3, /* F3 */
- Key.F4, /* F4 */
- Key.F5, /* F5 */
- Key.F6, /* F6 */
- Key.F7, /* F7 */
- Key.F8, /* F8 */
- Key.F9, /* F9 */
- Key.F10, /* F10 */
- Key.F11, /* F11 */
- Key.F12, /* F12 */
- Key.PrintScreen, /* Print Screen */
- Key.ScrollLock, /* Scroll Lock */
- Key.Pause, /* Pause */
- Key.Insert, /* Insert */
- Key.Home, /* Home */
- Key.PageUp, /* Page Up */
- Key.Delete, /* Delete Forward */
- Key.End, /* End */
- Key.PageDown, /* Page Down */
- Key.Right, /* Right Arrow */
- Key.Left, /* Left Arrow */
- Key.Down, /* Down Arrow */
- Key.Up, /* Up Arrow */
- Key.NumLock, /* Keypad NumLock or Clear */
- Key.KeypadDivide, /* Keypad / */
- Key.KeypadMultiply, /* Keypad * */
- Key.KeypadMinus, /* Keypad - */
- Key.KeypadPlus, /* Keypad + */
- Key.KeypadEnter, /* Keypad Enter */
- Key.Keypad1, /* Keypad 1 or End */
- Key.Keypad2, /* Keypad 2 or Down Arrow */
- Key.Keypad3, /* Keypad 3 or Page Down */
- Key.Keypad4, /* Keypad 4 or Left Arrow */
- Key.Keypad5, /* Keypad 5 */
- Key.Keypad6, /* Keypad 6 or Right Arrow */
- Key.Keypad7, /* Keypad 7 or Home */
- Key.Keypad8, /* Keypad 8 or Up Arrow */
- Key.Keypad9, /* Keypad 9 or Page Up */
- Key.Keypad0, /* Keypad 0 or Insert */
- Key.KeypadDecimal, /* Keypad . or Delete */
- Key.BackSlash, /* Non-US \ or | */
- Key.Unknown, /* Application */
- Key.Unknown, /* Power */
- Key.Unknown, /* Keypad = */
- Key.F13, /* F13 */
- Key.F14, /* F14 */
- Key.F15, /* F15 */
- Key.F16, /* F16 */
- Key.F17, /* F17 */
- Key.F18, /* F18 */
- Key.F19, /* F19 */
- Key.F20, /* F20 */
- Key.F21, /* F21 */
- Key.F22, /* F22 */
- Key.F23, /* F23 */
- Key.F24, /* F24 */
- Key.Unknown, /* Execute */
- Key.Unknown, /* Help */
- Key.Menu, /* Menu */
- Key.Unknown, /* Select */
- Key.Unknown, /* Stop */
- Key.Unknown, /* Again */
- Key.Unknown, /* Undo */
- Key.Unknown, /* Cut */
- Key.Unknown, /* Copy */
- Key.Unknown, /* Paste */
- Key.Unknown, /* Find */
- Key.Unknown, /* Mute */
- Key.Unknown, /* Volume Up */
- Key.Unknown, /* Volume Down */
- Key.CapsLock, /* Locking Caps Lock */
- Key.NumLock , /* Locking Num Lock */
- Key.ScrollLock, /* Locking Scroll Lock */
- Key.KeypadDecimal, /* Keypad Comma */
- Key.Unknown, /* Keypad Equal Sign for AS/400 */
- Key.Unknown, /* International1 */
- Key.Unknown, /* International2 */
- Key.Unknown, /* International3 */
- Key.Unknown, /* International4 */
- Key.Unknown, /* International5 */
- Key.Unknown, /* International6 */
- Key.Unknown, /* International7 */
- Key.Unknown, /* International8 */
- Key.Unknown, /* International9 */
- Key.Unknown, /* LANG1 */
- Key.Unknown, /* LANG2 */
- Key.Unknown, /* LANG3 */
- Key.Unknown, /* LANG4 */
- Key.Unknown, /* LANG5 */
- Key.Unknown, /* LANG6 */
- Key.Unknown, /* LANG7 */
- Key.Unknown, /* LANG8 */
- Key.Unknown, /* LANG9 */
- Key.Unknown, /* AlternateErase */
- Key.Unknown, /* SysReq/Attention */
- Key.Unknown, /* Cancel */
- Key.Unknown, /* Clear */
- Key.Unknown, /* Prior */
- Key.Enter, /* Return */
- Key.Unknown, /* Separator */
- Key.Unknown, /* Out */
- Key.Unknown, /* Oper */
- Key.Unknown, /* Clear/Again */
- Key.Unknown, /* CrSel/Props */
- Key.Unknown, /* ExSel */
- /* 0xA5-0xDF Reserved */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- Key.LControl, /* Left Control */
- Key.LShift, /* Left Shift */
- Key.LAlt, /* Left Alt */
- Key.LWin, /* Left GUI */
- Key.RControl, /* Right Control */
- Key.RShift, /* Right Shift */
- Key.RAlt, /* Right Alt */
- Key.RWin, /* Right GUI */
- /* 0xE8-0xFFFF Reserved */
- };
-
- #endregion
- }
-}
-
+#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;
+using System.Runtime.InteropServices;
+using OpenTK.Input;
+
+namespace OpenTK.Platform.MacOS
+{
+ using Carbon;
+ using CFAllocatorRef = System.IntPtr;
+ using CFDictionaryRef = System.IntPtr;
+ using CFIndex = System.IntPtr;
+ using CFRunLoop = System.IntPtr;
+ using CFString = System.IntPtr;
+ using CFStringRef = System.IntPtr; // Here used interchangeably with the CFString
+ using CFTypeRef = System.IntPtr;
+ using IOHIDDeviceRef = System.IntPtr;
+ using IOHIDElementRef = System.IntPtr;
+ using IOHIDManagerRef = System.IntPtr;
+ using IOHIDValueRef = System.IntPtr;
+ using IOOptionBits = System.IntPtr;
+ using IOReturn = System.IntPtr;
+
+ // Requires Mac OS X 10.5 or higher.
+ // Todo: create a driver for older installations. Maybe use CGGetLastMouseDelta for that?
+ class HIDInput : IInputDriver2, IMouseDriver2, IKeyboardDriver2
+ {
+ #region Fields
+
+ readonly IOHIDManagerRef hidmanager;
+
+ readonly Dictionary<IntPtr, MouseState> MouseDevices =
+ new Dictionary<IntPtr, MouseState>(new IntPtrEqualityComparer());
+ readonly Dictionary<int, IntPtr> MouseIndexToDevice =
+ new Dictionary<int, IntPtr>();
+ readonly Dictionary<IntPtr, KeyboardState> KeyboardDevices =
+ new Dictionary<IntPtr, KeyboardState>(new IntPtrEqualityComparer());
+ readonly Dictionary<int, IntPtr> KeyboardIndexToDevice =
+ new Dictionary<int, IntPtr>();
+
+ readonly CFRunLoop RunLoop = CF.CFRunLoopGetMain();
+ readonly CFString InputLoopMode = CF.RunLoopModeDefault;
+ readonly CFDictionary DeviceTypes = new CFDictionary();
+
+ readonly NativeMethods.IOHIDDeviceCallback HandleDeviceAdded;
+ readonly NativeMethods.IOHIDDeviceCallback HandleDeviceRemoved;
+ readonly NativeMethods.IOHIDValueCallback HandleDeviceValueReceived;
+
+ #endregion
+
+ #region Constructors
+
+ public HIDInput()
+ {
+ Debug.Print("Using HIDInput.");
+
+ HandleDeviceAdded = DeviceAdded;
+ HandleDeviceRemoved = DeviceRemoved;
+ HandleDeviceValueReceived = DeviceValueReceived;
+
+ hidmanager = CreateHIDManager();
+ RegisterHIDCallbacks(hidmanager);
+ }
+
+ #endregion
+
+ #region Private Members
+
+ IOHIDManagerRef CreateHIDManager()
+ {
+ return NativeMethods.IOHIDManagerCreate(IntPtr.Zero, IntPtr.Zero);
+ }
+
+ // Registers callbacks for device addition and removal. These callbacks
+ // are called when we run the loop in CheckDevicesMode
+ void RegisterHIDCallbacks(IOHIDManagerRef hidmanager)
+ {
+ NativeMethods.IOHIDManagerRegisterDeviceMatchingCallback(
+ hidmanager, HandleDeviceAdded, IntPtr.Zero);
+ NativeMethods.IOHIDManagerRegisterDeviceRemovalCallback(
+ hidmanager, HandleDeviceRemoved, IntPtr.Zero);
+ NativeMethods.IOHIDManagerScheduleWithRunLoop(hidmanager,
+ RunLoop, InputLoopMode);
+
+ NativeMethods.IOHIDManagerSetDeviceMatching(hidmanager, DeviceTypes.Ref);
+ NativeMethods.IOHIDManagerOpen(hidmanager, IOOptionBits.Zero);
+
+ OpenTK.Platform.MacOS.Carbon.CF.CFRunLoopRunInMode(InputLoopMode, 0.0, true);
+ }
+
+ void DeviceAdded(IntPtr context, IOReturn res, IntPtr sender, IOHIDDeviceRef device)
+ {
+ if (NativeMethods.IOHIDDeviceOpen(device, IOOptionBits.Zero) == IOReturn.Zero)
+ {
+ if (NativeMethods.IOHIDDeviceConformsTo(device,
+ HIDPage.GenericDesktop, (int)HIDUsageGD.Mouse))
+ {
+ if (!MouseDevices.ContainsKey(device))
+ {
+ Debug.Print("Mouse device {0} discovered", device);
+ MouseState state = new MouseState();
+ state.IsConnected = true;
+ MouseIndexToDevice.Add(MouseDevices.Count, device);
+ MouseDevices.Add(device, state);
+ }
+ else
+ {
+ Debug.Print("Mouse device {0} reconnected", device);
+ MouseState state = MouseDevices[device];
+ state.IsConnected = true;
+ MouseDevices[device] = state;
+ }
+ }
+
+ if (NativeMethods.IOHIDDeviceConformsTo(device,
+ HIDPage.GenericDesktop, (int)HIDUsageGD.Keyboard))
+ {
+ if (!KeyboardDevices.ContainsKey(device))
+ {
+ Debug.Print("Keyboard device {0} discovered", device);
+ KeyboardState state = new KeyboardState();
+ state.IsConnected = true;
+ KeyboardIndexToDevice.Add(KeyboardDevices.Count, device);
+ KeyboardDevices.Add(device, state);
+ }
+ else
+ {
+ Debug.Print("Keyboard device {0} reconnected", device);
+ KeyboardState state = KeyboardDevices[device];
+ state.IsConnected = true;
+ KeyboardDevices[device] = state;
+ }
+ }
+
+ NativeMethods.IOHIDDeviceRegisterInputValueCallback(device,
+ HandleDeviceValueReceived, IntPtr.Zero);
+ NativeMethods.IOHIDDeviceScheduleWithRunLoop(device, RunLoop, InputLoopMode);
+ }
+ }
+
+ void DeviceRemoved(IntPtr context, IOReturn res, IntPtr sender, IOHIDDeviceRef device)
+ {
+ if (NativeMethods.IOHIDDeviceConformsTo(device, HIDPage.GenericDesktop, (int)HIDUsageGD.Mouse) &&
+ MouseDevices.ContainsKey(device))
+ {
+ Debug.Print("Mouse device {0} disconnected", device);
+
+ // Keep the device in case it comes back later on
+ MouseState state = MouseDevices[device];
+ state.IsConnected = false;
+ MouseDevices[device] = state;
+ }
+
+ if (NativeMethods.IOHIDDeviceConformsTo(device, HIDPage.GenericDesktop, (int)HIDUsageGD.Keyboard) &&
+ KeyboardDevices.ContainsKey(device))
+ {
+ Debug.Print("Keyboard device {0} disconnected", device);
+
+ // Keep the device in case it comes back later on
+ KeyboardState state = KeyboardDevices[device];
+ state.IsConnected = false;
+ KeyboardDevices[device] = state;
+ }
+
+ NativeMethods.IOHIDDeviceRegisterInputValueCallback(device, null, IntPtr.Zero);
+ NativeMethods.IOHIDDeviceUnscheduleWithRunLoop(device, RunLoop, InputLoopMode);
+ }
+
+ void DeviceValueReceived(IntPtr context, IOReturn res, IntPtr sender, IOHIDValueRef val)
+ {
+ MouseState mouse;
+ KeyboardState keyboard;
+ if (MouseDevices.TryGetValue(sender, out mouse))
+ {
+ MouseDevices[sender] = UpdateMouse(mouse, val);
+ }
+ else if (KeyboardDevices.TryGetValue(sender, out keyboard))
+ {
+ KeyboardDevices[sender] = UpdateKeyboard(keyboard, val);
+ }
+ }
+
+ static MouseState UpdateMouse(MouseState state, IOHIDValueRef val)
+ {
+ IOHIDElementRef elem = NativeMethods.IOHIDValueGetElement(val);
+ int v_int = NativeMethods.IOHIDValueGetIntegerValue(val).ToInt32();
+ //double v_physical = NativeMethods.IOHIDValueGetScaledValue(val, IOHIDValueScaleType.Physical);
+ //double v_calbrated = NativeMethods.IOHIDValueGetScaledValue(val, IOHIDValueScaleType.Calibrated);
+ HIDPage page = NativeMethods.IOHIDElementGetUsagePage(elem);
+ int usage = NativeMethods.IOHIDElementGetUsage(elem);
+
+ switch (page)
+ {
+ case HIDPage.GenericDesktop:
+ switch ((HIDUsageGD)usage)
+ {
+ case HIDUsageGD.X:
+ state.X += v_int;
+ break;
+
+ case HIDUsageGD.Y:
+ state.Y += v_int;
+ break;
+
+ case HIDUsageGD.Wheel:
+ state.WheelPrecise += v_int;
+ break;
+ }
+ break;
+
+ case HIDPage.Button:
+ state[OpenTK.Input.MouseButton.Left + usage - 1] = v_int == 1;
+ break;
+ }
+
+ return state;
+ }
+
+ static KeyboardState UpdateKeyboard(KeyboardState state, IOHIDValueRef val)
+ {
+ IOHIDElementRef elem = NativeMethods.IOHIDValueGetElement(val);
+ int v_int = NativeMethods.IOHIDValueGetIntegerValue(val).ToInt32();
+ HIDPage page = NativeMethods.IOHIDElementGetUsagePage(elem);
+ int usage = NativeMethods.IOHIDElementGetUsage(elem);
+
+ switch (page)
+ {
+ case HIDPage.GenericDesktop:
+ case HIDPage.KeyboardOrKeypad:
+ if (usage >= RawKeyMap.Length || usage < 0)
+ Debug.Print("[Warning] Key {0} not mapped.", usage);
+ state.SetKeyState(RawKeyMap[usage], (byte)usage, v_int != 0);
+ break;
+ }
+
+ return state;
+ }
+
+ #endregion
+
+ #region IInputDriver2 Members
+
+ public IMouseDriver2 MouseDriver { get { return this; } }
+ public IKeyboardDriver2 KeyboardDriver { get { return this; } }
+ public IGamePadDriver GamePadDriver { get { throw new NotImplementedException(); } }
+
+ #endregion
+
+ #region IMouseDriver2 Members
+
+ MouseState IMouseDriver2.GetState()
+ {
+ MouseState master = new MouseState();
+ foreach (KeyValuePair<IntPtr, MouseState> item in MouseDevices)
+ {
+ master.MergeBits(item.Value);
+ }
+
+ return master;
+ }
+
+ MouseState IMouseDriver2.GetState(int index)
+ {
+ IntPtr device;
+ if (MouseIndexToDevice.TryGetValue(index, out device))
+ {
+ return MouseDevices[device];
+ }
+
+ return new MouseState();
+ }
+
+ void IMouseDriver2.SetPosition(double x, double y)
+ {
+ CG.SetLocalEventsSuppressionInterval(0.0);
+ CG.WarpMouseCursorPosition(new Carbon.HIPoint(x, y));
+ }
+
+ #endregion
+
+ #region IKeyboardDriver2
+
+ KeyboardState IKeyboardDriver2.GetState()
+ {
+ KeyboardState master = new KeyboardState();
+ foreach (KeyValuePair<IntPtr, KeyboardState> item in KeyboardDevices)
+ {
+ master.MergeBits(item.Value);
+ }
+
+ return master;
+ }
+
+ KeyboardState IKeyboardDriver2.GetState(int index)
+ {
+ IntPtr device;
+ if (KeyboardIndexToDevice.TryGetValue(index, out device))
+ {
+ return KeyboardDevices[device];
+ }
+
+ return new KeyboardState();
+ }
+
+ string IKeyboardDriver2.GetDeviceName(int index)
+ {
+ IntPtr device;
+ if (KeyboardIndexToDevice.TryGetValue(index, out device))
+ {
+ IntPtr vendor_id = NativeMethods.IOHIDDeviceGetProperty(device, NativeMethods.IOHIDVendorIDKey);
+ IntPtr product_id = NativeMethods.IOHIDDeviceGetProperty(device, NativeMethods.IOHIDProductIDKey);
+ // Todo: find out the real vendor/product name from the relevant ids.
+ return String.Format("{0}:{1}", vendor_id, product_id);
+ }
+ return String.Empty;
+ }
+
+ #endregion
+
+ #region NativeMethods
+
+ class NativeMethods
+ {
+ const string hid = "/System/Library/Frameworks/IOKit.framework/Versions/Current/IOKit";
+
+ public static readonly CFString IOHIDVendorIDKey = CF.CFSTR("VendorID");
+ public static readonly CFString IOHIDVendorIDSourceKey = CF.CFSTR("VendorIDSource");
+ public static readonly CFString IOHIDProductIDKey = CF.CFSTR("ProductID");
+ public static readonly CFString IOHIDVersionNumberKey = CF.CFSTR("VersionNumber");
+ public static readonly CFString IOHIDManufacturerKey = CF.CFSTR("Manufacturer");
+ public static readonly CFString IOHIDProductKey = CF.CFSTR("Product");
+ public static readonly CFString IOHIDDeviceUsageKey = CF.CFSTR("DeviceUsage");
+ public static readonly CFString IOHIDDeviceUsagePageKey = CF.CFSTR("DeviceUsagePage");
+ public static readonly CFString IOHIDDeviceUsagePairsKey = CF.CFSTR("DeviceUsagePairs");
+
+ [DllImport(hid)]
+ public static extern IOHIDManagerRef IOHIDManagerCreate(
+ CFAllocatorRef allocator, IOOptionBits options) ;
+
+ // This routine will be called when a new (matching) device is connected.
+ [DllImport(hid)]
+ public static extern void IOHIDManagerRegisterDeviceMatchingCallback(
+ IOHIDManagerRef inIOHIDManagerRef,
+ IOHIDDeviceCallback inIOHIDDeviceCallback,
+ IntPtr inContext);
+
+ // This routine will be called when a (matching) device is disconnected.
+ [DllImport(hid)]
+ public static extern void IOHIDManagerRegisterDeviceRemovalCallback(
+ IOHIDManagerRef inIOHIDManagerRef,
+ IOHIDDeviceCallback inIOHIDDeviceCallback,
+ IntPtr inContext);
+
+ [DllImport(hid)]
+ public static extern void IOHIDManagerScheduleWithRunLoop(
+ IOHIDManagerRef inIOHIDManagerRef,
+ CFRunLoop inCFRunLoop,
+ CFString inCFRunLoopMode);
+
+ [DllImport(hid)]
+ public static extern void IOHIDManagerSetDeviceMatching(
+ IOHIDManagerRef manager,
+ CFDictionaryRef matching) ;
+
+ [DllImport(hid)]
+ public static extern IOReturn IOHIDManagerOpen(
+ IOHIDManagerRef manager,
+ IOOptionBits options) ;
+
+ [DllImport(hid)]
+ public static extern IOReturn IOHIDDeviceOpen(
+ IOHIDDeviceRef manager,
+ IOOptionBits opts);
+
+ [DllImport(hid)]
+ public static extern CFTypeRef IOHIDDeviceGetProperty(
+ IOHIDDeviceRef device,
+ CFStringRef key);
+
+ [DllImport(hid)]
+ public static extern bool IOHIDDeviceConformsTo(
+ IOHIDDeviceRef inIOHIDDeviceRef, // IOHIDDeviceRef for the HID device
+ HIDPage inUsagePage, // the usage page to test conformance with
+ int inUsage); // the usage to test conformance with
+
+ [DllImport(hid)]
+ public static extern void IOHIDDeviceRegisterInputValueCallback(
+ IOHIDDeviceRef device,
+ IOHIDValueCallback callback,
+ IntPtr context);
+
+ [DllImport(hid)]
+ public static extern void IOHIDDeviceScheduleWithRunLoop(
+ IOHIDDeviceRef device,
+ CFRunLoop inCFRunLoop,
+ CFString inCFRunLoopMode);
+
+ [DllImport(hid)]
+ public static extern void IOHIDDeviceUnscheduleWithRunLoop(
+ IOHIDDeviceRef device,
+ CFRunLoop inCFRunLoop,
+ CFString inCFRunLoopMode);
+
+ [DllImport(hid)]
+ public static extern IOHIDElementRef IOHIDValueGetElement(IOHIDValueRef @value);
+
+ [DllImport(hid)]
+ public static extern CFIndex IOHIDValueGetIntegerValue(IOHIDValueRef @value);
+
+ [DllImport(hid)]
+ public static extern double IOHIDValueGetScaledValue(
+ IOHIDValueRef @value,
+ IOHIDValueScaleType type) ;
+
+ [DllImport(hid)]
+ public static extern int IOHIDElementGetUsage(IOHIDElementRef elem);
+
+ [DllImport(hid)]
+ public static extern HIDPage IOHIDElementGetUsagePage(IOHIDElementRef elem);
+
+ public delegate void IOHIDDeviceCallback(IntPtr ctx, IOReturn res, IntPtr sender, IOHIDDeviceRef device);
+ public delegate void IOHIDValueCallback(IntPtr ctx, IOReturn res, IntPtr sender, IOHIDValueRef val);
+ }
+
+ enum IOHIDValueScaleType
+ {
+ Physical, // [device min, device max]
+ Calibrated // [-1, +1]
+ }
+
+ enum HIDPage
+ {
+ Undefined = 0x00,
+ GenericDesktop = 0x01,
+ Simulation = 0x02,
+ VR = 0x03,
+ Sport = 0x04,
+ Game = 0x05,
+ /* Reserved 0x06 */
+ KeyboardOrKeypad = 0x07, /* USB Device Class Definition for Human Interface Devices (HID). Note: the usage type for all key codes is Selector (Sel). */
+ LEDs = 0x08,
+ Button = 0x09,
+ Ordinal = 0x0A,
+ Telephony = 0x0B,
+ Consumer = 0x0C,
+ Digitizer = 0x0D,
+ /* Reserved 0x0E */
+ PID = 0x0F, /* USB Physical Interface Device definitions for force feedback and related devices. */
+ Unicode = 0x10,
+ /* Reserved 0x11 - 0x13 */
+ AlphanumericDisplay = 0x14,
+ /* Reserved 0x15 - 0x7F */
+ /* Monitor 0x80 - 0x83 USB Device Class Definition for Monitor Devices */
+ /* Power 0x84 - 0x87 USB Device Class Definition for Power Devices */
+ PowerDevice = 0x84, /* Power Device Page */
+ BatterySystem = 0x85, /* Battery System Page */
+ /* Reserved 0x88 - 0x8B */
+ BarCodeScanner = 0x8C, /* (Point of Sale) USB Device Class Definition for Bar Code Scanner Devices */
+ WeighingDevice = 0x8D, /* (Point of Sale) USB Device Class Definition for Weighing Devices */
+ Scale = 0x8D, /* (Point of Sale) USB Device Class Definition for Scale Devices */
+ MagneticStripeReader = 0x8E,
+ /* ReservedPointofSalepages 0x8F */
+ CameraControl = 0x90, /* USB Device Class Definition for Image Class Devices */
+ Arcade = 0x91, /* OAAF Definitions for arcade and coinop related Devices */
+ /* Reserved 0x92 - 0xFEFF */
+ /* VendorDefined 0xFF00 - 0xFFFF */
+ VendorDefinedStart = 0xFF00
+ }
+
+ // Generic desktop usage
+ enum HIDUsageGD
+ {
+ Pointer = 0x01, /* Physical Collection */
+ Mouse = 0x02, /* Application Collection */
+ /* 0x03 Reserved */
+ Joystick = 0x04, /* Application Collection */
+ GamePad = 0x05, /* Application Collection */
+ Keyboard = 0x06, /* Application Collection */
+ Keypad = 0x07, /* Application Collection */
+ MultiAxisController = 0x08, /* Application Collection */
+ /* 0x09 - 0x2F Reserved */
+ X = 0x30, /* Dynamic Value */
+ Y = 0x31, /* Dynamic Value */
+ Z = 0x32, /* Dynamic Value */
+ Rx = 0x33, /* Dynamic Value */
+ Ry = 0x34, /* Dynamic Value */
+ Rz = 0x35, /* Dynamic Value */
+ Slider = 0x36, /* Dynamic Value */
+ Dial = 0x37, /* Dynamic Value */
+ Wheel = 0x38, /* Dynamic Value */
+ Hatswitch = 0x39, /* Dynamic Value */
+ CountedBuffer = 0x3A, /* Logical Collection */
+ ByteCount = 0x3B, /* Dynamic Value */
+ MotionWakeup = 0x3C, /* One-Shot Control */
+ Start = 0x3D, /* On/Off Control */
+ Select = 0x3E, /* On/Off Control */
+ /* 0x3F Reserved */
+ Vx = 0x40, /* Dynamic Value */
+ Vy = 0x41, /* Dynamic Value */
+ Vz = 0x42, /* Dynamic Value */
+ Vbrx = 0x43, /* Dynamic Value */
+ Vbry = 0x44, /* Dynamic Value */
+ Vbrz = 0x45, /* Dynamic Value */
+ Vno = 0x46, /* Dynamic Value */
+ /* 0x47 - 0x7F Reserved */
+ SystemControl = 0x80, /* Application Collection */
+ SystemPowerDown = 0x81, /* One-Shot Control */
+ SystemSleep = 0x82, /* One-Shot Control */
+ SystemWakeUp = 0x83, /* One-Shot Control */
+ SystemContextMenu = 0x84, /* One-Shot Control */
+ SystemMainMenu = 0x85, /* One-Shot Control */
+ SystemAppMenu = 0x86, /* One-Shot Control */
+ SystemMenuHelp = 0x87, /* One-Shot Control */
+ SystemMenuExit = 0x88, /* One-Shot Control */
+ SystemMenu = 0x89, /* Selector */
+ SystemMenuRight = 0x8A, /* Re-Trigger Control */
+ SystemMenuLeft = 0x8B, /* Re-Trigger Control */
+ SystemMenuUp = 0x8C, /* Re-Trigger Control */
+ SystemMenuDown = 0x8D, /* Re-Trigger Control */
+ /* 0x8E - 0x8F Reserved */
+ DPadUp = 0x90, /* On/Off Control */
+ DPadDown = 0x91, /* On/Off Control */
+ DPadRight = 0x92, /* On/Off Control */
+ DPadLeft = 0x93, /* On/Off Control */
+ /* 0x94 - 0xFFFF Reserved */
+ Reserved = 0xFFFF
+ }
+
+ enum HIDButton
+ {
+ Button_1 = 0x01, /* (primary/trigger) */
+ Button_2 = 0x02, /* (secondary) */
+ Button_3 = 0x03, /* (tertiary) */
+ Button_4 = 0x04, /* 4th button */
+ /* ... */
+ Button_65535 = 0xFFFF
+ }
+
+ enum HIDKey
+ {
+ ErrorRollOver = 0x01, /* ErrorRollOver */
+ POSTFail = 0x02, /* POSTFail */
+ ErrorUndefined = 0x03, /* ErrorUndefined */
+ A = 0x04, /* a or A */
+ B = 0x05, /* b or B */
+ C = 0x06, /* c or C */
+ D = 0x07, /* d or D */
+ E = 0x08, /* e or E */
+ F = 0x09, /* f or F */
+ G = 0x0A, /* g or G */
+ H = 0x0B, /* h or H */
+ I = 0x0C, /* i or I */
+ J = 0x0D, /* j or J */
+ K = 0x0E, /* k or K */
+ L = 0x0F, /* l or L */
+ M = 0x10, /* m or M */
+ N = 0x11, /* n or N */
+ O = 0x12, /* o or O */
+ P = 0x13, /* p or P */
+ Q = 0x14, /* q or Q */
+ R = 0x15, /* r or R */
+ S = 0x16, /* s or S */
+ T = 0x17, /* t or T */
+ U = 0x18, /* u or U */
+ V = 0x19, /* v or V */
+ W = 0x1A, /* w or W */
+ X = 0x1B, /* x or X */
+ Y = 0x1C, /* y or Y */
+ Z = 0x1D, /* z or Z */
+ Number1 = 0x1E, /* 1 or ! */
+ Number2 = 0x1F, /* 2 or @ */
+ Number3 = 0x20, /* 3 or # */
+ Number4 = 0x21, /* 4 or $ */
+ Number5 = 0x22, /* 5 or % */
+ Number6 = 0x23, /* 6 or ^ */
+ Number7 = 0x24, /* 7 or & */
+ Number8 = 0x25, /* 8 or * */
+ Number9 = 0x26, /* 9 or ( */
+ Number0 = 0x27, /* 0 or ) */
+ ReturnOrEnter = 0x28, /* Return (Enter) */
+ Escape = 0x29, /* Escape */
+ DeleteOrBackspace = 0x2A, /* Delete (Backspace) */
+ Tab = 0x2B, /* Tab */
+ Spacebar = 0x2C, /* Spacebar */
+ Hyphen = 0x2D, /* - or _ */
+ EqualSign = 0x2E, /* = or + */
+ OpenBracket = 0x2F, /* [ or { */
+ CloseBracket = 0x30, /* ] or } */
+ Backslash = 0x31, /* \ or | */
+ NonUSPound = 0x32, /* Non-US # or _ */
+ Semicolon = 0x33, /* ; or : */
+ Quote = 0x34, /* ' or " */
+ GraveAccentAndTilde = 0x35, /* Grave Accent and Tilde */
+ Comma = 0x36, /* , or < */
+ Period = 0x37, /* . or > */
+ Slash = 0x38, /* / or ? */
+ CapsLock = 0x39, /* Caps Lock */
+ F1 = 0x3A, /* F1 */
+ F2 = 0x3B, /* F2 */
+ F3 = 0x3C, /* F3 */
+ F4 = 0x3D, /* F4 */
+ F5 = 0x3E, /* F5 */
+ F6 = 0x3F, /* F6 */
+ F7 = 0x40, /* F7 */
+ F8 = 0x41, /* F8 */
+ F9 = 0x42, /* F9 */
+ F10 = 0x43, /* F10 */
+ F11 = 0x44, /* F11 */
+ F12 = 0x45, /* F12 */
+ PrintScreen = 0x46, /* Print Screen */
+ ScrollLock = 0x47, /* Scroll Lock */
+ Pause = 0x48, /* Pause */
+ Insert = 0x49, /* Insert */
+ Home = 0x4A, /* Home */
+ PageUp = 0x4B, /* Page Up */
+ DeleteForward = 0x4C, /* Delete Forward */
+ End = 0x4D, /* End */
+ PageDown = 0x4E, /* Page Down */
+ RightArrow = 0x4F, /* Right Arrow */
+ LeftArrow = 0x50, /* Left Arrow */
+ DownArrow = 0x51, /* Down Arrow */
+ UpArrow = 0x52, /* Up Arrow */
+ KeypadNumLock = 0x53, /* Keypad NumLock or Clear */
+ KeypadSlash = 0x54, /* Keypad / */
+ KeypadAsterisk = 0x55, /* Keypad * */
+ KeypadHyphen = 0x56, /* Keypad - */
+ KeypadPlus = 0x57, /* Keypad + */
+ KeypadEnter = 0x58, /* Keypad Enter */
+ Keypad1 = 0x59, /* Keypad 1 or End */
+ Keypad2 = 0x5A, /* Keypad 2 or Down Arrow */
+ Keypad3 = 0x5B, /* Keypad 3 or Page Down */
+ Keypad4 = 0x5C, /* Keypad 4 or Left Arrow */
+ Keypad5 = 0x5D, /* Keypad 5 */
+ Keypad6 = 0x5E, /* Keypad 6 or Right Arrow */
+ Keypad7 = 0x5F, /* Keypad 7 or Home */
+ Keypad8 = 0x60, /* Keypad 8 or Up Arrow */
+ Keypad9 = 0x61, /* Keypad 9 or Page Up */
+ Keypad0 = 0x62, /* Keypad 0 or Insert */
+ KeypadPeriod = 0x63, /* Keypad . or Delete */
+ NonUSBackslash = 0x64, /* Non-US \ or | */
+ Application = 0x65, /* Application */
+ Power = 0x66, /* Power */
+ KeypadEqualSign = 0x67, /* Keypad = */
+ F13 = 0x68, /* F13 */
+ F14 = 0x69, /* F14 */
+ F15 = 0x6A, /* F15 */
+ F16 = 0x6B, /* F16 */
+ F17 = 0x6C, /* F17 */
+ F18 = 0x6D, /* F18 */
+ F19 = 0x6E, /* F19 */
+ F20 = 0x6F, /* F20 */
+ F21 = 0x70, /* F21 */
+ F22 = 0x71, /* F22 */
+ F23 = 0x72, /* F23 */
+ F24 = 0x73, /* F24 */
+ Execute = 0x74, /* Execute */
+ Help = 0x75, /* Help */
+ Menu = 0x76, /* Menu */
+ Select = 0x77, /* Select */
+ Stop = 0x78, /* Stop */
+ Again = 0x79, /* Again */
+ Undo = 0x7A, /* Undo */
+ Cut = 0x7B, /* Cut */
+ Copy = 0x7C, /* Copy */
+ Paste = 0x7D, /* Paste */
+ Find = 0x7E, /* Find */
+ Mute = 0x7F, /* Mute */
+ VolumeUp = 0x80, /* Volume Up */
+ VolumeDown = 0x81, /* Volume Down */
+ LockingCapsLock = 0x82, /* Locking Caps Lock */
+ LockingNumLock = 0x83, /* Locking Num Lock */
+ LockingScrollLock = 0x84, /* Locking Scroll Lock */
+ KeypadComma = 0x85, /* Keypad Comma */
+ KeypadEqualSignAS400 = 0x86, /* Keypad Equal Sign for AS/400 */
+ International1 = 0x87, /* International1 */
+ International2 = 0x88, /* International2 */
+ International3 = 0x89, /* International3 */
+ International4 = 0x8A, /* International4 */
+ International5 = 0x8B, /* International5 */
+ International6 = 0x8C, /* International6 */
+ International7 = 0x8D, /* International7 */
+ International8 = 0x8E, /* International8 */
+ International9 = 0x8F, /* International9 */
+ LANG1 = 0x90, /* LANG1 */
+ LANG2 = 0x91, /* LANG2 */
+ LANG3 = 0x92, /* LANG3 */
+ LANG4 = 0x93, /* LANG4 */
+ LANG5 = 0x94, /* LANG5 */
+ LANG6 = 0x95, /* LANG6 */
+ LANG7 = 0x96, /* LANG7 */
+ LANG8 = 0x97, /* LANG8 */
+ LANG9 = 0x98, /* LANG9 */
+ AlternateErase = 0x99, /* AlternateErase */
+ SysReqOrAttention = 0x9A, /* SysReq/Attention */
+ Cancel = 0x9B, /* Cancel */
+ Clear = 0x9C, /* Clear */
+ Prior = 0x9D, /* Prior */
+ Return = 0x9E, /* Return */
+ Separator = 0x9F, /* Separator */
+ Out = 0xA0, /* Out */
+ Oper = 0xA1, /* Oper */
+ ClearOrAgain = 0xA2, /* Clear/Again */
+ CrSelOrProps = 0xA3, /* CrSel/Props */
+ ExSel = 0xA4, /* ExSel */
+ /* 0xA5-0xDF Reserved */
+ LeftControl = 0xE0, /* Left Control */
+ LeftShift = 0xE1, /* Left Shift */
+ LeftAlt = 0xE2, /* Left Alt */
+ LeftGUI = 0xE3, /* Left GUI */
+ RightControl = 0xE4, /* Right Control */
+ RightShift = 0xE5, /* Right Shift */
+ RightAlt = 0xE6, /* Right Alt */
+ RightGUI = 0xE7, /* Right GUI */
+ /* 0xE8-0xFFFF Reserved */
+ //_Reserved = 0xFFFF
+ }
+
+ // Maps HIDKey to OpenTK.Input.Key.
+ static readonly Key[] RawKeyMap = new Key[]
+ {
+ Key.Unknown,
+ Key.Unknown, /* ErrorRollOver */
+ Key.Unknown, /* POSTFail */
+ Key.Unknown, /* ErrorUndefined */
+ Key.A, /* a or A */
+ Key.B, /* b or B */
+ Key.C, /* c or C */
+ Key.D, /* d or D */
+ Key.E, /* e or E */
+ Key.F, /* f or F */
+ Key.G, /* g or G */
+ Key.H, /* h or H */
+ Key.I, /* i or I */
+ Key.J, /* j or J */
+ Key.K, /* k or K */
+ Key.L, /* l or L */
+ Key.M, /* m or M */
+ Key.N, /* n or N */
+ Key.O, /* o or O */
+ Key.P, /* p or P */
+ Key.Q, /* q or Q */
+ Key.R, /* r or R */
+ Key.S, /* s or S */
+ Key.T, /* t or T */
+ Key.U, /* u or U */
+ Key.V, /* v or V */
+ Key.W, /* w or W */
+ Key.X, /* x or X */
+ Key.Y, /* y or Y */
+ Key.Z, /* z or Z */
+ Key.Number1, /* 1 or ! */
+ Key.Number2, /* 2 or @ */
+ Key.Number3, /* 3 or # */
+ Key.Number4, /* 4 or $ */
+ Key.Number5, /* 5 or % */
+ Key.Number6, /* 6 or ^ */
+ Key.Number7, /* 7 or & */
+ Key.Number8, /* 8 or * */
+ Key.Number9, /* 9 or ( */
+ Key.Number0, /* 0 or ) */
+ Key.Enter, /* Return (Enter) */
+ Key.Escape, /* Escape */
+ Key.BackSpace, /* Delete (Backspace) */
+ Key.Tab, /* Tab */
+ Key.Space, /* Spacebar */
+ Key.Minus, /* - or _ */
+ Key.Plus, /* = or + */
+ Key.BracketLeft, /* [ or { */
+ Key.BracketRight, /* ] or } */
+ Key.BackSlash, /* \ or | */
+ Key.Minus, /* Non-US # or _ */
+ Key.Semicolon, /* ; or : */
+ Key.Quote, /* ' or " */
+ Key.Tilde, /* Grave Accent and Tilde */
+ Key.Comma, /* , or < */
+ Key.Period, /* . or > */
+ Key.Slash, /* / or ? */
+ Key.CapsLock, /* Caps Lock */
+ Key.F1, /* F1 */
+ Key.F2, /* F2 */
+ Key.F3, /* F3 */
+ Key.F4, /* F4 */
+ Key.F5, /* F5 */
+ Key.F6, /* F6 */
+ Key.F7, /* F7 */
+ Key.F8, /* F8 */
+ Key.F9, /* F9 */
+ Key.F10, /* F10 */
+ Key.F11, /* F11 */
+ Key.F12, /* F12 */
+ Key.PrintScreen, /* Print Screen */
+ Key.ScrollLock, /* Scroll Lock */
+ Key.Pause, /* Pause */
+ Key.Insert, /* Insert */
+ Key.Home, /* Home */
+ Key.PageUp, /* Page Up */
+ Key.Delete, /* Delete Forward */
+ Key.End, /* End */
+ Key.PageDown, /* Page Down */
+ Key.Right, /* Right Arrow */
+ Key.Left, /* Left Arrow */
+ Key.Down, /* Down Arrow */
+ Key.Up, /* Up Arrow */
+ Key.NumLock, /* Keypad NumLock or Clear */
+ Key.KeypadDivide, /* Keypad / */
+ Key.KeypadMultiply, /* Keypad * */
+ Key.KeypadMinus, /* Keypad - */
+ Key.KeypadPlus, /* Keypad + */
+ Key.KeypadEnter, /* Keypad Enter */
+ Key.Keypad1, /* Keypad 1 or End */
+ Key.Keypad2, /* Keypad 2 or Down Arrow */
+ Key.Keypad3, /* Keypad 3 or Page Down */
+ Key.Keypad4, /* Keypad 4 or Left Arrow */
+ Key.Keypad5, /* Keypad 5 */
+ Key.Keypad6, /* Keypad 6 or Right Arrow */
+ Key.Keypad7, /* Keypad 7 or Home */
+ Key.Keypad8, /* Keypad 8 or Up Arrow */
+ Key.Keypad9, /* Keypad 9 or Page Up */
+ Key.Keypad0, /* Keypad 0 or Insert */
+ Key.KeypadDecimal, /* Keypad . or Delete */
+ Key.BackSlash, /* Non-US \ or | */
+ Key.Unknown, /* Application */
+ Key.Unknown, /* Power */
+ Key.Unknown, /* Keypad = */
+ Key.F13, /* F13 */
+ Key.F14, /* F14 */
+ Key.F15, /* F15 */
+ Key.F16, /* F16 */
+ Key.F17, /* F17 */
+ Key.F18, /* F18 */
+ Key.F19, /* F19 */
+ Key.F20, /* F20 */
+ Key.F21, /* F21 */
+ Key.F22, /* F22 */
+ Key.F23, /* F23 */
+ Key.F24, /* F24 */
+ Key.Unknown, /* Execute */
+ Key.Unknown, /* Help */
+ Key.Menu, /* Menu */
+ Key.Unknown, /* Select */
+ Key.Unknown, /* Stop */
+ Key.Unknown, /* Again */
+ Key.Unknown, /* Undo */
+ Key.Unknown, /* Cut */
+ Key.Unknown, /* Copy */
+ Key.Unknown, /* Paste */
+ Key.Unknown, /* Find */
+ Key.Unknown, /* Mute */
+ Key.Unknown, /* Volume Up */
+ Key.Unknown, /* Volume Down */
+ Key.CapsLock, /* Locking Caps Lock */
+ Key.NumLock , /* Locking Num Lock */
+ Key.ScrollLock, /* Locking Scroll Lock */
+ Key.KeypadDecimal, /* Keypad Comma */
+ Key.Unknown, /* Keypad Equal Sign for AS/400 */
+ Key.Unknown, /* International1 */
+ Key.Unknown, /* International2 */
+ Key.Unknown, /* International3 */
+ Key.Unknown, /* International4 */
+ Key.Unknown, /* International5 */
+ Key.Unknown, /* International6 */
+ Key.Unknown, /* International7 */
+ Key.Unknown, /* International8 */
+ Key.Unknown, /* International9 */
+ Key.Unknown, /* LANG1 */
+ Key.Unknown, /* LANG2 */
+ Key.Unknown, /* LANG3 */
+ Key.Unknown, /* LANG4 */
+ Key.Unknown, /* LANG5 */
+ Key.Unknown, /* LANG6 */
+ Key.Unknown, /* LANG7 */
+ Key.Unknown, /* LANG8 */
+ Key.Unknown, /* LANG9 */
+ Key.Unknown, /* AlternateErase */
+ Key.Unknown, /* SysReq/Attention */
+ Key.Unknown, /* Cancel */
+ Key.Unknown, /* Clear */
+ Key.Unknown, /* Prior */
+ Key.Enter, /* Return */
+ Key.Unknown, /* Separator */
+ Key.Unknown, /* Out */
+ Key.Unknown, /* Oper */
+ Key.Unknown, /* Clear/Again */
+ Key.Unknown, /* CrSel/Props */
+ Key.Unknown, /* ExSel */
+ /* 0xA5-0xDF Reserved */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ Key.LControl, /* Left Control */
+ Key.LShift, /* Left Shift */
+ Key.LAlt, /* Left Alt */
+ Key.LWin, /* Left GUI */
+ Key.RControl, /* Right Control */
+ Key.RShift, /* Right Shift */
+ Key.RAlt, /* Right Alt */
+ Key.RWin, /* Right GUI */
+ /* 0xE8-0xFFFF Reserved */
+ };
+
+ #endregion
+ }
+}
+
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/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/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/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;