Decoupled new driver API from old public interface.

WinRawMouse can now detect mouse disconnection/connection events.
This commit is contained in:
the_fiddler 2010-10-29 11:27:40 +00:00
parent 2ea1b56b9d
commit 2934c9d004
26 changed files with 289 additions and 415 deletions

View file

@ -253,7 +253,6 @@ namespace OpenTK
//event EventHandler<KeyEventArgs> KeyDown;
//event EventHandler<KeyEventArgs> KeyUp;
//event EventHandler<DragEventArgs> DragDrop;
//event EventHandler<DragEventArgs> DragEnter;

View file

@ -34,8 +34,8 @@ namespace OpenTK.Input
// Defines the interface for a 2nd generation input driver.
interface IInputDriver2
{
IMouseDriver MouseDriver { get; }
IKeyboardDriver KeyboardDriver { get; }
IJoystickDriver JoystickDriver { get; }
IMouseDriver2 MouseDriver { get; }
IKeyboardDriver2 KeyboardDriver { get; }
IGamePadDriver GamePadDriver { get; }
}
}

View file

@ -34,6 +34,7 @@ namespace OpenTK.Input
/// <summary>
/// Defines the interface for JoystickDevice drivers.
/// </summary>
[Obsolete]
public interface IJoystickDriver
{
/// <summary>

View file

@ -13,24 +13,12 @@ namespace OpenTK.Input
/// <summary>
/// Defines the interface for KeyboardDevice drivers.
/// </summary>
[Obsolete]
public interface IKeyboardDriver
{
/// <summary>
/// Gets the list of available KeyboardDevices.
/// </summary>
IList<KeyboardDevice> Keyboard { get; }
/// <summary>
/// Retrieves the KeyboardState for the default keyboard device.
/// </summary>
/// <returns>A <see cref="OpenTK.Input.KeyboardState"/> structure containing the state of the keyboard device.</returns>
KeyboardState GetState();
/// <summary>
/// Retrieves the KeyboardState for the specified keyboard device.
/// </summary>
/// <param name="index">The index of the keyboard device.</param>
/// <returns>A <see cref="OpenTK.Input.KeyboardState"/> structure containing the state of the keyboard device.</returns>
KeyboardState GetState(int index);
}
}

View file

@ -13,24 +13,12 @@ namespace OpenTK.Input
/// <summary>
/// Defines the interface for MouseDevice drivers.
/// </summary>
[Obsolete]
public interface IMouseDriver
{
/// <summary>
/// Gets the list of available MouseDevices.
/// </summary>
IList<MouseDevice> Mouse { get; }
/// <summary>
/// Retrieves the MouseState for the default keyboard device.
/// </summary>
/// <returns>A <see cref="OpenTK.Input.MouseState"/> structure containing the state of the mouse device.</returns>
MouseState GetState();
/// <summary>
/// Retrieves the MouseState for the specified keyboard device.
/// </summary>
/// <param name="index">The index of the keyboard device.</param>
/// <returns>A <see cref="OpenTK.Input.MouseState"/> structure containing the state of the mouse device.</returns>
MouseState GetState(int index);
}
}

View file

@ -38,7 +38,7 @@ namespace OpenTK.Input
{
#region Fields
static readonly IKeyboardDriver driver =
static readonly IKeyboardDriver2 driver =
Platform.Factory.Default.CreateKeyboardDriver();
static readonly object SyncRoot = new object();
@ -49,7 +49,7 @@ namespace OpenTK.Input
/// <summary>
/// Retrieves the combined <see cref="OpenTK.Input.KeyboardState"/> for all keyboard devices.
/// </summary>
/// <returns>A <see cref="OpenTK.Input.KeyboardState"/> structure containing the combined state for all keyboard devices.</returns>
/// <returns>An <see cref="OpenTK.Input.KeyboardState"/> structure containing the combined state for all keyboard devices.</returns>
public static KeyboardState GetState()
{
lock (SyncRoot)
@ -62,7 +62,7 @@ namespace OpenTK.Input
/// Retrieves the <see cref="OpenTK.Input.KeyboardState"/> for the specified keyboard device.
/// </summary>
/// <param name="index">The index of the keyboard device.</param>
/// <returns>A <see cref="OpenTK.Input.KeyboardState"/> structure containing the state of the keyboard device.</returns>
/// <returns>An <see cref="OpenTK.Input.KeyboardState"/> structure containing the state of the keyboard device.</returns>
public static KeyboardState GetState(int index)
{
if (index < 0)
@ -75,5 +75,23 @@ namespace OpenTK.Input
}
#endregion
/// <summary>
/// Retrieves the device name for the keyboard device.
/// </summary>
/// <param name="index">The index of the keyboard device.</param>
/// <returns>A <see cref="System.String"/> with the name of the specified device or <see cref="System.String.Empty"/>.</returns>
/// <remarks>
/// <para>If no device exists at the specified index, the return value is <see cref="System.String.Empty"/>.</para></remarks>
public static string GetDeviceName(int index)
{
if (index < 0)
throw new ArgumentOutOfRangeException("index");
lock (SyncRoot)
{
return driver.GetDeviceName(index);
}
}
}
}

View file

@ -38,7 +38,7 @@ namespace OpenTK.Input
{
#region Fields
static readonly IMouseDriver driver =
static readonly IMouseDriver2 driver =
Platform.Factory.Default.CreateMouseDriver();
static readonly object SyncRoot = new object();

View file

@ -45,6 +45,7 @@ namespace OpenTK.Input
unsafe fixed int Buttons[NumInts];
int x, y;
float wheel;
bool is_connected;
#endregion
@ -179,6 +180,12 @@ namespace OpenTK.Input
get { return Wheel; }
}
public bool IsConnected
{
get { return is_connected; }
internal set { is_connected = value; }
}
/// <summary>
/// Checks whether two <see cref="MouseState" /> instances are equal.
/// </summary>
@ -314,6 +321,7 @@ namespace OpenTK.Input
WheelPrecise += other.WheelPrecise;
X += other.X;
Y += other.Y;
IsConnected |= other.IsConnected;
}
}

View file

@ -131,7 +131,10 @@
<Compile Include="DisplayDevice.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Input\IGamePadDriver.cs" />
<Compile Include="Input\IInputDriver2.cs" />
<Compile Include="Input\IKeyboardDriver2.cs" />
<Compile Include="Input\IMouseDriver2.cs" />
<Compile Include="WindowBorder.cs">
<SubType>Code</SubType>
</Compile>

View file

@ -114,12 +114,12 @@ namespace OpenTK.Platform
return default_implementation.CreateGraphicsMode();
}
public OpenTK.Input.IKeyboardDriver CreateKeyboardDriver()
public OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver()
{
return default_implementation.CreateKeyboardDriver();
}
public OpenTK.Input.IMouseDriver CreateMouseDriver()
public OpenTK.Input.IMouseDriver2 CreateMouseDriver()
{
return default_implementation.CreateMouseDriver();
}
@ -169,12 +169,12 @@ namespace OpenTK.Platform
throw new PlatformNotSupportedException(error_string);
}
public OpenTK.Input.IKeyboardDriver CreateKeyboardDriver()
public OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver()
{
throw new PlatformNotSupportedException(error_string);
}
public OpenTK.Input.IMouseDriver CreateMouseDriver()
public OpenTK.Input.IMouseDriver2 CreateMouseDriver()
{
throw new PlatformNotSupportedException(error_string);
}

View file

@ -47,8 +47,8 @@ namespace OpenTK.Platform
IGraphicsMode CreateGraphicsMode();
OpenTK.Input.IKeyboardDriver CreateKeyboardDriver();
OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver();
OpenTK.Input.IMouseDriver CreateMouseDriver();
OpenTK.Input.IMouseDriver2 CreateMouseDriver();
}
}

View file

