From 2430f82ff7a2175bb3f593779fe4aaf7659403c9 Mon Sep 17 00:00:00 2001 From: the_fiddler Date: Fri, 22 Oct 2010 14:57:06 +0000 Subject: [PATCH] Implemented raw keyboard input for Windows. Improved the interface for receiving input. Moved raw input window to its own thread. --- Source/OpenTK/Input/IInputDriver2.cs | 41 +++ Source/OpenTK/Input/InputDriver.cs | 146 ----------- Source/OpenTK/OpenTK.csproj | 6 +- Source/OpenTK/Platform/Windows/WMInput.cs | 46 +++- Source/OpenTK/Platform/Windows/WinFactory.cs | 35 ++- Source/OpenTK/Platform/Windows/WinRawInput.cs | 246 ++++++++++++------ .../OpenTK/Platform/Windows/WinRawKeyboard.cs | 29 ++- Source/OpenTK/Platform/Windows/WinRawMouse.cs | 94 +++---- 8 files changed, 328 insertions(+), 315 deletions(-) create mode 100644 Source/OpenTK/Input/IInputDriver2.cs delete mode 100644 Source/OpenTK/Input/InputDriver.cs diff --git a/Source/OpenTK/Input/IInputDriver2.cs b/Source/OpenTK/Input/IInputDriver2.cs new file mode 100644 index 00000000..5cfbcdfd --- /dev/null +++ b/Source/OpenTK/Input/IInputDriver2.cs @@ -0,0 +1,41 @@ +#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.Text; + +namespace OpenTK.Input +{ + // Defines the interface for a 2nd generation input driver. + interface IInputDriver2 + { + IMouseDriver MouseDriver { get; } + IKeyboardDriver KeyboardDriver { get; } + IJoystickDriver JoystickDriver { get; } + } +} diff --git a/Source/OpenTK/Input/InputDriver.cs b/Source/OpenTK/Input/InputDriver.cs deleted file mode 100644 index 4a137c99..00000000 --- a/Source/OpenTK/Input/InputDriver.cs +++ /dev/null @@ -1,146 +0,0 @@ -#region --- License --- -/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos - * See license.txt for license info - */ -#endregion - -using System; -using System.Collections.Generic; -using System.Text; - -using OpenTK.Input; -using OpenTK.Platform; - -namespace OpenTK -{ - internal class InputDriver : IInputDriver - { - private IInputDriver inputDriver; - - #region --- Constructors --- - - public InputDriver(GameWindow parent) - { - if (parent == null) - throw new ArgumentException("A valid window (IWindowInfo) must be specified to construct an InputDriver"); - - switch (Environment.OSVersion.Platform) - { - case PlatformID.Win32Windows: - case PlatformID.Win32NT: - case PlatformID.Win32S: - case PlatformID.WinCE: - if (Environment.OSVersion.Version.Major > 5 || - (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1)) - { - inputDriver = new OpenTK.Platform.Windows.WinRawInput((OpenTK.Platform.Windows.WinWindowInfo)parent.WindowInfo); - } - else - { - // Legacy or unknown windows version: - inputDriver = new OpenTK.Platform.Windows.WMInput((OpenTK.Platform.Windows.WinWindowInfo)parent.WindowInfo); - } - break; - - case PlatformID.Unix: - // TODO: Input is currently handled asychronously by the driver in X11GLNative. - //inputDriver = new OpenTK.Platform.X11.X11Input(parent.WindowInfo); - - break; - - default: - throw new PlatformNotSupportedException( - "Input handling is not supported on the current platform. Please report the problem to http://opentk.sourceforge.net"); - - } - } - - #endregion - - #region --- IInputDriver Members --- - - public void Poll() - { - inputDriver.Poll(); - } - - #endregion - - #region --- IKeyboardDriver Members --- - - public IList Keyboard - { - get { return inputDriver.Keyboard; } - } - - public KeyboardState GetState() - { - return (inputDriver as IKeyboardDriver).GetState(); - } - - public KeyboardState GetState(int index) - { - return (inputDriver as IKeyboardDriver).GetState(index); - } - - #endregion - - #region --- IMouseDriver Members --- - - public IList Mouse - { - get { return inputDriver.Mouse; } - } - - MouseState IMouseDriver.GetState() - { - throw new NotImplementedException(); - } - - MouseState IMouseDriver.GetState(int index) - { - throw new NotImplementedException(); - } - - #endregion - - #region --- IJoystickDriver Members --- - - public IList Joysticks - { - get { return inputDriver.Joysticks; } - } - - #endregion - - #region --- IDisposable Members --- - - private bool disposed; - - public void Dispose() - { - this.Dispose(true); - GC.SuppressFinalize(this); - } - - private void Dispose(bool manual) - { - if (!disposed) - { - if (manual) - { - inputDriver.Dispose(); - } - - disposed = true; - } - } - - ~InputDriver() - { - this.Dispose(false); - } - - #endregion - } -} diff --git a/Source/OpenTK/OpenTK.csproj b/Source/OpenTK/OpenTK.csproj index 8719568a..353f108b 100644 --- a/Source/OpenTK/OpenTK.csproj +++ b/Source/OpenTK/OpenTK.csproj @@ -1,4 +1,4 @@ - + Local @@ -131,6 +131,7 @@ Code + Code @@ -551,9 +552,6 @@ Code - - Code - Code diff --git a/Source/OpenTK/Platform/Windows/WMInput.cs b/Source/OpenTK/Platform/Windows/WMInput.cs index 90399ebc..c1b04ef1 100644 --- a/Source/OpenTK/Platform/Windows/WMInput.cs +++ b/Source/OpenTK/Platform/Windows/WMInput.cs @@ -1,7 +1,28 @@ -#region --- License --- -/* Copyright (c) 2007 Stefanos Apostolopoulos - * See license.txt for license information - */ +#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; @@ -16,7 +37,7 @@ using System.Drawing; namespace OpenTK.Platform.Windows { // Input driver for legacy (pre XP) Windows platforms. - sealed class WMInput : System.Windows.Forms.NativeWindow, IInputDriver + sealed class WMInput : System.Windows.Forms.NativeWindow, IInputDriver, IInputDriver2 { #region --- Fields --- @@ -315,5 +336,20 @@ namespace OpenTK.Platform.Windows } #endregion + + public IMouseDriver MouseDriver + { + get { throw new NotImplementedException(); } + } + + public IKeyboardDriver KeyboardDriver + { + get { throw new NotImplementedException(); } + } + + public IJoystickDriver JoystickDriver + { + get { return joystick_driver; } + } } } diff --git a/Source/OpenTK/Platform/Windows/WinFactory.cs b/Source/OpenTK/Platform/Windows/WinFactory.cs index 2616e770..b4c55db3 100644 --- a/Source/OpenTK/Platform/Windows/WinFactory.cs +++ b/Source/OpenTK/Platform/Windows/WinFactory.cs @@ -36,6 +36,9 @@ namespace OpenTK.Platform.Windows class WinFactory : IPlatformFactory { + readonly object SyncRoot = new object(); + IInputDriver2 inputDriver; + #region IPlatformFactory Members public virtual INativeWindow CreateNativeWindow(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice device) @@ -73,22 +76,34 @@ namespace OpenTK.Platform.Windows public virtual OpenTK.Input.IKeyboardDriver CreateKeyboardDriver() { - throw new NotImplementedException(); - // If Windows version is NT5 or higher, we are able to use raw input. - if (System.Environment.OSVersion.Version.Major >= 5) - return new WinRawKeyboard(); - else - return new WMInput(null); + + return InputDriver.KeyboardDriver; } public virtual OpenTK.Input.IMouseDriver CreateMouseDriver() { - if (System.Environment.OSVersion.Version.Major >= 5) - return new WinRawMouse(); - else - return new WMInput(null); + return InputDriver.MouseDriver; } #endregion + + IInputDriver2 InputDriver + { + get + { + lock (SyncRoot) + { + if (inputDriver == null) + { + // If Windows version is NT5 or higher, we are able to use raw input. + if (System.Environment.OSVersion.Version.Major >= 5) + inputDriver = new WinRawInput(); + else + inputDriver = new WMInput(null); + } + return inputDriver; + } + } + } } } diff --git a/Source/OpenTK/Platform/Windows/WinRawInput.cs b/Source/OpenTK/Platform/Windows/WinRawInput.cs index 4d4a2f77..baebfb92 100644 --- a/Source/OpenTK/Platform/Windows/WinRawInput.cs +++ b/Source/OpenTK/Platform/Windows/WinRawInput.cs @@ -1,7 +1,28 @@ -#region --- License --- -/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos - * See license.txt for license info - */ +#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 #region --- Using directives --- @@ -13,49 +34,51 @@ using System.Runtime.InteropServices; using System.Diagnostics; using System.Windows.Forms; using OpenTK.Input; +using System.Threading; #endregion namespace OpenTK.Platform.Windows { // Not complete. - sealed class WinRawInput : System.Windows.Forms.NativeWindow, IInputDriver + sealed class WinRawInput : IInputDriver, IInputDriver2 { // Input event data. - RawInput data = new RawInput(); - // The total number of input devices connected to this system. - static int deviceCount; - int rawInputStructSize = API.RawInputSize; + static RawInput data = new RawInput(); + static readonly int rawInputStructSize = API.RawInputSize; + static readonly Thread InputThread = new Thread(ProcessEvents); - private WinRawKeyboard keyboardDriver; - private WinRawMouse mouseDriver; + static WinRawKeyboard keyboardDriver; + static WinRawMouse mouseDriver; + static readonly WinMMJoystick joystickDriver = new WinMMJoystick(); - #region --- Constructors --- + static INativeWindow Native; + static WinWindowInfo Parent { get { return Native.WindowInfo as WinWindowInfo; } } + static readonly WindowProcedure WndProc = WindowProcedureImplementation; + static IntPtr OldWndProc; - internal WinRawInput(WinWindowInfo parent) + #region Constructors + + public WinRawInput() { - Debug.WriteLine("Initalizing windows raw input driver."); - Debug.Indent(); + InputThread.IsBackground = true; + InputThread.Start(); - AssignHandle(parent.WindowHandle); - WinWindowInfo win = new WinWindowInfo(this.Handle, parent); - Debug.Print("Input window attached to parent {0}", parent); - keyboardDriver = new WinRawKeyboard(this.Handle); - mouseDriver = new WinRawMouse(); - - Debug.Unindent(); - - //AllocateBuffer(); + while (mouseDriver == null || keyboardDriver == null) + Thread.Sleep(0); } #endregion - #region internal static int DeviceCount + #region Public Members - internal static int DeviceCount + #region DeviceCount + + public static int DeviceCount { get { + int deviceCount = 0; Functions.GetRawInputDeviceList(null, ref deviceCount, API.RawInputDeviceListSize); return deviceCount; } @@ -63,72 +86,103 @@ namespace OpenTK.Platform.Windows #endregion - #region protected override void WndProc(ref Message msg) + #endregion - /// - /// Processes the input Windows Message, routing the buffer to the correct Keyboard, Mouse or HID. - /// - /// The WM_INPUT message, containing the buffer on the input event. - protected override void WndProc(ref Message msg) + #region Private Members + + #region ConstructMessageWindow + + static INativeWindow ConstructMessageWindow() { - switch ((WindowMessage)msg.Msg) - { - case WindowMessage.INPUT: - int size = 0; - // Get the size of the input buffer - Functions.GetRawInputData(msg.LParam, GetRawInputDataEnum.INPUT, - IntPtr.Zero, ref size, API.RawInputHeaderSize); + Debug.WriteLine("Initializing windows raw input driver."); + Debug.Indent(); - //if (buffer == null || API.RawInputSize < size) - //{ - // throw new ApplicationException("Critical error when processing raw windows input."); - //} - if (size == Functions.GetRawInputData(msg.LParam, GetRawInputDataEnum.INPUT, - out data, ref size, API.RawInputHeaderSize)) - { - switch (data.Header.Type) - { - case RawInputDeviceType.KEYBOARD: - if (!keyboardDriver.ProcessKeyboardEvent(data)) - Functions.DefRawInputProc(ref data, 1, (uint)API.RawInputHeaderSize); - return; + // Create a new message-only window to retrieve WM_INPUT messages. + Native = new NativeWindow(); + Native.ProcessEvents(); + Functions.SetParent(Parent.WindowHandle, Constants.MESSAGE_ONLY); + Native.ProcessEvents(); - case RawInputDeviceType.MOUSE: - throw new NotSupportedException(); + // Subclass the window to retrieve the events we are interested in. + OldWndProc = Functions.SetWindowLong(Parent.WindowHandle, WndProc); - case RawInputDeviceType.HID: - Functions.DefRawInputProc(ref data, 1, (uint)API.RawInputHeaderSize); - return; + Debug.Print("Input window attached to parent {0}", Parent); + keyboardDriver = new WinRawKeyboard(Parent.WindowHandle); + mouseDriver = new WinRawMouse(Parent.WindowHandle); - default: - break; - } - } - else - { - throw new ApplicationException(String.Format( - "GetRawInputData returned invalid buffer. Windows error {0}. Please file a bug at http://opentk.sourceforge.net", - Marshal.GetLastWin32Error())); - } - break; - - case WindowMessage.DESTROY: - Debug.Print("Input window detached from parent {0}.", Handle); - ReleaseHandle(); - break; - - case WindowMessage.QUIT: - Debug.WriteLine("Input window quit."); - this.Dispose(); - break; - } - - base.WndProc(ref msg); + Debug.Unindent(); + return Native; } #endregion - #region --- IInputDriver Members --- + #region WindowProcedureImplementation + + // Processes the input Windows Message, routing the buffer to the correct Keyboard, Mouse or HID. + static IntPtr WindowProcedureImplementation(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + switch (message) + { + case WindowMessage.INPUT: + int size = 0; + // Get the size of the input buffer + Functions.GetRawInputData(lParam, GetRawInputDataEnum.INPUT, + IntPtr.Zero, ref size, API.RawInputHeaderSize); + + // Read the actual raw input structure + if (size == Functions.GetRawInputData(lParam, GetRawInputDataEnum.INPUT, + out data, ref size, API.RawInputHeaderSize)) + { + switch (data.Header.Type) + { + case RawInputDeviceType.KEYBOARD: + if (keyboardDriver.ProcessKeyboardEvent(data)) + return IntPtr.Zero; + break; + + case RawInputDeviceType.MOUSE: + if (mouseDriver.ProcessMouseEvent(data)) + return IntPtr.Zero; + break; + + case RawInputDeviceType.HID: + break; + } + } + break; + } + return Functions.CallWindowProc(OldWndProc, handle, message, wParam, lParam); + } + + #endregion + + #region ProcessEvents + + static void ProcessEvents() + { + INativeWindow native = ConstructMessageWindow(); + + MSG msg = new MSG(); + while (native.Exists) + { + int ret = Functions.GetMessage(ref msg, Parent.WindowHandle, 0, 0); + if (ret == -1) + { + throw new PlatformException(String.Format( + "An error happened while processing the message queue. Windows error: {0}", + Marshal.GetLastWin32Error())); + } + + Functions.TranslateMessage(ref msg); + Functions.DispatchMessage(ref msg); + } + } + + #endregion + + #endregion + + #region IInputDriver Members #region IInputDriver Members @@ -203,7 +257,7 @@ namespace OpenTK.Platform.Windows public IList Keyboard { - get { return keyboardDriver.Keyboard; } + get { return KeyboardDriver.Keyboard; } } public KeyboardState GetState() @@ -222,7 +276,7 @@ namespace OpenTK.Platform.Windows public IList Mouse { - get { return mouseDriver.Mouse; } + get { return MouseDriver.Mouse; } } MouseState IMouseDriver.GetState() @@ -248,7 +302,26 @@ namespace OpenTK.Platform.Windows #endregion - #region --- IDisposable Members --- + #region IInputDriver2 Members + + public IMouseDriver MouseDriver + { + get { return mouseDriver; } + } + + public IKeyboardDriver KeyboardDriver + { + get { return keyboardDriver; } + } + + public IJoystickDriver JoystickDriver + { + get { return joystickDriver; } + } + + #endregion + + #region IDisposable Members private bool disposed; @@ -265,7 +338,7 @@ namespace OpenTK.Platform.Windows if (manual) { keyboardDriver.Dispose(); - this.ReleaseHandle(); + //mouseDriver.Dispose(); } disposed = true; @@ -274,6 +347,7 @@ namespace OpenTK.Platform.Windows ~WinRawInput() { + Debug.Print("[Warning] Resource leaked: {0}.", this); Dispose(false); } diff --git a/Source/OpenTK/Platform/Windows/WinRawKeyboard.cs b/Source/OpenTK/Platform/Windows/WinRawKeyboard.cs index b4012dde..995d716e 100644 --- a/Source/OpenTK/Platform/Windows/WinRawKeyboard.cs +++ b/Source/OpenTK/Platform/Windows/WinRawKeyboard.cs @@ -1,7 +1,28 @@ -#region --- License --- -/* Copyright (c) 2007 Stefanos Apostolopoulos - * See license.txt for license info - */ +#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 #region --- Using directives --- diff --git a/Source/OpenTK/Platform/Windows/WinRawMouse.cs b/Source/OpenTK/Platform/Windows/WinRawMouse.cs index f242bd89..86ad4a33 100644 --- a/Source/OpenTK/Platform/Windows/WinRawMouse.cs +++ b/Source/OpenTK/Platform/Windows/WinRawMouse.cs @@ -1,7 +1,28 @@ -#region --- License --- -/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos - * See license.txt for license info - */ +#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; @@ -22,25 +43,17 @@ namespace OpenTK.Platform.Windows { List mice; Dictionary rawids; // ContextHandle instead of IntPtr for fast dictionary access - readonly INativeWindow native; - readonly IntPtr window; - readonly WindowProcedure WndProc; - readonly IntPtr OldWndProc; + readonly IntPtr Window; - internal WinRawMouse() + public WinRawMouse(IntPtr window) { Debug.WriteLine("Initializing mouse driver (WinRawMouse)."); Debug.Indent(); - // Create a new message-only window to retrieve WM_INPUT messages. - native = new NativeWindow(); - window = (native.WindowInfo as WinWindowInfo).WindowHandle; - //Functions.SetParent(window, Constants.MESSAGE_ONLY); - // Subclass the window to retrieve the events we are interested in. - WndProc = WindowProcedure; - OldWndProc = Functions.SetWindowLong(window, WndProc); - native.ProcessEvents(); + if (window == IntPtr.Zero) + throw new ArgumentNullException("window"); + Window = window; RegisterDevices(window, out mice, out rawids); Debug.Unindent(); @@ -52,7 +65,6 @@ namespace OpenTK.Platform.Windows public MouseState GetState() { - native.ProcessEvents(); if (mice.Count > 0) return mice[0]; else @@ -61,7 +73,6 @@ namespace OpenTK.Platform.Windows public MouseState GetState(int index) { - native.ProcessEvents(); if (index < mice.Count) return mice[index]; else @@ -172,49 +183,14 @@ namespace OpenTK.Platform.Windows return state; } - IntPtr WindowProcedure(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) - { - switch (message) - { - case WindowMessage.INPUT: - int expected_size = 0, real_size = 0; - RawInput data = new RawInput(); - - // Get the size of the input buffer - Functions.GetRawInputData(lParam, GetRawInputDataEnum.INPUT, - IntPtr.Zero, ref expected_size, API.RawInputHeaderSize); - - // Read the actual data - unsafe - { - real_size = Functions.GetRawInputData(lParam, GetRawInputDataEnum.INPUT, - &data, ref expected_size, API.RawInputHeaderSize); - } - - if (real_size == expected_size) - { - if (data.Header.Type == RawInputDeviceType.MOUSE) - { - if (ProcessEvent(data.Header.Device, data.Data.Mouse)) - { - return IntPtr.Zero; - } - } - } - // We didn't handle this message after all, give it back to the old WndProc. - goto default; - - default: - return Functions.CallWindowProc(OldWndProc, handle, message, wParam, lParam); - } - } - - bool ProcessEvent(IntPtr device, RawMouse raw) + public bool ProcessMouseEvent(RawInput rin) { if (mice.Count == 0) return false; - ContextHandle handle = new ContextHandle(device); + RawMouse raw = rin.Data.Mouse; + ContextHandle handle = new ContextHandle(rin.Header.Device); + MouseState mouse; if (rawids.ContainsKey(handle)) mouse = mice[rawids[handle]]; @@ -249,7 +225,5 @@ namespace OpenTK.Platform.Windows mice[rawids[handle]] = mouse; return true; } - - } }