// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; using System.Drawing; using System.Runtime.InteropServices; namespace osu.Framework.Platform.Windows.Native { internal static class Input { [DllImport("user32.dll")] public static extern bool RegisterRawInputDevices( [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] RawInputDevice[] pRawInputDevices, int uiNumDevices, int cbSize); [DllImport("user32.dll")] public static extern int GetRawInputData(IntPtr hRawInput, RawInputCommand uiCommand, out RawInputData pData, ref int pcbSize, int cbSizeHeader); internal static Rectangle VirtualScreenRect => new Rectangle( GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN), GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN)); internal const int WM_INPUT = 0x00FF; [DllImport("user32.dll")] public static extern int GetSystemMetrics(int nIndex); internal static Rectangle GetVirtualScreenRect() => new Rectangle( GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN), GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN) ); public const int SM_XVIRTUALSCREEN = 76; public const int SM_YVIRTUALSCREEN = 77; public const int SM_CXVIRTUALSCREEN = 78; public const int SM_CYVIRTUALSCREEN = 79; } /// /// Value type for raw input. /// public struct RawInputData { /// Header for the data. public RawInputHeader Header; /// Mouse raw input data. public RawMouse Mouse; // This struct is a lot larger but the remaining elements have been omitted until required (Keyboard / HID / Touch). } /// /// Contains information about the state of the mouse. /// public struct RawMouse { /// /// The mouse state. /// public RawMouseFlags Flags; /// /// Flags for the event. /// public RawMouseButtons ButtonFlags; /// /// If the mouse wheel is moved, this will contain the delta amount. /// public short ButtonData; /// /// Raw button data. /// public uint RawButtons; /// /// The motion in the X direction. This is signed relative motion or /// absolute motion, depending on the value of usFlags. /// public int LastX; /// /// The motion in the Y direction. This is signed relative motion or absolute motion, /// depending on the value of usFlags. /// public int LastY; /// /// The device-specific additional information for the event. /// public uint ExtraInformation; } /// /// Enumeration containing the flags for raw mouse data. /// [Flags] public enum RawMouseFlags : ushort { /// Relative to the last position. MoveRelative = 0, /// Absolute positioning. MoveAbsolute = 1, /// Coordinate data is mapped to a virtual desktop. VirtualDesktop = 2, /// Attributes for the mouse have changed. AttributesChanged = 4, /// WM_MOUSEMOVE and WM_INPUT don't coalesce MoveNoCoalesce = 8, } /// /// Enumeration containing the button data for raw mouse input. /// public enum RawMouseButtons : ushort { /// No button. None = 0, /// Left (button 1) down. LeftDown = 0x0001, /// Left (button 1) up. LeftUp = 0x0002, /// Right (button 2) down. RightDown = 0x0004, /// Right (button 2) up. RightUp = 0x0008, /// Middle (button 3) down. MiddleDown = 0x0010, /// Middle (button 3) up. MiddleUp = 0x0020, /// Button 4 down. Button4Down = 0x0040, /// Button 4 up. Button4Up = 0x0080, /// Button 5 down. Button5Down = 0x0100, /// Button 5 up. Button5Up = 0x0200, /// Mouse wheel moved. MouseWheel = 0x0400 } /// /// Enumeration contanining the command types to issue. /// public enum RawInputCommand { /// /// Get input data. /// Input = 0x10000003, /// /// Get header data. /// Header = 0x10000005 } /// /// Enumeration containing the type device the raw input is coming from. /// public enum RawInputType { /// /// Mouse input. /// Mouse = 0, /// /// Keyboard input. /// Keyboard = 1, /// /// Another device that is not the keyboard or the mouse. /// HID = 2 } /// /// Value type for a raw input header. /// [StructLayout(LayoutKind.Sequential)] public struct RawInputHeader { /// Type of device the input is coming from. public RawInputType Type; /// Size of the packet of data. public int Size; /// Handle to the device sending the data. public IntPtr Device; /// wParam from the window message. public IntPtr wParam; } [StructLayout(LayoutKind.Sequential)] public struct RawInputDevice { /// Top level collection Usage page for the raw input device. public HIDUsagePage UsagePage; /// Top level collection Usage for the raw input device. public HIDUsage Usage; /// Mode flag that specifies how to interpret the information provided by UsagePage and Usage. public RawInputDeviceFlags Flags; /// Handle to the target device. If NULL, it follows the keyboard focus. public IntPtr WindowHandle; } /// Enumeration containing flags for a raw input device. public enum RawInputDeviceFlags { /// No flags. None = 0, /// 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 PageOnly. Exclude = 0x00000010, /// If set, this specifies all devices whose top level collection is from the specified usUsagePage. Note that Usage 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. NoLegacy = 0x00000030, /// If set, this enables the caller to receive the input even when the caller is not in the foreground. Note that WindowHandle must be specified. InputSink = 0x00000100, /// If set, the mouse button click does not activate the other window. CaptureMouse = 0x00000200, /// 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 WindowHandle is NULL. NoHotKeys = 0x00000200, /// If set, application keys are handled. NoLegacy must be specified. Keyboard only. AppKeys = 0x00000400 } public enum HIDUsage : ushort { Pointer = 0x01, Mouse = 0x02, Joystick = 0x04, Gamepad = 0x05, Keyboard = 0x06, Keypad = 0x07, SystemControl = 0x80, } public enum HIDUsagePage : ushort { Undefined = 0x00, Generic = 0x01, Simulation = 0x02, VR = 0x03, Sport = 0x04, Game = 0x05, Keyboard = 0x07, LED = 0x08, Button = 0x09, Ordinal = 0x0A, Telephony = 0x0B, Consumer = 0x0C, Digitizer = 0x0D, PID = 0x0F, Unicode = 0x10, AlphaNumeric = 0x14, Medical = 0x40, MonitorPage0 = 0x80, MonitorPage1 = 0x81, MonitorPage2 = 0x82, MonitorPage3 = 0x83, PowerPage0 = 0x84, PowerPage1 = 0x85, PowerPage2 = 0x86, PowerPage3 = 0x87, BarCode = 0x8C, Scale = 0x8D, MSR = 0x8E } }