@ -7,7 +7,7 @@ namespace OpenTK.Platform.MacOS
{
using Input;
class CarbonInput : IInputDriver
class CarbonInput : IInputDriver, IInputDriver2
{
List<KeyboardDevice> dummy_keyboard_list = new List<KeyboardDevice>(1);
List<MouseDevice> dummy_mice_list = new List<MouseDevice>(1);
@ -35,16 +35,6 @@ namespace OpenTK.Platform.MacOS
get { return dummy_keyboard_list; }
}
public KeyboardState GetState()
{
throw new NotImplementedException();
}
public KeyboardState GetState(int index)
{
throw new NotImplementedException();
}
#endregion
#region IMouseDriver Members
@ -54,16 +44,6 @@ namespace OpenTK.Platform.MacOS
get { return dummy_mice_list; }
}
MouseState IMouseDriver.GetState()
{
throw new NotImplementedException();
}
MouseState IMouseDriver.GetState(int index)
{
throw new NotImplementedException();
}
#endregion
#region IJoystickDriver Members
@ -82,5 +62,20 @@ namespace OpenTK.Platform.MacOS
}
#endregion
public IMouseDriver2 MouseDriver
{
get { throw new NotImplementedException(); }
}
public IKeyboardDriver2 KeyboardDriver
{
get { throw new NotImplementedException(); }
}
public IGamePadDriver GamePadDriver
{
get { throw new NotImplementedException(); }
}
}
}

View file

@ -70,12 +70,12 @@ namespace OpenTK.Platform.MacOS
return new MacOSGraphicsMode();
}
public virtual OpenTK.Input.IKeyboardDriver CreateKeyboardDriver()
public virtual OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver()
{
throw new NotImplementedException();
}
public virtual OpenTK.Input.IMouseDriver CreateMouseDriver()
public virtual OpenTK.Input.IMouseDriver2 CreateMouseDriver()
{
throw new NotImplementedException();
}

View file

@ -59,6 +59,7 @@ namespace OpenTK.Platform.Windows
using RECT = OpenTK.Platform.Windows.Win32Rectangle;
using WNDPROC = System.IntPtr;
using LPDEVMODE = DeviceMode;
using HDEVNOTIFY = System.IntPtr;
using HRESULT = System.IntPtr;
using HMONITOR = System.IntPtr;
@ -845,7 +846,7 @@ namespace OpenTK.Platform.Windows
#endregion
[DllImport("user32.dll", SetLastError=true)]
[DllImport("user32.dll", SetLastError = true)]
public static extern BOOL SetForegroundWindow(HWND hWnd);
[DllImport("user32.dll", SetLastError = true)]
@ -854,6 +855,13 @@ namespace OpenTK.Platform.Windows
[DllImport("user32.dll", SetLastError = true)]
public static extern BOOL SetParent(HWND child, HWND newParent);
[DllImport("user32.dll", SetLastError = true)]
public static extern HDEVNOTIFY RegisterDeviceNotification(HANDLE hRecipient,
LPVOID NotificationFilter, DeviceNotification Flags);
[DllImport("user32.dll", SetLastError = true)]
public static extern BOOL UnregisterDeviceNotification(HDEVNOTIFY Handle);
#endregion
#region Display settings
@ -2794,6 +2802,30 @@ namespace OpenTK.Platform.Windows
#endregion
#region BroadcastHeader
struct BroadcastHeader
{
public DWORD Size;
public DeviceBroadcastType DeviceType;
DWORD dbch_reserved;
}
#endregion
#region BroadcastDeviceInterface
struct BroadcastDeviceInterface
{
public DWORD Size;
public DeviceBroadcastType DeviceType;
DWORD dbcc_reserved;
public Guid ClassGuid;
public char dbcc_name;
}
#endregion
#endregion
#region --- Enums ---
@ -4130,6 +4162,30 @@ namespace OpenTK.Platform.Windows
#endregion
#region DeviceNotification
enum DeviceNotification
{
WINDOW_HANDLE = 0x00000000,
SERVICE_HANDLE = 0x00000001,
ALL_INTERFACE_CLASSES = 0x00000004,
}
#endregion
#region DeviceBroadcastType
enum DeviceBroadcastType
{
OEM = 0,
VOLUME = 2,
PORT = 3,
INTERFACE = 5,
HANDLE = 6,
}
#endregion
#endregion
#region --- Callbacks ---
@ -4190,4 +4246,4 @@ namespace OpenTK.Platform.Windows
#pragma warning restore 3019
#pragma warning restore 0649
#pragma warning restore 0169
#pragma warning restore 0414
#pragma warning restore 0414

