Implemented KeyboardState.IsConnected property.

Implemented WinRawKeyboard.RefreshDevices().
General code clean-up and beautification.
This commit is contained in:
the_fiddler 2010-10-29 11:46:57 +00:00
parent eba9fef913
commit 2c5e7220c3
3 changed files with 210 additions and 217 deletions

View file

@ -43,6 +43,7 @@ namespace OpenTK.Input
const int NumInts = ((int)Key.LastKey + IntSize - 1) / IntSize;
// The following line triggers bogus CS0214 in gmcs 2.0.1, sigh...
unsafe fixed int Keys[NumInts];
bool is_connected;
#endregion
@ -84,6 +85,12 @@ namespace OpenTK.Input
return !ReadBit((int)key);
}
public bool IsConnected
{
get { return is_connected; }
internal set { is_connected = value; }
}
/// <summary>
/// Checks whether two <see cref="KeyboardState" /> instances are equal.
/// </summary>
@ -219,6 +226,7 @@ namespace OpenTK.Input
*(k1 + i) |= *(k2 + i);
}
}
IsConnected |= other.IsConnected;
}
#endregion

View file

@ -25,170 +25,103 @@
//
#endregion
#region --- Using directives ---
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using OpenTK.Input;
#endregion
namespace OpenTK.Platform.Windows
{
internal class WinRawKeyboard : IKeyboardDriver2
sealed class WinRawKeyboard : IKeyboardDriver2
{
readonly List<KeyboardState> keyboards = new List<KeyboardState>();
readonly List<string> names = new List<string>();
// ContextHandle instead of IntPtr for fast dictionary access
readonly Dictionary<ContextHandle, int> rawids = new Dictionary<ContextHandle, int>();
private List<KeyboardDevice> keyboards_old = new List<KeyboardDevice>();
private IntPtr window;
readonly IntPtr window;
readonly object UpdateLock = new object();
#region --- Constructors ---
#region Constructors
internal WinRawKeyboard()
: this(IntPtr.Zero)
{
}
internal WinRawKeyboard(IntPtr windowHandle)
public WinRawKeyboard(IntPtr windowHandle)
{
Debug.WriteLine("Initializing keyboard driver (WinRawKeyboard).");
Debug.Indent();
this.window = windowHandle;
UpdateKeyboardList();
RefreshDevices();
Debug.Unindent();
}
#endregion
#region UpdateKeyboardList
#region Public Members
internal void UpdateKeyboardList()
public void RefreshDevices()
{
int count = WinRawInput.DeviceCount;
RawInputDeviceList[] ridl = new RawInputDeviceList[count];
for (int i = 0; i < count; i++)
ridl[i] = new RawInputDeviceList();
Functions.GetRawInputDeviceList(ridl, ref count, API.RawInputDeviceListSize);
// Discover keyboard devices:
for (int i = 0; i < count; i++)
lock (UpdateLock)
{
uint size = 0;
Functions.GetRawInputDeviceInfo(ridl[i].Device, RawInputDeviceInfoEnum.DEVICENAME, IntPtr.Zero, ref size);
IntPtr name_ptr = Marshal.AllocHGlobal((IntPtr)size);
Functions.GetRawInputDeviceInfo(ridl[i].Device, RawInputDeviceInfoEnum.DEVICENAME, name_ptr, ref size);
string name = Marshal.PtrToStringAnsi(name_ptr);
Marshal.FreeHGlobal(name_ptr);
if (name.ToLower().Contains("root"))
for (int i = 0; i < keyboards.Count; i++)
{
// This is a terminal services device, skip it.
continue;
KeyboardState state = keyboards[i];
state.IsConnected = false;
keyboards[i] = state;
}
else if (ridl[i].Type == RawInputDeviceType.KEYBOARD || ridl[i].Type == RawInputDeviceType.HID)
int count = WinRawInput.DeviceCount;
RawInputDeviceList[] ridl = new RawInputDeviceList[count];
for (int i = 0; i < count; i++)
ridl[i] = new RawInputDeviceList();
Functions.GetRawInputDeviceList(ridl, ref count, API.RawInputDeviceListSize);
// Discover keyboard devices:
foreach (RawInputDeviceList dev in ridl)
{
// This is a keyboard or USB keyboard device. In the latter case, discover if it really is a
// keyboard device by qeurying the registry.
// remove the \??\
name = name.Substring(4);
string[] split = name.Split('#');
string id_01 = split[0]; // ACPI (Class code)
string id_02 = split[1]; // PNP0303 (SubClass code)
string id_03 = split[2]; // 3&13c0b0c5&0 (Protocol code)
// The final part is the class GUID and is not needed here
string findme = string.Format(
@"System\CurrentControlSet\Enum\{0}\{1}\{2}",
id_01, id_02, id_03);
RegistryKey regkey = Registry.LocalMachine.OpenSubKey(findme);
string deviceDesc =
(string)regkey.GetValue("DeviceDesc");
string deviceClass =
(string)regkey.GetValue("Class");
if (!String.IsNullOrEmpty(deviceClass) && deviceClass.ToLower().Equals("keyboard"))
string name = GetDeviceName(dev);
if (name.ToLower().Contains("root"))
{
KeyboardDevice kb = new KeyboardDevice();
kb.Description = deviceDesc;
// This is a terminal services device, skip it.
continue;
}
else if (dev.Type == RawInputDeviceType.KEYBOARD || dev.Type == RawInputDeviceType.HID)
{
// This is a keyboard or USB keyboard device. In the latter case, discover if it really is a
// keyboard device by qeurying the registry.
RegistryKey regkey = GetRegistryKey(name);
string deviceDesc = (string)regkey.GetValue("DeviceDesc");
string deviceClass = (string)regkey.GetValue("Class");
deviceDesc = deviceDesc.Substring(deviceDesc.LastIndexOf(';') + 1);
// Register the keyboard:
RawInputDeviceInfo info = new RawInputDeviceInfo();
int devInfoSize = API.RawInputDeviceInfoSize;
Functions.GetRawInputDeviceInfo(ridl[i].Device, RawInputDeviceInfoEnum.DEVICEINFO,
info, ref devInfoSize);
if (!String.IsNullOrEmpty(deviceClass) && deviceClass.ToLower().Equals("keyboard"))
{
// Register the keyboard:
RawInputDeviceInfo info = new RawInputDeviceInfo();
int devInfoSize = API.RawInputDeviceInfoSize;
Functions.GetRawInputDeviceInfo(dev.Device, RawInputDeviceInfoEnum.DEVICEINFO,
info, ref devInfoSize);
kb.NumberOfLeds = info.Device.Keyboard.NumberOfIndicators;
kb.NumberOfFunctionKeys = info.Device.Keyboard.NumberOfFunctionKeys;
kb.NumberOfKeys = info.Device.Keyboard.NumberOfKeysTotal;
//kb.DeviceID = (info.Device.Keyboard.Type << 32) + info.Device.Keyboard.SubType;
kb.DeviceID = ridl[i].Device;
//KeyboardDevice kb = new KeyboardDevice();
//kb.Description = deviceDesc;
//kb.NumberOfLeds = info.Device.Keyboard.NumberOfIndicators;
//kb.NumberOfFunctionKeys = info.Device.Keyboard.NumberOfFunctionKeys;
//kb.NumberOfKeys = info.Device.Keyboard.NumberOfKeysTotal;
//kb.DeviceID = dev.Device;
//if (!keyboards.Contains(kb))
//{
this.RegisterKeyboardDevice(kb);
keyboards_old.Add(kb);
//}
keyboards.Add(new KeyboardState());
names.Add(deviceDesc);
rawids.Add(new ContextHandle(ridl[i].Device), keyboards.Count - 1);
RegisterKeyboardDevice(window, deviceDesc);
KeyboardState state = new KeyboardState();
state.IsConnected = true;
keyboards.Add(state);
names.Add(deviceDesc);
rawids.Add(new ContextHandle(dev.Device), keyboards.Count - 1);
}
}
}
}
}
#endregion
#region internal void RegisterKeyboardDevice(Keyboard kb)
internal void RegisterKeyboardDevice(KeyboardDevice kb)
{
RawInputDevice[] rid = new RawInputDevice[1];
// Keyboard is 1/6 (page/id). See http://www.microsoft.com/whdc/device/input/HID_HWID.mspx
rid[0] = new RawInputDevice();
rid[0].UsagePage = 1;
rid[0].Usage = 6;
rid[0].Flags = RawInputDeviceFlags.INPUTSINK;
rid[0].Target = window;
if (!Functions.RegisterRawInputDevices(rid, 1, API.RawInputDeviceSize))
{
throw new ApplicationException(
String.Format(
"Raw input registration failed with error: {0}. Device: {1}",
Marshal.GetLastWin32Error(),
rid[0].ToString())
);
}
else
{
Debug.Print("Registered keyboard {0}", kb.ToString());
}
}
#endregion
#region internal bool ProcessKeyboardEvent(API.RawInput rin)
/// <summary>
/// Processes raw input events.
/// </summary>
/// <param name="rin"></param>
/// <returns></returns>
internal bool ProcessKeyboardEvent(RawInput rin)
public bool ProcessKeyboardEvent(RawInput rin)
{
bool processed = false;
@ -200,8 +133,7 @@ namespace OpenTK.Platform.Windows
KeyboardState keyboard;
if (!rawids.ContainsKey(handle))
{
keyboards.Add(new KeyboardState());
rawids.Add(handle, keyboards.Count - 1);
RefreshDevices();
}
keyboard = keyboards[rawids[handle]];
@ -247,21 +179,63 @@ namespace OpenTK.Platform.Windows
#endregion
#region --- IInputDevice Members ---
#region Private Members
public string Description
static RegistryKey GetRegistryKey(string name)
{
get { throw new Exception("The method or operation is not implemented."); }
// remove the \??\
name = name.Substring(4);
string[] split = name.Split('#');
string id_01 = split[0]; // ACPI (Class code)
string id_02 = split[1]; // PNP0303 (SubClass code)
string id_03 = split[2]; // 3&13c0b0c5&0 (Protocol code)
// The final part is the class GUID and is not needed here
string findme = string.Format(
@"System\CurrentControlSet\Enum\{0}\{1}\{2}",
id_01, id_02, id_03);
RegistryKey regkey = Registry.LocalMachine.OpenSubKey(findme);
return regkey;
}
public Input.InputDeviceType DeviceType
static string GetDeviceName(RawInputDeviceList dev)
{
get { return Input.InputDeviceType.Keyboard; }
uint size = 0;
Functions.GetRawInputDeviceInfo(dev.Device, RawInputDeviceInfoEnum.DEVICENAME, IntPtr.Zero, ref size);
IntPtr name_ptr = Marshal.AllocHGlobal((IntPtr)size);
Functions.GetRawInputDeviceInfo(dev.Device, RawInputDeviceInfoEnum.DEVICENAME, name_ptr, ref size);
string name = Marshal.PtrToStringAnsi(name_ptr);
Marshal.FreeHGlobal(name_ptr);
return name;
}
static void RegisterKeyboardDevice(IntPtr window, string name)
{
RawInputDevice[] rid = new RawInputDevice[1];
// Keyboard is 1/6 (page/id). See http://www.microsoft.com/whdc/device/input/HID_HWID.mspx
rid[0] = new RawInputDevice();
rid[0].UsagePage = 1;
rid[0].Usage = 6;
rid[0].Flags = RawInputDeviceFlags.INPUTSINK;
rid[0].Target = window;
if (!Functions.RegisterRawInputDevices(rid, 1, API.RawInputDeviceSize))
{
Debug.Print("[Warning] Raw input registration failed with error: {0}. Device: {1}",
Marshal.GetLastWin32Error(), rid[0].ToString());
}
else
{
Debug.Print("Registered keyboard {0}", name);
}
}
#endregion
#region --- IKeyboardDriver Members ---
#region IKeyboardDriver2 Members
public KeyboardState GetState()
{

View file

@ -28,7 +28,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using OpenTK.Input;
@ -39,7 +38,7 @@ namespace OpenTK.Platform.Windows
/// <summary>
/// Contains methods to register for and process mouse WM_INPUT messages.
/// </summary>
internal class WinRawMouse : IMouseDriver2
sealed class WinRawMouse : IMouseDriver2
{
readonly List<MouseState> mice = new List<MouseState>();
readonly List<string> names = new List<string>();
@ -47,6 +46,8 @@ namespace OpenTK.Platform.Windows
readonly IntPtr Window;
readonly object UpdateLock = new object();
#region Constructors
public WinRawMouse(IntPtr window)
{
Debug.WriteLine("Initializing mouse driver (WinRawMouse).");
@ -61,34 +62,10 @@ namespace OpenTK.Platform.Windows
Debug.Unindent();
}
#region IMouseDriver Members
public MouseState GetState()
{
lock (UpdateLock)
{
MouseState master = new MouseState();
foreach (MouseState ms in mice)
{
master.MergeBits(ms);
}
return master;
}
}
public MouseState GetState(int index)
{
lock (UpdateLock)
{
if (mice.Count > index)
return mice[index];
else
return new MouseState();
}
}
#endregion
#region Public Members
public void RefreshDevices()
{
lock (UpdateLock)
@ -134,8 +111,8 @@ namespace OpenTK.Platform.Windows
// mouse device by qeurying the registry.
RegistryKey regkey = FindRegistryKey(name);
string deviceDesc = (string)regkey.GetValue("DeviceDesc");
deviceDesc = deviceDesc.Substring(deviceDesc.LastIndexOf(';') + 1);
string deviceClass = (string)regkey.GetValue("Class");
deviceDesc = deviceDesc.Substring(deviceDesc.LastIndexOf(';') + 1);
if (!String.IsNullOrEmpty(deviceClass) && deviceClass.ToLower().Equals("mouse"))
{
@ -147,7 +124,7 @@ namespace OpenTK.Platform.Windows
Functions.GetRawInputDeviceInfo(dev.Device, RawInputDeviceInfoEnum.DEVICEINFO,
info, ref devInfoSize);
RegisterRawDevice(deviceDesc, Window);
RegisterRawDevice(Window, deviceDesc);
MouseState state = new MouseState();
state.IsConnected = true;
mice.Add(state);
@ -160,62 +137,6 @@ namespace OpenTK.Platform.Windows
}
}
static string GetDeviceName(RawInputDeviceList dev)
{
// get name size
uint size = 0;
Functions.GetRawInputDeviceInfo(dev.Device, RawInputDeviceInfoEnum.DEVICENAME, IntPtr.Zero, ref size);
// get actual name
IntPtr name_ptr = Marshal.AllocHGlobal((IntPtr)size);
Functions.GetRawInputDeviceInfo(dev.Device, RawInputDeviceInfoEnum.DEVICENAME, name_ptr, ref size);
string name = Marshal.PtrToStringAnsi(name_ptr);
Marshal.FreeHGlobal(name_ptr);
return name;
}
static RegistryKey FindRegistryKey(string name)
{
// remove the \??\
name = name.Substring(4);
string[] split = name.Split('#');
string id_01 = split[0]; // ACPI (Class code)
string id_02 = split[1]; // PNP0303 (SubClass code)
string id_03 = split[2]; // 3&13c0b0c5&0 (Protocol code)
// The final part is the class GUID and is not needed here
string findme = string.Format(
@"System\CurrentControlSet\Enum\{0}\{1}\{2}",
id_01, id_02, id_03);
RegistryKey regkey = Registry.LocalMachine.OpenSubKey(findme);
return regkey;
}
static void RegisterRawDevice(string device, IntPtr window)
{
RawInputDevice[] rid = new RawInputDevice[1];
// Mouse is 1/2 (page/id). See http://www.microsoft.com/whdc/device/input/HID_HWID.mspx
rid[0] = new RawInputDevice();
rid[0].UsagePage = 1;
rid[0].Usage = 2;
rid[0].Flags = RawInputDeviceFlags.INPUTSINK;
rid[0].Target = window;
if (!Functions.RegisterRawInputDevices(rid, 1, API.RawInputDeviceSize))
{
Debug.Print("[Warning] Raw input registration failed with error: {0}. Device: {1}",
Marshal.GetLastWin32Error(), rid[0].ToString());
}
else
{
Debug.Print("Registered mouse {0}", device);
}
}
public bool ProcessMouseEvent(RawInput rin)
{
RawMouse raw = rin.Data.Mouse;
@ -259,5 +180,95 @@ namespace OpenTK.Platform.Windows
return true;
}
}
#endregion
#region Private Members
static string GetDeviceName(RawInputDeviceList dev)
{
// get name size
uint size = 0;
Functions.GetRawInputDeviceInfo(dev.Device, RawInputDeviceInfoEnum.DEVICENAME, IntPtr.Zero, ref size);
// get actual name
IntPtr name_ptr = Marshal.AllocHGlobal((IntPtr)size);
Functions.GetRawInputDeviceInfo(dev.Device, RawInputDeviceInfoEnum.DEVICENAME, name_ptr, ref size);
string name = Marshal.PtrToStringAnsi(name_ptr);
Marshal.FreeHGlobal(name_ptr);
return name;
}
static RegistryKey FindRegistryKey(string name)
{
// remove the \??\
name = name.Substring(4);
string[] split = name.Split('#');
string id_01 = split[0]; // ACPI (Class code)
string id_02 = split[1]; // PNP0303 (SubClass code)
string id_03 = split[2]; // 3&13c0b0c5&0 (Protocol code)
// The final part is the class GUID and is not needed here
string findme = string.Format(
@"System\CurrentControlSet\Enum\{0}\{1}\{2}",
id_01, id_02, id_03);
RegistryKey regkey = Registry.LocalMachine.OpenSubKey(findme);
return regkey;
}
static void RegisterRawDevice(IntPtr window, string device)
{
RawInputDevice[] rid = new RawInputDevice[1];
// Mouse is 1/2 (page/id). See http://www.microsoft.com/whdc/device/input/HID_HWID.mspx
rid[0] = new RawInputDevice();
rid[0].UsagePage = 1;
rid[0].Usage = 2;
rid[0].Flags = RawInputDeviceFlags.INPUTSINK;
rid[0].Target = window;
if (!Functions.RegisterRawInputDevices(rid, 1, API.RawInputDeviceSize))
{
Debug.Print("[Warning] Raw input registration failed with error: {0}. Device: {1}",
Marshal.GetLastWin32Error(), rid[0].ToString());
}
else
{
Debug.Print("Registered mouse {0}", device);
}
}
#endregion
#region IMouseDriver2 Members
public MouseState GetState()
{
lock (UpdateLock)
{
MouseState master = new MouseState();
foreach (MouseState ms in mice)
{
master.MergeBits(ms);
}
return master;
}
}
public MouseState GetState(int index)
{
lock (UpdateLock)
{
if (mice.Count > index)
return mice[index];
else
return new MouseState();
}
}
#endregion
}
}