mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 09:46:54 +02:00
[Refactor]Port C++/CX to C++/WinRT (#34198)
## Summary of the Pull Request Removes all C++/CX code, replacing it with C++/WinRT. ## Detailed Description of the Pull Request / Additional comments Removes all C++/CX code. Renames interop namespaces to be better consumed by CsWinRT. Standardizes all projects on net8.0-windows10.0.20348.0, which is a requirement for C++/WinRT usage. FileLocksmithLibInterop brought to stdcpplatest and static analysis errors were corrected. Removed now unneeded string conversion code from FileLocksmithLibInterop. Changed interop KeyboardHook to use a single hook across all instances. Required because on C++/WinRT we don't have the .NET runtime to bind a object instance to a delegate and be able to pass it to a C function pointer argument (still no idea why this worked correctly on C++/CX to be honest). This change actually makes us create less low level keyboard hooks. Changed some code that depended on arrays since WinRT/C++ returns null instead of an empty array through the interface. ## Validation Steps Performed Built and tested runtime.
This commit is contained in:
@@ -15,6 +15,9 @@
|
||||
<ProjectReference Include="..\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" />
|
||||
<ProjectReference Include="..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Windows.CsWinRT" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Experimentation is live, forcing inclusion -->
|
||||
<ItemGroup Condition="'$(IsExperimentationLive)'!=''">
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<UseWPF>true</UseWPF>
|
||||
<AssemblyName>PowerToys.Common.UI</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Windows.CsWinRT" />
|
||||
<PackageReference Include="ControlzEx" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<Description>PowerToys FilePreviewCommon</Description>
|
||||
<AssemblyName>PowerToys.FilePreviewCommon</AssemblyName>
|
||||
|
||||
@@ -7,7 +7,7 @@ using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO.Abstractions;
|
||||
using System.Reflection;
|
||||
using interop;
|
||||
using PowerToys.Interop;
|
||||
|
||||
namespace ManagedCommon
|
||||
{
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<Description>PowerToys ManagedCommon</Description>
|
||||
<AssemblyName>PowerToys.ManagedCommon</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- See https://learn.microsoft.com/windows/apps/develop/platform/csharp-winrt/net-projection-from-cppwinrt-component for more info -->
|
||||
<PropertyGroup>
|
||||
<CsWinRTIncludes>PowerToys.Interop</CsWinRTIncludes>
|
||||
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
|
||||
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Windows.CsWinRT" />
|
||||
<PackageReference Include="System.IO.Abstractions" />
|
||||
<PackageReference Include="System.Management" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<Description>PowerToys Telemetry</Description>
|
||||
<AssemblyName>PowerToys.ManagedTelemetry</AssemblyName>
|
||||
|
||||
39
src/common/interop/CommonManaged.cpp
Normal file
39
src/common/interop/CommonManaged.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#include "pch.h"
|
||||
#include "CommonManaged.h"
|
||||
#include "CommonManaged.g.cpp"
|
||||
#include <common/version/version.h>
|
||||
#include "../../modules/videoconference/VideoConferenceShared/MicrophoneDevice.h"
|
||||
#include "../../modules/videoconference/VideoConferenceShared/VideoCaptureDeviceList.h"
|
||||
|
||||
namespace winrt::PowerToys::Interop::implementation
|
||||
{
|
||||
hstring CommonManaged::GetProductVersion()
|
||||
{
|
||||
return hstring{ get_product_version() };
|
||||
}
|
||||
winrt::Windows::Foundation::Collections::IVector<hstring> CommonManaged::GetAllActiveMicrophoneDeviceNames()
|
||||
{
|
||||
auto names = std::vector<winrt::hstring>();
|
||||
for (const auto& device : MicrophoneDevice::getAllActive())
|
||||
{
|
||||
names.push_back(device->name().data());
|
||||
}
|
||||
return winrt::multi_threaded_vector(std::move(names));
|
||||
}
|
||||
winrt::Windows::Foundation::Collections::IVector<hstring> CommonManaged::GetAllVideoCaptureDeviceNames()
|
||||
{
|
||||
auto names = std::vector<winrt::hstring>();
|
||||
VideoCaptureDeviceList vcdl;
|
||||
vcdl.EnumerateDevices();
|
||||
|
||||
for (UINT32 i = 0; i < vcdl.Count(); ++i)
|
||||
{
|
||||
auto name = vcdl.GetDeviceName(i).data();
|
||||
if (name != L"PowerToys VideoConference Mute")
|
||||
{
|
||||
names.push_back(name);
|
||||
}
|
||||
}
|
||||
return winrt::multi_threaded_vector(std::move(names));
|
||||
}
|
||||
}
|
||||
20
src/common/interop/CommonManaged.h
Normal file
20
src/common/interop/CommonManaged.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "CommonManaged.g.h"
|
||||
|
||||
namespace winrt::PowerToys::Interop::implementation
|
||||
{
|
||||
struct CommonManaged : CommonManagedT<CommonManaged>
|
||||
{
|
||||
CommonManaged() = default;
|
||||
|
||||
static hstring GetProductVersion();
|
||||
static winrt::Windows::Foundation::Collections::IVector<hstring> GetAllActiveMicrophoneDeviceNames();
|
||||
static winrt::Windows::Foundation::Collections::IVector<hstring> GetAllVideoCaptureDeviceNames();
|
||||
};
|
||||
}
|
||||
namespace winrt::PowerToys::Interop::factory_implementation
|
||||
{
|
||||
struct CommonManaged : CommonManagedT<CommonManaged, implementation::CommonManaged>
|
||||
{
|
||||
};
|
||||
}
|
||||
11
src/common/interop/CommonManaged.idl
Normal file
11
src/common/interop/CommonManaged.idl
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace PowerToys
|
||||
{
|
||||
namespace Interop
|
||||
{
|
||||
[default_interface] static runtimeclass CommonManaged {
|
||||
static String GetProductVersion();
|
||||
static Windows.Foundation.Collections.IVector<String> GetAllActiveMicrophoneDeviceNames();
|
||||
static Windows.Foundation.Collections.IVector<String> GetAllVideoCaptureDeviceNames();
|
||||
}
|
||||
}
|
||||
}
|
||||
146
src/common/interop/Constants.cpp
Normal file
146
src/common/interop/Constants.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
#include "pch.h"
|
||||
#include "Constants.h"
|
||||
#include "Constants.g.cpp"
|
||||
#include "shared_constants.h"
|
||||
#include <ShlObj.h>
|
||||
|
||||
namespace winrt::PowerToys::Interop::implementation
|
||||
{
|
||||
uint32_t Constants::VK_WIN_BOTH()
|
||||
{
|
||||
return CommonSharedConstants::VK_WIN_BOTH;
|
||||
}
|
||||
hstring Constants::AppDataPath()
|
||||
{
|
||||
PWSTR local_app_path;
|
||||
winrt::check_hresult(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &local_app_path));
|
||||
winrt::hstring result{ local_app_path };
|
||||
CoTaskMemFree(local_app_path);
|
||||
result = result + L"\\" + CommonSharedConstants::APPDATA_PATH;
|
||||
return result;
|
||||
}
|
||||
hstring Constants::PowerLauncherSharedEvent()
|
||||
{
|
||||
return CommonSharedConstants::POWER_LAUNCHER_SHARED_EVENT;
|
||||
}
|
||||
hstring Constants::PowerLauncherCentralizedHookSharedEvent()
|
||||
{
|
||||
return CommonSharedConstants::POWER_LAUNCHER_CENTRALIZED_HOOK_SHARED_EVENT;
|
||||
}
|
||||
hstring Constants::RunSendSettingsTelemetryEvent()
|
||||
{
|
||||
return CommonSharedConstants::RUN_SEND_SETTINGS_TELEMETRY_EVENT;
|
||||
}
|
||||
hstring Constants::RunExitEvent()
|
||||
{
|
||||
return CommonSharedConstants::RUN_EXIT_EVENT;
|
||||
}
|
||||
hstring Constants::FZEExitEvent()
|
||||
{
|
||||
return CommonSharedConstants::FZE_EXIT_EVENT;
|
||||
}
|
||||
hstring Constants::FZEToggleEvent()
|
||||
{
|
||||
return CommonSharedConstants::FANCY_ZONES_EDITOR_TOGGLE_EVENT;
|
||||
}
|
||||
hstring Constants::ColorPickerSendSettingsTelemetryEvent()
|
||||
{
|
||||
return CommonSharedConstants::COLOR_PICKER_SEND_SETTINGS_TELEMETRY_EVENT;
|
||||
}
|
||||
hstring Constants::ShowColorPickerSharedEvent()
|
||||
{
|
||||
return CommonSharedConstants::SHOW_COLOR_PICKER_SHARED_EVENT;
|
||||
}
|
||||
hstring Constants::ShowAdvancedPasteSharedEvent()
|
||||
{
|
||||
return CommonSharedConstants::SHOW_ADVANCED_PASTE_SHARED_EVENT;
|
||||
}
|
||||
hstring Constants::AdvancedPasteMarkdownEvent()
|
||||
{
|
||||
return CommonSharedConstants::ADVANCED_PASTE_MARKDOWN_EVENT;
|
||||
}
|
||||
hstring Constants::AdvancedPasteJsonEvent()
|
||||
{
|
||||
return CommonSharedConstants::ADVANCED_PASTE_JSON_EVENT;
|
||||
}
|
||||
hstring Constants::ShowPowerOCRSharedEvent()
|
||||
{
|
||||
return CommonSharedConstants::SHOW_POWEROCR_SHARED_EVENT;
|
||||
}
|
||||
hstring Constants::MouseJumpShowPreviewEvent()
|
||||
{
|
||||
return CommonSharedConstants::MOUSE_JUMP_SHOW_PREVIEW_EVENT;
|
||||
}
|
||||
hstring Constants::AwakeExitEvent()
|
||||
{
|
||||
return CommonSharedConstants::AWAKE_EXIT_EVENT;
|
||||
}
|
||||
hstring Constants::ShowPeekEvent()
|
||||
{
|
||||
return CommonSharedConstants::SHOW_PEEK_SHARED_EVENT;
|
||||
}
|
||||
hstring Constants::PowerAccentExitEvent()
|
||||
{
|
||||
return CommonSharedConstants::POWERACCENT_EXIT_EVENT;
|
||||
}
|
||||
hstring Constants::ShortcutGuideTriggerEvent()
|
||||
{
|
||||
return CommonSharedConstants::SHORTCUT_GUIDE_TRIGGER_EVENT;
|
||||
}
|
||||
hstring Constants::RegistryPreviewTriggerEvent()
|
||||
{
|
||||
return CommonSharedConstants::REGISTRY_PREVIEW_TRIGGER_EVENT;
|
||||
}
|
||||
hstring Constants::MeasureToolTriggerEvent()
|
||||
{
|
||||
return CommonSharedConstants::MEASURE_TOOL_TRIGGER_EVENT;
|
||||
}
|
||||
hstring Constants::GcodePreviewResizeEvent()
|
||||
{
|
||||
return CommonSharedConstants::GCODE_PREVIEW_RESIZE_EVENT;
|
||||
}
|
||||
hstring Constants::QoiPreviewResizeEvent()
|
||||
{
|
||||
return CommonSharedConstants::QOI_PREVIEW_RESIZE_EVENT;
|
||||
}
|
||||
hstring Constants::DevFilesPreviewResizeEvent()
|
||||
{
|
||||
return CommonSharedConstants::DEV_FILES_PREVIEW_RESIZE_EVENT;
|
||||
}
|
||||
hstring Constants::MarkdownPreviewResizeEvent()
|
||||
{
|
||||
return CommonSharedConstants::MARKDOWN_PREVIEW_RESIZE_EVENT;
|
||||
}
|
||||
hstring Constants::PdfPreviewResizeEvent()
|
||||
{
|
||||
return CommonSharedConstants::PDF_PREVIEW_RESIZE_EVENT;
|
||||
}
|
||||
hstring Constants::SvgPreviewResizeEvent()
|
||||
{
|
||||
return CommonSharedConstants::SVG_PREVIEW_RESIZE_EVENT;
|
||||
}
|
||||
hstring Constants::ShowHostsSharedEvent()
|
||||
{
|
||||
return CommonSharedConstants::SHOW_HOSTS_EVENT;
|
||||
}
|
||||
hstring Constants::ShowHostsAdminSharedEvent()
|
||||
{
|
||||
return CommonSharedConstants::SHOW_HOSTS_ADMIN_EVENT;
|
||||
}
|
||||
hstring Constants::CropAndLockThumbnailEvent()
|
||||
{
|
||||
return CommonSharedConstants::CROP_AND_LOCK_THUMBNAIL_EVENT;
|
||||
}
|
||||
hstring Constants::CropAndLockReparentEvent()
|
||||
{
|
||||
return CommonSharedConstants::CROP_AND_LOCK_REPARENT_EVENT;
|
||||
}
|
||||
hstring Constants::ShowEnvironmentVariablesSharedEvent()
|
||||
{
|
||||
return CommonSharedConstants::SHOW_ENVIRONMENT_VARIABLES_EVENT;
|
||||
}
|
||||
hstring Constants::ShowEnvironmentVariablesAdminSharedEvent()
|
||||
{
|
||||
return CommonSharedConstants::SHOW_ENVIRONMENT_VARIABLES_ADMIN_EVENT;
|
||||
}
|
||||
}
|
||||
50
src/common/interop/Constants.h
Normal file
50
src/common/interop/Constants.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
#include "Constants.g.h"
|
||||
namespace winrt::PowerToys::Interop::implementation
|
||||
{
|
||||
struct Constants : ConstantsT<Constants>
|
||||
{
|
||||
Constants() = default;
|
||||
|
||||
static uint32_t VK_WIN_BOTH();
|
||||
static hstring AppDataPath();
|
||||
static hstring PowerLauncherSharedEvent();
|
||||
static hstring PowerLauncherCentralizedHookSharedEvent();
|
||||
static hstring RunSendSettingsTelemetryEvent();
|
||||
static hstring RunExitEvent();
|
||||
static hstring FZEExitEvent();
|
||||
static hstring FZEToggleEvent();
|
||||
static hstring ColorPickerSendSettingsTelemetryEvent();
|
||||
static hstring ShowColorPickerSharedEvent();
|
||||
static hstring ShowAdvancedPasteSharedEvent();
|
||||
static hstring AdvancedPasteMarkdownEvent();
|
||||
static hstring AdvancedPasteJsonEvent();
|
||||
static hstring ShowPowerOCRSharedEvent();
|
||||
static hstring MouseJumpShowPreviewEvent();
|
||||
static hstring AwakeExitEvent();
|
||||
static hstring ShowPeekEvent();
|
||||
static hstring PowerAccentExitEvent();
|
||||
static hstring ShortcutGuideTriggerEvent();
|
||||
static hstring RegistryPreviewTriggerEvent();
|
||||
static hstring MeasureToolTriggerEvent();
|
||||
static hstring GcodePreviewResizeEvent();
|
||||
static hstring QoiPreviewResizeEvent();
|
||||
static hstring DevFilesPreviewResizeEvent();
|
||||
static hstring MarkdownPreviewResizeEvent();
|
||||
static hstring PdfPreviewResizeEvent();
|
||||
static hstring SvgPreviewResizeEvent();
|
||||
static hstring ShowHostsSharedEvent();
|
||||
static hstring ShowHostsAdminSharedEvent();
|
||||
static hstring CropAndLockThumbnailEvent();
|
||||
static hstring CropAndLockReparentEvent();
|
||||
static hstring ShowEnvironmentVariablesSharedEvent();
|
||||
static hstring ShowEnvironmentVariablesAdminSharedEvent();
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::PowerToys::Interop::factory_implementation
|
||||
{
|
||||
struct Constants : ConstantsT<Constants, implementation::Constants>
|
||||
{
|
||||
};
|
||||
}
|
||||
41
src/common/interop/Constants.idl
Normal file
41
src/common/interop/Constants.idl
Normal file
@@ -0,0 +1,41 @@
|
||||
namespace PowerToys
|
||||
{
|
||||
namespace Interop
|
||||
{
|
||||
[default_interface] static runtimeclass Constants {
|
||||
static UInt32 VK_WIN_BOTH {get; };
|
||||
static String AppDataPath();
|
||||
static String PowerLauncherSharedEvent();
|
||||
static String PowerLauncherCentralizedHookSharedEvent();
|
||||
static String RunSendSettingsTelemetryEvent();
|
||||
static String RunExitEvent();
|
||||
static String FZEExitEvent();
|
||||
static String FZEToggleEvent();
|
||||
static String ColorPickerSendSettingsTelemetryEvent();
|
||||
static String ShowColorPickerSharedEvent();
|
||||
static String ShowAdvancedPasteSharedEvent();
|
||||
static String AdvancedPasteMarkdownEvent();
|
||||
static String AdvancedPasteJsonEvent();
|
||||
static String ShowPowerOCRSharedEvent();
|
||||
static String MouseJumpShowPreviewEvent();
|
||||
static String AwakeExitEvent();
|
||||
static String ShowPeekEvent();
|
||||
static String PowerAccentExitEvent();
|
||||
static String ShortcutGuideTriggerEvent();
|
||||
static String RegistryPreviewTriggerEvent();
|
||||
static String MeasureToolTriggerEvent();
|
||||
static String GcodePreviewResizeEvent();
|
||||
static String QoiPreviewResizeEvent();
|
||||
static String DevFilesPreviewResizeEvent();
|
||||
static String MarkdownPreviewResizeEvent();
|
||||
static String PdfPreviewResizeEvent();
|
||||
static String SvgPreviewResizeEvent();
|
||||
static String ShowHostsSharedEvent();
|
||||
static String ShowHostsAdminSharedEvent();
|
||||
static String CropAndLockThumbnailEvent();
|
||||
static String CropAndLockReparentEvent();
|
||||
static String ShowEnvironmentVariablesSharedEvent();
|
||||
static String ShowEnvironmentVariablesAdminSharedEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,94 +1,89 @@
|
||||
#include "pch.h"
|
||||
#include "HotkeyManager.h"
|
||||
#include "HotkeyManager.g.cpp"
|
||||
|
||||
using namespace interop;
|
||||
|
||||
HotkeyManager::HotkeyManager()
|
||||
namespace winrt::PowerToys::Interop::implementation
|
||||
{
|
||||
keyboardEventCallback = gcnew KeyboardEventCallback(this, &HotkeyManager::KeyboardEventProc);
|
||||
isActiveCallback = gcnew IsActiveCallback(this, &HotkeyManager::IsActiveProc);
|
||||
filterKeyboardCallback = gcnew FilterKeyboardEvent(this, &HotkeyManager::FilterKeyboardProc);
|
||||
|
||||
keyboardHook = gcnew KeyboardHook(
|
||||
keyboardEventCallback,
|
||||
isActiveCallback,
|
||||
filterKeyboardCallback);
|
||||
hotkeys = gcnew Dictionary<HOTKEY_HANDLE, HotkeyCallback ^>();
|
||||
pressedKeys = gcnew Hotkey();
|
||||
keyboardHook->Start();
|
||||
}
|
||||
|
||||
HotkeyManager::~HotkeyManager()
|
||||
{
|
||||
delete keyboardHook;
|
||||
}
|
||||
|
||||
// When all Shortcut keys are pressed, fire the HotkeyCallback event.
|
||||
void HotkeyManager::KeyboardEventProc(KeyboardEvent ^ /*ev*/)
|
||||
{
|
||||
// pressedKeys always stores the latest keyboard state
|
||||
auto pressedKeysHandle = GetHotkeyHandle(pressedKeys);
|
||||
if (hotkeys->ContainsKey(pressedKeysHandle))
|
||||
HotkeyManager::HotkeyManager()
|
||||
{
|
||||
hotkeys[pressedKeysHandle]->Invoke();
|
||||
|
||||
// After invoking the hotkey send a dummy key to prevent Start Menu from activating
|
||||
INPUT dummyEvent[1] = {};
|
||||
dummyEvent[0].type = INPUT_KEYBOARD;
|
||||
dummyEvent[0].ki.wVk = 0xFF;
|
||||
dummyEvent[0].ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
SendInput(1, dummyEvent, sizeof(INPUT));
|
||||
keyboardEventCallback = KeyboardEventCallback{ this, &HotkeyManager::KeyboardEventProc };
|
||||
isActiveCallback = IsActiveCallback{ this, &HotkeyManager::IsActiveProc };
|
||||
filterKeyboardCallback = FilterKeyboardEvent{ this, &HotkeyManager::FilterKeyboardProc };
|
||||
keyboardHook = KeyboardHook{ keyboardEventCallback, isActiveCallback, filterKeyboardCallback };
|
||||
keyboardHook.Start();
|
||||
}
|
||||
}
|
||||
|
||||
// Hotkeys are intended to be global, therefore they are always active no matter the
|
||||
// context in which the keypress occurs.
|
||||
bool HotkeyManager::IsActiveProc()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// When all Shortcut keys are pressed, fire the HotkeyCallback event.
|
||||
void HotkeyManager::KeyboardEventProc(KeyboardEvent ev)
|
||||
{
|
||||
// pressedKeys always stores the latest keyboard state
|
||||
auto pressedKeysHandle = GetHotkeyHandle(pressedKeys);
|
||||
if (hotkeys.find(pressedKeysHandle) != hotkeys.end())
|
||||
{
|
||||
hotkeys[pressedKeysHandle]();
|
||||
|
||||
// KeyboardEvent callback is only fired for relevant key events.
|
||||
bool HotkeyManager::FilterKeyboardProc(KeyboardEvent ^ ev)
|
||||
{
|
||||
// Updating the pressed keys here so we know if the keypress event should be propagated or not.
|
||||
pressedKeys->Win = (GetAsyncKeyState(VK_LWIN) & 0x8000) || (GetAsyncKeyState(VK_RWIN) & 0x8000);
|
||||
pressedKeys->Ctrl = GetAsyncKeyState(VK_CONTROL) & 0x8000;
|
||||
pressedKeys->Alt = GetAsyncKeyState(VK_MENU) & 0x8000;
|
||||
pressedKeys->Shift = GetAsyncKeyState(VK_SHIFT) & 0x8000;
|
||||
pressedKeys->Key = static_cast<unsigned char>(ev->key);
|
||||
// After invoking the hotkey send a dummy key to prevent Start Menu from activating
|
||||
INPUT dummyEvent[1] = {};
|
||||
dummyEvent[0].type = INPUT_KEYBOARD;
|
||||
dummyEvent[0].ki.wVk = 0xFF;
|
||||
dummyEvent[0].ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
SendInput(1, dummyEvent, sizeof(INPUT));
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to hotkey handle
|
||||
auto pressedKeysHandle = GetHotkeyHandle(pressedKeys);
|
||||
|
||||
// Check if any hotkey matches the pressed keys if the current key event is a key down event
|
||||
if ((ev->message == WM_KEYDOWN || ev->message == WM_SYSKEYDOWN) && hotkeys->ContainsKey(pressedKeysHandle))
|
||||
// Hotkeys are intended to be global, therefore they are always active no matter the
|
||||
// context in which the keypress occurs.
|
||||
bool HotkeyManager::IsActiveProc()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool HotkeyManager::FilterKeyboardProc(KeyboardEvent ev)
|
||||
{
|
||||
// Updating the pressed keys here so we know if the keypress event should be propagated or not.
|
||||
pressedKeys.Win = (GetAsyncKeyState(VK_LWIN) & 0x8000) || (GetAsyncKeyState(VK_RWIN) & 0x8000);
|
||||
pressedKeys.Ctrl = GetAsyncKeyState(VK_CONTROL) & 0x8000;
|
||||
pressedKeys.Alt = GetAsyncKeyState(VK_MENU) & 0x8000;
|
||||
pressedKeys.Shift = GetAsyncKeyState(VK_SHIFT) & 0x8000;
|
||||
pressedKeys.Key = static_cast<unsigned char>(ev.key);
|
||||
|
||||
return false;
|
||||
}
|
||||
// Convert to hotkey handle
|
||||
auto pressedKeysHandle = GetHotkeyHandle(pressedKeys);
|
||||
|
||||
// NOTE: Replaces old hotkey if one already present.
|
||||
HOTKEY_HANDLE HotkeyManager::RegisterHotkey(Hotkey ^ hotkey, HotkeyCallback ^ callback)
|
||||
{
|
||||
auto handle = GetHotkeyHandle(hotkey);
|
||||
hotkeys[handle] = callback;
|
||||
return handle;
|
||||
}
|
||||
// Check if any hotkey matches the pressed keys if the current key event is a key down event
|
||||
if ((ev.message == WM_KEYDOWN || ev.message == WM_SYSKEYDOWN) && hotkeys.find(pressedKeysHandle)!=hotkeys.end())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void HotkeyManager::UnregisterHotkey(HOTKEY_HANDLE handle)
|
||||
{
|
||||
hotkeys->Remove(handle);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
HOTKEY_HANDLE HotkeyManager::GetHotkeyHandle(Hotkey ^ hotkey)
|
||||
{
|
||||
HOTKEY_HANDLE handle = hotkey->Key;
|
||||
handle |= hotkey->Win << 8;
|
||||
handle |= hotkey->Ctrl << 9;
|
||||
handle |= hotkey->Shift << 10;
|
||||
handle |= hotkey->Alt << 11;
|
||||
return handle;
|
||||
uint16_t HotkeyManager::RegisterHotkey(winrt::PowerToys::Interop::Hotkey const& _hotkey, winrt::PowerToys::Interop::HotkeyCallback const& _callback)
|
||||
{
|
||||
auto handle = GetHotkeyHandle(_hotkey);
|
||||
hotkeys[handle] = _callback;
|
||||
return handle;
|
||||
}
|
||||
|
||||
void HotkeyManager::UnregisterHotkey(uint16_t _handle)
|
||||
{
|
||||
auto iter = hotkeys.find(_handle);
|
||||
if (iter != hotkeys.end()) {
|
||||
hotkeys.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
void HotkeyManager::Close()
|
||||
{
|
||||
}
|
||||
|
||||
uint16_t HotkeyManager::GetHotkeyHandle(Hotkey hotkey)
|
||||
{
|
||||
uint16_t handle = hotkey.Key;
|
||||
handle |= hotkey.Win << 8;
|
||||
handle |= hotkey.Ctrl << 9;
|
||||
handle |= hotkey.Shift << 10;
|
||||
handle |= hotkey.Alt << 11;
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,54 +1,33 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include "KeyboardHook.h"
|
||||
#include "HotkeyManager.g.h"
|
||||
|
||||
namespace interop
|
||||
namespace winrt::PowerToys::Interop::implementation
|
||||
{
|
||||
public
|
||||
ref struct Hotkey
|
||||
struct HotkeyManager : HotkeyManagerT<HotkeyManager>
|
||||
{
|
||||
bool Win;
|
||||
bool Ctrl;
|
||||
bool Shift;
|
||||
bool Alt;
|
||||
unsigned char Key;
|
||||
|
||||
Hotkey()
|
||||
{
|
||||
Win = false;
|
||||
Ctrl = false;
|
||||
Shift = false;
|
||||
Alt = false;
|
||||
Key = 0;
|
||||
}
|
||||
};
|
||||
|
||||
public
|
||||
delegate void HotkeyCallback();
|
||||
|
||||
typedef unsigned short HOTKEY_HANDLE;
|
||||
|
||||
public
|
||||
ref class HotkeyManager
|
||||
{
|
||||
public:
|
||||
HotkeyManager();
|
||||
~HotkeyManager();
|
||||
|
||||
HOTKEY_HANDLE RegisterHotkey(Hotkey ^ hotkey, HotkeyCallback ^ callback);
|
||||
void UnregisterHotkey(HOTKEY_HANDLE handle);
|
||||
uint16_t RegisterHotkey(winrt::PowerToys::Interop::Hotkey const& _hotkey, winrt::PowerToys::Interop::HotkeyCallback const& _callback);
|
||||
void UnregisterHotkey(uint16_t _handle);
|
||||
void Close();
|
||||
|
||||
private:
|
||||
KeyboardHook ^ keyboardHook;
|
||||
Dictionary<HOTKEY_HANDLE, HotkeyCallback ^> ^ hotkeys;
|
||||
Hotkey ^ pressedKeys;
|
||||
KeyboardEventCallback ^ keyboardEventCallback;
|
||||
IsActiveCallback ^ isActiveCallback;
|
||||
FilterKeyboardEvent ^ filterKeyboardCallback;
|
||||
KeyboardHook keyboardHook{ nullptr };
|
||||
std::map<uint16_t, HotkeyCallback> hotkeys;
|
||||
Hotkey pressedKeys{ };
|
||||
KeyboardEventCallback keyboardEventCallback;
|
||||
IsActiveCallback isActiveCallback;
|
||||
FilterKeyboardEvent filterKeyboardCallback;
|
||||
|
||||
void KeyboardEventProc(KeyboardEvent ^ ev);
|
||||
void KeyboardEventProc(KeyboardEvent ev);
|
||||
bool IsActiveProc();
|
||||
bool FilterKeyboardProc(KeyboardEvent ^ ev);
|
||||
HOTKEY_HANDLE GetHotkeyHandle(Hotkey ^ hotkey);
|
||||
bool FilterKeyboardProc(KeyboardEvent ev);
|
||||
uint16_t GetHotkeyHandle(Hotkey hotkey);
|
||||
};
|
||||
}
|
||||
namespace winrt::PowerToys::Interop::factory_implementation
|
||||
{
|
||||
struct HotkeyManager : HotkeyManagerT<HotkeyManager, implementation::HotkeyManager>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
23
src/common/interop/HotkeyManager.idl
Normal file
23
src/common/interop/HotkeyManager.idl
Normal file
@@ -0,0 +1,23 @@
|
||||
namespace PowerToys
|
||||
{
|
||||
namespace Interop
|
||||
{
|
||||
struct Hotkey
|
||||
{
|
||||
Boolean Win;
|
||||
Boolean Ctrl;
|
||||
Boolean Shift;
|
||||
Boolean Alt;
|
||||
UInt8 Key;
|
||||
};
|
||||
delegate void HotkeyCallback();
|
||||
|
||||
[default_interface] runtimeclass HotkeyManager : Windows.Foundation.IClosable
|
||||
{
|
||||
HotkeyManager();
|
||||
UInt16 RegisterHotkey(Hotkey _hotkey, HotkeyCallback _callback);
|
||||
void UnregisterHotkey(UInt16 _handle);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,73 +1,99 @@
|
||||
#include "pch.h"
|
||||
#include "KeyboardHook.h"
|
||||
#include <exception>
|
||||
#include <msclr/marshal.h>
|
||||
#include <msclr/marshal_cppstd.h>
|
||||
#include "KeyboardHook.g.cpp"
|
||||
#include <common/debug_control.h>
|
||||
#include <common/utils/winapi_error.h>
|
||||
|
||||
using namespace interop;
|
||||
using namespace System::Runtime::InteropServices;
|
||||
using namespace System;
|
||||
using namespace System::Diagnostics;
|
||||
|
||||
KeyboardHook::KeyboardHook(
|
||||
KeyboardEventCallback ^ keyboardEventCallback,
|
||||
IsActiveCallback ^ isActiveCallback,
|
||||
FilterKeyboardEvent ^ filterKeyboardEvent)
|
||||
namespace winrt::PowerToys::Interop::implementation
|
||||
{
|
||||
this->keyboardEventCallback = keyboardEventCallback;
|
||||
this->isActiveCallback = isActiveCallback;
|
||||
this->filterKeyboardEvent = filterKeyboardEvent;
|
||||
}
|
||||
std::mutex KeyboardHook::instancesMutex;
|
||||
std::unordered_set<KeyboardHook*> KeyboardHook::instances;
|
||||
|
||||
KeyboardHook::~KeyboardHook()
|
||||
{
|
||||
// Unregister low level hook procedure
|
||||
UnhookWindowsHookEx(hookHandle);
|
||||
}
|
||||
KeyboardHook::KeyboardHook(winrt::PowerToys::Interop::KeyboardEventCallback const& keyboardEventCallback, winrt::PowerToys::Interop::IsActiveCallback const& isActiveCallback, winrt::PowerToys::Interop::FilterKeyboardEvent const& filterKeyboardEvent)
|
||||
{
|
||||
this->keyboardEventCallback = keyboardEventCallback;
|
||||
this->isActiveCallback = isActiveCallback;
|
||||
this->filterKeyboardEvent = filterKeyboardEvent;
|
||||
}
|
||||
|
||||
void KeyboardHook::Start()
|
||||
{
|
||||
hookProc = gcnew HookProcDelegate(this, &KeyboardHook::HookProc);
|
||||
void KeyboardHook::Close()
|
||||
{
|
||||
std::unique_lock lock { instancesMutex };
|
||||
auto iter = instances.find(this);
|
||||
if (iter != instances.end())
|
||||
{
|
||||
instances.erase(iter);
|
||||
}
|
||||
if (instances.size() < 1 && hookHandle != nullptr)
|
||||
{
|
||||
if (UnhookWindowsHookEx(hookHandle))
|
||||
{
|
||||
hookHandle = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KeyboardHook::Start()
|
||||
{
|
||||
#if defined(DISABLE_LOWLEVEL_HOOKS_WHEN_DEBUGGED)
|
||||
const bool hookDisabled = IsDebuggerPresent();
|
||||
const bool hookDisabled = IsDebuggerPresent();
|
||||
#else
|
||||
const bool hookDisabled = false;
|
||||
const bool hookDisabled = false;
|
||||
#endif
|
||||
if (!hookDisabled)
|
||||
{
|
||||
// register low level hook procedure
|
||||
hookHandle = SetWindowsHookEx(
|
||||
WH_KEYBOARD_LL,
|
||||
(HOOKPROC)(void*)Marshal::GetFunctionPointerForDelegate(hookProc),
|
||||
0,
|
||||
0);
|
||||
if (hookHandle == nullptr)
|
||||
if (!hookDisabled)
|
||||
{
|
||||
DWORD errorCode = GetLastError();
|
||||
show_last_error_message(L"SetWindowsHookEx", errorCode, L"PowerToys - Interop");
|
||||
std::unique_lock lock { instancesMutex };
|
||||
assert(instances.find(this) == instances.end());
|
||||
// register low level hook procedure
|
||||
instances.insert(this);
|
||||
if (hookHandle == nullptr)
|
||||
{
|
||||
hookHandle = SetWindowsHookEx(
|
||||
WH_KEYBOARD_LL,
|
||||
HookProc,
|
||||
0,
|
||||
0);
|
||||
if (hookHandle == nullptr)
|
||||
{
|
||||
DWORD errorCode = GetLastError();
|
||||
show_last_error_message(L"SetWindowsHookEx", errorCode, L"PowerToys - Interop");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LRESULT KeyboardHook::HookProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (nCode == HC_ACTION)
|
||||
{
|
||||
std::vector<KeyboardHook*> instances_copy;
|
||||
{
|
||||
/* Use a copy of instances, to iterate through the copy without needing to maintain the lock */
|
||||
std::unique_lock lock{ instancesMutex };
|
||||
instances_copy.reserve(instances.size());
|
||||
std::copy(instances.begin(), instances.end(), std::back_inserter(instances_copy));
|
||||
}
|
||||
|
||||
for (auto const& s_instance : instances_copy)
|
||||
{
|
||||
if (s_instance->isActiveCallback())
|
||||
{
|
||||
KeyboardEvent ev;
|
||||
ev.message = wParam;
|
||||
ev.key = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam)->vkCode;
|
||||
ev.dwExtraInfo = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam)->dwExtraInfo;
|
||||
|
||||
// Ignore the keyboard hook if the FilterkeyboardEvent returns false.
|
||||
if ((s_instance->filterKeyboardEvent != nullptr && !s_instance->filterKeyboardEvent(ev)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
s_instance->keyboardEventCallback(ev);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return CallNextHookEx(NULL, nCode, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT __clrcall KeyboardHook::HookProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (nCode == HC_ACTION && isActiveCallback->Invoke())
|
||||
{
|
||||
KeyboardEvent ^ ev = gcnew KeyboardEvent();
|
||||
ev->message = wParam;
|
||||
ev->key = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam)->vkCode;
|
||||
ev->dwExtraInfo = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam)->dwExtraInfo;
|
||||
|
||||
// Ignore the keyboard hook if the FilterkeyboardEvent returns false.
|
||||
if ((filterKeyboardEvent != nullptr && !filterKeyboardEvent->Invoke(ev)))
|
||||
{
|
||||
return CallNextHookEx(hookHandle, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
keyboardEventCallback->Invoke(ev);
|
||||
return 1;
|
||||
}
|
||||
return CallNextHookEx(hookHandle, nCode, wParam, lParam);
|
||||
}
|
||||
@@ -1,48 +1,35 @@
|
||||
#pragma once
|
||||
#include "KeyboardHook.g.h"
|
||||
#include <mutex>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <cinttypes>
|
||||
|
||||
using namespace System::Threading;
|
||||
using namespace System::Collections::Generic;
|
||||
|
||||
namespace interop
|
||||
namespace winrt::PowerToys::Interop::implementation
|
||||
{
|
||||
public
|
||||
ref struct KeyboardEvent
|
||||
struct KeyboardHook : KeyboardHookT<KeyboardHook>
|
||||
{
|
||||
WPARAM message;
|
||||
int key;
|
||||
uint64_t dwExtraInfo;
|
||||
};
|
||||
|
||||
public
|
||||
delegate void KeyboardEventCallback(KeyboardEvent ^ ev);
|
||||
public
|
||||
delegate bool IsActiveCallback();
|
||||
public
|
||||
delegate bool FilterKeyboardEvent(KeyboardEvent ^ ev);
|
||||
|
||||
public
|
||||
ref class KeyboardHook
|
||||
{
|
||||
public:
|
||||
KeyboardHook(
|
||||
KeyboardEventCallback ^ keyboardEventCallback,
|
||||
IsActiveCallback ^ isActiveCallback,
|
||||
FilterKeyboardEvent ^ filterKeyboardEvent);
|
||||
~KeyboardHook();
|
||||
// KeyboardHook() = default;
|
||||
|
||||
KeyboardHook(winrt::PowerToys::Interop::KeyboardEventCallback const& keyboardEventCallback, winrt::PowerToys::Interop::IsActiveCallback const& isActiveCallback, winrt::PowerToys::Interop::FilterKeyboardEvent const& filterKeyboardEvent);
|
||||
void Start();
|
||||
void Close();
|
||||
|
||||
private:
|
||||
delegate LRESULT HookProcDelegate(int nCode, WPARAM wParam, LPARAM lParam);
|
||||
KeyboardEventCallback ^ keyboardEventCallback;
|
||||
IsActiveCallback ^ isActiveCallback;
|
||||
FilterKeyboardEvent ^ filterKeyboardEvent;
|
||||
HHOOK hookHandle;
|
||||
HookProcDelegate ^ hookProc;
|
||||
winrt::PowerToys::Interop::KeyboardEventCallback keyboardEventCallback;
|
||||
winrt::PowerToys::Interop::IsActiveCallback isActiveCallback;
|
||||
winrt::PowerToys::Interop::FilterKeyboardEvent filterKeyboardEvent;
|
||||
|
||||
LRESULT __clrcall HookProc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||
// This class used to be C++/CX, which meant it ran on .NET runtime and was able to send function pointer for delegates as hook procedures for SetWindowsHookEx which kept an object reference.
|
||||
// There doesn't seem to be a way to do this outside of the .NET runtime that allows us to get a proper C-style function.
|
||||
// The alternative when porting to C++/winrt is to keep track of every instance and use a single proc instead of one per object. This should also make it lighter.
|
||||
static std::mutex instancesMutex;
|
||||
static std::unordered_set<KeyboardHook*> instances;
|
||||
static inline HHOOK hookHandle = nullptr;
|
||||
static LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||
};
|
||||
}
|
||||
namespace winrt::PowerToys::Interop::factory_implementation
|
||||
{
|
||||
struct KeyboardHook : KeyboardHookT<KeyboardHook, implementation::KeyboardHook>
|
||||
{
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
23
src/common/interop/KeyboardHook.idl
Normal file
23
src/common/interop/KeyboardHook.idl
Normal file
@@ -0,0 +1,23 @@
|
||||
typedef UInt64 WPARAM;
|
||||
|
||||
namespace PowerToys
|
||||
{
|
||||
namespace Interop
|
||||
{
|
||||
struct KeyboardEvent
|
||||
{
|
||||
WPARAM message;
|
||||
Int32 key;
|
||||
UInt64 dwExtraInfo;
|
||||
};
|
||||
|
||||
[version(1.0), uuid(7b820173-a54a-4a38-b810-810e05c14344)] delegate void KeyboardEventCallback(KeyboardEvent ev);
|
||||
[version(1.0), uuid(e3a8bb91-0dfd-4d77-8472-75a47b7af8f8)] delegate Boolean IsActiveCallback();
|
||||
[version(1.0), uuid(94b900ee-d9e8-4630-9064-737eeb9c18ad)] delegate Boolean FilterKeyboardEvent(KeyboardEvent ev);
|
||||
|
||||
[default_interface] runtimeclass KeyboardHook: Windows.Foundation.IClosable {
|
||||
KeyboardHook(KeyboardEventCallback keyboardEventCallback, IsActiveCallback isActiveCallback, FilterKeyboardEvent filterKeyboardEvent);
|
||||
void Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/common/interop/LayoutMapManaged.cpp
Normal file
19
src/common/interop/LayoutMapManaged.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "pch.h"
|
||||
#include "LayoutMapManaged.h"
|
||||
#include "LayoutMapManaged.g.cpp"
|
||||
|
||||
namespace winrt::PowerToys::Interop::implementation
|
||||
{
|
||||
hstring LayoutMapManaged::GetKeyName(uint32_t key)
|
||||
{
|
||||
return hstring{ _map->GetKeyName(key) };
|
||||
}
|
||||
uint32_t LayoutMapManaged::GetKeyValue(hstring const& name)
|
||||
{
|
||||
return _map->GetKeyFromName(std::wstring(name));
|
||||
}
|
||||
void LayoutMapManaged::Updatelayout()
|
||||
{
|
||||
_map->UpdateLayout();
|
||||
}
|
||||
}
|
||||
24
src/common/interop/LayoutMapManaged.h
Normal file
24
src/common/interop/LayoutMapManaged.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "LayoutMapManaged.g.h"
|
||||
#include "keyboard_layout.h"
|
||||
|
||||
namespace winrt::PowerToys::Interop::implementation
|
||||
{
|
||||
struct LayoutMapManaged : LayoutMapManagedT<LayoutMapManaged>
|
||||
{
|
||||
LayoutMapManaged() = default;
|
||||
|
||||
hstring GetKeyName(uint32_t key);
|
||||
uint32_t GetKeyValue(hstring const& name);
|
||||
void Updatelayout();
|
||||
|
||||
private:
|
||||
std::unique_ptr<LayoutMap> _map = std::make_unique<LayoutMap>();
|
||||
};
|
||||
}
|
||||
namespace winrt::PowerToys::Interop::factory_implementation
|
||||
{
|
||||
struct LayoutMapManaged : LayoutMapManagedT<LayoutMapManaged, implementation::LayoutMapManaged>
|
||||
{
|
||||
};
|
||||
}
|
||||
12
src/common/interop/LayoutMapManaged.idl
Normal file
12
src/common/interop/LayoutMapManaged.idl
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace PowerToys
|
||||
{
|
||||
namespace Interop
|
||||
{
|
||||
[default_interface] runtimeclass LayoutMapManaged {
|
||||
LayoutMapManaged();
|
||||
String GetKeyName(UInt32 key);
|
||||
UInt32 GetKeyValue(String name);
|
||||
void Updatelayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
3
src/common/interop/PowerToys.Interop.def
Normal file
3
src/common/interop/PowerToys.Interop.def
Normal file
@@ -0,0 +1,3 @@
|
||||
EXPORTS
|
||||
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
|
||||
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<PropertyGroup>
|
||||
<AssemblyTitle>PowerToys.Interop</AssemblyTitle>
|
||||
</PropertyGroup>
|
||||
@@ -25,16 +25,25 @@
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{F055103B-F80B-4D0C-BF48-057C55620033}</ProjectGuid>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<Keyword>ManagedCProj</Keyword>
|
||||
<RootNamespace>PowerToysInterop</RootNamespace>
|
||||
<RootNamespace>PowerToys.Interop</RootNamespace>
|
||||
<ProjectName>PowerToys.Interop</ProjectName>
|
||||
<CppWinRTOptimized>true</CppWinRTOptimized>
|
||||
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
|
||||
<CppWinRTGenerateWindowsMetadata>true</CppWinRTGenerateWindowsMetadata>
|
||||
<MinimalCoreWin>true</MinimalCoreWin>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
||||
<AppContainerApplication>false</AppContainerApplication>
|
||||
<AppxPackage>false</AppxPackage>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CLRSupport>NetCore</CLRSupport>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
@@ -55,93 +64,122 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||
<ClCompile>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>PowerToysInterop;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<PreprocessorDefinitions>_WINRT_DLL;WINRT_LEAN_AND_MEAN;PowerToysInterop;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)src\common\interop;../../;../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<OmitDefaultLibName>false</OmitDefaultLibName>
|
||||
<AdditionalOptions>/Zc:twoPhase- </AdditionalOptions>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalOptions>%(AdditionalOptions) /bigobj /Zc:twoPhase- </AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>WindowsApp.lib;shell32.lib;advapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
<ModuleDefinitionFile>PowerToys.Interop.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<AssemblyVersionFiles Include="Generated Files\AssemblyInfo.cpp" />
|
||||
</ItemGroup>
|
||||
<Target Name="GenerateAssemblyInfo" BeforeTargets="PrepareForBuild">
|
||||
<ItemGroup>
|
||||
<HeaderLines Include="#include "../pch.h"" />
|
||||
<HeaderLines Include="using namespace System%3b" />
|
||||
<HeaderLines Include="using namespace System::Reflection%3b" />
|
||||
<HeaderLines Include="using namespace System::Runtime::CompilerServices%3b" />
|
||||
<HeaderLines Include="using namespace System::Runtime::InteropServices%3b" />
|
||||
<HeaderLines Include="using namespace System::Security::Permissions%3b" />
|
||||
<HeaderLines Include="[assembly: AssemblyTitleAttribute(L"$(AssemblyTitle)")]%3b" />
|
||||
<HeaderLines Include="[assembly: AssemblyDescriptionAttribute("")]%3b" />
|
||||
<HeaderLines Include="[assembly: AssemblyConfigurationAttribute("")]%3b" />
|
||||
<HeaderLines Include="[assembly: AssemblyCompanyAttribute("$(AssemblyCompany)")]%3b" />
|
||||
<HeaderLines Include="[assembly: AssemblyCopyrightAttribute("$(AssemblyCopyright)")]%3b" />
|
||||
<HeaderLines Include="[assembly: AssemblyProductAttribute("$(AssemblyTitle)")]%3b" />
|
||||
<HeaderLines Include="[assembly: AssemblyTrademarkAttribute("")]%3b" />
|
||||
<HeaderLines Include="[assembly: AssemblyCultureAttribute("")]%3b" />
|
||||
<HeaderLines Include="[assembly: AssemblyVersionAttribute("$(Version).0")]%3b" />
|
||||
<HeaderLines Include="[assembly: ComVisible(false)]%3b" />
|
||||
<HeaderLines Include="[assembly:CLSCompliantAttribute(true)]%3b" />
|
||||
</ItemGroup>
|
||||
<WriteLinesToFile File="Generated Files\AssemblyInfo.cpp" Lines="@(HeaderLines)" Overwrite="true" Encoding="Unicode" WriteOnlyWhenDifferent="true" />
|
||||
</Target>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\modules\videoconference\VideoConferenceShared\MicrophoneDevice.h" />
|
||||
<ClInclude Include="..\..\modules\videoconference\VideoConferenceShared\VideoCaptureDeviceList.h" />
|
||||
<ClInclude Include="HotkeyManager.h" />
|
||||
<ClInclude Include="KeyboardHook.h" />
|
||||
<ClInclude Include="async_message_queue.h" />
|
||||
<ClInclude Include="CommonManaged.h">
|
||||
<DependentUpon>CommonManaged.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Constants.h">
|
||||
<DependentUpon>KeyboardListener.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HotkeyManager.h">
|
||||
<DependentUpon>HotkeyManager.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="KeyboardHook.h">
|
||||
<DependentUpon>KeyboardHook.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="keyboard_layout.h" />
|
||||
<ClInclude Include="keyboard_layout_impl.h" />
|
||||
<ClInclude Include="LayoutMapManaged.h">
|
||||
<DependentUpon>LayoutMapManaged.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="shared_constants.h" />
|
||||
<ClInclude Include="TwoWayPipeMessageIPCManaged.h">
|
||||
<DependentUpon>TwoWayPipeMessageIPCManaged.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="two_way_pipe_message_ipc.h" />
|
||||
<ClInclude Include="two_way_pipe_message_ipc_impl.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\modules\videoconference\VideoConferenceShared\MicrophoneDevice.cpp">
|
||||
<CompileAsManaged>false</CompileAsManaged>
|
||||
<ClCompile Include="..\..\modules\videoconference\VideoConferenceShared\MicrophoneDevice.cpp" />
|
||||
<ClCompile Include="..\..\modules\videoconference\VideoConferenceShared\VideoCaptureDeviceList.cpp" />
|
||||
<ClCompile Include="CommonManaged.cpp">
|
||||
<DependentUpon>CommonManaged.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\videoconference\VideoConferenceShared\VideoCaptureDeviceList.cpp">
|
||||
<CompileAsManaged>false</CompileAsManaged>
|
||||
<ClCompile Include="Constants.cpp">
|
||||
<DependentUpon>KeyboardListener.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Generated Files\AssemblyInfo.cpp" />
|
||||
<ClCompile Include="HotkeyManager.cpp" />
|
||||
<ClCompile Include="interop.cpp" />
|
||||
<ClCompile Include="KeyboardHook.cpp" />
|
||||
<ClCompile Include="keyboard_layout.cpp">
|
||||
<CompileAsManaged>false</CompileAsManaged>
|
||||
<ClCompile Include="HotkeyManager.cpp">
|
||||
<DependentUpon>HotkeyManager.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="two_way_pipe_message_ipc.cpp">
|
||||
<CompileAsManaged>false</CompileAsManaged>
|
||||
<ClCompile Include="KeyboardHook.cpp">
|
||||
<DependentUpon>KeyboardHook.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="keyboard_layout.cpp" />
|
||||
<ClCompile Include="LayoutMapManaged.cpp">
|
||||
<DependentUpon>LayoutMapManaged.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TwoWayPipeMessageIPCManaged.cpp">
|
||||
<DependentUpon>TwoWayPipeMessageIPCManaged.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="two_way_pipe_message_ipc.cpp" />
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="interop.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="PowerToys.Interop.def" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="PropertySheet.props" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="CommonManaged.idl" />
|
||||
<Midl Include="Constants.idl" />
|
||||
<Midl Include="HotkeyManager.idl" />
|
||||
<Midl Include="KeyboardHook.idl" />
|
||||
<Midl Include="LayoutMapManaged.idl" />
|
||||
<Midl Include="TwoWayPipeMessageIPCManaged.idl" />
|
||||
</ItemGroup>
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -18,12 +18,6 @@
|
||||
<ClInclude Include="pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="KeyboardHook.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HotkeyManager.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -36,23 +30,38 @@
|
||||
<ClInclude Include="shared_constants.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Constants.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="keyboard_layout.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="keyboard_layout_impl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="LayoutMapManaged.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CommonManaged.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="two_way_pipe_message_ipc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="two_way_pipe_message_ipc_impl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="async_message_queue.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HotkeyManager.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Constants.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="interop.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Generated Files\AssemblyInfo.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="KeyboardHook.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HotkeyManager.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="two_way_pipe_message_ipc.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="keyboard_layout.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@@ -62,6 +71,30 @@
|
||||
<ClCompile Include="..\..\modules\videoconference\VideoConferenceShared\VideoCaptureDeviceList.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Constants.cpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="LayoutMapManaged.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CommonManaged.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="two_way_pipe_message_ipc.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HotkeyManager.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Constants.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="interop.rc">
|
||||
@@ -69,9 +102,33 @@
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="PowerToys.Interop.def">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
<None Include="PropertySheet.props" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<Midl Include="HotkeyManager.idl">
|
||||
<Filter>Source Files</Filter>
|
||||
</Midl>
|
||||
<Midl Include="Constants.idl">
|
||||
<Filter>Source Files</Filter>
|
||||
</Midl>
|
||||
<Midl Include="LayoutMapManaged.idl">
|
||||
<Filter>Source Files</Filter>
|
||||
</Midl>
|
||||
<Midl Include="CommonManaged.idl">
|
||||
<Filter>Source Files</Filter>
|
||||
</Midl>
|
||||
<Midl Include="KeyboardHook.idl">
|
||||
<Filter>Source Files</Filter>
|
||||
</Midl>
|
||||
<Midl Include="TwoWayPipeMessageIPCManaged.idl">
|
||||
<Filter>Source Files</Filter>
|
||||
</Midl>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
16
src/common/interop/PropertySheet.props
Normal file
16
src/common/interop/PropertySheet.props
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ImportGroup Label="PropertySheets" />
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<!--
|
||||
To customize common C++/WinRT project properties:
|
||||
* right-click the project node
|
||||
* expand the Common Properties item
|
||||
* select the C++/WinRT property page
|
||||
|
||||
For more advanced scenarios, and complete documentation, please see:
|
||||
https://github.com/Microsoft/cppwinrt/tree/master/nuget
|
||||
-->
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup />
|
||||
</Project>
|
||||
37
src/common/interop/TwoWayPipeMessageIPCManaged.cpp
Normal file
37
src/common/interop/TwoWayPipeMessageIPCManaged.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "pch.h"
|
||||
#include "TwoWayPipeMessageIPCManaged.h"
|
||||
#include "TwoWayPipeMessageIPCManaged.g.cpp"
|
||||
#include "two_way_pipe_message_ipc_impl.h"
|
||||
#include <functional>
|
||||
|
||||
namespace winrt::PowerToys::Interop::implementation
|
||||
{
|
||||
TwoWayPipeMessageIPCManaged::TwoWayPipeMessageIPCManaged(hstring const& inputPipeName, hstring const& outputPipeName, winrt::PowerToys::Interop::TwoWayPipeIPCReadCallback const& _callback)
|
||||
{
|
||||
this->_callback = _callback;
|
||||
if (_callback != nullptr)
|
||||
{
|
||||
_internalReadCallback = [this](const std::wstring& msg) {
|
||||
this->_callback(msg);
|
||||
};
|
||||
}
|
||||
_pipe = new TwoWayPipeMessageIPC(std::wstring{ inputPipeName }, std::wstring{ outputPipeName }, _internalReadCallback);
|
||||
}
|
||||
|
||||
void TwoWayPipeMessageIPCManaged::Send(hstring const& msg)
|
||||
{
|
||||
_pipe->send(std::wstring{ msg });
|
||||
}
|
||||
void TwoWayPipeMessageIPCManaged::Start()
|
||||
{
|
||||
_pipe->start(nullptr);
|
||||
}
|
||||
void TwoWayPipeMessageIPCManaged::End()
|
||||
{
|
||||
_pipe->end();
|
||||
}
|
||||
void TwoWayPipeMessageIPCManaged::Close()
|
||||
{
|
||||
delete _pipe;
|
||||
}
|
||||
}
|
||||
28
src/common/interop/TwoWayPipeMessageIPCManaged.h
Normal file
28
src/common/interop/TwoWayPipeMessageIPCManaged.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include "TwoWayPipeMessageIPCManaged.g.h"
|
||||
#include "two_way_pipe_message_ipc.h"
|
||||
|
||||
namespace winrt::PowerToys::Interop::implementation
|
||||
{
|
||||
struct TwoWayPipeMessageIPCManaged : TwoWayPipeMessageIPCManagedT<TwoWayPipeMessageIPCManaged>
|
||||
{
|
||||
TwoWayPipeMessageIPCManaged() = default;
|
||||
|
||||
TwoWayPipeMessageIPCManaged(hstring const& inputPipeName, hstring const& outputPipeName, winrt::PowerToys::Interop::TwoWayPipeIPCReadCallback const& _callback);
|
||||
void Send(hstring const& msg);
|
||||
void Start();
|
||||
void End();
|
||||
void Close();
|
||||
|
||||
private:
|
||||
TwoWayPipeMessageIPC* _pipe;
|
||||
TwoWayPipeIPCReadCallback _callback;
|
||||
std::function<void(const std::wstring& msg)> _internalReadCallback;
|
||||
};
|
||||
}
|
||||
namespace winrt::PowerToys::Interop::factory_implementation
|
||||
{
|
||||
struct TwoWayPipeMessageIPCManaged : TwoWayPipeMessageIPCManagedT<TwoWayPipeMessageIPCManaged, implementation::TwoWayPipeMessageIPCManaged>
|
||||
{
|
||||
};
|
||||
}
|
||||
14
src/common/interop/TwoWayPipeMessageIPCManaged.idl
Normal file
14
src/common/interop/TwoWayPipeMessageIPCManaged.idl
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace PowerToys
|
||||
{
|
||||
namespace Interop
|
||||
{
|
||||
delegate void TwoWayPipeIPCReadCallback(String message);
|
||||
[default_interface] runtimeclass TwoWayPipeMessageIPCManaged : Windows.Foundation.IClosable
|
||||
{
|
||||
TwoWayPipeMessageIPCManaged(String inputPipeName, String outputPipeName, TwoWayPipeIPCReadCallback _callback);
|
||||
void Send(String msg);
|
||||
void Start();
|
||||
void End();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using interop;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using PowerToys.Interop;
|
||||
|
||||
namespace Microsoft.Interop.Tests
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||
@@ -46,7 +46,15 @@
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- See https://learn.microsoft.com/windows/apps/develop/platform/csharp-winrt/net-projection-from-cppwinrt-component for more info -->
|
||||
<PropertyGroup>
|
||||
<CsWinRTIncludes>PowerToys.Interop</CsWinRTIncludes>
|
||||
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
|
||||
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Windows.CsWinRT" />
|
||||
<PackageReference Include="MSTest" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,299 +0,0 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include <msclr/marshal.h>
|
||||
#include <msclr/marshal_cppstd.h>
|
||||
#include <functional>
|
||||
#include "keyboard_layout.h"
|
||||
#include "two_way_pipe_message_ipc.h"
|
||||
#include "shared_constants.h"
|
||||
|
||||
// We cannot use C++/WinRT APIs when compiled with /clr (we'll get a runtime crash). os-detect API is used
|
||||
// in both native C++ and C++/CX.
|
||||
// We also cannot compile it as a library, since we use different cppruntime linkage in C++/CX and native C++.
|
||||
// Therefore the simplest way is to compile these functions as native using the pragmas below.
|
||||
#pragma managed(push, off)
|
||||
#include "../utils/os-detect.h"
|
||||
// TODO: move to a separate library in common
|
||||
#include "../../modules/videoconference/VideoConferenceShared/MicrophoneDevice.h"
|
||||
#include "../../modules/videoconference/VideoConferenceShared/VideoCaptureDeviceList.h"
|
||||
#pragma managed(pop)
|
||||
|
||||
#include <common/version/version.h>
|
||||
|
||||
using namespace System;
|
||||
using namespace System::Runtime::InteropServices;
|
||||
using System::Collections::Generic::List;
|
||||
|
||||
// https://learn.microsoft.com/cpp/dotnet/how-to-wrap-native-class-for-use-by-csharp?view=vs-2019
|
||||
namespace interop
|
||||
{
|
||||
public
|
||||
ref class LayoutMapManaged
|
||||
{
|
||||
public:
|
||||
LayoutMapManaged() :
|
||||
_map(new LayoutMap) {}
|
||||
|
||||
~LayoutMapManaged()
|
||||
{
|
||||
delete _map;
|
||||
}
|
||||
|
||||
String ^ GetKeyName(DWORD key)
|
||||
{
|
||||
return gcnew String(_map->GetKeyName(key).c_str());
|
||||
}
|
||||
|
||||
DWORD GetKeyValue(String ^ name)
|
||||
{
|
||||
return _map->GetKeyFromName(msclr::interop::marshal_as<std::wstring>(name));
|
||||
}
|
||||
|
||||
void Updatelayout()
|
||||
{
|
||||
_map->UpdateLayout();
|
||||
}
|
||||
|
||||
protected:
|
||||
!LayoutMapManaged()
|
||||
{
|
||||
delete _map;
|
||||
}
|
||||
|
||||
private:
|
||||
LayoutMap* _map;
|
||||
};
|
||||
|
||||
public
|
||||
ref class TwoWayPipeMessageIPCManaged
|
||||
{
|
||||
public:
|
||||
delegate void ReadCallback(String ^ message);
|
||||
|
||||
TwoWayPipeMessageIPCManaged(String ^ inputPipeName, String ^ outputPipeName, ReadCallback ^ callback)
|
||||
{
|
||||
_wrapperCallback = gcnew InternalReadCallback(this, &TwoWayPipeMessageIPCManaged::ReadCallbackHelper);
|
||||
_callback = callback;
|
||||
|
||||
TwoWayPipeMessageIPC::callback_function cb = nullptr;
|
||||
if (callback != nullptr)
|
||||
{
|
||||
cb = (TwoWayPipeMessageIPC::callback_function)(void*)Marshal::GetFunctionPointerForDelegate(_wrapperCallback);
|
||||
}
|
||||
_pipe = new TwoWayPipeMessageIPC(
|
||||
msclr::interop::marshal_as<std::wstring>(inputPipeName),
|
||||
msclr::interop::marshal_as<std::wstring>(outputPipeName),
|
||||
cb);
|
||||
}
|
||||
|
||||
~TwoWayPipeMessageIPCManaged()
|
||||
{
|
||||
delete _pipe;
|
||||
}
|
||||
|
||||
void Send(String ^ msg)
|
||||
{
|
||||
_pipe->send(msclr::interop::marshal_as<std::wstring>(msg));
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
_pipe->start(nullptr);
|
||||
}
|
||||
|
||||
void End()
|
||||
{
|
||||
_pipe->end();
|
||||
}
|
||||
|
||||
protected:
|
||||
!TwoWayPipeMessageIPCManaged()
|
||||
{
|
||||
delete _pipe;
|
||||
}
|
||||
|
||||
private:
|
||||
delegate void InternalReadCallback(const std::wstring& msg);
|
||||
|
||||
TwoWayPipeMessageIPC* _pipe;
|
||||
ReadCallback ^ _callback;
|
||||
InternalReadCallback ^ _wrapperCallback;
|
||||
|
||||
void ReadCallbackHelper(const std::wstring& msg)
|
||||
{
|
||||
_callback(gcnew String(msg.c_str()));
|
||||
}
|
||||
};
|
||||
|
||||
public
|
||||
ref class CommonManaged
|
||||
{
|
||||
public:
|
||||
static String ^ GetProductVersion() {
|
||||
return gcnew String(get_product_version().c_str());
|
||||
}
|
||||
|
||||
static List<String ^> ^ GetAllActiveMicrophoneDeviceNames() {
|
||||
auto names = gcnew List<String ^>();
|
||||
for (const auto& device : MicrophoneDevice::getAllActive())
|
||||
{
|
||||
names->Add(gcnew String(device->name().data()));
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
static List<String ^> ^
|
||||
GetAllVideoCaptureDeviceNames() {
|
||||
auto names = gcnew List<String ^>();
|
||||
VideoCaptureDeviceList vcdl;
|
||||
vcdl.EnumerateDevices();
|
||||
|
||||
for (UINT32 i = 0; i < vcdl.Count(); ++i)
|
||||
{
|
||||
auto name = gcnew String(vcdl.GetDeviceName(i).data());
|
||||
if (name != L"PowerToys VideoConference Mute")
|
||||
{
|
||||
names->Add(name);
|
||||
}
|
||||
}
|
||||
return names;
|
||||
}
|
||||
};
|
||||
|
||||
public
|
||||
ref class Constants
|
||||
{
|
||||
public:
|
||||
literal int VK_WIN_BOTH = CommonSharedConstants::VK_WIN_BOTH;
|
||||
|
||||
static String ^ AppDataPath() {
|
||||
auto localPath = Environment::GetFolderPath(Environment::SpecialFolder::LocalApplicationData);
|
||||
auto powerToysPath = gcnew String(CommonSharedConstants::APPDATA_PATH);
|
||||
return System::IO::Path::Combine(localPath, powerToysPath);
|
||||
}
|
||||
|
||||
static String ^ PowerLauncherSharedEvent() {
|
||||
return gcnew String(CommonSharedConstants::POWER_LAUNCHER_SHARED_EVENT);
|
||||
}
|
||||
|
||||
static String ^ PowerLauncherCentralizedHookSharedEvent() {
|
||||
return gcnew String(CommonSharedConstants::POWER_LAUNCHER_CENTRALIZED_HOOK_SHARED_EVENT);
|
||||
}
|
||||
|
||||
static String ^ RunSendSettingsTelemetryEvent() {
|
||||
return gcnew String(CommonSharedConstants::RUN_SEND_SETTINGS_TELEMETRY_EVENT);
|
||||
}
|
||||
|
||||
static String ^ RunExitEvent() {
|
||||
return gcnew String(CommonSharedConstants::RUN_EXIT_EVENT);
|
||||
}
|
||||
|
||||
static String ^ FZEExitEvent() {
|
||||
return gcnew String(CommonSharedConstants::FZE_EXIT_EVENT);
|
||||
}
|
||||
|
||||
static String ^ FZEToggleEvent() {
|
||||
return gcnew String(CommonSharedConstants::FANCY_ZONES_EDITOR_TOGGLE_EVENT);
|
||||
}
|
||||
|
||||
static String ^ ColorPickerSendSettingsTelemetryEvent() {
|
||||
return gcnew String(CommonSharedConstants::COLOR_PICKER_SEND_SETTINGS_TELEMETRY_EVENT);
|
||||
}
|
||||
|
||||
static String ^ ShowColorPickerSharedEvent() {
|
||||
return gcnew String(CommonSharedConstants::SHOW_COLOR_PICKER_SHARED_EVENT);
|
||||
}
|
||||
|
||||
static String ^ ShowAdvancedPasteSharedEvent() {
|
||||
return gcnew String(CommonSharedConstants::SHOW_ADVANCED_PASTE_SHARED_EVENT);
|
||||
}
|
||||
|
||||
static String ^ AdvancedPasteMarkdownEvent() {
|
||||
return gcnew String(CommonSharedConstants::ADVANCED_PASTE_MARKDOWN_EVENT);
|
||||
}
|
||||
|
||||
static String ^ AdvancedPasteJsonEvent() {
|
||||
return gcnew String(CommonSharedConstants::ADVANCED_PASTE_JSON_EVENT);
|
||||
}
|
||||
|
||||
static String ^ ShowPowerOCRSharedEvent() {
|
||||
return gcnew String(CommonSharedConstants::SHOW_POWEROCR_SHARED_EVENT);
|
||||
}
|
||||
|
||||
static String ^ MouseJumpShowPreviewEvent() {
|
||||
return gcnew String(CommonSharedConstants::MOUSE_JUMP_SHOW_PREVIEW_EVENT);
|
||||
}
|
||||
|
||||
static String ^ AwakeExitEvent() {
|
||||
return gcnew String(CommonSharedConstants::AWAKE_EXIT_EVENT);
|
||||
}
|
||||
|
||||
static String^ ShowPeekEvent() {
|
||||
return gcnew String(CommonSharedConstants::SHOW_PEEK_SHARED_EVENT);
|
||||
}
|
||||
|
||||
static String ^ PowerAccentExitEvent() {
|
||||
return gcnew String(CommonSharedConstants::POWERACCENT_EXIT_EVENT);
|
||||
}
|
||||
|
||||
static String ^ ShortcutGuideTriggerEvent() {
|
||||
return gcnew String(CommonSharedConstants::SHORTCUT_GUIDE_TRIGGER_EVENT);
|
||||
}
|
||||
|
||||
static String ^ RegistryPreviewTriggerEvent() {
|
||||
return gcnew String(CommonSharedConstants::REGISTRY_PREVIEW_TRIGGER_EVENT);
|
||||
}
|
||||
|
||||
static String ^ MeasureToolTriggerEvent() {
|
||||
return gcnew String(CommonSharedConstants::MEASURE_TOOL_TRIGGER_EVENT);
|
||||
}
|
||||
|
||||
static String ^ GcodePreviewResizeEvent() {
|
||||
return gcnew String(CommonSharedConstants::GCODE_PREVIEW_RESIZE_EVENT);
|
||||
}
|
||||
|
||||
static String ^ QoiPreviewResizeEvent() {
|
||||
return gcnew String(CommonSharedConstants::QOI_PREVIEW_RESIZE_EVENT);
|
||||
}
|
||||
|
||||
static String ^ DevFilesPreviewResizeEvent() {
|
||||
return gcnew String(CommonSharedConstants::DEV_FILES_PREVIEW_RESIZE_EVENT);
|
||||
}
|
||||
|
||||
static String ^ MarkdownPreviewResizeEvent() {
|
||||
return gcnew String(CommonSharedConstants::MARKDOWN_PREVIEW_RESIZE_EVENT);
|
||||
}
|
||||
|
||||
static String ^ PdfPreviewResizeEvent() {
|
||||
return gcnew String(CommonSharedConstants::PDF_PREVIEW_RESIZE_EVENT);
|
||||
}
|
||||
|
||||
static String ^ SvgPreviewResizeEvent() {
|
||||
return gcnew String(CommonSharedConstants::SVG_PREVIEW_RESIZE_EVENT);
|
||||
}
|
||||
|
||||
static String ^ ShowHostsSharedEvent() {
|
||||
return gcnew String(CommonSharedConstants::SHOW_HOSTS_EVENT);
|
||||
}
|
||||
|
||||
static String ^ ShowHostsAdminSharedEvent() {
|
||||
return gcnew String(CommonSharedConstants::SHOW_HOSTS_ADMIN_EVENT);
|
||||
}
|
||||
|
||||
static String ^ CropAndLockThumbnailEvent() {
|
||||
return gcnew String(CommonSharedConstants::CROP_AND_LOCK_THUMBNAIL_EVENT);
|
||||
}
|
||||
|
||||
static String ^ CropAndLockReparentEvent() {
|
||||
return gcnew String(CommonSharedConstants::CROP_AND_LOCK_REPARENT_EVENT);
|
||||
}
|
||||
|
||||
static String ^ ShowEnvironmentVariablesSharedEvent() {
|
||||
return gcnew String(CommonSharedConstants::SHOW_ENVIRONMENT_VARIABLES_EVENT);
|
||||
}
|
||||
|
||||
static String ^ ShowEnvironmentVariablesAdminSharedEvent() {
|
||||
return gcnew String(CommonSharedConstants::SHOW_ENVIRONMENT_VARIABLES_ADMIN_EVENT);
|
||||
}
|
||||
};
|
||||
}
|
||||
1
src/common/interop/pch.cpp
Normal file
1
src/common/interop/pch.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "pch.h"
|
||||
@@ -3,13 +3,12 @@
|
||||
// This also affects IntelliSense performance, including code completion and many code browsing features.
|
||||
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
|
||||
// Do not add files here that you will be updating frequently as this negates the performance advantage.
|
||||
|
||||
#ifndef PCH_H
|
||||
#define PCH_H
|
||||
|
||||
#pragma once
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
// add headers that you want to pre-compile here
|
||||
#include <unknwn.h>
|
||||
#include <winrt/base.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <Windows.h>
|
||||
#include <Endpointvolume.h>
|
||||
|
||||
#endif //PCH_H
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
#include <functional>
|
||||
class TwoWayPipeMessageIPC
|
||||
{
|
||||
public:
|
||||
typedef void (*callback_function)(const std::wstring&);
|
||||
typedef std::function<void(const std::wstring&)>callback_function;
|
||||
TwoWayPipeMessageIPC(
|
||||
std::wstring _input_pipe_name,
|
||||
std::wstring _output_pipe_name,
|
||||
|
||||
Reference in New Issue
Block a user