mirror of
https://github.com/RawAccelOfficial/rawaccel.git
synced 2025-05-11 10:26:58 +02:00
filter raw input based on id
use device id (from device instance) over first hardware id use buffered method for all ioctls update gui/DeviceIDManager to match driver behavior respond to device change events desync MouseData and PointData accessors
This commit is contained in:
parent
0fc716f652
commit
0e60e22b73
18 changed files with 213 additions and 115 deletions
|
@ -29,6 +29,7 @@
|
|||
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-version.h" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel.hpp" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)utility-install.hpp" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)utility-rawinput.hpp" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)x64-util.hpp" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)vec2.h" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
|
||||
#define RA_DEV_TYPE 0x8888u
|
||||
|
||||
#define RA_READ CTL_CODE(RA_DEV_TYPE, 0x888, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
#define RA_READ CTL_CODE(RA_DEV_TYPE, 0x888, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define RA_WRITE CTL_CODE(RA_DEV_TYPE, 0x889, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define RA_GET_VERSION CTL_CODE(RA_DEV_TYPE, 0x88a, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
#define RA_GET_VERSION CTL_CODE(RA_DEV_TYPE, 0x88a, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "vec2.h"
|
||||
#include "accel-base.hpp"
|
||||
|
||||
#define MAX_HWID_LEN 200
|
||||
#define MAX_DEV_ID_LEN 200
|
||||
|
||||
namespace rawaccel {
|
||||
|
||||
|
@ -25,7 +25,7 @@ namespace rawaccel {
|
|||
vec2d sens = { 1, 1 };
|
||||
vec2d dir_multipliers = {};
|
||||
milliseconds time_min = DEFAULT_TIME_MIN;
|
||||
wchar_t device_hw_id[MAX_HWID_LEN] = {0};
|
||||
wchar_t device_id[MAX_DEV_ID_LEN] = {0};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
74
common/utility-rawinput.hpp
Normal file
74
common/utility-rawinput.hpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
#pragma once
|
||||
|
||||
#pragma comment(lib, "cfgmgr32.lib")
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <vector>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <cfgmgr32.h>
|
||||
#include <initguid.h> // needed for devpkey.h to parse properly
|
||||
#include <devpkey.h>
|
||||
|
||||
// returns device handles corresponding to a "device id"
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/install/device-ids
|
||||
std::vector<HANDLE> rawinput_handles_from_dev_id(const std::wstring& dev_id, DWORD input_type = RIM_TYPEMOUSE) {
|
||||
const UINT RI_ERROR = -1;
|
||||
|
||||
UINT num_devs = 0;
|
||||
|
||||
if (GetRawInputDeviceList(NULL, &num_devs, sizeof(RAWINPUTDEVICELIST)) == RI_ERROR) {
|
||||
throw std::system_error(GetLastError(), std::system_category(), "GetRawInputDeviceList failed");
|
||||
}
|
||||
|
||||
auto devs = std::vector<RAWINPUTDEVICELIST>(num_devs);
|
||||
|
||||
if (GetRawInputDeviceList(&devs[0], &num_devs, sizeof(RAWINPUTDEVICELIST)) == RI_ERROR) {
|
||||
throw std::system_error(GetLastError(), std::system_category(), "GetRawInputDeviceList failed");
|
||||
}
|
||||
|
||||
std::vector<HANDLE> handles;
|
||||
|
||||
for (auto&& dev : devs) {
|
||||
if (dev.dwType != input_type) continue;
|
||||
|
||||
WCHAR name[256] = {};
|
||||
UINT name_size = sizeof(name);
|
||||
|
||||
if (GetRawInputDeviceInfoW(dev.hDevice, RIDI_DEVICENAME, name, &name_size) == RI_ERROR) {
|
||||
throw std::system_error(GetLastError(), std::system_category(), "GetRawInputDeviceInfoW failed");
|
||||
}
|
||||
|
||||
ULONG id_size = 0;
|
||||
DEVPROPTYPE type;
|
||||
CONFIGRET cm_res;
|
||||
|
||||
cm_res = CM_Get_Device_Interface_PropertyW(name, &DEVPKEY_Device_InstanceId,
|
||||
&type, NULL, &id_size, 0);
|
||||
|
||||
if (cm_res != CR_BUFFER_SMALL && cm_res != CR_SUCCESS) {
|
||||
throw std::runtime_error("CM_Get_Device_Interface_PropertyW failed (" +
|
||||
std::to_string(cm_res) + ')');
|
||||
}
|
||||
|
||||
std::wstring id((static_cast<size_t>(id_size) + 1) / 2, '\0');
|
||||
|
||||
cm_res = CM_Get_Device_Interface_PropertyW(name, &DEVPKEY_Device_InstanceId,
|
||||
&type, reinterpret_cast<PBYTE>(&id[0]), &id_size, 0);
|
||||
|
||||
if (cm_res != CR_SUCCESS) {
|
||||
throw std::runtime_error("CM_Get_Device_Interface_PropertyW failed (" +
|
||||
std::to_string(cm_res) + ')');
|
||||
}
|
||||
|
||||
// remove instance id
|
||||
id.resize(id.find_last_of('\\'));
|
||||
|
||||
if (id == dev_id) handles.push_back(dev.hDevice);
|
||||
}
|
||||
|
||||
return handles;
|
||||
}
|
||||
|
|
@ -58,8 +58,8 @@ Arguments:
|
|||
|
||||
bool any = num_packets > 0;
|
||||
bool rel_move = !(InputDataStart->Flags & MOUSE_MOVE_ABSOLUTE);
|
||||
bool dev_match = global.args.device_hw_id[0] == 0 ||
|
||||
wcsncmp(devExt->hwid, global.args.device_hw_id, MAX_HWID_LEN) == 0;
|
||||
bool dev_match = global.args.device_id[0] == 0 ||
|
||||
wcsncmp(devExt->dev_id, global.args.device_id, MAX_DEV_ID_LEN) == 0;
|
||||
|
||||
if (any && rel_move && dev_match) {
|
||||
// if IO is backed up to the point where we get more than 1 packet here
|
||||
|
@ -146,6 +146,8 @@ Return Value:
|
|||
NTSTATUS status;
|
||||
void* buffer;
|
||||
|
||||
size_t bytes_out = 0;
|
||||
|
||||
UNREFERENCED_PARAMETER(Queue);
|
||||
UNREFERENCED_PARAMETER(OutputBufferLength);
|
||||
UNREFERENCED_PARAMETER(InputBufferLength);
|
||||
|
@ -166,6 +168,7 @@ Return Value:
|
|||
}
|
||||
else {
|
||||
*reinterpret_cast<ra::settings*>(buffer) = global.args;
|
||||
bytes_out = sizeof(ra::settings);
|
||||
}
|
||||
break;
|
||||
case RA_WRITE:
|
||||
|
@ -205,6 +208,7 @@ Return Value:
|
|||
}
|
||||
else {
|
||||
*reinterpret_cast<ra::version_t*>(buffer) = { RA_VER_MAJOR, RA_VER_MINOR, RA_VER_PATCH };
|
||||
bytes_out = sizeof(ra::version_t);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -212,7 +216,7 @@ Return Value:
|
|||
break;
|
||||
}
|
||||
|
||||
WdfRequestComplete(Request, status);
|
||||
WdfRequestCompleteWithInformation(Request, status, bytes_out);
|
||||
|
||||
}
|
||||
#pragma warning(pop) // enable 28118 again
|
||||
|
@ -480,25 +484,31 @@ Return Value:
|
|||
}
|
||||
|
||||
//
|
||||
// get device hwid
|
||||
// get device id from bus driver
|
||||
//
|
||||
WDFMEMORY memory = NULL;
|
||||
DEVICE_OBJECT* pdo = WdfDeviceWdmGetPhysicalDevice(hDevice);
|
||||
|
||||
NTSTATUS hwid_query = WdfDeviceAllocAndQueryProperty(
|
||||
hDevice,
|
||||
DevicePropertyHardwareID,
|
||||
PagedPool,
|
||||
WDF_NO_OBJECT_ATTRIBUTES,
|
||||
&memory);
|
||||
KEVENT ke;
|
||||
KeInitializeEvent(&ke, NotificationEvent, FALSE);
|
||||
IO_STATUS_BLOCK iosb = {};
|
||||
PIRP Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
|
||||
pdo, NULL, 0, NULL, &ke, &iosb);
|
||||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(Irp);
|
||||
stack->MinorFunction = IRP_MN_QUERY_ID;
|
||||
stack->Parameters.QueryId.IdType = BusQueryDeviceID;
|
||||
|
||||
if (!NT_SUCCESS(hwid_query)) {
|
||||
DebugPrint(("WdfDeviceAllocAndQueryProperty failed: 0x%x\n", hwid_query));
|
||||
NTSTATUS nts = IoCallDriver(pdo, Irp);
|
||||
|
||||
if (nts == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(&ke, Executive, KernelMode, FALSE, NULL);
|
||||
}
|
||||
else {
|
||||
auto dev_ext = FilterGetData(hDevice);
|
||||
void* buffer = WdfMemoryGetBuffer(memory, NULL);
|
||||
wcsncpy(dev_ext->hwid, reinterpret_cast<wchar_t*>(buffer), MAX_HWID_LEN);
|
||||
WdfObjectDelete(memory);
|
||||
|
||||
if (NT_SUCCESS(nts)) {
|
||||
auto* id_ptr = reinterpret_cast<WCHAR*>(iosb.Information);
|
||||
wcsncpy(FilterGetData(hDevice)->dev_id, id_ptr, MAX_DEV_ID_LEN);
|
||||
DebugPrint(("Device ID = %ws\n", id_ptr));
|
||||
ExFreePool(id_ptr);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -21,7 +21,7 @@ typedef struct _DEVICE_EXTENSION {
|
|||
counter_t counter;
|
||||
vec2d carry;
|
||||
CONNECT_DATA UpperConnectData;
|
||||
WCHAR hwid[MAX_HWID_LEN];
|
||||
WCHAR dev_id[MAX_DEV_ID_LEN];
|
||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
||||
|
||||
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, FilterGetData)
|
||||
|
|
3
grapher/Form1.Designer.cs
generated
3
grapher/Form1.Designer.cs
generated
|
@ -261,7 +261,6 @@ namespace grapher
|
|||
this.optionsPanel.Name = "optionsPanel";
|
||||
this.optionsPanel.Size = new System.Drawing.Size(483, 956);
|
||||
this.optionsPanel.TabIndex = 34;
|
||||
this.optionsPanel.Paint += new System.Windows.Forms.PaintEventHandler(this.optionsPanel_Paint);
|
||||
//
|
||||
// toggleButton
|
||||
//
|
||||
|
@ -1308,8 +1307,6 @@ namespace grapher
|
|||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.Name = "RawAcceleration";
|
||||
this.Text = "Raw Accel";
|
||||
this.Load += new System.EventHandler(this.Form1_Load);
|
||||
this.Paint += new System.Windows.Forms.PaintEventHandler(this.RawAcceleration_Paint);
|
||||
this.optionsPanel.ResumeLayout(false);
|
||||
this.optionsPanel.PerformLayout();
|
||||
this.menuStrip1.ResumeLayout(false);
|
||||
|
|
|
@ -155,19 +155,18 @@ namespace grapher
|
|||
|
||||
protected override void WndProc(ref Message m)
|
||||
{
|
||||
if (m.Msg == 0x00ff)
|
||||
if (m.Msg == 0x00ff) // WM_INPUT
|
||||
{
|
||||
AccelGUI.MouseWatcher.ReadMouseMove(m);
|
||||
}
|
||||
else if (m.Msg == 0x00fe) // WM_INPUT_DEVICE_CHANGE
|
||||
{
|
||||
AccelGUI.UpdateInputManagers();
|
||||
}
|
||||
|
||||
base.WndProc(ref m);
|
||||
}
|
||||
|
||||
private void Form1_Load(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void ResetAutoScroll()
|
||||
{
|
||||
chartsPanel.AutoScrollPosition = Constants.Origin;
|
||||
|
@ -187,16 +186,6 @@ namespace grapher
|
|||
};
|
||||
}
|
||||
|
||||
private void RawAcceleration_Paint(object sender, PaintEventArgs e)
|
||||
{
|
||||
//AccelGUI.AccelCharts.DrawLastMovement();
|
||||
}
|
||||
|
||||
#endregion Method
|
||||
|
||||
private void optionsPanel_Paint(object sender, PaintEventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,6 +100,8 @@ namespace grapher
|
|||
|
||||
public DeviceIDManager DeviceIDManager { get; }
|
||||
|
||||
public Action UpdateInputManagers { get; private set; }
|
||||
|
||||
private Timer ChartRefresh { get; }
|
||||
|
||||
private Font SmallButtonFont { get; }
|
||||
|
@ -147,7 +149,7 @@ namespace grapher
|
|||
args = newArgs,
|
||||
minimumTime = driverSettings.minimumTime,
|
||||
directionalMultipliers = driverSettings.directionalMultipliers,
|
||||
deviceHardwareID = DeviceIDManager.HWID,
|
||||
deviceID = DeviceIDManager.ID,
|
||||
};
|
||||
|
||||
ButtonDelay(WriteButton);
|
||||
|
@ -168,6 +170,14 @@ namespace grapher
|
|||
{
|
||||
UpdateShownActiveValues(args);
|
||||
UpdateGraph(args);
|
||||
|
||||
UpdateInputManagers = () =>
|
||||
{
|
||||
MouseWatcher.UpdateHandles(args.deviceID);
|
||||
DeviceIDManager.Update(args.deviceID);
|
||||
};
|
||||
|
||||
UpdateInputManagers();
|
||||
}
|
||||
|
||||
public void UpdateGraph(DriverSettings args)
|
||||
|
|
|
@ -10,10 +10,10 @@ namespace grapher.Models.Devices
|
|||
{
|
||||
public class DeviceIDItem
|
||||
{
|
||||
public DeviceIDItem(string name, string hwid, DeviceIDManager manager)
|
||||
public DeviceIDItem(string name, string id, DeviceIDManager manager)
|
||||
{
|
||||
Name = name;
|
||||
HWID = hwid;
|
||||
ID = id;
|
||||
Manager = manager;
|
||||
DeviceIDMenuItem = new ToolStripMenuItem();
|
||||
DeviceIDMenuItem.Checked = false;
|
||||
|
@ -26,7 +26,7 @@ namespace grapher.Models.Devices
|
|||
|
||||
public string Name { get; }
|
||||
|
||||
public string HWID { get; }
|
||||
public string ID { get; }
|
||||
|
||||
private DeviceIDManager Manager { get; }
|
||||
|
||||
|
@ -40,9 +40,9 @@ namespace grapher.Models.Devices
|
|||
DeviceIDMenuItem.Checked = false;
|
||||
}
|
||||
|
||||
private string MenuItemText() => string.IsNullOrWhiteSpace(HWID) ? $"{Name}" : $"{Name}: {HWID}";
|
||||
private string MenuItemText() => string.IsNullOrEmpty(ID) ? $"{Name}" : $"{Name}: {ID}";
|
||||
|
||||
private string DisconnectedText() => $"Disconnected: {HWID}";
|
||||
private string DisconnectedText() => $"Disconnected: {ID}";
|
||||
|
||||
public void SetDisconnected()
|
||||
{
|
||||
|
@ -59,14 +59,14 @@ namespace grapher.Models.Devices
|
|||
{
|
||||
return obj is DeviceIDItem item &&
|
||||
Name == item.Name &&
|
||||
HWID == item.HWID;
|
||||
ID == item.ID;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
int hashCode = -1692744877;
|
||||
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Name);
|
||||
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(HWID);
|
||||
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(ID);
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,27 +19,26 @@ namespace grapher.Models.Devices
|
|||
|
||||
public ToolStripMenuItem DeviceIDsMenuItem { get; }
|
||||
|
||||
public string HWID { get => SelectedDeviceID.HWID; }
|
||||
public string ID { get => SelectedDeviceID.ID; }
|
||||
|
||||
public DeviceIDItem SelectedDeviceID { get; private set; }
|
||||
|
||||
public Dictionary<string, DeviceIDItem> DeviceIDs { get; private set; }
|
||||
|
||||
public static IEnumerable<(string, string)> GetDeviceHardwareIDs(string PNPClass = "Mouse")
|
||||
public static IEnumerable<(string, string)> GetDeviceIDs(string PNPClass = "Mouse")
|
||||
{
|
||||
ManagementObjectSearcher searcher = new ManagementObjectSearcher(new SelectQuery("Win32_PnPEntity"));
|
||||
|
||||
foreach (ManagementObject obj in searcher.Get())
|
||||
{
|
||||
if (obj["PNPClass"] != null && obj["PNPClass"].ToString().Equals(PNPClass) && obj["HardwareID"] != null)
|
||||
if (obj["PNPClass"] != null && obj["PNPClass"].ToString().Equals(PNPClass) && obj["DeviceID"] != null)
|
||||
{
|
||||
string[] hwidArray = (string[])(obj["HardwareID"]);
|
||||
if (hwidArray.Length > 0)
|
||||
{
|
||||
string hwid = hwidArray[0].ToString();
|
||||
string name = obj["Name"].ToString();
|
||||
yield return (name, hwid);
|
||||
}
|
||||
string name = obj["Name"].ToString();
|
||||
|
||||
string devInstanceID = obj["DeviceID"].ToString();
|
||||
string devID = devInstanceID.Remove(devInstanceID.LastIndexOf('\\'));
|
||||
|
||||
yield return (name, devID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,35 +54,31 @@ namespace grapher.Models.Devices
|
|||
SelectedDeviceID.SetActivated();
|
||||
}
|
||||
|
||||
public void OnStartup(string hwid)
|
||||
public void Update(string devID)
|
||||
{
|
||||
var nonEmptyHwid = !string.IsNullOrWhiteSpace(hwid);
|
||||
|
||||
DeviceIDsMenuItem.DropDownItems.Clear();
|
||||
|
||||
bool found = string.IsNullOrEmpty(devID);
|
||||
|
||||
var anyDevice = new DeviceIDItem("Any", string.Empty, this);
|
||||
if (!nonEmptyHwid)
|
||||
{
|
||||
SetActive(anyDevice);
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
if (found) SetActive(anyDevice);
|
||||
|
||||
foreach (var device in GetDeviceHardwareIDs())
|
||||
foreach (var device in GetDeviceIDs().Distinct())
|
||||
{
|
||||
var deviceItem = new DeviceIDItem(device.Item1, device.Item2, this);
|
||||
if (deviceItem.HWID.Equals(hwid))
|
||||
if (!found && deviceItem.ID.Equals(devID))
|
||||
{
|
||||
SetActive(deviceItem);
|
||||
found = true;
|
||||
deviceItem.SetActivated();
|
||||
SelectedDeviceID = deviceItem;
|
||||
}
|
||||
}
|
||||
|
||||
if (nonEmptyHwid && !found)
|
||||
if (!found)
|
||||
{
|
||||
var deviceItem = new DeviceIDItem(string.Empty, hwid, this);
|
||||
var deviceItem = new DeviceIDItem(string.Empty, devID, this);
|
||||
deviceItem.SetDisconnected();
|
||||
anyDevice.SetActivated();
|
||||
SetActive(deviceItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ namespace grapher.Models.Mouse
|
|||
|
||||
public MouseData()
|
||||
{
|
||||
Lock = new Object();
|
||||
X = 0;
|
||||
Y = 0;
|
||||
}
|
||||
|
@ -17,18 +16,13 @@ namespace grapher.Models.Mouse
|
|||
|
||||
#region Properties
|
||||
|
||||
public Object Lock { get; }
|
||||
|
||||
private int X { get; set; }
|
||||
private int Y { get; set; }
|
||||
|
||||
public void Set(int x, int y)
|
||||
{
|
||||
lock (Lock)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
#endregion Properties
|
||||
|
@ -37,11 +31,8 @@ namespace grapher.Models.Mouse
|
|||
|
||||
public void Get(out int x, out int y)
|
||||
{
|
||||
lock (Lock)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
}
|
||||
x = X;
|
||||
y = Y;
|
||||
}
|
||||
|
||||
#endregion Methods
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using grapher.Models.Serialized;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
|
||||
|
@ -397,7 +398,11 @@ namespace grapher.Models.Mouse
|
|||
/// <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>
|
||||
NoHotKeys = 0x00000200,
|
||||
/// <summary>If set, application keys are handled. NoLegacy must be specified. Keyboard only.</summary>
|
||||
AppKeys = 0x00000400
|
||||
AppKeys = 0x00000400,
|
||||
/// <summary>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.</summary>
|
||||
ExInputSink = 0x00001000,
|
||||
/// <summary>If set, this enables the caller to receive WM_INPUT_DEVICE_CHANGE notifications for device arrival and device removal.</summary>
|
||||
DevNotify = 0x00002000
|
||||
}
|
||||
|
||||
/// <summary>Value type for raw input devices.</summary>
|
||||
|
@ -685,12 +690,13 @@ namespace grapher.Models.Mouse
|
|||
AccelCharts = accelCharts;
|
||||
SettingsManager = setMngr;
|
||||
MouseData = new MouseData();
|
||||
DeviceHandles = new List<IntPtr>();
|
||||
|
||||
RAWINPUTDEVICE device = new RAWINPUTDEVICE();
|
||||
device.WindowHandle = ContainingForm.Handle;
|
||||
device.UsagePage = HIDUsagePage.Generic;
|
||||
device.Usage = HIDUsage.Mouse;
|
||||
device.Flags = RawInputDeviceFlags.InputSink;
|
||||
device.Flags = RawInputDeviceFlags.InputSink | RawInputDeviceFlags.DevNotify;
|
||||
|
||||
RAWINPUTDEVICE[] devices = new RAWINPUTDEVICE[1];
|
||||
devices[0] = device;
|
||||
|
@ -711,6 +717,10 @@ namespace grapher.Models.Mouse
|
|||
|
||||
private MouseData MouseData { get; }
|
||||
|
||||
private List<IntPtr> DeviceHandles { get; }
|
||||
|
||||
private bool AnyDevice { get; set; }
|
||||
|
||||
private double PollTime
|
||||
{
|
||||
get => 1000 / SettingsManager.PollRateField.Data;
|
||||
|
@ -720,6 +730,16 @@ namespace grapher.Models.Mouse
|
|||
|
||||
#region Methods
|
||||
|
||||
public void UpdateHandles(string devID)
|
||||
{
|
||||
DeviceHandles.Clear();
|
||||
AnyDevice = string.IsNullOrEmpty(devID);
|
||||
if (!AnyDevice)
|
||||
{
|
||||
RawInputInterop.AddHandlesFromID(devID, DeviceHandles);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateLastMove()
|
||||
{
|
||||
MouseData.Get(out var x, out var y);
|
||||
|
@ -728,15 +748,14 @@ namespace grapher.Models.Mouse
|
|||
|
||||
public void ReadMouseMove(Message message)
|
||||
{
|
||||
RawInput rawInput = new RawInput();
|
||||
int outSize = 0;
|
||||
RawInput rawInput;
|
||||
int size = Marshal.SizeOf(typeof(RawInput));
|
||||
|
||||
outSize = GetRawInputData((IntPtr)message.LParam, RawInputCommand.Input, out rawInput, ref size, Marshal.SizeOf(typeof(RAWINPUTHEADER)));
|
||||
_ = GetRawInputData(message.LParam, RawInputCommand.Input, out rawInput, ref size, Marshal.SizeOf(typeof(RAWINPUTHEADER)));
|
||||
|
||||
bool relative = !rawInput.Data.Mouse.Flags.HasFlag(RawMouseFlags.MoveAbsolute);
|
||||
bool deviceMatch = AnyDevice || DeviceHandles.Contains(rawInput.Header.Device);
|
||||
|
||||
if (relative && (rawInput.Data.Mouse.LastX != 0 || rawInput.Data.Mouse.LastY != 0))
|
||||
if (relative && deviceMatch && (rawInput.Data.Mouse.LastX != 0 || rawInput.Data.Mouse.LastY != 0))
|
||||
{
|
||||
double x = rawInput.Data.Mouse.LastX;
|
||||
double y = rawInput.Data.Mouse.LastY;
|
||||
|
|
|
@ -8,7 +8,6 @@ namespace grapher.Models.Mouse
|
|||
|
||||
public PointData()
|
||||
{
|
||||
Lock = new Object();
|
||||
X = new double[] { 0.01 };
|
||||
Y = new double[] { 0.01 };
|
||||
}
|
||||
|
@ -17,18 +16,13 @@ namespace grapher.Models.Mouse
|
|||
|
||||
#region Properties
|
||||
|
||||
public Object Lock { get; }
|
||||
|
||||
private double[] X { get; set; }
|
||||
private double[] Y { get; set; }
|
||||
|
||||
public void Set(double x, double y)
|
||||
{
|
||||
lock(Lock)
|
||||
{
|
||||
X[0] = x;
|
||||
Y[0] = y;
|
||||
}
|
||||
X[0] = x;
|
||||
Y[0] = y;
|
||||
}
|
||||
|
||||
#endregion Properties
|
||||
|
@ -37,11 +31,8 @@ namespace grapher.Models.Mouse
|
|||
|
||||
public void Get(out double[] x, out double[] y)
|
||||
{
|
||||
lock(Lock)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Methods
|
||||
|
|
|
@ -125,7 +125,8 @@ namespace grapher.Models.Serialized
|
|||
bool wholeOrNoY = accelSettings.combineMagnitudes ||
|
||||
accelSettings.modes.y == AccelMode.noaccel;
|
||||
|
||||
return accelSettings.sensitivity.x == 1 &&
|
||||
return string.IsNullOrEmpty(accelSettings.deviceID) &&
|
||||
accelSettings.sensitivity.x == 1 &&
|
||||
accelSettings.sensitivity.y == 1 &&
|
||||
accelSettings.directionalMultipliers.x <= 0 &&
|
||||
accelSettings.directionalMultipliers.y <= 0 &&
|
||||
|
|
|
@ -42,14 +42,14 @@ namespace grapher.Models.Serialized
|
|||
|
||||
public Field PollRateField { get; private set; }
|
||||
|
||||
public DeviceIDManager DeviceIDManager { get; }
|
||||
|
||||
private ToolStripMenuItem AutoWriteMenuItem { get; set; }
|
||||
|
||||
private ToolStripMenuItem ShowLastMouseMoveMenuItem { get; set; }
|
||||
|
||||
private ToolStripMenuItem ShowVelocityAndGainMoveMenuItem { get; set; }
|
||||
|
||||
private DeviceIDManager DeviceIDManager { get; }
|
||||
|
||||
#endregion Properties
|
||||
|
||||
#region Methods
|
||||
|
@ -74,7 +74,6 @@ namespace grapher.Models.Serialized
|
|||
ShowLastMouseMoveMenuItem.Checked = RawAccelSettings.GUISettings.ShowLastMouseMove;
|
||||
ShowVelocityAndGainMoveMenuItem.Checked = RawAccelSettings.GUISettings.ShowVelocityAndGain;
|
||||
AutoWriteMenuItem.Checked = RawAccelSettings.GUISettings.AutoWriteToDriverOnStartup;
|
||||
DeviceIDManager.OnStartup(RawAccelSettings.AccelerationSettings.deviceHardwareID);
|
||||
}
|
||||
|
||||
public SettingsErrors TryUpdateAccel(DriverSettings settings)
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <msclr\marshal_cppstd.h>
|
||||
|
||||
#include <rawaccel.hpp>
|
||||
#include <rawaccel-version.h>
|
||||
#include <utility-rawinput.hpp>
|
||||
|
||||
#include "wrapper_io.hpp"
|
||||
|
||||
using namespace System;
|
||||
using namespace System::Collections::Generic;
|
||||
using namespace System::Runtime::InteropServices;
|
||||
using namespace System::Reflection;
|
||||
|
||||
|
@ -78,9 +81,9 @@ public ref struct DriverSettings
|
|||
[JsonProperty(Required = Required::Default)]
|
||||
double minimumTime;
|
||||
|
||||
[JsonProperty("Device Hardware ID", Required = Required::Default)]
|
||||
[MarshalAs(UnmanagedType::ByValTStr, SizeConst = MAX_HWID_LEN)]
|
||||
String^ deviceHardwareID;
|
||||
[JsonProperty("Device ID", Required = Required::Default)]
|
||||
[MarshalAs(UnmanagedType::ByValTStr, SizeConst = MAX_DEV_ID_LEN)]
|
||||
String^ deviceID = "";
|
||||
|
||||
bool ShouldSerializeminimumTime()
|
||||
{
|
||||
|
@ -221,6 +224,24 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
public ref struct RawInputInterop
|
||||
{
|
||||
static void AddHandlesFromID(String^ deviceID, List<IntPtr>^ rawInputHandles)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::vector<HANDLE> nativeHandles = rawinput_handles_from_dev_id(
|
||||
msclr::interop::marshal_as<std::wstring>(deviceID));
|
||||
|
||||
for (auto nh : nativeHandles) rawInputHandles->Add(IntPtr(nh));
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
throw gcnew System::Exception(gcnew String(e.what()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public ref struct DriverInterop
|
||||
{
|
||||
literal double WriteDelayMs = WRITE_DELAY;
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies />
|
||||
<AdditionalDependencies>User32.lib;</AdditionalDependencies>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)/common;</AdditionalIncludeDirectories>
|
||||
|
@ -72,7 +72,7 @@
|
|||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies />
|
||||
<AdditionalDependencies>User32.lib;</AdditionalDependencies>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>copy /Y "$(TargetPath)" "$(SolutionDir)signed\$(TargetFileName)" &
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue