[Win] Raw input parsing moved to input drivers

This commit is contained in:
thefiddler 2014-07-31 15:44:11 +02:00
parent a51a85c517
commit 3fee0bd8d0
4 changed files with 231 additions and 200 deletions

View file

@ -94,32 +94,30 @@ namespace OpenTK.Platform.Windows
switch (message) switch (message)
{ {
case WindowMessage.INPUT: case WindowMessage.INPUT:
int size = BlittableValueType<RawInput>.Stride;
RawInput data;
//RawInput data;
// Read the actual raw input structure
if (size == Functions.GetRawInputData(lParam, GetRawInputDataEnum.INPUT,
out data, ref size, API.RawInputHeaderSize))
{ {
switch (data.Header.Type) // Retrieve the raw input data buffer
RawInputHeader header;
if (Functions.GetRawInputData(lParam, out header) == RawInputHeader.SizeInBytes)
{
switch (header.Type)
{ {
case RawInputDeviceType.KEYBOARD: case RawInputDeviceType.KEYBOARD:
if (((WinRawKeyboard)KeyboardDriver).ProcessKeyboardEvent(ref data)) if (((WinRawKeyboard)KeyboardDriver).ProcessKeyboardEvent(lParam))
return IntPtr.Zero; return IntPtr.Zero;
break; break;
case RawInputDeviceType.MOUSE: case RawInputDeviceType.MOUSE:
if (((WinRawMouse)MouseDriver).ProcessMouseEvent(ref data)) if (((WinRawMouse)MouseDriver).ProcessMouseEvent(lParam))
return IntPtr.Zero; return IntPtr.Zero;
break; break;
case RawInputDeviceType.HID: case RawInputDeviceType.HID:
if (((WinRawJoystick)JoystickDriver).ProcessEvent(ref data)) if (((WinRawJoystick)JoystickDriver).ProcessEvent(lParam))
return IntPtr.Zero; return IntPtr.Zero;
break; break;
} }
} }
}
break; break;
case WindowMessage.DEVICECHANGE: case WindowMessage.DEVICECHANGE:

View file

@ -137,6 +137,7 @@ namespace OpenTK.Platform.Windows
readonly object UpdateLock = new object(); readonly object UpdateLock = new object();
readonly DeviceCollection<Device> Devices = new DeviceCollection<Device>(); readonly DeviceCollection<Device> Devices = new DeviceCollection<Device>();
byte[] HIDData = new byte[1024];
byte[] PreparsedData = new byte[1024]; byte[] PreparsedData = new byte[1024];
HidProtocolValueCaps[] AxisCaps = new HidProtocolValueCaps[4]; HidProtocolValueCaps[] AxisCaps = new HidProtocolValueCaps[4];
HidProtocolButtonCaps[] ButtonCaps = new HidProtocolButtonCaps[4]; HidProtocolButtonCaps[] ButtonCaps = new HidProtocolButtonCaps[4];
@ -153,8 +154,8 @@ namespace OpenTK.Platform.Windows
Window = window; Window = window;
DeviceTypes = new RawInputDevice[] DeviceTypes = new RawInputDevice[]
{ {
new RawInputDevice(HIDUsageGD.Joystick, RawInputDeviceFlags.INPUTSINK, window), new RawInputDevice(HIDUsageGD.Joystick, RawInputDeviceFlags.DEVNOTIFY | RawInputDeviceFlags.EXINPUTSINK, window),
new RawInputDevice(HIDUsageGD.GamePad, RawInputDeviceFlags.INPUTSINK, window), new RawInputDevice(HIDUsageGD.GamePad, RawInputDeviceFlags.DEVNOTIFY | RawInputDeviceFlags.EXINPUTSINK, window),
}; };
if (!Functions.RegisterRawInputDevices(DeviceTypes, DeviceTypes.Length, API.RawInputDeviceSize)) if (!Functions.RegisterRawInputDevices(DeviceTypes, DeviceTypes.Length, API.RawInputDeviceSize))
@ -192,7 +193,8 @@ namespace OpenTK.Platform.Windows
IntPtr handle = dev.Device; IntPtr handle = dev.Device;
Guid guid = GetDeviceGuid(handle); Guid guid = GetDeviceGuid(handle);
long hardware_id = guid.GetHashCode(); //long hardware_id = guid.GetHashCode();
long hardware_id = handle.ToInt64();
Device device = Devices.FromHardwareId(hardware_id); Device device = Devices.FromHardwareId(hardware_id);
if (device != null) if (device != null)
@ -215,9 +217,24 @@ namespace OpenTK.Platform.Windows
} }
} }
public unsafe bool ProcessEvent(ref RawInput rin) public unsafe bool ProcessEvent(IntPtr raw)
{ {
IntPtr handle = rin.Header.Device; // Query the size of the raw HID data buffer
int size = 0;
Functions.GetRawInputData(raw, GetRawInputDataEnum.INPUT, IntPtr.Zero, ref size, RawInputHeader.SizeInBytes);
if (size > HIDData.Length)
{
Array.Resize(ref HIDData, size);
}
// Retrieve the raw HID data buffer
if (Functions.GetRawInputData(raw, HIDData) > 0)
{
fixed (byte* pdata = HIDData)
{
RawInput* rin = (RawInput*)pdata;
IntPtr handle = rin->Header.Device;
Device stick = GetDevice(handle); Device stick = GetDevice(handle);
if (stick == null) if (stick == null)
{ {
@ -243,8 +260,8 @@ namespace OpenTK.Platform.Windows
// Query current state // Query current state
// Allocate enough storage to hold the data of the current report // Allocate enough storage to hold the data of the current report
int size = HidProtocol.MaxDataListLength(HidProtocolReportType.Input, PreparsedData); int report_count = HidProtocol.MaxDataListLength(HidProtocolReportType.Input, PreparsedData);
if (size == 0) if (report_count == 0)
{ {
Debug.Print("[WinRawJoystick] HidProtocol.MaxDataListLength() failed with {0}", Debug.Print("[WinRawJoystick] HidProtocol.MaxDataListLength() failed with {0}",
Marshal.GetLastWin32Error()); Marshal.GetLastWin32Error());
@ -252,28 +269,29 @@ namespace OpenTK.Platform.Windows
} }
// Fill the data buffer // Fill the data buffer
if (DataBuffer.Length < size) if (DataBuffer.Length < report_count)
{ {
Array.Resize(ref DataBuffer, size); Array.Resize(ref DataBuffer, report_count);
} }
fixed (void* pdata = &rin.Data.HID.RawData)
{
if (HidProtocol.GetData(HidProtocolReportType.Input, if (HidProtocol.GetData(HidProtocolReportType.Input,
DataBuffer, ref size, PreparsedData, DataBuffer, ref size, PreparsedData,
(IntPtr)pdata, rin.Data.HID.Size) != HidProtocolStatus.Success) new IntPtr((void*)&rin->Data.HID.RawData),
rin->Data.HID.Size) != HidProtocolStatus.Success)
{ {
Debug.Print("[WinRawJoystick] HidProtocol.GetData() failed with {0}", Debug.Print("[WinRawJoystick] HidProtocol.GetData() failed with {0}",
Marshal.GetLastWin32Error()); Marshal.GetLastWin32Error());
return false; return false;
} }
}
UpdateAxes(stick, caps, AxisCaps, axis_caps_count, DataBuffer); UpdateAxes(stick, caps, AxisCaps, axis_caps_count, DataBuffer);
UpdateButtons(stick, caps, ButtonCaps, button_caps_count, DataBuffer); UpdateButtons(stick, caps, ButtonCaps, button_caps_count, DataBuffer);
return true; return true;
} }
}
return false;
}
#endregion #endregion

View file

@ -153,10 +153,13 @@ namespace OpenTK.Platform.Windows
} }
} }
public bool ProcessKeyboardEvent(ref RawInput rin) public bool ProcessKeyboardEvent(IntPtr raw)
{ {
bool processed = false; bool processed = false;
RawInput rin;
if (Functions.GetRawInputData(raw, out rin) > 0)
{
bool pressed = bool pressed =
rin.Data.Keyboard.Message == (int)WindowMessage.KEYDOWN || rin.Data.Keyboard.Message == (int)WindowMessage.KEYDOWN ||
rin.Data.Keyboard.Message == (int)WindowMessage.SYSKEYDOWN; rin.Data.Keyboard.Message == (int)WindowMessage.SYSKEYDOWN;
@ -196,10 +199,13 @@ namespace OpenTK.Platform.Windows
lock (UpdateLock) lock (UpdateLock)
{ {
keyboards[keyboard_handle] = keyboard; keyboards[keyboard_handle] = keyboard;
return processed; processed = true;
} }
} }
return processed;
}
#endregion #endregion
#region Private Members #region Private Members

