diff --git a/Source/OpenTK/INativeWindow.cs b/Source/OpenTK/INativeWindow.cs index 03927607..106ae60c 100644 --- a/Source/OpenTK/INativeWindow.cs +++ b/Source/OpenTK/INativeWindow.cs @@ -253,7 +253,6 @@ namespace OpenTK //event EventHandler KeyDown; //event EventHandler KeyUp; - //event EventHandler DragDrop; //event EventHandler DragEnter; diff --git a/Source/OpenTK/Input/IInputDriver2.cs b/Source/OpenTK/Input/IInputDriver2.cs index 5cfbcdfd..1ff89748 100644 --- a/Source/OpenTK/Input/IInputDriver2.cs +++ b/Source/OpenTK/Input/IInputDriver2.cs @@ -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; } } } diff --git a/Source/OpenTK/Input/IJoystickDriver.cs b/Source/OpenTK/Input/IJoystickDriver.cs index bb2e030f..0b6f73b9 100644 --- a/Source/OpenTK/Input/IJoystickDriver.cs +++ b/Source/OpenTK/Input/IJoystickDriver.cs @@ -34,6 +34,7 @@ namespace OpenTK.Input /// /// Defines the interface for JoystickDevice drivers. /// + [Obsolete] public interface IJoystickDriver { /// diff --git a/Source/OpenTK/Input/IKeyboardDriver.cs b/Source/OpenTK/Input/IKeyboardDriver.cs index b2806917..20685074 100644 --- a/Source/OpenTK/Input/IKeyboardDriver.cs +++ b/Source/OpenTK/Input/IKeyboardDriver.cs @@ -13,24 +13,12 @@ namespace OpenTK.Input /// /// Defines the interface for KeyboardDevice drivers. /// + [Obsolete] public interface IKeyboardDriver { /// /// Gets the list of available KeyboardDevices. /// IList Keyboard { get; } - - /// - /// Retrieves the KeyboardState for the default keyboard device. - /// - /// A structure containing the state of the keyboard device. - KeyboardState GetState(); - - /// - /// Retrieves the KeyboardState for the specified keyboard device. - /// - /// The index of the keyboard device. - /// A structure containing the state of the keyboard device. - KeyboardState GetState(int index); } } diff --git a/Source/OpenTK/Input/IMouseDriver.cs b/Source/OpenTK/Input/IMouseDriver.cs index 9e60a5db..97713234 100644 --- a/Source/OpenTK/Input/IMouseDriver.cs +++ b/Source/OpenTK/Input/IMouseDriver.cs @@ -13,24 +13,12 @@ namespace OpenTK.Input /// /// Defines the interface for MouseDevice drivers. /// + [Obsolete] public interface IMouseDriver { /// /// Gets the list of available MouseDevices. /// IList Mouse { get; } - - /// - /// Retrieves the MouseState for the default keyboard device. - /// - /// A structure containing the state of the mouse device. - MouseState GetState(); - - /// - /// Retrieves the MouseState for the specified keyboard device. - /// - /// The index of the keyboard device. - /// A structure containing the state of the mouse device. - MouseState GetState(int index); } } diff --git a/Source/OpenTK/Input/Keyboard.cs b/Source/OpenTK/Input/Keyboard.cs index f2838c9f..ea35b050 100644 --- a/Source/OpenTK/Input/Keyboard.cs +++ b/Source/OpenTK/Input/Keyboard.cs @@ -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 /// /// Retrieves the combined for all keyboard devices. /// - /// A structure containing the combined state for all keyboard devices. + /// An structure containing the combined state for all keyboard devices. public static KeyboardState GetState() { lock (SyncRoot) @@ -62,7 +62,7 @@ namespace OpenTK.Input /// Retrieves the for the specified keyboard device. /// /// The index of the keyboard device. - /// A structure containing the state of the keyboard device. + /// An structure containing the state of the keyboard device. public static KeyboardState GetState(int index) { if (index < 0) @@ -75,5 +75,23 @@ namespace OpenTK.Input } #endregion + + /// + /// Retrieves the device name for the keyboard device. + /// + /// The index of the keyboard device. + /// A with the name of the specified device or . + /// + /// If no device exists at the specified index, the return value is . + public static string GetDeviceName(int index) + { + if (index < 0) + throw new ArgumentOutOfRangeException("index"); + + lock (SyncRoot) + { + return driver.GetDeviceName(index); + } + } } } diff --git a/Source/OpenTK/Input/Mouse.cs b/Source/OpenTK/Input/Mouse.cs index 0747339f..c3f42c17 100644 --- a/Source/OpenTK/Input/Mouse.cs +++ b/Source/OpenTK/Input/Mouse.cs @@ -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(); diff --git a/Source/OpenTK/Input/MouseState.cs b/Source/OpenTK/Input/MouseState.cs index 5338d133..44acc9c3 100644 --- a/Source/OpenTK/Input/MouseState.cs +++ b/Source/OpenTK/Input/MouseState.cs @@ -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; } + } + /// /// Checks whether two instances are equal. /// @@ -314,6 +321,7 @@ namespace OpenTK.Input WheelPrecise += other.WheelPrecise; X += other.X; Y += other.Y; + IsConnected |= other.IsConnected; } } diff --git a/Source/OpenTK/OpenTK.csproj b/Source/OpenTK/OpenTK.csproj index 353f108b..974e460d 100644 --- a/Source/OpenTK/OpenTK.csproj +++ b/Source/OpenTK/OpenTK.csproj @@ -131,7 +131,10 @@ Code + + + Code diff --git a/Source/OpenTK/Platform/Factory.cs b/Source/OpenTK/Platform/Factory.cs index b352c714..cb9ab3d9 100644 --- a/Source/OpenTK/Platform/Factory.cs +++ b/Source/OpenTK/Platform/Factory.cs @@ -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); } diff --git a/Source/OpenTK/Platform/IPlatformFactory.cs b/Source/OpenTK/Platform/IPlatformFactory.cs index caae6db1..94761623 100644 --- a/Source/OpenTK/Platform/IPlatformFactory.cs +++ b/Source/OpenTK/Platform/IPlatformFactory.cs @@ -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(); } } diff --git a/Source/OpenTK/Platform/MacOS/CarbonInput.cs b/Source/OpenTK/Platform/MacOS/CarbonInput.cs index 5355a443..615c0899 100644 --- a/Source/OpenTK/Platform/MacOS/CarbonInput.cs +++ b/Source/OpenTK/Platform/MacOS/CarbonInput.cs @@ -7,7 +7,7 @@ namespace OpenTK.Platform.MacOS { using Input; - class CarbonInput : IInputDriver + class CarbonInput : IInputDriver, IInputDriver2 { List dummy_keyboard_list = new List(1); List dummy_mice_list = new List(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(); } + } } } diff --git a/Source/OpenTK/Platform/MacOS/MacOSFactory.cs b/Source/OpenTK/Platform/MacOS/MacOSFactory.cs index 25619903..e16a58bc 100644 --- a/Source/OpenTK/Platform/MacOS/MacOSFactory.cs +++ b/Source/OpenTK/Platform/MacOS/MacOSFactory.cs @@ -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(); } diff --git a/Source/OpenTK/Platform/Windows/API.cs b/Source/OpenTK/Platform/Windows/API.cs index 94081054..99dc7dac 100644 --- a/Source/OpenTK/Platform/Windows/API.cs +++ b/Source/OpenTK/Platform/Windows/API.cs @@ -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 \ No newline at end of file +#pragma warning restore 0414 diff --git a/Source/OpenTK/Platform/Windows/WMInput.cs b/Source/OpenTK/Platform/Windows/WMInput.cs index c1b04ef1..1dd3e2dd 100644 --- a/Source/OpenTK/Platform/Windows/WMInput.cs +++ b/Source/OpenTK/Platform/Windows/WMInput.cs @@ -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 Keyboard - { - get { return keyboards; } - } - - public KeyboardState GetState() - { - throw new NotImplementedException(); - } - - public KeyboardState GetState(int index) - { - throw new NotImplementedException(); - } - - #endregion - - #region IMouseDriver Members - - public IList Mouse - { - get { return mice; } - } - - MouseState IMouseDriver.GetState() - { - throw new NotImplementedException(); - } - - MouseState IMouseDriver.GetState(int index) - { - throw new NotImplementedException(); - } - - #endregion - - #region IJoystickDriver Members - - public IList 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(); } } } } diff --git a/Source/OpenTK/Platform/Windows/WinFactory.cs b/Source/OpenTK/Platform/Windows/WinFactory.cs index e5b02e50..796eb7ad 100644 --- a/Source/OpenTK/Platform/Windows/WinFactory.cs +++ b/Source/OpenTK/Platform/Windows/WinFactory.cs @@ -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; } diff --git a/Source/OpenTK/Platform/Windows/WinGLNative.cs b/Source/OpenTK/Platform/Windows/WinGLNative.cs index b6994aa9..6d409f9b 100644 --- a/Source/OpenTK/Platform/Windows/WinGLNative.cs +++ b/Source/OpenTK/Platform/Windows/WinGLNative.cs @@ -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 diff --git a/Source/OpenTK/Platform/Windows/WinMMJoystick.cs b/Source/OpenTK/Platform/Windows/WinMMJoystick.cs index 497ea179..ea3c2a5e 100644 --- a/Source/OpenTK/Platform/Windows/WinMMJoystick.cs +++ b/Source/OpenTK/Platform/Windows/WinMMJoystick.cs @@ -36,7 +36,7 @@ using System.Diagnostics; namespace OpenTK.Platform.Windows { - sealed class WinMMJoystick : IJoystickDriver + sealed class WinMMJoystick : IJoystickDriver, IGamePadDriver { #region Fields diff --git a/Source/OpenTK/Platform/Windows/WinRawInput.cs b/Source/OpenTK/Platform/Windows/WinRawInput.cs index baebfb92..03e2f67b 100644 --- a/Source/OpenTK/Platform/Windows/WinRawInput.cs +++ b/Source/OpenTK/Platform/Windows/WinRawInput.cs @@ -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 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 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 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; } } diff --git a/Source/OpenTK/Platform/Windows/WinRawKeyboard.cs b/Source/OpenTK/Platform/Windows/WinRawKeyboard.cs index 6c13116d..4747ecb2 100644 --- a/Source/OpenTK/Platform/Windows/WinRawKeyboard.cs +++ b/Source/OpenTK/Platform/Windows/WinRawKeyboard.cs @@ -39,9 +39,10 @@ using OpenTK.Input; namespace OpenTK.Platform.Windows { - internal class WinRawKeyboard : IKeyboardDriver, IDisposable + internal class WinRawKeyboard : IKeyboardDriver2 { readonly List keyboards = new List(); + readonly List names = new List(); // ContextHandle instead of IntPtr for fast dictionary access readonly Dictionary rawids = new Dictionary(); private List keyboards_old = new List(); @@ -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 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 } } diff --git a/Source/OpenTK/Platform/Windows/WinRawMouse.cs b/Source/OpenTK/Platform/Windows/WinRawMouse.cs index 1b98be16..3c16d48f 100644 --- a/Source/OpenTK/Platform/Windows/WinRawMouse.cs +++ b/Source/OpenTK/Platform/Windows/WinRawMouse.cs @@ -39,10 +39,11 @@ namespace OpenTK.Platform.Windows /// /// Contains methods to register for and process mouse WM_INPUT messages. /// - internal class WinRawMouse : IMouseDriver + internal class WinRawMouse : IMouseDriver2 { - List mice; - Dictionary rawids; // ContextHandle instead of IntPtr for fast dictionary access + readonly List mice = new List(); + readonly List names = new List(); + readonly Dictionary rawids = new Dictionary(); 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 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 mice, out Dictionary rawids) + public void RefreshDevices() { - int count = WinRawInput.DeviceCount; - mice = new List(); - rawids = new Dictionary(); - - 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]]; diff --git a/Source/OpenTK/Platform/X11/X11Factory.cs b/Source/OpenTK/Platform/X11/X11Factory.cs index a5a82c08..5c46c942 100644 --- a/Source/OpenTK/Platform/X11/X11Factory.cs +++ b/Source/OpenTK/Platform/X11/X11Factory.cs @@ -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. diff --git a/Source/OpenTK/Platform/X11/X11Input.cs b/Source/OpenTK/Platform/X11/X11Input.cs index 3d77cd99..ae4473b1 100644 --- a/Source/OpenTK/Platform/X11/X11Input.cs +++ b/Source/OpenTK/Platform/X11/X11Input.cs @@ -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 @@ -238,16 +228,6 @@ namespace OpenTK.Platform.X11 get { return (IList)dummy_mice_list; } //return mouseDriver.Mouse; } - MouseState IMouseDriver.GetState() - { - throw new NotImplementedException(); - } - - MouseState IMouseDriver.GetState(int index) - { - throw new NotImplementedException(); - } - #endregion #region public IList Joysticks diff --git a/Source/OpenTK/Platform/X11/X11Keyboard.cs b/Source/OpenTK/Platform/X11/X11Keyboard.cs index d346e4fd..d67dd56a 100644 --- a/Source/OpenTK/Platform/X11/X11Keyboard.cs +++ b/Source/OpenTK/Platform/X11/X11Keyboard.cs @@ -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 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() diff --git a/Source/OpenTK/Platform/X11/X11Mouse.cs b/Source/OpenTK/Platform/X11/X11Mouse.cs index 5a57364b..881c488e 100644 --- a/Source/OpenTK/Platform/X11/X11Mouse.cs +++ b/Source/OpenTK/Platform/X11/X11Mouse.cs @@ -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; diff --git a/Source/OpenTK/Platform/X11/XI2Mouse.cs b/Source/OpenTK/Platform/X11/XI2Mouse.cs index 5290e2de..a8f31832 100644 --- a/Source/OpenTK/Platform/X11/XI2Mouse.cs +++ b/Source/OpenTK/Platform/X11/XI2Mouse.cs @@ -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 mice = new List(); Dictionary rawids = new Dictionary(); // maps raw ids to mouse ids