diff --git a/Source/OpenTK/GameWindow.cs b/Source/OpenTK/GameWindow.cs
index 1b21e82d..b403877e 100644
--- a/Source/OpenTK/GameWindow.cs
+++ b/Source/OpenTK/GameWindow.cs
@@ -19,8 +19,6 @@ namespace OpenTK
private INativeWindow glWindow;
private ResizeEventArgs resizeEventArgs = new ResizeEventArgs();
- public Keyboard Key = new Keyboard();
-
#region --- Contructors ---
///
@@ -75,7 +73,7 @@ namespace OpenTK
#endregion
- #region --- IGLWindow Members ---
+ #region --- IGLControl Members ---
#region public bool IsIdle
@@ -178,6 +176,11 @@ namespace OpenTK
public event UpdateFrameEvent UpdateFrameNotify;
public event RenderFrameEvent RenderFrameNotify;
+ public IKeyboard Key
+ {
+ get { return glWindow.Key; }
+ }
+
#endregion
#region --- IResizable Members ---
diff --git a/Source/OpenTK/Input/IKeyboard.cs b/Source/OpenTK/Input/IKeyboard.cs
index 00f58e2a..11eef01b 100644
--- a/Source/OpenTK/Input/IKeyboard.cs
+++ b/Source/OpenTK/Input/IKeyboard.cs
@@ -4,9 +4,9 @@ using System.Text;
namespace OpenTK.Input
{
- interface IKeyboard
+ public interface IKeyboard
{
bool this[Keys k] { get; set; }
- void Poll();
+ //void Poll();
}
}
diff --git a/Source/OpenTK/Input/Keyboard.cs b/Source/OpenTK/Input/Keyboard.cs
index 32c3c2de..e7156ab6 100644
--- a/Source/OpenTK/Input/Keyboard.cs
+++ b/Source/OpenTK/Input/Keyboard.cs
@@ -13,7 +13,7 @@ namespace OpenTK.Input
if (Environment.OSVersion.Platform == PlatformID.Win32NT ||
Environment.OSVersion.Platform == PlatformID.Win32Windows)
{
- keyboard = new OpenTK.Platform.Windows.WinKeyboard();
+ keyboard = new OpenTK.Platform.Windows.WinRawKeyboard();
}
else if (Environment.OSVersion.Platform == PlatformID.Unix ||
Environment.OSVersion.Platform == (PlatformID)128) // some older versions of Mono reported 128.
@@ -28,16 +28,15 @@ namespace OpenTK.Input
}
}
+ #region --- IKeyboard members ---
+
public bool this[Keys k]
{
get { return keyboard[k]; }
set { keyboard[k] = value; }
}
- public void Poll()
- {
- keyboard.Poll();
- }
+ #endregion
}
public enum Keys : int
diff --git a/Source/OpenTK/Platform/IGameWindow.cs b/Source/OpenTK/Platform/IGameWindow.cs
index e250914c..b1049129 100644
--- a/Source/OpenTK/Platform/IGameWindow.cs
+++ b/Source/OpenTK/Platform/IGameWindow.cs
@@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.Text;
+using OpenTK.Input;
+
namespace OpenTK.Platform
{
interface IGameWindow : IDisposable
@@ -13,6 +15,8 @@ namespace OpenTK.Platform
event UpdateFrameEvent UpdateFrameNotify;
event RenderFrameEvent RenderFrameNotify;
+
+ IKeyboard Key { get; }
}
public delegate void UpdateFrameEvent(EventArgs e);
diff --git a/Source/OpenTK/Platform/INativeWindow.cs b/Source/OpenTK/Platform/INativeWindow.cs
index 1640901e..d01a4fa4 100644
--- a/Source/OpenTK/Platform/INativeWindow.cs
+++ b/Source/OpenTK/Platform/INativeWindow.cs
@@ -13,6 +13,7 @@ namespace OpenTK.Platform
bool IsIdle { get; }
bool Quit { get; set; }
bool Fullscreen { get; set; }
+ OpenTK.Input.IKeyboard Key { get; }
IGLContext Context { get; }
}
}
diff --git a/Source/OpenTK/Platform/Windows/API.cs b/Source/OpenTK/Platform/Windows/API.cs
index 3ff33cdf..824775b7 100644
--- a/Source/OpenTK/Platform/Windows/API.cs
+++ b/Source/OpenTK/Platform/Windows/API.cs
@@ -51,13 +51,26 @@ namespace OpenTK.Platform.Windows
///
internal static class API
{
- // Prevent BeforeFieldInit optimization.
- static API() { }
+ // Prevent BeforeFieldInit optimization, and initialize 'size' fields.
+ static API()
+ {
+ RawInputHeaderSize = (uint)Marshal.SizeOf(typeof(RawInputHeader));
+ RawInputSize = (uint)Marshal.SizeOf(typeof(RawInput));
+ }
#region Constants
internal struct Constants
{
+ // Mouse indicator flags (found in winuser.h)
+ internal const int MOUSE_MOVE_RELATIVE = 0;
+ internal const int MOUSE_MOVE_ABSOLUTE = 1;
+ internal const int MOUSE_VIRTUAL_DESKTOP = 0x02; // the coordinates are mapped to the virtual desktop
+ internal const int MOUSE_ATTRIBUTES_CHANGED = 0x04; // requery for mouse attributes
+
+ // Found in winuser.h
+ internal const int KEYBOARD_OVERRUN_MAKE_CODE = 0xFF;
+
// WM_ACTIVATE state values (found in winuser.h)
internal const int WA_INACTIVE = 0;
internal const int WA_ACTIVE = 1;
@@ -107,6 +120,7 @@ namespace OpenTK.Platform.Windows
internal const int WM_WINDOWPOSCHANGED = 0x0047;
// Keyboard events (found in winuser.h)
+ internal const int WM_INPUT = 0x00FF; // Raw input. XP and higher only.
internal const int WM_KEYDOWN = 0x0100;
internal const int WM_KEYUP = 0x101;
internal const int WM_SYSKEYDOWN = 0x0104;
@@ -150,7 +164,7 @@ namespace OpenTK.Platform.Windows
#endregion
- #region WINAPI methods
+ #region --- Functions ---
#region Message handling
@@ -677,6 +691,7 @@ namespace OpenTK.Platform.Windows
/// TRUE if the function succeeds; otherwise, FALSE. If the function fails, call GetLastError for more information.
///
[DllImport("user32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
public static extern BOOL RegisterRawInputDevices(
RawInputDevice[] RawInputDevices,
UINT NumDevices,
@@ -799,17 +814,17 @@ namespace OpenTK.Platform.Windows
///
///
/// Specifies what data will be returned in pData. It can be one of the following values.
- /// RIDI_PREPARSEDDATA
+ /// RawInputDeviceInfoEnum.PREPARSEDDATA
/// Data points to the previously parsed data.
- /// RIDI_DEVICENAME
+ /// RawInputDeviceInfoEnum.DEVICENAME
/// Data points to a string that contains the device name.
/// For this Command only, the value in Size is the character count (not the byte count).
- /// RIDI_DEVICEINFO
- /// Data points to an RID_DEVICE_INFO structure.
+ /// RawInputDeviceInfoEnum.DEVICEINFO
+ /// Data points to an RawInputDeviceInfo structure.
///
///
/// ointer to a buffer that contains the information specified by Command.
- /// If Command is RIDI_DEVICEINFO, set RawInputDeviceInfo.Size to sizeof(RawInputDeviceInfo)
+ /// If Command is RawInputDeviceInfoEnum.DEVICEINFO, set RawInputDeviceInfo.Size to sizeof(RawInputDeviceInfo)
/// before calling GetRawInputDeviceInfo. (This is done automatically in OpenTK)
///
///
@@ -839,10 +854,10 @@ namespace OpenTK.Platform.Windows
/// Handle to the RawInput structure. This comes from the lParam in WM_INPUT.
///
/// Command flag. This parameter can be one of the following values.
- /// RID_INPUT
- /// Get the raw data from the RAWINPUT structure.
- /// RID_HEADER
- /// Get the header information from the RAWINPUT structure.
+ /// RawInputDateEnum.INPUT
+ /// Get the raw data from the RawInput structure.
+ /// RawInputDateEnum.HEADER
+ /// Get the header information from the RawInput structure.
///
/// Pointer to the data that comes from the RawInput structure. This depends on the value of uiCommand. If Data is NULL, the required size of the buffer is returned in Size.
/// Pointer to a variable that specifies the size, in bytes, of the data in Data.
@@ -858,21 +873,52 @@ namespace OpenTK.Platform.Windows
[DllImport("user32.dll", SetLastError = true)]
public static extern UINT GetRawInputData(
HRAWINPUT RawInput,
- UINT Command,
+ GetRawInputDataEnum Command,
[Out] LPVOID Data,
[In, Out] ref UINT Size,
UINT SizeHeader
);
+ ///
+ /// Gets the raw input from the specified device.
+ ///
+ /// Handle to the RawInput structure. This comes from the lParam in WM_INPUT.
+ ///
+ /// Command flag. This parameter can be one of the following values.
+ /// RawInputDateEnum.INPUT
+ /// Get the raw data from the RawInput structure.
+ /// RawInputDateEnum.HEADER
+ /// Get the header information from the RawInput structure.
+ ///
+ /// Pointer to the data that comes from the RawInput structure. This depends on the value of uiCommand. If Data is NULL, the required size of the buffer is returned in Size.
+ /// Pointer to a variable that specifies the size, in bytes, of the data in Data.
+ /// Size, in bytes, of RawInputHeader.
+ ///
+ /// If Data is NULL and the function is successful, the return value is 0. If Data is not NULL and the function is successful, the return value is the number of bytes copied into Data.
+ /// If there is an error, the return value is (UINT)-1.
+ ///
+ ///
+ /// GetRawInputData gets the raw input one RawInput structure at a time. In contrast, GetRawInputBuffer gets an array of RawInput structures.
+ ///
+ [System.Security.SuppressUnmanagedCodeSecurity]
+ [DllImport("user32.dll", SetLastError = true)]
+ public static extern UINT GetRawInputData(
+ HRAWINPUT RawInput,
+ GetRawInputDataEnum Command,
+ [MarshalAs(UnmanagedType.Struct)] [Out] RawInput Data,
+ [In, Out] ref UINT Size,
+ UINT SizeHeader
+ );
+
#endregion
#endregion
#endregion
- #region WINAPI structs
+ #region --- Structures ---
- #region internal struct CreateStruct
+ #region CreateStruct
internal struct CreateStruct
{
@@ -962,7 +1008,7 @@ namespace OpenTK.Platform.Windows
#endregion
- #region PixelFormatDescriptor struct
+ #region PixelFormatDescriptor
///
/// Describes a pixel format. It is used when interfacing with the WINAPI to create a new Context.
/// Found in WinGDI.h
@@ -1002,93 +1048,7 @@ namespace OpenTK.Platform.Windows
}
#endregion
- #region PixelFormatDescriptorFlags enum
- [Flags]
- internal enum PixelFormatDescriptorFlags : int
- {
- // PixelFormatDescriptor flags
- DOUBLEBUFFER,
- STEREO,
- DRAW_TO_WINDOW,
- DRAW_TO_BITMAP,
- SUPPORT_GDI,
- SUPPORT_OPENGL,
- GENERIC_FORMAT,
- NEED_PALETTE,
- NEED_SYSTEM_PALETTE,
- SWAP_EXCHANGE,
- SWAP_COPY,
- SWAP_LAYER_BUFFERS,
- GENERIC_ACCELERATED,
- SUPPORT_DIRECTDRAW,
-
- // PixelFormatDescriptor flags for use in ChoosePixelFormat only
- DEPTH_DONTCARE = unchecked((int)0x20000000),
- DOUBLEBUFFER_DONTCARE = unchecked((int)0x40000000),
- STEREO_DONTCARE = unchecked((int)0x80000000)
- }
- #endregion
-
- #region WindowPlacementOptions enum
-
- internal enum WindowPlacementOptions
- {
- TOP = 0,
- BOTTOM = 1,
- TOPMOST = -1,
- NOTOPMOST = -2
- }
-
- #endregion
-
- #region WindowClass
- [StructLayout(LayoutKind.Sequential)]
- internal class WindowClass
- {
- internal WindowClassStyle style = WindowClassStyle.VRedraw | WindowClassStyle.HRedraw | WindowClassStyle.OwnDC;
- [MarshalAs(UnmanagedType.FunctionPtr)]
- internal WindowProcedureEventHandler WindowProcedure;
- internal int ClassExtraBytes;
- internal int WindowExtraBytes;
- //[MarshalAs(UnmanagedType.
- internal IntPtr Instance;
- internal IntPtr Icon;
- internal IntPtr Cursor;
- internal IntPtr BackgroundBrush;
- //[MarshalAs(UnmanagedType.LPStr)]
- internal IntPtr MenuName;
- //[MarshalAs(UnmanagedType.LPStr)]
- internal IntPtr ClassName;
- //internal string ClassName;
- }
- #endregion
-
- #region WindowClassStyle enum
- [Flags]
- internal enum WindowClassStyle
- {
- //None = 0x0000,
- VRedraw = 0x0001,
- HRedraw = 0x0002,
- DoubleClicks = 0x0008,
- OwnDC = 0x0020,
- ClassDC = 0x0040,
- ParentDC = 0x0080,
- NoClose = 0x0200,
- SaveBits = 0x0800,
- ByteAlignClient = 0x1000,
- ByteAlignWindow = 0x2000,
- GlobalClass = 0x4000,
-
- Ime = 0x00010000,
-
- // #if(_WIN32_WINNT >= 0x0501)
- DropShadow = 0x00020000
- // #endif /* _WIN32_WINNT >= 0x0501 */
- }
- #endregion
-
- #region DeviceMode class
+ #region DeviceMode
/*
typedef struct _devicemode {
BCHAR dmDeviceName[CCHDEVICENAME];
@@ -1192,6 +1152,30 @@ namespace OpenTK.Platform.Windows
#endregion DeviceMode class
+ #region Window Handling
+
+ #region WindowClass
+ [StructLayout(LayoutKind.Sequential)]
+ internal class WindowClass
+ {
+ internal WindowClassStyle style = WindowClassStyle.VRedraw | WindowClassStyle.HRedraw | WindowClassStyle.OwnDC;
+ [MarshalAs(UnmanagedType.FunctionPtr)]
+ internal WindowProcedureEventHandler WindowProcedure;
+ internal int ClassExtraBytes;
+ internal int WindowExtraBytes;
+ //[MarshalAs(UnmanagedType.
+ internal IntPtr Instance;
+ internal IntPtr Icon;
+ internal IntPtr Cursor;
+ internal IntPtr BackgroundBrush;
+ //[MarshalAs(UnmanagedType.LPStr)]
+ internal IntPtr MenuName;
+ //[MarshalAs(UnmanagedType.LPStr)]
+ internal IntPtr ClassName;
+ //internal string ClassName;
+ }
+ #endregion
+
#region public struct MinMaxInfo
///
@@ -1326,6 +1310,8 @@ namespace OpenTK.Platform.Windows
#endregion
+ #endregion
+
#region Raw Input structures
#region RawInputDevice
@@ -1348,27 +1334,12 @@ namespace OpenTK.Platform.Windows
///
public USHORT Usage;
///
- /// Mode flag that specifies how to interpret the information provided by usUsagePage and usUsage. It can be zero (the default) or one of the following values. By default, the operating system sends raw input from devices with the specified top level collection (TLC) to the registered application as long as it has the window focus.
- /// RIDEV_APPKEYS
- /// Microsoft Windows XP Service Pack 1 (SP1): If set, the application command keys are handled. RIDEV_APPKEYS can be specified only if RIDEV_NOLEGACY is specified for a keyboard device.
- /// RIDEV_CAPTUREMOUSE
- /// If set, the mouse button click does not activate the other window.
- /// RIDEV_EXCLUDE
- /// If set, this specifies the top level collections to exclude when reading a complete usage page. This flag only affects a TLC whose usage page is already specified with RIDEV_PAGEONLY.
- /// RIDEV_EXINPUTSINK
- /// If set, this enables the caller to receive input in the background only if the foreground application does not process it. In other words, if the foreground application is not registered for raw input, then the background application that is registered will receive the input.
- /// RIDEV_INPUTSINK
- /// If set, this enables the caller to receive the input even when the caller is not in the foreground. Note that hwndTarget must be specified.
- /// RIDEV_NOHOTKEYS
- /// If set, the application-defined keyboard device hotkeys are not handled. However, the system hotkeys; for example, ALT+TAB and CTRL+ALT+DEL, are still handled. By default, all keyboard hotkeys are handled. RIDEV_NOHOTKEYS can be specified even if RIDEV_NOLEGACY is not specified and hwndTarget is NULL.
- /// RIDEV_NOLEGACY
- /// If set, this prevents any devices specified by usUsagePage or usUsage from generating legacy messages. This is only for the mouse and keyboard. See Remarks.
- /// RIDEV_PAGEONLY
- /// If set, this specifies all devices whose top level collection is from the specified usUsagePage. Note that usUsage must be zero. To exclude a particular top level collection, use RIDEV_EXCLUDE.
- /// RIDEV_REMOVE
- /// If set, this removes the top level collection from the inclusion list. This tells the operating system to stop reading from a device which matches the top level collection.
+ /// Mode flag that specifies how to interpret the information provided by UsagePage and Usage.
+ /// It can be zero (the default) or one of the following values.
+ /// By default, the operating system sends raw input from devices with the specified top level collection (TLC)
+ /// to the registered application as long as it has the window focus.
///
- public INT Flags;
+ public RawInputDeviceFlags Flags;
///
/// Handle to the target window. If NULL it follows the keyboard focus.
///
@@ -1390,21 +1361,17 @@ namespace OpenTK.Platform.Windows
///
public HANDLE Device;
///
- /// Type of device. This can be one of the following values.
- /// RIM_TYPEHID
- /// The device is an Human Interface Device (HID) that is not a keyboard and not a mouse.
- /// RIM_TYPEKEYBOARD
- /// The device is a keyboard.
- /// RIM_TYPEMOUSE
- /// The device is a mouse.
+ /// Type of device.
///
- public DWORD Type;
+ public RawInputDeviceType Type;
}
#endregion
#region RawInput
+ public static uint RawInputSize;
+
///
/// Contains the raw input from a device.
///
@@ -1417,9 +1384,11 @@ namespace OpenTK.Platform.Windows
[StructLayout(LayoutKind.Sequential)]
public class RawInput
{
- public RawInputHeader Header;
+ public RawInputHeader Header;
+ public RawInputData Data;
+
[StructLayout(LayoutKind.Explicit)]
- public struct Data
+ public struct RawInputData
{
[FieldOffset(0)]
public RawMouse Mouse;
@@ -1434,6 +1403,8 @@ namespace OpenTK.Platform.Windows
#region RawInputHeader
+ public static readonly uint RawInputHeaderSize;
+
///
/// Contains the header information that is part of the raw input data.
///
@@ -1444,15 +1415,9 @@ namespace OpenTK.Platform.Windows
public struct RawInputHeader
{
///
- /// Type of raw input. It can be one of the following values.
- /// RIM_TYPEHID
- /// Raw input comes from some device that is not a keyboard or a mouse.
- /// RIM_TYPEKEYBOARD
- /// Raw input comes from the keyboard.
- /// RIM_TYPEMOUSE
- /// Raw input comes from the mouse.
+ /// Type of raw input.
///
- public DWORD Type;
+ public RawInputDeviceType Type;
///
/// Size, in bytes, of the entire input packet of data. This includesRAWINPUT plus possible extra input reports in the RAWHID variable length array.
///
@@ -1490,7 +1455,7 @@ namespace OpenTK.Platform.Windows
/// RI_KEY_TERMSRV_SET_LED
/// RI_KEY_TERMSRV_SHADOW
///
- public USHORT Flags;
+ public RawInputKeyboardDataFlags Flags;
///
/// Reserved; must be zero.
///
@@ -1538,44 +1503,10 @@ namespace OpenTK.Platform.Windows
[FieldOffset(2)]
ULONG Buttons;
///
- /// Transition state of the mouse buttons. This member can be one or more of the following values.
- /// RI_MOUSE_LEFT_BUTTON_DOWN
- /// Left button changed to down.
- /// RI_MOUSE_LEFT_BUTTON_UP
- /// Left button changed to up.
- /// RI_MOUSE_MIDDLE_BUTTON_DOWN
- /// Middle button changed to down.
- /// RI_MOUSE_MIDDLE_BUTTON_UP
- /// Middle button changed to up.
- /// RI_MOUSE_RIGHT_BUTTON_DOWN
- /// Right button changed to down.
- /// RI_MOUSE_RIGHT_BUTTON_UP
- /// Right button changed to up.
- /// RI_MOUSE_BUTTON_1_DOWN
- /// RI_MOUSE_LEFT_BUTTON_DOWN
- /// RI_MOUSE_BUTTON_1_UP
- /// RI_MOUSE_LEFT_BUTTON_UP
- /// RI_MOUSE_BUTTON_2_DOWN
- /// RI_MOUSE_RIGHT_BUTTON_DOWN
- /// RI_MOUSE_BUTTON_2_UP
- /// RI_MOUSE_RIGHT_BUTTON_UP
- /// RI_MOUSE_BUTTON_3_DOWN
- /// RI_MOUSE_MIDDLE_BUTTON_DOWN
- /// RI_MOUSE_BUTTON_3_UP
- /// RI_MOUSE_MIDDLE_BUTTON_UP
- /// RI_MOUSE_BUTTON_4_DOWN
- /// XBUTTON1 changed to down.
- /// RI_MOUSE_BUTTON_4_UP
- /// XBUTTON1 changed to up.
- /// RI_MOUSE_BUTTON_5_DOWN
- /// XBUTTON2 changed to down.
- /// RI_MOUSE_BUTTON_5_UP
- /// XBUTTON2 changed to up.
- /// RI_MOUSE_WHEEL
- /// Raw input comes from a mouse wheel. The wheel delta is stored in usButtonData.
+ /// Transition state of the mouse buttons.
///
[FieldOffset(2)]
- public USHORT ButtonFlags;
+ public RawInputMouseState ButtonFlags;
///
/// If usButtonFlags is RI_MOUSE_WHEEL, this member is a signed value that specifies the wheel delta.
///
@@ -1648,15 +1579,8 @@ namespace OpenTK.Platform.Windows
///
DWORD Size = Marshal.SizeOf(typeof(RawInputDeviceInfo));
///
- /// Type of raw input data. This member can be one of the following values.
- /// RIM_TYPEHID
- /// Data comes from an HID that is not a keyboard or a mouse.
- /// RIM_TYPEKEYBOARD
- /// Data comes from a keyboard.
- /// RIM_TYPEMOUSE
- /// Data comes from a mouse.
- ///
- public DWORD Type;
+ /// Type of raw input data.
+ public RawInputDeviceType Type;
[StructLayout(LayoutKind.Explicit)]
public struct Device
{
@@ -1777,7 +1701,205 @@ namespace OpenTK.Platform.Windows
#endregion
- #region Callbacks
+ #region --- Enums ---
+
+ #region PixelFormatDescriptorFlags enum
+ [Flags]
+ internal enum PixelFormatDescriptorFlags : int
+ {
+ // PixelFormatDescriptor flags
+ DOUBLEBUFFER,
+ STEREO,
+ DRAW_TO_WINDOW,
+ DRAW_TO_BITMAP,
+ SUPPORT_GDI,
+ SUPPORT_OPENGL,
+ GENERIC_FORMAT,
+ NEED_PALETTE,
+ NEED_SYSTEM_PALETTE,
+ SWAP_EXCHANGE,
+ SWAP_COPY,
+ SWAP_LAYER_BUFFERS,
+ GENERIC_ACCELERATED,
+ SUPPORT_DIRECTDRAW,
+
+ // PixelFormatDescriptor flags for use in ChoosePixelFormat only
+ DEPTH_DONTCARE = unchecked((int)0x20000000),
+ DOUBLEBUFFER_DONTCARE = unchecked((int)0x40000000),
+ STEREO_DONTCARE = unchecked((int)0x80000000)
+ }
+ #endregion
+
+ #region WindowPlacementOptions enum
+
+ internal enum WindowPlacementOptions
+ {
+ TOP = 0,
+ BOTTOM = 1,
+ TOPMOST = -1,
+ NOTOPMOST = -2
+ }
+
+ #endregion
+
+ #region WindowClassStyle enum
+ [Flags]
+ internal enum WindowClassStyle
+ {
+ //None = 0x0000,
+ VRedraw = 0x0001,
+ HRedraw = 0x0002,
+ DoubleClicks = 0x0008,
+ OwnDC = 0x0020,
+ ClassDC = 0x0040,
+ ParentDC = 0x0080,
+ NoClose = 0x0200,
+ SaveBits = 0x0800,
+ ByteAlignClient = 0x1000,
+ ByteAlignWindow = 0x2000,
+ GlobalClass = 0x4000,
+
+ Ime = 0x00010000,
+
+ // #if(_WIN32_WINNT >= 0x0501)
+ DropShadow = 0x00020000
+ // #endif /* _WIN32_WINNT >= 0x0501 */
+ }
+ #endregion
+
+ #region RawInputDeviceFlags enum
+
+ public enum RawInputDeviceFlags : int
+ {
+ ///
+ /// If set, this removes the top level collection from the inclusion list.
+ /// This tells the operating system to stop reading from a device which matches the top level collection.
+ ///
+ REMOVE = 0x00000001,
+ ///
+ /// If set, this specifies the top level collections to exclude when reading a complete usage page.
+ /// This flag only affects a TLC whose usage page is already specified with RawInputDeviceEnum.PAGEONLY.
+ ///
+ EXCLUDE = 0x00000010,
+ ///
+ /// If set, this specifies all devices whose top level collection is from the specified UsagePage.
+ /// Note that usUsage must be zero. To exclude a particular top level collection, use EXCLUDE.
+ ///
+ PAGEONLY = 0x00000020,
+ ///
+ /// If set, this prevents any devices specified by UsagePage or Usage from generating legacy messages.
+ /// This is only for the mouse and keyboard. See RawInputDevice Remarks.
+ ///
+ NOLEGACY = 0x00000030,
+ ///
+ /// If set, this enables the caller to receive the input even when the caller is not in the foreground.
+ /// Note that Target must be specified in RawInputDevice.
+ ///
+ INPUTSINK = 0x00000100,
+ ///
+ /// If set, the mouse button click does not activate the other window.
+ ///
+ CAPTUREMOUSE = 0x00000200, // effective when mouse nolegacy is specified, otherwise it would be an error
+ ///
+ /// If set, the application-defined keyboard device hotkeys are not handled.
+ /// However, the system hotkeys; for example, ALT+TAB and CTRL+ALT+DEL, are still handled.
+ /// By default, all keyboard hotkeys are handled.
+ /// NOHOTKEYS can be specified even if NOLEGACY is not specified and Target is NULL in RawInputDevice.
+ ///
+ NOHOTKEYS = 0x00000200, // effective for keyboard.
+ ///
+ /// Microsoft Windows XP Service Pack 1 (SP1): If set, the application command keys are handled. APPKEYS can be specified only if NOLEGACY is specified for a keyboard device.
+ ///
+ APPKEYS = 0x00000400, // effective for keyboard.
+ ///
+ /// If set, this enables the caller to receive input in the background only if the foreground application
+ /// does not process it. In other words, if the foreground application is not registered for raw input,
+ /// then the background application that is registered will receive the input.
+ ///
+ EXINPUTSINK = 0x00001000,
+ DEVNOTIFY = 0x00002000,
+ //EXMODEMASK = 0x000000F0
+ }
+
+ #endregion
+
+ #region GetRawInputDataEnum
+
+ public enum GetRawInputDataEnum
+ {
+ INPUT = 0x10000003,
+ HEADER = 0x10000005
+ }
+
+ #endregion
+
+ #region RawInputDeviceInfoEnum
+
+ public enum RawInputDeviceInfoEnum
+ {
+ PREPARSEDDATA = 0x20000005,
+ DEVICENAME = 0x20000007, // the return valus is the character length, not the byte size
+ DEVICEINFO = 0x2000000b
+ }
+
+ #endregion
+
+ #region RawInputMouseState
+
+ public enum RawInputMouseState : ushort
+ {
+ LEFT_BUTTON_DOWN = 0x0001, // Left Button changed to down.
+ LEFT_BUTTON_UP = 0x0002, // Left Button changed to up.
+ RIGHT_BUTTON_DOWN = 0x0004, // Right Button changed to down.
+ RIGHT_BUTTON_UP = 0x0008, // Right Button changed to up.
+ MIDDLE_BUTTON_DOWN = 0x0010, // Middle Button changed to down.
+ MIDDLE_BUTTON_UP = 0x0020, // Middle Button changed to up.
+
+ BUTTON_1_DOWN = LEFT_BUTTON_DOWN,
+ BUTTON_1_UP = LEFT_BUTTON_UP,
+ BUTTON_2_DOWN = RIGHT_BUTTON_DOWN,
+ BUTTON_2_UP = RIGHT_BUTTON_UP,
+ BUTTON_3_DOWN = MIDDLE_BUTTON_DOWN,
+ BUTTON_3_UP = MIDDLE_BUTTON_UP,
+
+ BUTTON_4_DOWN = 0x0040,
+ BUTTON_4_UP = 0x0080,
+ BUTTON_5_DOWN = 0x0100,
+ BUTTON_5_UP = 0x0200,
+
+ WHEEL = 0x0400
+ }
+
+ #endregion
+
+ #region RawInputKeyboardDataFlags
+
+ public enum RawInputKeyboardDataFlags : ushort
+ {
+ MAKE = 0,
+ BREAK = 1,
+ E0 = 2,
+ E1 = 4,
+ TERMSRV_SET_LED = 8,
+ TERMSRV_SHADOW = 0x10
+ }
+
+ #endregion
+
+ #region RawInputDeviceType
+
+ public enum RawInputDeviceType : int
+ {
+ MOUSE = 0,
+ KEYBOARD = 1,
+ HID = 2
+ }
+
+ #endregion
+
+ #endregion
+
+ #region --- Callbacks ---
[UnmanagedFunctionPointerAttribute(CallingConvention.Winapi)]
internal delegate void WindowProcedureEventHandler(object sender, WindowProcedureEventArgs e);
diff --git a/Source/OpenTK/Platform/Windows/WinGLNative.cs b/Source/OpenTK/Platform/Windows/WinGLNative.cs
index 1f66a509..07316ba7 100644
--- a/Source/OpenTK/Platform/Windows/WinGLNative.cs
+++ b/Source/OpenTK/Platform/Windows/WinGLNative.cs
@@ -24,6 +24,8 @@ namespace OpenTK.Platform.Windows
private bool disposed;
+ private WinRawKeyboard key;
+
#region --- Contructors ---
///
@@ -72,6 +74,12 @@ namespace OpenTK.Platform.Windows
0.0f
)
);
+
+ if (Environment.OSVersion.Version.Major > 5 ||
+ (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1))
+ key = new WinRawKeyboard(this.Handle); // WinXP and higher support raw input.
+ else
+ throw new PlatformNotSupportedException("Input is not implemented for platforms prior to Windows XP, yet.");
}
/*
@@ -167,12 +175,21 @@ namespace OpenTK.Platform.Windows
//this.OnResize(resizeEventArgs);
return;
- case API.Constants.WM_KEYDOWN:
+ case API.Constants.WM_KEYDOWN: // Legacy input events
case API.Constants.WM_KEYUP:
- if (this.ProcessKey(ref m))
- return;
- else
+ break;
+
+ case API.Constants.WM_INPUT: // Raw input
+ API.RawInput rin = WinRawInput.ProcessEvent(ref msg);
+ if (rin.Header.Type == API.RawInputDeviceType.KEYBOARD)
+ {
+ if (this.key.ProcessEvent(rin))
+ return;
+ else
+ break;
break;
+ }
+ break;
case API.Constants.WM_CLOSE:
API.PostQuitMessage(0);
@@ -200,7 +217,7 @@ namespace OpenTK.Platform.Windows
#endregion
- #region --- IGLWindow Members ---
+ #region --- INativeWindow Members ---
#region public void ProcessEvents()
@@ -230,6 +247,15 @@ namespace OpenTK.Platform.Windows
#endregion
+ #region public IKeyboard Key
+
+ public IKeyboard Key
+ {
+ get { return this.key; }
+ }
+
+ #endregion
+
#region public bool Quit
private bool quit;
diff --git a/Source/OpenTK/Platform/Windows/WinRawInput.cs b/Source/OpenTK/Platform/Windows/WinRawInput.cs
new file mode 100644
index 00000000..1e74cb23
--- /dev/null
+++ b/Source/OpenTK/Platform/Windows/WinRawInput.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms;
+using System.Runtime.InteropServices;
+
+namespace OpenTK.Platform.Windows
+{
+ static class WinRawInput
+ {
+ private static API.RawInput data = new API.RawInput();
+ internal static API.RawInput ProcessEvent(ref System.Windows.Forms.Message msg)
+ {
+ if (msg.Msg == API.Constants.WM_INPUT)
+ {
+ uint size = 0;
+ // Get the size of the input data
+ API.GetRawInputData(
+ msg.LParam,
+ API.GetRawInputDataEnum.INPUT,
+ IntPtr.Zero,
+ ref size,
+ API.RawInputHeaderSize
+ );
+
+ if (data == null || API.RawInputSize < size)
+ {
+ throw new Exception("WTF?!");
+ }
+
+ if (size ==
+ API.GetRawInputData(
+ msg.LParam,
+ API.GetRawInputDataEnum.INPUT,
+ data,
+ ref size,
+ API.RawInputHeaderSize))
+ {
+ return data;
+ }
+ else
+ {
+ throw new Exception(
+ "GetRawInputData returned invalid data. Please file a bug in http://opentk.sourceforge.net"
+ );
+ }
+ }
+ throw new Exception("Never reach this!");
+ }
+ }
+}
diff --git a/Source/OpenTK/Platform/Windows/WinRawKeyboard.cs b/Source/OpenTK/Platform/Windows/WinRawKeyboard.cs
new file mode 100644
index 00000000..19464352
--- /dev/null
+++ b/Source/OpenTK/Platform/Windows/WinRawKeyboard.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+
+using OpenTK.Input;
+
+namespace OpenTK.Platform.Windows
+{
+ internal class WinRawKeyboard : OpenTK.Input.IKeyboard
+ {
+ private bool[] keys = new bool[(int)Keys.MaxKeys];
+
+ internal WinRawKeyboard()
+ : this(IntPtr.Zero)
+ {
+ }
+
+ internal WinRawKeyboard(IntPtr windowHandle)
+ {
+ API.RawInputDevice[] rid = new API.RawInputDevice[1];
+ // Keyboard is 1/6 (page/id). See http://www.microsoft.com/whdc/device/input/HID_HWID.mspx
+ rid[0] = new API.RawInputDevice();
+ rid[0].UsagePage = 1;
+ rid[0].Usage = 6;
+
+ rid[0].Flags =
+ API.RawInputDeviceFlags.APPKEYS |
+ API.RawInputDeviceFlags.NOLEGACY;
+
+ rid[0].Target = windowHandle;
+
+ if (!API.RegisterRawInputDevices(rid, 1, API.RawInputHeaderSize))
+ {
+ /*throw new ApplicationException(
+ String.Format("Raw input registration failed for keyboard. Error {0}", Marshal.GetLastWin32Error())
+ );*/
+ }
+ }
+
+ internal bool ProcessEvent(API.RawInput rin)
+ {
+ if (rin.Data.Keyboard.VKey == API.Constants.VK_ESCAPE)
+ {
+ if (rin.Data.Keyboard.Message == API.Constants.WM_KEYDOWN)
+ keys[(int)Keys.Escape] = true;
+ else
+ keys[(int)Keys.Escape] = false;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ #region --- IKeyboard members ---
+
+ public bool this[Keys k]
+ {
+ get { return keys[(int)k]; }
+ set
+ {
+ /*keys[(int)k] = value;*/
+ throw new NotImplementedException();
+ }
+ }
+
+ #endregion
+ }
+
+
+}
diff --git a/Source/OpenTK/Platform/X11/X11GLNative.cs b/Source/OpenTK/Platform/X11/X11GLNative.cs
index 6b39ad76..40febeb2 100644
--- a/Source/OpenTK/Platform/X11/X11GLNative.cs
+++ b/Source/OpenTK/Platform/X11/X11GLNative.cs
@@ -9,6 +9,7 @@ using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
+using OpenTK.Input;
//using OpenTK.OpenGL;
@@ -27,6 +28,8 @@ namespace OpenTK.Platform.X11
private DisplayMode mode = new DisplayMode();
+ //private X11Keyboard key;
+
// Number of pending events.
private int pending = 0;
// C# ResizeEventArgs
@@ -170,7 +173,7 @@ namespace OpenTK.Platform.X11
#endregion
- #region --- IGLWindow Members ---
+ #region --- INativeWindow Members ---
#region public void ProcessEvents()
@@ -268,6 +271,15 @@ namespace OpenTK.Platform.X11
#endregion
+ #region public Keyboard Key
+
+ public IKeyboard Key
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ #endregion
+
#region public bool Quit
private bool quit;