View file

@ -37,11 +37,11 @@ using System.Drawing;
namespace OpenTK.Platform.Windows
{
// Input driver for legacy (pre XP) Windows platforms.
sealed class WMInput : System.Windows.Forms.NativeWindow, IInputDriver, IInputDriver2
sealed class WMInput : System.Windows.Forms.NativeWindow, IInputDriver2
{
#region --- Fields ---
WinMMJoystick joystick_driver = new WinMMJoystick();
WinMMJoystick gamepad_driver = new WinMMJoystick();
// Driver supports only one keyboard and mouse;
KeyboardDevice keyboard = new KeyboardDevice();
MouseDevice mouse = new MouseDevice();
@ -249,66 +249,6 @@ namespace OpenTK.Platform.Windows
#endregion
#region --- IInputDriver Members ---
#region IInputDriver Members
public void Poll()
{
joystick_driver.Poll();
}
#endregion
#region IKeyboardDriver Members
public IList<KeyboardDevice> Keyboard
{
get { return keyboards; }
}
public KeyboardState GetState()
{
throw new NotImplementedException();
}
public KeyboardState GetState(int index)
{
throw new NotImplementedException();
}
#endregion
#region IMouseDriver Members
public IList<MouseDevice> Mouse
{
get { return mice; }
}
MouseState IMouseDriver.GetState()
{
throw new NotImplementedException();
}
MouseState IMouseDriver.GetState(int index)
{
throw new NotImplementedException();
}
#endregion
#region IJoystickDriver Members
public IList<JoystickDevice> Joysticks
{
get { return joystick_driver.Joysticks; }
}
#endregion
#endregion
#region --- IDisposable Members ---
private bool disposed;
@ -337,19 +277,19 @@ namespace OpenTK.Platform.Windows
#endregion
public IMouseDriver MouseDriver
public IMouseDriver2 MouseDriver
{
get { throw new NotImplementedException(); }
}
public IKeyboardDriver KeyboardDriver
public IKeyboardDriver2 KeyboardDriver
{
get { throw new NotImplementedException(); }
}
public IJoystickDriver JoystickDriver
public IGamePadDriver GamePadDriver
{
get { return joystick_driver; }
get { throw new NotImplementedException(); }
}
}
}

View file

@ -74,12 +74,12 @@ namespace OpenTK.Platform.Windows
return new WinGraphicsMode();
}
public virtual OpenTK.Input.IKeyboardDriver CreateKeyboardDriver()
public virtual OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver()
{
return InputDriver.KeyboardDriver;
}
public virtual OpenTK.Input.IMouseDriver CreateMouseDriver()
public virtual OpenTK.Input.IMouseDriver2 CreateMouseDriver()
{
return InputDriver.MouseDriver;
}

View file

@ -1227,16 +1227,6 @@ namespace OpenTK.Platform.Windows
get { return mice; }
}
MouseState IMouseDriver.GetState()
{
throw new NotImplementedException();
}
MouseState IMouseDriver.GetState(int index)
{
throw new NotImplementedException();
}
#endregion
#region IJoystickDriver Members

View file

