A game framework written with osu! in mind.
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2// See the LICENCE file in the repository root for full licence text.
3
4using System;
5using System.Drawing;
6using System.Runtime.InteropServices;
7
8namespace osu.Framework.Platform.Windows.Native
9{
10 internal static class Input
11 {
12 [DllImport("user32.dll")]
13 public static extern bool RegisterRawInputDevices(
14 [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
15 RawInputDevice[] pRawInputDevices,
16 int uiNumDevices,
17 int cbSize);
18
19 [DllImport("user32.dll")]
20 public static extern int GetRawInputData(IntPtr hRawInput, RawInputCommand uiCommand, out RawInputData pData, ref int pcbSize, int cbSizeHeader);
21
22 internal static Rectangle VirtualScreenRect => new Rectangle(
23 GetSystemMetrics(SM_XVIRTUALSCREEN),
24 GetSystemMetrics(SM_YVIRTUALSCREEN),
25 GetSystemMetrics(SM_CXVIRTUALSCREEN),
26 GetSystemMetrics(SM_CYVIRTUALSCREEN));
27
28 internal const int WM_INPUT = 0x00FF;
29
30 [DllImport("user32.dll")]
31 public static extern int GetSystemMetrics(int nIndex);
32
33 internal static Rectangle GetVirtualScreenRect() => new Rectangle(
34 GetSystemMetrics(SM_XVIRTUALSCREEN),
35 GetSystemMetrics(SM_YVIRTUALSCREEN),
36 GetSystemMetrics(SM_CXVIRTUALSCREEN),
37 GetSystemMetrics(SM_CYVIRTUALSCREEN)
38 );
39
40 public const int SM_XVIRTUALSCREEN = 76;
41 public const int SM_YVIRTUALSCREEN = 77;
42 public const int SM_CXVIRTUALSCREEN = 78;
43 public const int SM_CYVIRTUALSCREEN = 79;
44 }
45
46 /// <summary>
47 /// Value type for raw input.
48 /// </summary>
49 public struct RawInputData
50 {
51 /// <summary>Header for the data.</summary>
52 public RawInputHeader Header;
53
54 /// <summary>Mouse raw input data.</summary>
55 public RawMouse Mouse;
56
57 // This struct is a lot larger but the remaining elements have been omitted until required (Keyboard / HID / Touch).
58 }
59
60 /// <summary>
61 /// Contains information about the state of the mouse.
62 /// </summary>
63 public struct RawMouse
64 {
65 /// <summary>
66 /// The mouse state.
67 /// </summary>
68 public RawMouseFlags Flags;
69
70 /// <summary>
71 /// Flags for the event.
72 /// </summary>
73 public RawMouseButtons ButtonFlags;
74
75 /// <summary>
76 /// If the mouse wheel is moved, this will contain the delta amount.
77 /// </summary>
78 public short ButtonData;
79
80 /// <summary>
81 /// Raw button data.
82 /// </summary>
83 public uint RawButtons;
84
85 /// <summary>
86 /// The motion in the X direction. This is signed relative motion or
87 /// absolute motion, depending on the value of usFlags.
88 /// </summary>
89 public int LastX;
90
91 /// <summary>
92 /// The motion in the Y direction. This is signed relative motion or absolute motion,
93 /// depending on the value of usFlags.
94 /// </summary>
95 public int LastY;
96
97 /// <summary>
98 /// The device-specific additional information for the event.
99 /// </summary>
100 public uint ExtraInformation;
101 }
102
103 /// <summary>
104 /// Enumeration containing the flags for raw mouse data.
105 /// </summary>
106 [Flags]
107 public enum RawMouseFlags : ushort
108 {
109 /// <summary>Relative to the last position.</summary>
110 MoveRelative = 0,
111
112 /// <summary>Absolute positioning.</summary>
113 MoveAbsolute = 1,
114
115 /// <summary>Coordinate data is mapped to a virtual desktop.</summary>
116 VirtualDesktop = 2,
117
118 /// <summary>Attributes for the mouse have changed.</summary>
119 AttributesChanged = 4,
120
121 /// <summary>WM_MOUSEMOVE and WM_INPUT don't coalesce</summary>
122 MoveNoCoalesce = 8,
123 }
124
125 /// <summary>
126 /// Enumeration containing the button data for raw mouse input.
127 /// </summary>
128 public enum RawMouseButtons : ushort
129 {
130 /// <summary>No button.</summary>
131 None = 0,
132
133 /// <summary>Left (button 1) down.</summary>
134 LeftDown = 0x0001,
135
136 /// <summary>Left (button 1) up.</summary>
137 LeftUp = 0x0002,
138
139 /// <summary>Right (button 2) down.</summary>
140 RightDown = 0x0004,
141
142 /// <summary>Right (button 2) up.</summary>
143 RightUp = 0x0008,
144
145 /// <summary>Middle (button 3) down.</summary>
146 MiddleDown = 0x0010,
147
148 /// <summary>Middle (button 3) up.</summary>
149 MiddleUp = 0x0020,
150
151 /// <summary>Button 4 down.</summary>
152 Button4Down = 0x0040,
153
154 /// <summary>Button 4 up.</summary>
155 Button4Up = 0x0080,
156
157 /// <summary>Button 5 down.</summary>
158 Button5Down = 0x0100,
159
160 /// <summary>Button 5 up.</summary>
161 Button5Up = 0x0200,
162
163 /// <summary>Mouse wheel moved.</summary>
164 MouseWheel = 0x0400
165 }
166
167 /// <summary>
168 /// Enumeration contanining the command types to issue.
169 /// </summary>
170 public enum RawInputCommand
171 {
172 /// <summary>
173 /// Get input data.
174 /// </summary>
175 Input = 0x10000003,
176
177 /// <summary>
178 /// Get header data.
179 /// </summary>
180 Header = 0x10000005
181 }
182
183 /// <summary>
184 /// Enumeration containing the type device the raw input is coming from.
185 /// </summary>
186 public enum RawInputType
187 {
188 /// <summary>
189 /// Mouse input.
190 /// </summary>
191 Mouse = 0,
192
193 /// <summary>
194 /// Keyboard input.
195 /// </summary>
196 Keyboard = 1,
197
198 /// <summary>
199 /// Another device that is not the keyboard or the mouse.
200 /// </summary>
201 HID = 2
202 }
203
204 /// <summary>
205 /// Value type for a raw input header.
206 /// </summary>
207 [StructLayout(LayoutKind.Sequential)]
208 public struct RawInputHeader
209 {
210 /// <summary>Type of device the input is coming from.</summary>
211 public RawInputType Type;
212
213 /// <summary>Size of the packet of data.</summary>
214 public int Size;
215
216 /// <summary>Handle to the device sending the data.</summary>
217 public IntPtr Device;
218
219 /// <summary>wParam from the window message.</summary>
220 public IntPtr wParam;
221 }
222
223 [StructLayout(LayoutKind.Sequential)]
224 public struct RawInputDevice
225 {
226 /// <summary>Top level collection Usage page for the raw input device.</summary>
227 public HIDUsagePage UsagePage;
228
229 /// <summary>Top level collection Usage for the raw input device. </summary>
230 public HIDUsage Usage;
231
232 /// <summary>Mode flag that specifies how to interpret the information provided by UsagePage and Usage.</summary>
233 public RawInputDeviceFlags Flags;
234
235 /// <summary>Handle to the target device. If NULL, it follows the keyboard focus.</summary>
236 public IntPtr WindowHandle;
237 }
238
239 /// <summary>Enumeration containing flags for a raw input device.</summary>
240 public enum RawInputDeviceFlags
241 {
242 /// <summary>No flags.</summary>
243 None = 0,
244
245 /// <summary>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.</summary>
246 Remove = 0x00000001,
247
248 /// <summary>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.</summary>
249 Exclude = 0x00000010,
250
251 /// <summary>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.</summary>
252 PageOnly = 0x00000020,
253
254 /// <summary>If set, this prevents any devices specified by UsagePage or Usage from generating legacy messages. This is only for the mouse and keyboard.</summary>
255 NoLegacy = 0x00000030,
256
257 /// <summary>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.</summary>
258 InputSink = 0x00000100,
259
260 /// <summary>If set, the mouse button click does not activate the other window.</summary>
261 CaptureMouse = 0x00000200,
262
263 /// <summary>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.</summary>
264 NoHotKeys = 0x00000200,
265
266 /// <summary>If set, application keys are handled. NoLegacy must be specified. Keyboard only.</summary>
267 AppKeys = 0x00000400
268 }
269
270 public enum HIDUsage : ushort
271 {
272 Pointer = 0x01,
273 Mouse = 0x02,
274 Joystick = 0x04,
275 Gamepad = 0x05,
276 Keyboard = 0x06,
277 Keypad = 0x07,
278 SystemControl = 0x80,
279 }
280
281 public enum HIDUsagePage : ushort
282 {
283 Undefined = 0x00,
284 Generic = 0x01,
285 Simulation = 0x02,
286 VR = 0x03,
287 Sport = 0x04,
288 Game = 0x05,
289 Keyboard = 0x07,
290 LED = 0x08,
291 Button = 0x09,
292 Ordinal = 0x0A,
293 Telephony = 0x0B,
294 Consumer = 0x0C,
295 Digitizer = 0x0D,
296 PID = 0x0F,
297 Unicode = 0x10,
298 AlphaNumeric = 0x14,
299 Medical = 0x40,
300 MonitorPage0 = 0x80,
301 MonitorPage1 = 0x81,
302 MonitorPage2 = 0x82,
303 MonitorPage3 = 0x83,
304 PowerPage0 = 0x84,
305 PowerPage1 = 0x85,
306 PowerPage2 = 0x86,
307 PowerPage3 = 0x87,
308 BarCode = 0x8C,
309 Scale = 0x8D,
310 MSR = 0x8E
311 }
312}