View file

@ -149,7 +149,12 @@ namespace OpenTK.Platform.Windows
} }
} }
public bool ProcessMouseEvent(ref RawInput rin) public bool ProcessMouseEvent(IntPtr raw_buffer)
{
bool processed = false;
RawInput rin;
if (Functions.GetRawInputData(raw_buffer, out rin) > 0)
{ {
RawMouse raw = rin.Data.Mouse; RawMouse raw = rin.Data.Mouse;
ContextHandle handle = new ContextHandle(rin.Header.Device); ContextHandle handle = new ContextHandle(rin.Header.Device);
@ -171,7 +176,8 @@ namespace OpenTK.Platform.Windows
mouse = mice[mouse_handle]; mouse = mice[mouse_handle];
// Set and release capture of the mouse to fix http://www.opentk.com/node/2133, Patch by Artfunkel // Set and release capture of the mouse to fix http://www.opentk.com/node/2133, Patch by Artfunkel
if ((raw.ButtonFlags & RawInputMouseState.LEFT_BUTTON_DOWN) != 0){ if ((raw.ButtonFlags & RawInputMouseState.LEFT_BUTTON_DOWN) != 0)
{
mouse.EnableBit((int)MouseButton.Left); mouse.EnableBit((int)MouseButton.Left);
Functions.SetCapture(Window); Functions.SetCapture(Window);
} }
@ -241,10 +247,13 @@ namespace OpenTK.Platform.Windows
lock (UpdateLock) lock (UpdateLock)
{ {
mice[mouse_handle] = mouse; mice[mouse_handle] = mouse;
return true; processed = true;
} }
} }
return processed;
}
#endregion #endregion
#region Private Members #region Private Members