@ -36,7 +36,7 @@ using System.Diagnostics;
namespace OpenTK.Platform.Windows
{
sealed class WinMMJoystick : IJoystickDriver
sealed class WinMMJoystick : IJoystickDriver, IGamePadDriver
{
#region Fields

View file

@ -41,7 +41,7 @@ using System.Threading;
namespace OpenTK.Platform.Windows
{
// Not complete.
sealed class WinRawInput : IInputDriver, IInputDriver2
sealed class WinRawInput : IInputDriver2
{
// Input event data.
static RawInput data = new RawInput();
@ -56,6 +56,9 @@ namespace OpenTK.Platform.Windows
static WinWindowInfo Parent { get { return Native.WindowInfo as WinWindowInfo; } }
static readonly WindowProcedure WndProc = WindowProcedureImplementation;
static IntPtr OldWndProc;
static IntPtr DevNotifyHandle;
static readonly Guid DeviceInterfaceHid = new Guid("4D1E55B2-F16F-11CF-88CB-001111000030");
#region Constructors
@ -102,6 +105,7 @@ namespace OpenTK.Platform.Windows
Native.ProcessEvents();
Functions.SetParent(Parent.WindowHandle, Constants.MESSAGE_ONLY);
Native.ProcessEvents();
RegisterForDeviceNotifications();
// Subclass the window to retrieve the events we are interested in.
OldWndProc = Functions.SetWindowLong(Parent.WindowHandle, WndProc);
@ -114,6 +118,21 @@ namespace OpenTK.Platform.Windows
return Native;
}
static void RegisterForDeviceNotifications()
{
BroadcastDeviceInterface bdi = new BroadcastDeviceInterface();
bdi.Size = BlittableValueType.StrideOf(bdi);
bdi.DeviceType = DeviceBroadcastType.INTERFACE;
bdi.ClassGuid = DeviceInterfaceHid;
unsafe
{
DevNotifyHandle = Functions.RegisterDeviceNotification(Parent.WindowHandle,
new IntPtr((void*)&bdi), DeviceNotification.WINDOW_HANDLE);
}
if (DevNotifyHandle == IntPtr.Zero)
Debug.Print("[Warning] Failed to register for device notifications. Error: {0}", Marshal.GetLastWin32Error());
}
#endregion
#region WindowProcedureImplementation
@ -150,6 +169,10 @@ namespace OpenTK.Platform.Windows
}
}
break;
case WindowMessage.DEVICECHANGE:
mouseDriver.RefreshDevices();
break;
}
return Functions.CallWindowProc(OldWndProc, handle, message, wParam, lParam);
}
@ -182,139 +205,19 @@ namespace OpenTK.Platform.Windows
#endregion
#region IInputDriver Members
#region IInputDriver Members
public void Poll()
{
return;
#if false
// We will do a buffered read for all input devices and route the RawInput structures
// to the correct 'ProcessData' handlers. First, we need to find out the size of the
// buffer to allocate for the structures. Then we allocate the buffer and read the
// structures, calling the correct handler for each one. Last, we free the allocated
// buffer.
int size = 0;
Functions.GetRawInputBuffer(IntPtr.Zero, ref size, API.RawInputHeaderSize);
size *= 256;
IntPtr rin_data = Marshal.AllocHGlobal(size);
while (true)
{
// Iterate reading all available RawInput structures and routing them to their respective
// handlers.
int num = Functions.GetRawInputBuffer(rin_data, ref size, API.RawInputHeaderSize);
if (num == 0)
break;
else if (num < 0)
{
/*int error = Marshal.GetLastWin32Error();
if (error == 122)
{
// Enlarge the buffer, it was too small.
AllocateBuffer();
}
else
{
throw new ApplicationException(String.Format(
"GetRawInputBuffer failed with code: {0}", error));
}*/
Debug.Print("GetRawInputBuffer failed with code: {0}", Marshal.GetLastWin32Error());
//AllocateBuffer();
break;
}
RawInput[] rin_structs = new RawInput[num];
IntPtr next_rin = rin_data;
for (int i = 0; i < num; i++)
{
rin_structs[i] = (RawInput)Marshal.PtrToStructure(next_rin, typeof(RawInput));
switch (rin_structs[i].Header.Type)
{
case RawInputDeviceType.KEYBOARD:
keyboardDriver.ProcessKeyboardEvent(rin_structs[i]);
break;
case RawInputDeviceType.MOUSE:
mouseDriver.ProcessEvent(rin_structs[i]);
break;
}
next_rin = Functions.NextRawInputStructure(next_rin);
}
Functions.DefRawInputProc(rin_structs, num, (uint)API.RawInputHeaderSize);
}
Marshal.FreeHGlobal(rin_data);
#endif
}
#endregion
#region IKeyboardDriver Members
public IList<KeyboardDevice> Keyboard
{
get { return KeyboardDriver.Keyboard; }
}
public KeyboardState GetState()
{
throw new NotImplementedException();
}
public KeyboardState GetState(int index)
{
throw new NotImplementedException();
}
#endregion
#region IMouseDriver Members
public IList<MouseDevice> Mouse
{
get { return MouseDriver.Mouse; }
}
MouseState IMouseDriver.GetState()
{
throw new NotImplementedException();
}
MouseState IMouseDriver.GetState(int index)
{
throw new NotImplementedException();
}
#endregion
#region IJoystickDriver Members
public IList<JoystickDevice> Joysticks
{
get { throw new NotImplementedException(); }
}
#endregion
#endregion
#region IInputDriver2 Members
public IMouseDriver MouseDriver
public IMouseDriver2 MouseDriver
{
get { return mouseDriver; }
}
public IKeyboardDriver KeyboardDriver
public IKeyboardDriver2 KeyboardDriver
{
get { return keyboardDriver; }
}
public IJoystickDriver JoystickDriver
public IGamePadDriver GamePadDriver
{
get { return joystickDriver; }
}
@ -337,10 +240,9 @@ namespace OpenTK.Platform.Windows
{
if (manual)
{
keyboardDriver.Dispose();
//mouseDriver.Dispose();
}
Functions.UnregisterDeviceNotification(DevNotifyHandle);
disposed = true;
}
}

