diff options
| author | a1xd <[email protected]> | 2021-09-24 02:04:43 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-09-24 02:04:43 -0400 |
| commit | 2896b8a09ce42e965705c58593b8738adc454f7f (patch) | |
| tree | 71e4d0cff60b5a1ad11427d78e1f8c7b775e5690 /wrapper/input.cpp | |
| parent | Merge pull request #107 from a1xd/1.5.0-fix (diff) | |
| parent | make note clearer (diff) | |
| download | rawaccel-1.6.0.tar.xz rawaccel-1.6.0.zip | |
v1.6
Diffstat (limited to 'wrapper/input.cpp')
| -rw-r--r-- | wrapper/input.cpp | 120 |
1 files changed, 66 insertions, 54 deletions
diff --git a/wrapper/input.cpp b/wrapper/input.cpp index 3ce257a..334a0ec 100644 --- a/wrapper/input.cpp +++ b/wrapper/input.cpp @@ -1,79 +1,91 @@ #include "input.h" -#include "interop-exception.h" - -#include <msclr\marshal_cppstd.h> -#include <algorithm> using namespace System; using namespace System::Collections::Generic; +using namespace System::Runtime::InteropServices; -std::vector<HANDLE> rawinput_handles_from_id(const std::wstring& device_id) -{ - std::vector<HANDLE> handles; +[StructLayout(LayoutKind::Sequential, CharSet = CharSet::Unicode)] +public ref struct RawInputDevice { + System::IntPtr handle; - rawinput_foreach([&](const auto& dev) { - if (dev.id == device_id) handles.push_back(dev.handle); - }); + [MarshalAs(UnmanagedType::ByValTStr, SizeConst = MAX_NAME_LEN)] + System::String^ name; - return handles; -} + [MarshalAs(UnmanagedType::ByValTStr, SizeConst = MAX_DEV_ID_LEN)] + System::String^ id; +}; -std::vector<std::wstring> rawinput_id_list() +static int CompareByID(RawInputDevice^ x, RawInputDevice^ y) { - std::vector<std::wstring> ids; - - rawinput_foreach([&](const auto& dev) { - ids.push_back(dev.id); - }); - - std::sort(ids.begin(), ids.end()); - ids.erase(std::unique(ids.begin(), ids.end()), ids.end()); - return ids; + return String::Compare(x->id, y->id); } -public ref struct RawInputInteropException : InteropException { - RawInputInteropException(System::String^ what) : - InteropException(what) {} - RawInputInteropException(const char* what) : - InteropException(what) {} - RawInputInteropException(const std::exception& e) : - InteropException(e) {} -}; +public ref struct MultiHandleDevice { + System::String^ name; + System::String^ id; + List<System::IntPtr>^ handles; -public ref struct RawInputInterop -{ - static void AddHandlesFromID(String^ deviceID, List<IntPtr>^ rawInputHandles) + // Returned list represents the current connected raw input devices, + // where each device has a distinct device id + // https://docs.microsoft.com/en-us/windows-hardware/drivers/install/device-ids + static IList<MultiHandleDevice^>^ GetList() { - try - { - std::vector<HANDLE> nativeHandles = rawinput_handles_from_id( - msclr::interop::marshal_as<std::wstring>(deviceID)); + return ListMaker::MakeList()->AsReadOnly(); + } - for (auto nh : nativeHandles) rawInputHandles->Add(IntPtr(nh)); - } - catch (const std::exception& e) + ref class ListMaker { + List<RawInputDevice^>^ devices = gcnew List<RawInputDevice^>(); + + delegate void NativeDevHandler(rawinput_device&); + + void Add(rawinput_device& dev) { - throw gcnew RawInputInteropException(e); + devices->Add(Marshal::PtrToStructure<RawInputDevice^>(IntPtr(&dev))); } - } - static List<String^>^ GetDeviceIDs() - { - try + ListMaker() {} + public: + static List<MultiHandleDevice^>^ MakeList() { - auto ids = gcnew List<String^>(); + auto maker = gcnew ListMaker(); + NativeDevHandler^ del = gcnew NativeDevHandler(maker, &Add); + GCHandle gch = GCHandle::Alloc(del); + auto fp = static_cast<void (*)(rawinput_device&)>( + Marshal::GetFunctionPointerForDelegate(del).ToPointer()); + rawinput_foreach(fp); + gch.Free(); - for (auto&& name : rawinput_id_list()) - { - ids->Add(msclr::interop::marshal_as<String^>(name)); + auto ret = gcnew List<MultiHandleDevice^>(); + auto count = maker->devices->Count; + auto first = 0; + auto last = 0; + + if (count > 0) { + maker->devices->Sort(gcnew Comparison<RawInputDevice^>(&CompareByID)); + while (++last != count) { + if (!String::Equals(maker->devices[first]->id, maker->devices[last]->id)) { + auto range = maker->devices->GetRange(first, last - first); + ret->Add(gcnew MultiHandleDevice(range)); + first = last; + } + } + auto range = maker->devices->GetRange(first, last - first); + ret->Add(gcnew MultiHandleDevice(range)); } - return ids; + return ret; } - catch (const std::exception& e) - { - throw gcnew RawInputInteropException(e); + }; + +private: + MultiHandleDevice(IEnumerable<RawInputDevice^>^ seq) + { + auto it = seq->GetEnumerator(); + if (it->MoveNext()) { + name = it->Current->name; + id = it->Current->id; + handles = gcnew List<IntPtr>(); + do handles->Add(it->Current->handle); while (it->MoveNext()); } } - }; |