View file

@ -39,9 +39,10 @@ using OpenTK.Input;
namespace OpenTK.Platform.Windows
{
internal class WinRawKeyboard : IKeyboardDriver, IDisposable
internal 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>();
@ -142,6 +143,7 @@ namespace OpenTK.Platform.Windows
//}
keyboards.Add(new KeyboardState());
names.Add(deviceDesc);
rawids.Add(new ContextHandle(ridl[i].Device), keyboards.Count - 1);
}
}
@ -261,11 +263,6 @@ namespace OpenTK.Platform.Windows
#region --- IKeyboardDriver Members ---
public IList<KeyboardDevice> Keyboard
{
get { return keyboards_old; }
}
public KeyboardState GetState()
{
lock (UpdateLock)
@ -290,35 +287,17 @@ namespace OpenTK.Platform.Windows
}
}
#endregion
#region --- IDisposable Members ---
private bool disposed;
public void Dispose()
public string GetDeviceName(int index)
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool manual)
{
if (!disposed)
lock (UpdateLock)
{
if (manual)
{
keyboards_old.Clear();
}
disposed = true;
if (names.Count > index)
return names[index];
else
return String.Empty;
}
}
~WinRawKeyboard()
{
Dispose(false);
}
#endregion
}
}

View file

@ -39,10 +39,11 @@ namespace OpenTK.Platform.Windows
/// <summary>
/// Contains methods to register for and process mouse WM_INPUT messages.
/// </summary>
internal class WinRawMouse : IMouseDriver
internal class WinRawMouse : IMouseDriver2
{
List<MouseState> mice;
Dictionary<ContextHandle, int> rawids; // ContextHandle instead of IntPtr for fast dictionary access
readonly List<MouseState> mice = new List<MouseState>();
readonly List<string> names = new List<string>();
readonly Dictionary<ContextHandle, int> rawids = new Dictionary<ContextHandle, int>();
readonly IntPtr Window;
readonly object UpdateLock = new object();
@ -55,15 +56,13 @@ namespace OpenTK.Platform.Windows
throw new ArgumentNullException("window");
Window = window;
RegisterDevices(window, out mice, out rawids);
RefreshDevices();
Debug.Unindent();
}
#region IMouseDriver Members
public IList<MouseDevice> Mouse { get { throw new NotImplementedException(); } }
public MouseState GetState()
{
lock (UpdateLock)
@ -90,77 +89,114 @@ namespace OpenTK.Platform.Windows
#endregion
static int RegisterDevices(IntPtr window, out List<MouseState> mice, out Dictionary<ContextHandle, int> rawids)
public void RefreshDevices()
{
int count = WinRawInput.DeviceCount;
mice = new List<MouseState>();
rawids = new Dictionary<ContextHandle, int>();
RawInputDeviceList[] ridl = new RawInputDeviceList[count];
for (int i = 0; i < count; i++)
ridl[i] = new RawInputDeviceList();
Functions.GetRawInputDeviceList(ridl, ref count, API.RawInputDeviceListSize);
// Discover mouse 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"))
// Mark all devices as disconnected. We will check which of those
// are connected later on.
for (int i = 0; i < mice.Count; i++)
{
// This is a terminal services device, skip it.
continue;
MouseState state = mice[i];
state.IsConnected = false;
mice[i] = state;
}
else if (ridl[i].Type == RawInputDeviceType.MOUSE || 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 mouse devices
foreach (RawInputDeviceList dev in ridl)
{
// This is a mouse or a USB mouse device. In the latter case, discover if it really is a
// mouse 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");
deviceDesc = deviceDesc.Substring(deviceDesc.LastIndexOf(';') + 1);
string deviceClass = (string)regkey.GetValue("Class");
if (!String.IsNullOrEmpty(deviceClass) && deviceClass.ToLower().Equals("mouse"))
ContextHandle id = new ContextHandle(dev.Device);
if (rawids.ContainsKey(id))
{
// Register the device:
RawInputDeviceInfo info = new RawInputDeviceInfo();
int devInfoSize = API.RawInputDeviceInfoSize;
Functions.GetRawInputDeviceInfo(ridl[i].Device, RawInputDeviceInfoEnum.DEVICEINFO,
info, ref devInfoSize);
// Device already registered, mark as connected
MouseState state = mice[rawids[id]];
state.IsConnected = true;
mice[rawids[id]] = state;
continue;
}
mice.Add(RegisterRawDevice(deviceDesc, window));
rawids.Add(new ContextHandle(ridl[i].Device), mice.Count - 1);
// Unregistered device, find what it is
string name = GetDeviceName(dev);
if (name.ToLower().Contains("root"))
{
// This is a terminal services device, skip it.
continue;
}
else if (dev.Type == RawInputDeviceType.MOUSE || dev.Type == RawInputDeviceType.HID)
{
// This is a mouse or a USB mouse device. In the latter case, discover if it really is a
// 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");
if (!String.IsNullOrEmpty(deviceClass) && deviceClass.ToLower().Equals("mouse"))
{
if (!rawids.ContainsKey(new ContextHandle(dev.Device)))
{
// Register the device:
RawInputDeviceInfo info = new RawInputDeviceInfo();
int devInfoSize = API.RawInputDeviceInfoSize;
Functions.GetRawInputDeviceInfo(dev.Device, RawInputDeviceInfoEnum.DEVICEINFO,
info, ref devInfoSize);
RegisterRawDevice(deviceDesc, Window);
MouseState state = new MouseState();
state.IsConnected = true;
mice.Add(state);
names.Add(deviceDesc);
rawids.Add(new ContextHandle(dev.Device), mice.Count - 1);
}
}
}
}
}
return count;
}
static MouseState RegisterRawDevice(string device, IntPtr window)
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)
{
MouseState state = new MouseState();
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();
@ -171,40 +207,24 @@ namespace OpenTK.Platform.Windows
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())
);
Debug.Print("[Warning] Raw input registration failed with error: {0}. Device: {1}",
Marshal.GetLastWin32Error(), rid[0].ToString());
}
else
{
Debug.Print("Registered mouse {0}", device);
Point p = new Point();
if (Functions.GetCursorPos(ref p))
{
state.X = p.X;
state.Y = p.Y;
}
}
return state;
}
public bool ProcessMouseEvent(RawInput rin)
{
if (mice.Count == 0)
return false;
RawMouse raw = rin.Data.Mouse;
ContextHandle handle = new ContextHandle(rin.Header.Device);
MouseState mouse;
if (!rawids.ContainsKey(handle))
{
mice.Add(new MouseState());
rawids.Add(handle, mice.Count - 1);
RefreshDevices();
}
mouse = mice[rawids[handle]];

View file

@ -78,12 +78,12 @@ namespace OpenTK.Platform.X11
return new X11GraphicsMode();
}
public virtual OpenTK.Input.IKeyboardDriver CreateKeyboardDriver()
public virtual OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver()
{
return new X11Keyboard(null);
}
public virtual OpenTK.Input.IMouseDriver CreateMouseDriver()
public virtual OpenTK.Input.IMouseDriver2 CreateMouseDriver()
{
if (XI2Mouse.IsSupported(IntPtr.Zero))
return new XI2Mouse(null); // Requires xorg 1.7 or higher.

View file

@ -219,16 +219,6 @@ namespace OpenTK.Platform.X11
get { return dummy_keyboard_list; }//return keyboardDriver.Keyboard;
}
public KeyboardState GetState()
{
throw new NotImplementedException();
}
public KeyboardState GetState(int index)
{
throw new NotImplementedException();
}
#endregion
#region public IList<Mouse> Mouse
@ -238,16 +228,6 @@ namespace OpenTK.Platform.X11
get { return (IList<MouseDevice>)dummy_mice_list; } //return mouseDriver.Mouse;
}
MouseState IMouseDriver.GetState()
{
throw new NotImplementedException();
}
MouseState IMouseDriver.GetState(int index)
{
throw new NotImplementedException();
}
#endregion
#region public IList<JoystickDevice> Joysticks

View file

@ -33,11 +33,13 @@ namespace OpenTK.Platform.X11
{
// Standard keyboard driver that relies on xlib input events.
// Only one keyboard supported.
sealed class X11Keyboard : IKeyboardDriver
sealed class X11Keyboard : IKeyboardDriver2
{
readonly X11WindowInfo window;
readonly X11KeyMap keymap = new X11KeyMap();
readonly static string name = "Core X11 keyboard";
KeyboardState state = new KeyboardState();
// Can either attach itself to the specified window or can hook the root window.
public X11Keyboard(X11WindowInfo win)
@ -64,9 +66,6 @@ namespace OpenTK.Platform.X11
}
}
// Todo: remove this
public IList<KeyboardDevice> Keyboard { get { throw new NotSupportedException(); } }
public KeyboardState GetState()
{
ProcessEvents();
@ -76,11 +75,19 @@ namespace OpenTK.Platform.X11
public KeyboardState GetState(int index)
{
// X11Keyboard supports a single keyboard only
if (index < 0 || index > 1)
throw new ArgumentOutOfRangeException("index");
ProcessEvents();
return state;
if (index == 0)
return state;
else
return new KeyboardState();
}
public string GetDeviceName(int index)
{
if (index == 0)
return name;
else
return String.Empty;
}
void ProcessEvents()

View file

@ -32,7 +32,7 @@ using OpenTK.Input;
namespace OpenTK.Platform.X11
{
sealed class X11Mouse : IMouseDriver
sealed class X11Mouse : IMouseDriver2
{
MouseState mouse = new MouseState();
X11WindowInfo window;

View file

@ -35,7 +35,7 @@ namespace OpenTK.Platform.X11
{
// Todo: multi-mouse support. Right now we aggregate all data into a single mouse device.
// This should be easy: just read the device id and route the data to the correct device.
sealed class XI2Mouse : IMouseDriver
sealed class XI2Mouse : IMouseDriver2
{
List<MouseState> mice = new List<MouseState>();
Dictionary<int, int> rawids = new Dictionary<int, int>(); // maps raw ids to mouse ids