mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-15 19:27:56 +01:00
More deux, two
This commit is contained in:
@@ -365,6 +365,7 @@
|
|||||||
<Project Path="src/modules/Deux/SDK/Microsoft.CommandPalette.Extensions/Microsoft.CommandPalette.Extensions.vcxproj" Id="7997dad4-31d6-496b-95db-6c028d699370" />
|
<Project Path="src/modules/Deux/SDK/Microsoft.CommandPalette.Extensions/Microsoft.CommandPalette.Extensions.vcxproj" Id="7997dad4-31d6-496b-95db-6c028d699370" />
|
||||||
</Folder>
|
</Folder>
|
||||||
<Folder Name="/modules/Deux/UI/">
|
<Folder Name="/modules/Deux/UI/">
|
||||||
|
<Project Path="src/modules/Deux/UI/CmdPalKeyboardService/CmdPalKeyboardService.vcxproj" Id="fc192bce-bfbb-40f5-8c2d-9858de12c31f" />
|
||||||
<Project Path="src/modules/Deux/UI/Microsoft.CommandPalette.UI.Models/Microsoft.CommandPalette.UI.Models.csproj">
|
<Project Path="src/modules/Deux/UI/Microsoft.CommandPalette.UI.Models/Microsoft.CommandPalette.UI.Models.csproj">
|
||||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||||
<Platform Solution="*|x64" Project="x64" />
|
<Platform Solution="*|x64" Project="x64" />
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
EXPORTS
|
||||||
|
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
|
||||||
|
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
|
||||||
@@ -0,0 +1,176 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" 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 Label="Globals">
|
||||||
|
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
|
||||||
|
<CppWinRTGenerateWindowsMetadata>true</CppWinRTGenerateWindowsMetadata>
|
||||||
|
<ProjectGuid>{FC192BCE-BFBB-40F5-8C2D-9858DE12C31F}</ProjectGuid>
|
||||||
|
<ProjectName>CmdPalKeyboardService</ProjectName>
|
||||||
|
<RootNamespace>CmdPalKeyboardService</RootNamespace>
|
||||||
|
<AppxPackage>false</AppxPackage>
|
||||||
|
</PropertyGroup>
|
||||||
|
<!-- BEGIN common.build.pre.props -->
|
||||||
|
<PropertyGroup Label="Configuration">
|
||||||
|
<EnableHybridCRT>true</EnableHybridCRT>
|
||||||
|
<UseCrtSDKReferenceStaticWarning Condition="'$(EnableHybridCRT)'=='true'">false</UseCrtSDKReferenceStaticWarning>
|
||||||
|
</PropertyGroup>
|
||||||
|
<!-- END common.build.pre.props -->
|
||||||
|
<!-- BEGIN cppwinrt.build.pre.props -->
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<CppWinRTEnabled>true</CppWinRTEnabled>
|
||||||
|
<CppWinRTOptimized>true</CppWinRTOptimized>
|
||||||
|
<DefaultLanguage>en-US</DefaultLanguage>
|
||||||
|
<MinimumVisualStudioVersion>17.0</MinimumVisualStudioVersion>
|
||||||
|
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<MinimalCoreWin>true</MinimalCoreWin>
|
||||||
|
<AppContainerApplication>true</AppContainerApplication>
|
||||||
|
<WindowsStoreApp>true</WindowsStoreApp>
|
||||||
|
<ApplicationType>Windows Store</ApplicationType>
|
||||||
|
<UseCrtSDKReference Condition="'$(EnableHybridCRT)'=='true'">false</UseCrtSDKReference>
|
||||||
|
<!-- The SDK reference breaks the Hybrid CRT -->
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<!-- We have to use the Desktop platform for Hybrid CRT to work. -->
|
||||||
|
<_VC_Target_Library_Platform>Desktop</_VC_Target_Library_Platform>
|
||||||
|
<_NoWinAPIFamilyApp>true</_NoWinAPIFamilyApp>
|
||||||
|
</PropertyGroup>
|
||||||
|
<!-- END cppwinrt.build.pre.props -->
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
<GenerateManifest>false</GenerateManifest>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets">
|
||||||
|
<Import Project="PropertySheet.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetName>CmdPalKeyboardService</TargetName>
|
||||||
|
<OutDir>..\..\..\..\..\$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup>
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<AdditionalOptions>%(AdditionalOptions) /bigobj</AdditionalOptions>
|
||||||
|
<PreprocessorDefinitions>_WINRT_DLL;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>../../../..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||||
|
<ModuleDefinitionFile>CmdPalKeyboardService.def</ModuleDefinitionFile>
|
||||||
|
<AdditionalDependencies>Shell32.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||||
|
<ClCompile>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||||
|
<ClCompile>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="pch.h" />
|
||||||
|
<ClInclude Include="KeyboardListener.h">
|
||||||
|
<DependentUpon>KeyboardListener.idl</DependentUpon>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="pch.cpp">
|
||||||
|
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="KeyboardListener.cpp">
|
||||||
|
<DependentUpon>KeyboardListener.idl</DependentUpon>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Midl Include="KeyboardListener.idl" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
<None Include="CmdPalKeyboardService.def" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="PropertySheet.props" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<Import Project="..\..\..\..\..\deps\spdlog.props" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
<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.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>
|
||||||
|
<!-- BEGIN common.build.post.props -->
|
||||||
|
<!--
|
||||||
|
The Hybrid CRT model statically links the runtime and STL and dynamically
|
||||||
|
links the UCRT instead of the VC++ CRT. The UCRT ships with Windows.
|
||||||
|
WinAppSDK asserts that this is "supported according to the CRT maintainer."
|
||||||
|
|
||||||
|
This must come before Microsoft.Cpp.targets because it manipulates ClCompile.RuntimeLibrary.
|
||||||
|
-->
|
||||||
|
<ItemDefinitionGroup Condition="'$(EnableHybridCRT)'=='true' and '$(Configuration)'=='Debug'">
|
||||||
|
<ClCompile>
|
||||||
|
<!-- We use MultiThreadedDebug, rather than MultiThreadedDebugDLL, to avoid DLL dependencies on VCRUNTIME140d.dll and MSVCP140d.dll. -->
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<!-- Link statically against the runtime and STL, but link dynamically against the CRT by ignoring the static CRT
|
||||||
|
lib and instead linking against the Universal CRT DLL import library. This "hybrid" linking mechanism is
|
||||||
|
supported according to the CRT maintainer. Dynamic linking against the CRT makes the binaries a bit smaller
|
||||||
|
than they would otherwise be if the CRT, runtime, and STL were all statically linked in. -->
|
||||||
|
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries);libucrtd.lib</IgnoreSpecificDefaultLibraries>
|
||||||
|
<AdditionalOptions>%(AdditionalOptions) /defaultlib:ucrtd.lib</AdditionalOptions>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(EnableHybridCRT)'=='true' and ('$(Configuration)'=='Release' or '$(Configuration)'=='AuditMode')">
|
||||||
|
<ClCompile>
|
||||||
|
<!-- We use MultiThreaded, rather than MultiThreadedDLL, to avoid DLL dependencies on VCRUNTIME140.dll and MSVCP140.dll. -->
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<!-- Link statically against the runtime and STL, but link dynamically against the CRT by ignoring the static CRT
|
||||||
|
lib and instead linking against the Universal CRT DLL import library. This "hybrid" linking mechanism is
|
||||||
|
supported according to the CRT maintainer. Dynamic linking against the CRT makes the binaries a bit smaller
|
||||||
|
than they would otherwise be if the CRT, runtime, and STL were all statically linked in. -->
|
||||||
|
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries);libucrt.lib</IgnoreSpecificDefaultLibraries>
|
||||||
|
<AdditionalOptions>%(AdditionalOptions) /defaultlib:ucrt.lib</AdditionalOptions>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<!-- END common.build.post.props -->
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0"
|
||||||
|
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Resources">
|
||||||
|
<UniqueIdentifier>accd3aa8-1ba0-4223-9bbe-0c431709210b</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Generated Files">
|
||||||
|
<UniqueIdentifier>{926ab91d-31b4-48c3-b9a4-e681349f27f0}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="pch.cpp" />
|
||||||
|
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="pch.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Midl Include="KeyboardListener.idl" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="CmdPalKeyboardService.def" />
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="PropertySheet.props" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
165
src/modules/Deux/UI/CmdPalKeyboardService/KeyboardListener.cpp
Normal file
165
src/modules/Deux/UI/CmdPalKeyboardService/KeyboardListener.cpp
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "KeyboardListener.h"
|
||||||
|
#include "KeyboardListener.g.cpp"
|
||||||
|
|
||||||
|
// #include <common/logger/logger.h>
|
||||||
|
// #include <common/utils/logger_helper.h>
|
||||||
|
#include <common/utils/winapi_error.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace winrt::CmdPalKeyboardService::implementation
|
||||||
|
{
|
||||||
|
KeyboardListener::KeyboardListener()
|
||||||
|
{
|
||||||
|
s_instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardListener::Start()
|
||||||
|
{
|
||||||
|
#if defined(DISABLE_LOWLEVEL_HOOKS_WHEN_DEBUGGED)
|
||||||
|
const bool hook_disabled = IsDebuggerPresent();
|
||||||
|
#else
|
||||||
|
const bool hook_disabled = false;
|
||||||
|
#endif
|
||||||
|
if (!hook_disabled)
|
||||||
|
{
|
||||||
|
if (!s_llKeyboardHook)
|
||||||
|
{
|
||||||
|
s_llKeyboardHook = SetWindowsHookExW(WH_KEYBOARD_LL, LowLevelKeyboardProc, NULL, NULL);
|
||||||
|
if (!s_llKeyboardHook)
|
||||||
|
{
|
||||||
|
DWORD errorCode = GetLastError();
|
||||||
|
show_last_error_message(L"SetWindowsHookEx", errorCode, L"CmdPalKeyboardService");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardListener::Stop()
|
||||||
|
{
|
||||||
|
if (s_llKeyboardHook && UnhookWindowsHookEx(s_llKeyboardHook))
|
||||||
|
{
|
||||||
|
s_llKeyboardHook = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardListener::SetHotkeyAction(bool win, bool ctrl, bool shift, bool alt, uint8_t key, hstring const& id)
|
||||||
|
{
|
||||||
|
Hotkey hotkey = { .win = win, .ctrl = ctrl, .shift = shift, .alt = alt, .key = key };
|
||||||
|
std::unique_lock lock{ mutex };
|
||||||
|
|
||||||
|
HotkeyDescriptor desc = { .hotkey = hotkey, .id = std::wstring(id) };
|
||||||
|
hotkeyDescriptors.insert(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardListener::ClearHotkey(hstring const& id)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::unique_lock lock{ mutex };
|
||||||
|
auto it = hotkeyDescriptors.begin();
|
||||||
|
while (it != hotkeyDescriptors.end())
|
||||||
|
{
|
||||||
|
if (it->id == id)
|
||||||
|
{
|
||||||
|
it = hotkeyDescriptors.erase(it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardListener::ClearHotkeys()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::unique_lock lock{ mutex };
|
||||||
|
auto it = hotkeyDescriptors.begin();
|
||||||
|
while (it != hotkeyDescriptors.end())
|
||||||
|
{
|
||||||
|
it = hotkeyDescriptors.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardListener::SetProcessCommand(ProcessCommand processCommand)
|
||||||
|
{
|
||||||
|
m_processCommandCb = [trigger = std::move(processCommand)](hstring const& id) {
|
||||||
|
trigger(id);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT KeyboardListener::DoLowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
const auto& keyPressInfo = *reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
|
||||||
|
|
||||||
|
if ((wParam != WM_KEYDOWN) && (wParam != WM_SYSKEYDOWN))
|
||||||
|
{
|
||||||
|
return CallNextHookEx(NULL, nCode, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
Hotkey hotkey{
|
||||||
|
.win = (GetAsyncKeyState(VK_LWIN) & 0x8000) || (GetAsyncKeyState(VK_RWIN) & 0x8000),
|
||||||
|
.ctrl = static_cast<bool>(GetAsyncKeyState(VK_CONTROL) & 0x8000),
|
||||||
|
.shift = static_cast<bool>(GetAsyncKeyState(VK_SHIFT) & 0x8000),
|
||||||
|
.alt = static_cast<bool>(GetAsyncKeyState(VK_MENU) & 0x8000),
|
||||||
|
.key = static_cast<unsigned char>(keyPressInfo.vkCode)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (hotkey == Hotkey{})
|
||||||
|
{
|
||||||
|
return CallNextHookEx(NULL, nCode, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool do_action = false;
|
||||||
|
std::wstring actionId{};
|
||||||
|
|
||||||
|
{
|
||||||
|
// Hold the lock for the shortest possible duration
|
||||||
|
std::unique_lock lock{ mutex };
|
||||||
|
HotkeyDescriptor dummy{ .hotkey = hotkey };
|
||||||
|
auto it = hotkeyDescriptors.find(dummy);
|
||||||
|
if (it != hotkeyDescriptors.end())
|
||||||
|
{
|
||||||
|
do_action = true;
|
||||||
|
actionId = it->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_action)
|
||||||
|
{
|
||||||
|
m_processCommandCb(hstring{ actionId });
|
||||||
|
|
||||||
|
// 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));
|
||||||
|
|
||||||
|
// Swallow the key press
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CallNextHookEx(NULL, nCode, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT KeyboardListener::LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (s_instance == nullptr)
|
||||||
|
{
|
||||||
|
return CallNextHookEx(NULL, nCode, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nCode < 0)
|
||||||
|
{
|
||||||
|
return CallNextHookEx(NULL, nCode, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_instance->DoLowLevelKeyboardProc(nCode, wParam, lParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
67
src/modules/Deux/UI/CmdPalKeyboardService/KeyboardListener.h
Normal file
67
src/modules/Deux/UI/CmdPalKeyboardService/KeyboardListener.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "KeyboardListener.g.h"
|
||||||
|
#include <mutex>
|
||||||
|
#include <spdlog/stopwatch.h>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
namespace winrt::CmdPalKeyboardService::implementation
|
||||||
|
{
|
||||||
|
struct KeyboardListener : KeyboardListenerT<KeyboardListener>
|
||||||
|
{
|
||||||
|
struct Hotkey
|
||||||
|
{
|
||||||
|
bool win = false;
|
||||||
|
bool ctrl = false;
|
||||||
|
bool shift = false;
|
||||||
|
bool alt = false;
|
||||||
|
unsigned char key = 0;
|
||||||
|
|
||||||
|
std::strong_ordering operator<=>(const Hotkey&) const = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HotkeyDescriptor
|
||||||
|
{
|
||||||
|
Hotkey hotkey;
|
||||||
|
std::wstring id;
|
||||||
|
|
||||||
|
bool operator<(const HotkeyDescriptor& other) const
|
||||||
|
{
|
||||||
|
return hotkey < other.hotkey;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
KeyboardListener();
|
||||||
|
|
||||||
|
void Start();
|
||||||
|
void Stop();
|
||||||
|
void SetHotkeyAction(bool win, bool ctrl, bool shift, bool alt, uint8_t key, hstring const& id);
|
||||||
|
void ClearHotkey(hstring const& id);
|
||||||
|
void ClearHotkeys();
|
||||||
|
void SetProcessCommand(ProcessCommand processCommand);
|
||||||
|
|
||||||
|
static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
private:
|
||||||
|
LRESULT CALLBACK DoLowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
static inline KeyboardListener* s_instance;
|
||||||
|
HHOOK s_llKeyboardHook = nullptr;
|
||||||
|
|
||||||
|
// Max DWORD for key code to disable keys.
|
||||||
|
const DWORD VK_DISABLED = 0x100;
|
||||||
|
DWORD vkCodePressed = VK_DISABLED;
|
||||||
|
|
||||||
|
std::multiset<HotkeyDescriptor> hotkeyDescriptors;
|
||||||
|
std::mutex mutex;
|
||||||
|
|
||||||
|
std::function<void(hstring const&)> m_processCommandCb;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace winrt::CmdPalKeyboardService::factory_implementation
|
||||||
|
{
|
||||||
|
struct KeyboardListener : KeyboardListenerT<KeyboardListener, implementation::KeyboardListener>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
namespace CmdPalKeyboardService
|
||||||
|
{
|
||||||
|
[version(1.0), uuid(78ab07cd-e128-4e73-86aa-e48e6b6d01ff)] delegate void ProcessCommand(String id);
|
||||||
|
|
||||||
|
[default_interface] runtimeclass KeyboardListener {
|
||||||
|
KeyboardListener();
|
||||||
|
void Start();
|
||||||
|
void Stop();
|
||||||
|
|
||||||
|
void SetHotkeyAction(Boolean win, Boolean ctrl, Boolean shift, Boolean alt, UInt8 key, String id);
|
||||||
|
void ClearHotkey(String id);
|
||||||
|
void ClearHotkeys();
|
||||||
|
void SetProcessCommand(ProcessCommand processCommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
453
src/modules/Deux/UI/CmdPalKeyboardService/KeyboardListener_h.h
Normal file
453
src/modules/Deux/UI/CmdPalKeyboardService/KeyboardListener_h.h
Normal file
@@ -0,0 +1,453 @@
|
|||||||
|
/* Header file automatically generated from KeyboardListener.idl */
|
||||||
|
/*
|
||||||
|
* File built with Microsoft(R) MIDLRT Compiler Engine Version 10.00.0231
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma warning( disable: 4049 ) /* more than 64k source lines */
|
||||||
|
|
||||||
|
/* verify that the <rpcndr.h> version is high enough to compile this file*/
|
||||||
|
#ifndef __REQUIRED_RPCNDR_H_VERSION__
|
||||||
|
#define __REQUIRED_RPCNDR_H_VERSION__ 500
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* verify that the <rpcsal.h> version is high enough to compile this file*/
|
||||||
|
#ifndef __REQUIRED_RPCSAL_H_VERSION__
|
||||||
|
#define __REQUIRED_RPCSAL_H_VERSION__ 100
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <rpc.h>
|
||||||
|
#include <rpcndr.h>
|
||||||
|
|
||||||
|
#ifndef __RPCNDR_H_VERSION__
|
||||||
|
#error this stub requires an updated version of <rpcndr.h>
|
||||||
|
#endif /* __RPCNDR_H_VERSION__ */
|
||||||
|
|
||||||
|
#ifndef COM_NO_WINDOWS_H
|
||||||
|
#include <windows.h>
|
||||||
|
#include <ole2.h>
|
||||||
|
#endif /*COM_NO_WINDOWS_H*/
|
||||||
|
#ifndef __KeyboardListener_h_h__
|
||||||
|
#define __KeyboardListener_h_h__
|
||||||
|
#ifndef __KeyboardListener_h_p_h__
|
||||||
|
#define __KeyboardListener_h_p_h__
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Ensure that the setting of the /ns_prefix command line switch is consistent for all headers.
|
||||||
|
// If you get an error from the compiler indicating "warning C4005: 'CHECK_NS_PREFIX_STATE': macro redefinition", this
|
||||||
|
// indicates that you have included two different headers with different settings for the /ns_prefix MIDL command line switch
|
||||||
|
#if !defined(DISABLE_NS_PREFIX_CHECKS)
|
||||||
|
#define CHECK_NS_PREFIX_STATE "always"
|
||||||
|
#endif // !defined(DISABLE_NS_PREFIX_CHECKS)
|
||||||
|
|
||||||
|
|
||||||
|
#pragma push_macro("MIDL_CONST_ID")
|
||||||
|
#undef MIDL_CONST_ID
|
||||||
|
#define MIDL_CONST_ID const __declspec(selectany)
|
||||||
|
|
||||||
|
|
||||||
|
// Header files for imported files
|
||||||
|
#include "winrtbase.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.AI.MachineLearning.MachineLearningContract\5.0.0.0\Windows.AI.MachineLearning.MachineLearningContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.AI.MachineLearning.Preview.MachineLearningPreviewContract\2.0.0.0\Windows.AI.MachineLearning.Preview.MachineLearningPreviewContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.ApplicationModel.Calls.Background.CallsBackgroundContract\4.0.0.0\Windows.ApplicationModel.Calls.Background.CallsBackgroundContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.ApplicationModel.Calls.CallsPhoneContract\7.0.0.0\Windows.ApplicationModel.Calls.CallsPhoneContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.ApplicationModel.Calls.CallsVoipContract\5.0.0.0\Windows.ApplicationModel.Calls.CallsVoipContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.ApplicationModel.CommunicationBlocking.CommunicationBlockingContract\2.0.0.0\Windows.ApplicationModel.CommunicationBlocking.CommunicationBlockingContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.ApplicationModel.SocialInfo.SocialInfoContract\2.0.0.0\Windows.ApplicationModel.SocialInfo.SocialInfoContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.ApplicationModel.StartupTaskContract\3.0.0.0\Windows.ApplicationModel.StartupTaskContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.Devices.Custom.CustomDeviceContract\1.0.0.0\Windows.Devices.Custom.CustomDeviceContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.Devices.DevicesLowLevelContract\3.0.0.0\Windows.Devices.DevicesLowLevelContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.Devices.Printers.PrintersContract\1.0.0.0\Windows.Devices.Printers.PrintersContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.Devices.SmartCards.SmartCardBackgroundTriggerContract\3.0.0.0\Windows.Devices.SmartCards.SmartCardBackgroundTriggerContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.Devices.SmartCards.SmartCardEmulatorContract\6.0.0.0\Windows.Devices.SmartCards.SmartCardEmulatorContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.Foundation.FoundationContract\4.0.0.0\Windows.Foundation.FoundationContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.Foundation.UniversalApiContract\19.0.0.0\Windows.Foundation.UniversalApiContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.Gaming.XboxLive.StorageApiContract\1.0.0.0\Windows.Gaming.XboxLive.StorageApiContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.Graphics.Printing3D.Printing3DContract\4.0.0.0\Windows.Graphics.Printing3D.Printing3DContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.Networking.Connectivity.WwanContract\3.0.0.0\Windows.Networking.Connectivity.WwanContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.Networking.Sockets.ControlChannelTriggerContract\3.0.0.0\Windows.Networking.Sockets.ControlChannelTriggerContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.Security.Isolation.IsolatedWindowsEnvironmentContract\5.0.0.0\Windows.Security.Isolation.Isolatedwindowsenvironmentcontract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.Services.Maps.GuidanceContract\3.0.0.0\Windows.Services.Maps.GuidanceContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.Services.Maps.LocalSearchContract\4.0.0.0\Windows.Services.Maps.LocalSearchContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.Services.Store.StoreContract\4.0.0.0\Windows.Services.Store.StoreContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.Services.TargetedContent.TargetedContentContract\1.0.0.0\Windows.Services.TargetedContent.TargetedContentContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.Storage.Provider.CloudFilesContract\7.0.0.0\Windows.Storage.Provider.CloudFilesContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.System.Profile.ProfileHardwareTokenContract\1.0.0.0\Windows.System.Profile.ProfileHardwareTokenContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.System.Profile.ProfileRetailInfoContract\1.0.0.0\Windows.System.Profile.ProfileRetailInfoContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.System.Profile.ProfileSharedModeContract\2.0.0.0\Windows.System.Profile.ProfileSharedModeContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.System.Profile.SystemManufacturers.SystemManufacturersContract\3.0.0.0\Windows.System.Profile.SystemManufacturers.SystemManufacturersContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.System.SystemManagementContract\7.0.0.0\Windows.System.SystemManagementContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.UI.UIAutomation.UIAutomationContract\2.0.0.0\Windows.UI.UIAutomation.UIAutomationContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.UI.ViewManagement.ViewManagementViewScalingContract\1.0.0.0\Windows.UI.ViewManagement.ViewManagementViewScalingContract.h"
|
||||||
|
#include "C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0\Windows.UI.Xaml.Core.Direct.XamlDirectContract\5.0.0.0\Windows.UI.Xaml.Core.Direct.XamlDirectContract.h"
|
||||||
|
|
||||||
|
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||||
|
#if defined(__MIDL_USE_C_ENUM)
|
||||||
|
#define MIDL_ENUM enum
|
||||||
|
#else
|
||||||
|
#define MIDL_ENUM enum class
|
||||||
|
#endif
|
||||||
|
/* Forward Declarations */
|
||||||
|
#ifndef ____x_ABI_CCmdPalKeyboardService_CIProcessCommand_FWD_DEFINED__
|
||||||
|
#define ____x_ABI_CCmdPalKeyboardService_CIProcessCommand_FWD_DEFINED__
|
||||||
|
namespace ABI {
|
||||||
|
namespace CmdPalKeyboardService {
|
||||||
|
interface IProcessCommand;
|
||||||
|
} /* CmdPalKeyboardService */
|
||||||
|
} /* ABI */
|
||||||
|
#define __x_ABI_CCmdPalKeyboardService_CIProcessCommand ABI::CmdPalKeyboardService::IProcessCommand
|
||||||
|
|
||||||
|
#endif // ____x_ABI_CCmdPalKeyboardService_CIProcessCommand_FWD_DEFINED__
|
||||||
|
|
||||||
|
#ifndef ____x_ABI_CCmdPalKeyboardService_CIKeyboardListener_FWD_DEFINED__
|
||||||
|
#define ____x_ABI_CCmdPalKeyboardService_CIKeyboardListener_FWD_DEFINED__
|
||||||
|
namespace ABI {
|
||||||
|
namespace CmdPalKeyboardService {
|
||||||
|
interface IKeyboardListener;
|
||||||
|
} /* CmdPalKeyboardService */
|
||||||
|
} /* ABI */
|
||||||
|
#define __x_ABI_CCmdPalKeyboardService_CIKeyboardListener ABI::CmdPalKeyboardService::IKeyboardListener
|
||||||
|
|
||||||
|
#endif // ____x_ABI_CCmdPalKeyboardService_CIKeyboardListener_FWD_DEFINED__
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Delegate CmdPalKeyboardService.ProcessCommand
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#if !defined(____x_ABI_CCmdPalKeyboardService_CIProcessCommand_INTERFACE_DEFINED__)
|
||||||
|
#define ____x_ABI_CCmdPalKeyboardService_CIProcessCommand_INTERFACE_DEFINED__
|
||||||
|
namespace ABI {
|
||||||
|
namespace CmdPalKeyboardService {
|
||||||
|
/* [object, uuid("78ab07cd-e128-4e73-86aa-e48e6b6d01ff"), version] */
|
||||||
|
MIDL_INTERFACE("78ab07cd-e128-4e73-86aa-e48e6b6d01ff")
|
||||||
|
IProcessCommand : public IUnknown
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE Invoke(
|
||||||
|
/* [in] */HSTRING id
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
MIDL_CONST_ID IID & IID_IProcessCommand=__uuidof(IProcessCommand);
|
||||||
|
|
||||||
|
} /* CmdPalKeyboardService */
|
||||||
|
} /* ABI */
|
||||||
|
|
||||||
|
EXTERN_C const IID IID___x_ABI_CCmdPalKeyboardService_CIProcessCommand;
|
||||||
|
#endif /* !defined(____x_ABI_CCmdPalKeyboardService_CIProcessCommand_INTERFACE_DEFINED__) */
|
||||||
|
|
||||||
|
namespace ABI {
|
||||||
|
namespace CmdPalKeyboardService {
|
||||||
|
class KeyboardListener;
|
||||||
|
} /* CmdPalKeyboardService */
|
||||||
|
} /* ABI */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Interface CmdPalKeyboardService.IKeyboardListener
|
||||||
|
*
|
||||||
|
* Interface is a part of the implementation of type CmdPalKeyboardService.KeyboardListener
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* The IID for this interface was automatically generated by MIDLRT.
|
||||||
|
*
|
||||||
|
* Interface IID generation seed: CmdPalKeyboardService.IKeyboardListener:HRESULT Start();HRESULT Stop();HRESULT SetHotkeyAction(Boolean,Boolean,Boolean,Boolean,UInt8,String);HRESULT ClearHotkey(String);HRESULT ClearHotkeys();HRESULT SetProcessCommand(CmdPalKeyboardService.ProcessCommand*);
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#if !defined(____x_ABI_CCmdPalKeyboardService_CIKeyboardListener_INTERFACE_DEFINED__)
|
||||||
|
#define ____x_ABI_CCmdPalKeyboardService_CIKeyboardListener_INTERFACE_DEFINED__
|
||||||
|
extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_CmdPalKeyboardService_IKeyboardListener[] = L"CmdPalKeyboardService.IKeyboardListener";
|
||||||
|
namespace ABI {
|
||||||
|
namespace CmdPalKeyboardService {
|
||||||
|
/* [uuid("2ae4bb1c-96bd-5c41-a41b-f25b9523efe9"), version, object, exclusiveto] */
|
||||||
|
MIDL_INTERFACE("2ae4bb1c-96bd-5c41-a41b-f25b9523efe9")
|
||||||
|
IKeyboardListener : public IInspectable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE Start(void) = 0;
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE Stop(void) = 0;
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE SetHotkeyAction(
|
||||||
|
/* [in] */::boolean win,
|
||||||
|
/* [in] */::boolean ctrl,
|
||||||
|
/* [in] */::boolean shift,
|
||||||
|
/* [in] */::boolean alt,
|
||||||
|
/* [in] */::byte key,
|
||||||
|
/* [in] */HSTRING id
|
||||||
|
) = 0;
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE ClearHotkey(
|
||||||
|
/* [in] */HSTRING id
|
||||||
|
) = 0;
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE ClearHotkeys(void) = 0;
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE SetProcessCommand(
|
||||||
|
/* [in] */ABI::CmdPalKeyboardService::IProcessCommand * processCommand
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
MIDL_CONST_ID IID & IID_IKeyboardListener=__uuidof(IKeyboardListener);
|
||||||
|
|
||||||
|
} /* CmdPalKeyboardService */
|
||||||
|
} /* ABI */
|
||||||
|
|
||||||
|
EXTERN_C const IID IID___x_ABI_CCmdPalKeyboardService_CIKeyboardListener;
|
||||||
|
#endif /* !defined(____x_ABI_CCmdPalKeyboardService_CIKeyboardListener_INTERFACE_DEFINED__) */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Class CmdPalKeyboardService.KeyboardListener
|
||||||
|
*
|
||||||
|
* RuntimeClass can be activated.
|
||||||
|
*
|
||||||
|
* Class implements the following interfaces:
|
||||||
|
* CmdPalKeyboardService.IKeyboardListener ** Default Interface **
|
||||||
|
*
|
||||||
|
* Class Threading Model: Both Single and Multi Threaded Apartment
|
||||||
|
*
|
||||||
|
* Class Marshaling Behavior: Agile - Class is agile
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RUNTIMECLASS_CmdPalKeyboardService_KeyboardListener_DEFINED
|
||||||
|
#define RUNTIMECLASS_CmdPalKeyboardService_KeyboardListener_DEFINED
|
||||||
|
extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_CmdPalKeyboardService_KeyboardListener[] = L"CmdPalKeyboardService.KeyboardListener";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#else // !defined(__cplusplus)
|
||||||
|
/* Forward Declarations */
|
||||||
|
#ifndef ____x_ABI_CCmdPalKeyboardService_CIProcessCommand_FWD_DEFINED__
|
||||||
|
#define ____x_ABI_CCmdPalKeyboardService_CIProcessCommand_FWD_DEFINED__
|
||||||
|
typedef interface __x_ABI_CCmdPalKeyboardService_CIProcessCommand __x_ABI_CCmdPalKeyboardService_CIProcessCommand;
|
||||||
|
|
||||||
|
#endif // ____x_ABI_CCmdPalKeyboardService_CIProcessCommand_FWD_DEFINED__
|
||||||
|
|
||||||
|
#ifndef ____x_ABI_CCmdPalKeyboardService_CIKeyboardListener_FWD_DEFINED__
|
||||||
|
#define ____x_ABI_CCmdPalKeyboardService_CIKeyboardListener_FWD_DEFINED__
|
||||||
|
typedef interface __x_ABI_CCmdPalKeyboardService_CIKeyboardListener __x_ABI_CCmdPalKeyboardService_CIKeyboardListener;
|
||||||
|
|
||||||
|
#endif // ____x_ABI_CCmdPalKeyboardService_CIKeyboardListener_FWD_DEFINED__
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Delegate CmdPalKeyboardService.ProcessCommand
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#if !defined(____x_ABI_CCmdPalKeyboardService_CIProcessCommand_INTERFACE_DEFINED__)
|
||||||
|
#define ____x_ABI_CCmdPalKeyboardService_CIProcessCommand_INTERFACE_DEFINED__
|
||||||
|
/* [object, uuid("78ab07cd-e128-4e73-86aa-e48e6b6d01ff"), version] */
|
||||||
|
typedef struct __x_ABI_CCmdPalKeyboardService_CIProcessCommandVtbl
|
||||||
|
{
|
||||||
|
BEGIN_INTERFACE
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
|
||||||
|
__RPC__in __x_ABI_CCmdPalKeyboardService_CIProcessCommand * This,
|
||||||
|
/* [in] */ __RPC__in REFIID riid,
|
||||||
|
/* [annotation][iid_is][out] */
|
||||||
|
_COM_Outptr_ void **ppvObject);
|
||||||
|
|
||||||
|
ULONG ( STDMETHODCALLTYPE *AddRef )(
|
||||||
|
__RPC__in __x_ABI_CCmdPalKeyboardService_CIProcessCommand * This);
|
||||||
|
|
||||||
|
ULONG ( STDMETHODCALLTYPE *Release )(
|
||||||
|
__RPC__in __x_ABI_CCmdPalKeyboardService_CIProcessCommand * This);
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *Invoke )(
|
||||||
|
__x_ABI_CCmdPalKeyboardService_CIProcessCommand * This,
|
||||||
|
/* [in] */HSTRING id
|
||||||
|
);
|
||||||
|
END_INTERFACE
|
||||||
|
|
||||||
|
} __x_ABI_CCmdPalKeyboardService_CIProcessCommandVtbl;
|
||||||
|
|
||||||
|
interface __x_ABI_CCmdPalKeyboardService_CIProcessCommand
|
||||||
|
{
|
||||||
|
CONST_VTBL struct __x_ABI_CCmdPalKeyboardService_CIProcessCommandVtbl *lpVtbl;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef COBJMACROS
|
||||||
|
#define __x_ABI_CCmdPalKeyboardService_CIProcessCommand_QueryInterface(This,riid,ppvObject) \
|
||||||
|
( (This)->lpVtbl->QueryInterface(This,riid,ppvObject) )
|
||||||
|
|
||||||
|
#define __x_ABI_CCmdPalKeyboardService_CIProcessCommand_AddRef(This) \
|
||||||
|
( (This)->lpVtbl->AddRef(This) )
|
||||||
|
|
||||||
|
#define __x_ABI_CCmdPalKeyboardService_CIProcessCommand_Release(This) \
|
||||||
|
( (This)->lpVtbl->Release(This) )
|
||||||
|
|
||||||
|
#define __x_ABI_CCmdPalKeyboardService_CIProcessCommand_Invoke(This,id) \
|
||||||
|
( (This)->lpVtbl->Invoke(This,id) )
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* COBJMACROS */
|
||||||
|
|
||||||
|
|
||||||
|
EXTERN_C const IID IID___x_ABI_CCmdPalKeyboardService_CIProcessCommand;
|
||||||
|
#endif /* !defined(____x_ABI_CCmdPalKeyboardService_CIProcessCommand_INTERFACE_DEFINED__) */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Interface CmdPalKeyboardService.IKeyboardListener
|
||||||
|
*
|
||||||
|
* Interface is a part of the implementation of type CmdPalKeyboardService.KeyboardListener
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* The IID for this interface was automatically generated by MIDLRT.
|
||||||
|
*
|
||||||
|
* Interface IID generation seed: CmdPalKeyboardService.IKeyboardListener:HRESULT Start();HRESULT Stop();HRESULT SetHotkeyAction(Boolean,Boolean,Boolean,Boolean,UInt8,String);HRESULT ClearHotkey(String);HRESULT ClearHotkeys();HRESULT SetProcessCommand(CmdPalKeyboardService.ProcessCommand*);
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#if !defined(____x_ABI_CCmdPalKeyboardService_CIKeyboardListener_INTERFACE_DEFINED__)
|
||||||
|
#define ____x_ABI_CCmdPalKeyboardService_CIKeyboardListener_INTERFACE_DEFINED__
|
||||||
|
extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_CmdPalKeyboardService_IKeyboardListener[] = L"CmdPalKeyboardService.IKeyboardListener";
|
||||||
|
/* [uuid("2ae4bb1c-96bd-5c41-a41b-f25b9523efe9"), version, object, exclusiveto] */
|
||||||
|
typedef struct __x_ABI_CCmdPalKeyboardService_CIKeyboardListenerVtbl
|
||||||
|
{
|
||||||
|
BEGIN_INTERFACE
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *QueryInterface)(
|
||||||
|
__RPC__in __x_ABI_CCmdPalKeyboardService_CIKeyboardListener * This,
|
||||||
|
/* [in] */ __RPC__in REFIID riid,
|
||||||
|
/* [annotation][iid_is][out] */
|
||||||
|
_COM_Outptr_ void **ppvObject
|
||||||
|
);
|
||||||
|
|
||||||
|
ULONG ( STDMETHODCALLTYPE *AddRef )(
|
||||||
|
__RPC__in __x_ABI_CCmdPalKeyboardService_CIKeyboardListener * This
|
||||||
|
);
|
||||||
|
|
||||||
|
ULONG ( STDMETHODCALLTYPE *Release )(
|
||||||
|
__RPC__in __x_ABI_CCmdPalKeyboardService_CIKeyboardListener * This
|
||||||
|
);
|
||||||
|
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *GetIids )(
|
||||||
|
__RPC__in __x_ABI_CCmdPalKeyboardService_CIKeyboardListener * This,
|
||||||
|
/* [out] */ __RPC__out ULONG *iidCount,
|
||||||
|
/* [size_is][size_is][out] */ __RPC__deref_out_ecount_full_opt(*iidCount) IID **iids
|
||||||
|
);
|
||||||
|
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *GetRuntimeClassName )(
|
||||||
|
__RPC__in __x_ABI_CCmdPalKeyboardService_CIKeyboardListener * This,
|
||||||
|
/* [out] */ __RPC__deref_out_opt HSTRING *className
|
||||||
|
);
|
||||||
|
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *GetTrustLevel )(
|
||||||
|
__RPC__in __x_ABI_CCmdPalKeyboardService_CIKeyboardListener * This,
|
||||||
|
/* [OUT ] */ __RPC__out TrustLevel *trustLevel
|
||||||
|
);
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *Start )(
|
||||||
|
__x_ABI_CCmdPalKeyboardService_CIKeyboardListener * This
|
||||||
|
);
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *Stop )(
|
||||||
|
__x_ABI_CCmdPalKeyboardService_CIKeyboardListener * This
|
||||||
|
);
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *SetHotkeyAction )(
|
||||||
|
__x_ABI_CCmdPalKeyboardService_CIKeyboardListener * This,
|
||||||
|
/* [in] */boolean win,
|
||||||
|
/* [in] */boolean ctrl,
|
||||||
|
/* [in] */boolean shift,
|
||||||
|
/* [in] */boolean alt,
|
||||||
|
/* [in] */byte key,
|
||||||
|
/* [in] */HSTRING id
|
||||||
|
);
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *ClearHotkey )(
|
||||||
|
__x_ABI_CCmdPalKeyboardService_CIKeyboardListener * This,
|
||||||
|
/* [in] */HSTRING id
|
||||||
|
);
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *ClearHotkeys )(
|
||||||
|
__x_ABI_CCmdPalKeyboardService_CIKeyboardListener * This
|
||||||
|
);
|
||||||
|
HRESULT ( STDMETHODCALLTYPE *SetProcessCommand )(
|
||||||
|
__x_ABI_CCmdPalKeyboardService_CIKeyboardListener * This,
|
||||||
|
/* [in] */__x_ABI_CCmdPalKeyboardService_CIProcessCommand * processCommand
|
||||||
|
);
|
||||||
|
END_INTERFACE
|
||||||
|
|
||||||
|
} __x_ABI_CCmdPalKeyboardService_CIKeyboardListenerVtbl;
|
||||||
|
|
||||||
|
interface __x_ABI_CCmdPalKeyboardService_CIKeyboardListener
|
||||||
|
{
|
||||||
|
CONST_VTBL struct __x_ABI_CCmdPalKeyboardService_CIKeyboardListenerVtbl *lpVtbl;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef COBJMACROS
|
||||||
|
#define __x_ABI_CCmdPalKeyboardService_CIKeyboardListener_QueryInterface(This,riid,ppvObject) \
|
||||||
|
( (This)->lpVtbl->QueryInterface(This,riid,ppvObject) )
|
||||||
|
|
||||||
|
#define __x_ABI_CCmdPalKeyboardService_CIKeyboardListener_AddRef(This) \
|
||||||
|
( (This)->lpVtbl->AddRef(This) )
|
||||||
|
|
||||||
|
#define __x_ABI_CCmdPalKeyboardService_CIKeyboardListener_Release(This) \
|
||||||
|
( (This)->lpVtbl->Release(This) )
|
||||||
|
|
||||||
|
#define __x_ABI_CCmdPalKeyboardService_CIKeyboardListener_GetIids(This,iidCount,iids) \
|
||||||
|
( (This)->lpVtbl->GetIids(This,iidCount,iids) )
|
||||||
|
|
||||||
|
#define __x_ABI_CCmdPalKeyboardService_CIKeyboardListener_GetRuntimeClassName(This,className) \
|
||||||
|
( (This)->lpVtbl->GetRuntimeClassName(This,className) )
|
||||||
|
|
||||||
|
#define __x_ABI_CCmdPalKeyboardService_CIKeyboardListener_GetTrustLevel(This,trustLevel) \
|
||||||
|
( (This)->lpVtbl->GetTrustLevel(This,trustLevel) )
|
||||||
|
|
||||||
|
#define __x_ABI_CCmdPalKeyboardService_CIKeyboardListener_Start(This) \
|
||||||
|
( (This)->lpVtbl->Start(This) )
|
||||||
|
|
||||||
|
#define __x_ABI_CCmdPalKeyboardService_CIKeyboardListener_Stop(This) \
|
||||||
|
( (This)->lpVtbl->Stop(This) )
|
||||||
|
|
||||||
|
#define __x_ABI_CCmdPalKeyboardService_CIKeyboardListener_SetHotkeyAction(This,win,ctrl,shift,alt,key,id) \
|
||||||
|
( (This)->lpVtbl->SetHotkeyAction(This,win,ctrl,shift,alt,key,id) )
|
||||||
|
|
||||||
|
#define __x_ABI_CCmdPalKeyboardService_CIKeyboardListener_ClearHotkey(This,id) \
|
||||||
|
( (This)->lpVtbl->ClearHotkey(This,id) )
|
||||||
|
|
||||||
|
#define __x_ABI_CCmdPalKeyboardService_CIKeyboardListener_ClearHotkeys(This) \
|
||||||
|
( (This)->lpVtbl->ClearHotkeys(This) )
|
||||||
|
|
||||||
|
#define __x_ABI_CCmdPalKeyboardService_CIKeyboardListener_SetProcessCommand(This,processCommand) \
|
||||||
|
( (This)->lpVtbl->SetProcessCommand(This,processCommand) )
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* COBJMACROS */
|
||||||
|
|
||||||
|
|
||||||
|
EXTERN_C const IID IID___x_ABI_CCmdPalKeyboardService_CIKeyboardListener;
|
||||||
|
#endif /* !defined(____x_ABI_CCmdPalKeyboardService_CIKeyboardListener_INTERFACE_DEFINED__) */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Class CmdPalKeyboardService.KeyboardListener
|
||||||
|
*
|
||||||
|
* RuntimeClass can be activated.
|
||||||
|
*
|
||||||
|
* Class implements the following interfaces:
|
||||||
|
* CmdPalKeyboardService.IKeyboardListener ** Default Interface **
|
||||||
|
*
|
||||||
|
* Class Threading Model: Both Single and Multi Threaded Apartment
|
||||||
|
*
|
||||||
|
* Class Marshaling Behavior: Agile - Class is agile
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RUNTIMECLASS_CmdPalKeyboardService_KeyboardListener_DEFINED
|
||||||
|
#define RUNTIMECLASS_CmdPalKeyboardService_KeyboardListener_DEFINED
|
||||||
|
extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_CmdPalKeyboardService_KeyboardListener[] = L"CmdPalKeyboardService.KeyboardListener";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif // defined(__cplusplus)
|
||||||
|
#pragma pop_macro("MIDL_CONST_ID")
|
||||||
|
#endif // __KeyboardListener_h_p_h__
|
||||||
|
|
||||||
|
#endif // __KeyboardListener_h_h__
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?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>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
|
||||||
|
</packages>
|
||||||
1
src/modules/Deux/UI/CmdPalKeyboardService/pch.cpp
Normal file
1
src/modules/Deux/UI/CmdPalKeyboardService/pch.cpp
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#include "pch.h"
|
||||||
4
src/modules/Deux/UI/CmdPalKeyboardService/pch.h
Normal file
4
src/modules/Deux/UI/CmdPalKeyboardService/pch.h
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Unknwn.h>
|
||||||
|
#include <winrt/Windows.Foundation.h>
|
||||||
|
#include <winrt/Windows.Foundation.Collections.h>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation
|
||||||
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
namespace Microsoft.CommandPalette.UI.Models;
|
||||||
|
|
||||||
|
public class CommandHotKey(Hotkey? hotkey, string commandId)
|
||||||
|
{
|
||||||
|
public string CommandId { get; set; } = commandId;
|
||||||
|
|
||||||
|
public Hotkey? Hotkey { get; set; } = hotkey;
|
||||||
|
}
|
||||||
@@ -9,11 +9,11 @@ using Microsoft.CommandPalette.UI.Models.Helpers;
|
|||||||
|
|
||||||
namespace Microsoft.CommandPalette.UI.Models;
|
namespace Microsoft.CommandPalette.UI.Models;
|
||||||
|
|
||||||
public record HotkeySettings
|
public record Hotkey
|
||||||
{
|
{
|
||||||
private const int VKTAB = 0x09;
|
private const int VKTAB = 0x09;
|
||||||
|
|
||||||
public HotkeySettings()
|
public Hotkey()
|
||||||
{
|
{
|
||||||
Win = false;
|
Win = false;
|
||||||
Ctrl = false;
|
Ctrl = false;
|
||||||
@@ -23,14 +23,14 @@ public record HotkeySettings
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="HotkeySettings"/> class.
|
/// Initializes a new instance of the <see cref="Hotkey"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="win">Should Windows key be used</param>
|
/// <param name="win">Should Windows key be used</param>
|
||||||
/// <param name="ctrl">Should Ctrl key be used</param>
|
/// <param name="ctrl">Should Ctrl key be used</param>
|
||||||
/// <param name="alt">Should Alt key be used</param>
|
/// <param name="alt">Should Alt key be used</param>
|
||||||
/// <param name="shift">Should Shift key be used</param>
|
/// <param name="shift">Should Shift key be used</param>
|
||||||
/// <param name="code">Go to https://learn.microsoft.com/windows/win32/inputdev/virtual-key-codes to see list of v-keys</param>
|
/// <param name="code">Go to https://learn.microsoft.com/windows/win32/inputdev/virtual-key-codes to see list of v-keys</param>
|
||||||
public HotkeySettings(bool win, bool ctrl, bool alt, bool shift, int code)
|
public Hotkey(bool win, bool ctrl, bool alt, bool shift, int code)
|
||||||
{
|
{
|
||||||
Win = win;
|
Win = win;
|
||||||
Ctrl = ctrl;
|
Ctrl = ctrl;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation
|
||||||
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using Windows.System;
|
||||||
|
|
||||||
|
namespace Microsoft.CommandPalette.UI.Models;
|
||||||
|
|
||||||
|
public class KeyPressedEventArgs(VirtualKey key) : EventArgs
|
||||||
|
{
|
||||||
|
public VirtualKey Key { get; } = key;
|
||||||
|
}
|
||||||
@@ -11,9 +11,9 @@ public partial class SettingsModel
|
|||||||
* Make sure that any new types you add are added to JsonSerializationContext!
|
* Make sure that any new types you add are added to JsonSerializationContext!
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
public static HotkeySettings DefaultActivationShortcut { get; } = new HotkeySettings(true, false, true, false, 0x20); // win+alt+space
|
public static Hotkey DefaultActivationShortcut { get; } = new Hotkey(true, false, true, false, 0x20); // win+alt+space
|
||||||
|
|
||||||
public HotkeySettings? Hotkey { get; set; } = DefaultActivationShortcut;
|
public Hotkey? Hotkey { get; set; } = DefaultActivationShortcut;
|
||||||
|
|
||||||
public bool UseLowLevelGlobalHotkey { get; set; }
|
public bool UseLowLevelGlobalHotkey { get; set; }
|
||||||
|
|
||||||
@@ -40,4 +40,6 @@ public partial class SettingsModel
|
|||||||
public WindowPosition? LastWindowPosition { get; set; }
|
public WindowPosition? LastWindowPosition { get; set; }
|
||||||
|
|
||||||
public TimeSpan AutoGoHomeInterval { get; set; } = Timeout.InfiniteTimeSpan;
|
public TimeSpan AutoGoHomeInterval { get; set; } = Timeout.InfiniteTimeSpan;
|
||||||
|
|
||||||
|
public List<CommandHotKey> CommandHotkeys { get; set; } = [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,5 +6,4 @@ namespace Microsoft.CommandPalette.UI.Services.Extensions;
|
|||||||
|
|
||||||
public interface IExtensionService
|
public interface IExtensionService
|
||||||
{
|
{
|
||||||
CommandViewModel
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,257 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation
|
||||||
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using CmdPalKeyboardService;
|
||||||
|
using Microsoft.CommandPalette.UI.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Windows.System;
|
||||||
|
using Windows.Win32;
|
||||||
|
using Windows.Win32.Foundation;
|
||||||
|
using Windows.Win32.UI.Input.KeyboardAndMouse;
|
||||||
|
using Windows.Win32.UI.WindowsAndMessaging;
|
||||||
|
|
||||||
|
namespace Microsoft.CommandPalette.UI.Services;
|
||||||
|
|
||||||
|
public partial class KeyboardService : IDisposable
|
||||||
|
{
|
||||||
|
private readonly KeyboardListener _keyboardListener;
|
||||||
|
private readonly SettingsService _settingsService;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
private readonly List<CommandHotKey> _hotkeys = [];
|
||||||
|
|
||||||
|
private HWND _hwnd;
|
||||||
|
private bool _disposed;
|
||||||
|
private UnhookWindowsHookExSafeHandle? _handle;
|
||||||
|
private HOOKPROC? _hookProc; // Keep reference to prevent GC collection
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event that is raised when a key is pressed down.
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<KeyPressedEventArgs>? KeyPressed;
|
||||||
|
|
||||||
|
public KeyboardService(SettingsService settingsService, ILogger logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_settingsService = settingsService;
|
||||||
|
_keyboardListener = new KeyboardListener();
|
||||||
|
_keyboardListener.Start();
|
||||||
|
|
||||||
|
StartListening();
|
||||||
|
|
||||||
|
_settingsService.SettingsChanged += SettingsChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetProcessCommand(HWND hwnd, ProcessCommand processCommand)
|
||||||
|
{
|
||||||
|
_hwnd = hwnd;
|
||||||
|
_keyboardListener.SetProcessCommand(processCommand);
|
||||||
|
SetupHotkeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SettingsChanged(SettingsModel sender, object? e)
|
||||||
|
{
|
||||||
|
SetupHotkeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UnregisterHotkeys()
|
||||||
|
{
|
||||||
|
_keyboardListener.ClearHotkeys();
|
||||||
|
|
||||||
|
while (_hotkeys.Count > 0)
|
||||||
|
{
|
||||||
|
PInvoke.UnregisterHotKey(_hwnd, _hotkeys.Count - 1);
|
||||||
|
_hotkeys.RemoveAt(_hotkeys.Count - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupHotkeys()
|
||||||
|
{
|
||||||
|
UnregisterHotkeys();
|
||||||
|
|
||||||
|
var globalHotkey = _settingsService.CurrentSettings.Hotkey;
|
||||||
|
if (globalHotkey is not null)
|
||||||
|
{
|
||||||
|
if (_settingsService.CurrentSettings.UseLowLevelGlobalHotkey)
|
||||||
|
{
|
||||||
|
_keyboardListener.SetHotkeyAction(globalHotkey.Win, globalHotkey.Ctrl, globalHotkey.Shift, globalHotkey.Alt, (byte)globalHotkey.Code, string.Empty);
|
||||||
|
_hotkeys.Add(new(globalHotkey, string.Empty));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var vk = globalHotkey.Code;
|
||||||
|
var modifiers =
|
||||||
|
(globalHotkey.Alt ? HOT_KEY_MODIFIERS.MOD_ALT : 0) |
|
||||||
|
(globalHotkey.Ctrl ? HOT_KEY_MODIFIERS.MOD_CONTROL : 0) |
|
||||||
|
(globalHotkey.Shift ? HOT_KEY_MODIFIERS.MOD_SHIFT : 0) |
|
||||||
|
(globalHotkey.Win ? HOT_KEY_MODIFIERS.MOD_WIN : 0)
|
||||||
|
;
|
||||||
|
|
||||||
|
var success = PInvoke.RegisterHotKey(_hwnd, _hotkeys.Count, modifiers, (uint)vk);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
_hotkeys.Add(new(globalHotkey, string.Empty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var commandHotkey in _settingsService.CurrentSettings.CommandHotkeys)
|
||||||
|
{
|
||||||
|
var key = commandHotkey.Hotkey;
|
||||||
|
if (key is not null)
|
||||||
|
{
|
||||||
|
if (_settingsService.CurrentSettings.UseLowLevelGlobalHotkey)
|
||||||
|
{
|
||||||
|
_keyboardListener.SetHotkeyAction(key.Win, key.Ctrl, key.Shift, key.Alt, (byte)key.Code, commandHotkey.CommandId);
|
||||||
|
_hotkeys.Add(new(commandHotkey.Hotkey, commandHotkey.CommandId));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var vk = key.Code;
|
||||||
|
var modifiers =
|
||||||
|
(key.Alt ? HOT_KEY_MODIFIERS.MOD_ALT : 0) |
|
||||||
|
(key.Ctrl ? HOT_KEY_MODIFIERS.MOD_CONTROL : 0) |
|
||||||
|
(key.Shift ? HOT_KEY_MODIFIERS.MOD_SHIFT : 0) |
|
||||||
|
(key.Win ? HOT_KEY_MODIFIERS.MOD_WIN : 0)
|
||||||
|
;
|
||||||
|
var success = PInvoke.RegisterHotKey(_hwnd, _hotkeys.Count, modifiers, (uint)vk);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
_hotkeys.Add(commandHotkey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool StartListening()
|
||||||
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RegisterKeyboardHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log_FailedToRegisterHook(ex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RegisterKeyboardHook()
|
||||||
|
{
|
||||||
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
|
if (_handle is not null && !_handle.IsInvalid)
|
||||||
|
{
|
||||||
|
// Hook is already set
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_hookProc = KeyEventHook;
|
||||||
|
if (!SetWindowKeyHook(_hookProc))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Failed to register keyboard hook.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SetWindowKeyHook(HOOKPROC hookProc)
|
||||||
|
{
|
||||||
|
if (_handle is not null && !_handle.IsInvalid)
|
||||||
|
{
|
||||||
|
// Hook is already set
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_handle = PInvoke.SetWindowsHookEx(
|
||||||
|
WINDOWS_HOOK_ID.WH_KEYBOARD,
|
||||||
|
hookProc,
|
||||||
|
PInvoke.GetModuleHandle(null),
|
||||||
|
PInvoke.GetCurrentThreadId());
|
||||||
|
|
||||||
|
// Check if the hook was successfully set
|
||||||
|
return _handle is not null && !_handle.IsInvalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsKeyDownHook(LPARAM lParam)
|
||||||
|
{
|
||||||
|
// The 30th bit tells what the previous key state is with 0 being the "UP" state
|
||||||
|
// For more info see https://learn.microsoft.com/windows/win32/winmsg/keyboardproc#lparam-in
|
||||||
|
return ((lParam.Value >> 30) & 1) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LRESULT KeyEventHook(int nCode, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (nCode >= 0 && IsKeyDownHook(lParam))
|
||||||
|
{
|
||||||
|
InvokeKeyDown((VirtualKey)wParam.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log_ErrorInvokingKeyDownHook(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call next hook in chain - pass null as first parameter for current hook
|
||||||
|
return PInvoke.CallNextHookEx(null, nCode, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InvokeKeyDown(VirtualKey virtualKey)
|
||||||
|
{
|
||||||
|
if (!_disposed)
|
||||||
|
{
|
||||||
|
KeyPressed?.Invoke(this, new KeyPressedEventArgs(virtualKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
UnregisterHotkeys();
|
||||||
|
|
||||||
|
if (_settingsService is not null)
|
||||||
|
{
|
||||||
|
_settingsService.SettingsChanged -= SettingsChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UnregisterKeyboardHook()
|
||||||
|
{
|
||||||
|
if (_handle is not null && !_handle.IsInvalid)
|
||||||
|
{
|
||||||
|
// The SafeHandle should automatically call UnhookWindowsHookEx when disposed
|
||||||
|
_handle.Dispose();
|
||||||
|
_handle = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_hookProc = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!_disposed)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
UnregisterKeyboardHook();
|
||||||
|
}
|
||||||
|
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[LoggerMessage(Level = LogLevel.Error, Message = "Failed to register hook")]
|
||||||
|
partial void Log_FailedToRegisterHook(Exception ex);
|
||||||
|
|
||||||
|
[LoggerMessage(Level = LogLevel.Error, Message = "Failed when invoking key down keyboard hook event")]
|
||||||
|
partial void Log_ErrorInvokingKeyDownHook(Exception ex);
|
||||||
|
}
|
||||||
@@ -26,10 +26,22 @@
|
|||||||
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" />
|
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<!-- This lets us actually reference types from Microsoft.Terminal.UI -->
|
||||||
|
<CsWinRTIncludes>Microsoft.Terminal.UI;CmdPalKeyboardService</CsWinRTIncludes>
|
||||||
|
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
<ProjectReference Include="..\..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||||
<ProjectReference Include="..\..\SDK\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
|
<ProjectReference Include="..\..\SDK\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
|
||||||
<ProjectReference Include="..\Microsoft.CommandPalette.UI.Models\Microsoft.CommandPalette.UI.Models.csproj" />
|
<ProjectReference Include="..\Microsoft.CommandPalette.UI.Models\Microsoft.CommandPalette.UI.Models.csproj" />
|
||||||
|
|
||||||
|
<ProjectReference Include="..\CmdPalKeyboardService\CmdPalKeyboardService.vcxproj">
|
||||||
|
<ReferenceOutputAssembly>True</ReferenceOutputAssembly>
|
||||||
|
<Private>True</Private>
|
||||||
|
<CopyLocalSatelliteAssemblies>True</CopyLocalSatelliteAssemblies>
|
||||||
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -80,6 +80,7 @@ public partial class App : Application
|
|||||||
services.AddSingleton<IExtensionService, JsonRPCExtensionService>();
|
services.AddSingleton<IExtensionService, JsonRPCExtensionService>();
|
||||||
|
|
||||||
// Register services
|
// Register services
|
||||||
|
services.AddSingleton<KeyboardService>();
|
||||||
services.AddSingleton<TrayIconService>();
|
services.AddSingleton<TrayIconService>();
|
||||||
|
|
||||||
// Register view models
|
// Register view models
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ using Windows.Win32.Foundation;
|
|||||||
using Windows.Win32.Graphics.Dwm;
|
using Windows.Win32.Graphics.Dwm;
|
||||||
using Windows.Win32.Graphics.Gdi;
|
using Windows.Win32.Graphics.Gdi;
|
||||||
using Windows.Win32.UI.HiDpi;
|
using Windows.Win32.UI.HiDpi;
|
||||||
using Windows.Win32.UI.Input.KeyboardAndMouse;
|
|
||||||
using Windows.Win32.UI.WindowsAndMessaging;
|
using Windows.Win32.UI.WindowsAndMessaging;
|
||||||
using WinRT;
|
using WinRT;
|
||||||
using WinUIEx;
|
using WinUIEx;
|
||||||
@@ -50,6 +49,7 @@ public sealed partial class MainWindow : WindowEx,
|
|||||||
private readonly ShellPage _shellPage;
|
private readonly ShellPage _shellPage;
|
||||||
private readonly SettingsService _settingsService;
|
private readonly SettingsService _settingsService;
|
||||||
private readonly TrayIconService _trayIconService;
|
private readonly TrayIconService _trayIconService;
|
||||||
|
private readonly KeyboardService _keyboardService;
|
||||||
private const int DefaultWidth = 800;
|
private const int DefaultWidth = 800;
|
||||||
private const int DefaultHeight = 480;
|
private const int DefaultHeight = 480;
|
||||||
|
|
||||||
@@ -61,9 +61,6 @@ public sealed partial class MainWindow : WindowEx,
|
|||||||
private readonly WNDPROC? _hotkeyWndProc;
|
private readonly WNDPROC? _hotkeyWndProc;
|
||||||
private readonly WNDPROC? _originalWndProc;
|
private readonly WNDPROC? _originalWndProc;
|
||||||
|
|
||||||
// private readonly List<TopLevelHotkey> _hotkeys = [];
|
|
||||||
// private readonly KeyboardListener _keyboardListener;
|
|
||||||
// private readonly LocalKeyboardListener _localKeyboardListener;
|
|
||||||
private readonly HiddenOwnerWindowBehavior _hiddenOwnerBehavior = new();
|
private readonly HiddenOwnerWindowBehavior _hiddenOwnerBehavior = new();
|
||||||
private bool _ignoreHotKeyWhenFullScreen = true;
|
private bool _ignoreHotKeyWhenFullScreen = true;
|
||||||
|
|
||||||
@@ -73,7 +70,7 @@ public sealed partial class MainWindow : WindowEx,
|
|||||||
|
|
||||||
private WindowPosition _currentWindowPosition = new();
|
private WindowPosition _currentWindowPosition = new();
|
||||||
|
|
||||||
public MainWindow(ShellPage shellPage, SettingsService settingsService, TrayIconService trayIconService, ILogger logger)
|
public MainWindow(ShellPage shellPage, SettingsService settingsService, TrayIconService trayIconService, KeyboardService keyboardService, ILogger logger)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
@@ -81,6 +78,7 @@ public sealed partial class MainWindow : WindowEx,
|
|||||||
_shellPage = shellPage;
|
_shellPage = shellPage;
|
||||||
_settingsService = settingsService;
|
_settingsService = settingsService;
|
||||||
_trayIconService = trayIconService;
|
_trayIconService = trayIconService;
|
||||||
|
_keyboardService = keyboardService;
|
||||||
|
|
||||||
RootElement.Children.Add(_shellPage);
|
RootElement.Children.Add(_shellPage);
|
||||||
|
|
||||||
@@ -95,9 +93,9 @@ public sealed partial class MainWindow : WindowEx,
|
|||||||
// }
|
// }
|
||||||
_hiddenOwnerBehavior.ShowInTaskbar(this, Debugger.IsAttached);
|
_hiddenOwnerBehavior.ShowInTaskbar(this, Debugger.IsAttached);
|
||||||
|
|
||||||
// _keyboardListener = new KeyboardListener();
|
_keyboardService.KeyPressed += KeyboardService_OnKeyPressed;
|
||||||
// _keyboardListener.Start();
|
_keyboardService.SetProcessCommand(_hwnd, new CmdPalKeyboardService.ProcessCommand(HandleSummon));
|
||||||
// _keyboardListener.SetProcessCommand(new CmdPalKeyboardService.ProcessCommand(HandleSummon));
|
|
||||||
this.SetIcon();
|
this.SetIcon();
|
||||||
AppWindow.Title = RS_.GetString("AppName");
|
AppWindow.Title = RS_.GetString("AppName");
|
||||||
RestoreWindowPosition();
|
RestoreWindowPosition();
|
||||||
@@ -143,13 +141,18 @@ public sealed partial class MainWindow : WindowEx,
|
|||||||
Summon(string.Empty);
|
Summon(string.Empty);
|
||||||
});
|
});
|
||||||
|
|
||||||
// _localKeyboardListener = new LocalKeyboardListener();
|
|
||||||
// _localKeyboardListener.KeyPressed += LocalKeyboardListener_OnKeyPressed;
|
|
||||||
// _localKeyboardListener.Start();
|
|
||||||
// Force window to be created, and then cloaked. This will offset initial animation when the window is shown.
|
// Force window to be created, and then cloaked. This will offset initial animation when the window is shown.
|
||||||
HideWindow();
|
HideWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void KeyboardService_OnKeyPressed(object? sender, KeyPressedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Key == VirtualKey.GoBack)
|
||||||
|
{
|
||||||
|
WeakReferenceMessenger.Default.Send(new GoBackMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Receive(ShowWindowMessage message)
|
public void Receive(ShowWindowMessage message)
|
||||||
{
|
{
|
||||||
ShowHwnd(message.Hwnd, _settingsService.CurrentSettings.SummonOn);
|
ShowHwnd(message.Hwnd, _settingsService.CurrentSettings.SummonOn);
|
||||||
@@ -187,7 +190,7 @@ public sealed partial class MainWindow : WindowEx,
|
|||||||
WeakReferenceMessenger.Default.Send(new GoHomeMessage(WithAnimation: false, FocusSearch: false));
|
WeakReferenceMessenger.Default.Send(new GoHomeMessage(WithAnimation: false, FocusSearch: false));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void LocalKeyboardListener_OnKeyPressed(object? sender, LocalKeyboardListenerKeyPressedEventArgs e)
|
private static void KeyboardService_OnKeyPressed(object? sender, LocalKeyboardListenerKeyPressedEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Key == VirtualKey.GoBack)
|
if (e.Key == VirtualKey.GoBack)
|
||||||
{
|
{
|
||||||
@@ -266,8 +269,6 @@ public sealed partial class MainWindow : WindowEx,
|
|||||||
|
|
||||||
private void HotReloadSettings()
|
private void HotReloadSettings()
|
||||||
{
|
{
|
||||||
SetupHotkey(_settingsService.CurrentSettings);
|
|
||||||
|
|
||||||
_ignoreHotKeyWhenFullScreen = _settingsService.CurrentSettings.IgnoreShortcutWhenFullscreen;
|
_ignoreHotKeyWhenFullScreen = _settingsService.CurrentSettings.IgnoreShortcutWhenFullscreen;
|
||||||
|
|
||||||
_autoGoHomeInterval = _settingsService.CurrentSettings.AutoGoHomeInterval;
|
_autoGoHomeInterval = _settingsService.CurrentSettings.AutoGoHomeInterval;
|
||||||
@@ -634,13 +635,13 @@ public sealed partial class MainWindow : WindowEx,
|
|||||||
|
|
||||||
// var extensionService = serviceProvider.GetService<IExtensionService>()!;
|
// var extensionService = serviceProvider.GetService<IExtensionService>()!;
|
||||||
// extensionService.SignalStopExtensionsAsync();
|
// extensionService.SignalStopExtensionsAsync();
|
||||||
// _trayIconService.Destroy();
|
_trayIconService.Destroy();
|
||||||
|
|
||||||
// WinUI bug is causing a crash on shutdown when FailFastOnErrors is set to true (#51773592).
|
// WinUI bug is causing a crash on shutdown when FailFastOnErrors is set to true (#51773592).
|
||||||
// Workaround by turning it off before shutdown.
|
// Workaround by turning it off before shutdown.
|
||||||
App.Current.DebugSettings.FailFastOnErrors = false;
|
App.Current.DebugSettings.FailFastOnErrors = false;
|
||||||
|
|
||||||
// _localKeyboardListener.Dispose();
|
_keyboardService.Dispose();
|
||||||
DisposeAcrylic();
|
DisposeAcrylic();
|
||||||
|
|
||||||
// _keyboardListener.Stop();
|
// _keyboardListener.Stop();
|
||||||
@@ -817,76 +818,6 @@ public sealed partial class MainWindow : WindowEx,
|
|||||||
// know till the message is being handled.
|
// know till the message is being handled.
|
||||||
WeakReferenceMessenger.Default.Send<HotkeySummonMessage>(new(commandId, _hwnd));
|
WeakReferenceMessenger.Default.Send<HotkeySummonMessage>(new(commandId, _hwnd));
|
||||||
|
|
||||||
private void UnregisterHotkeys()
|
|
||||||
{
|
|
||||||
// _keyboardListener.ClearHotkeys();
|
|
||||||
|
|
||||||
// while (_hotkeys.Count > 0)
|
|
||||||
// {
|
|
||||||
// PInvoke.UnregisterHotKey(_hwnd, _hotkeys.Count - 1);
|
|
||||||
// _hotkeys.RemoveAt(_hotkeys.Count - 1);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetupHotkey(SettingsModel settings)
|
|
||||||
{
|
|
||||||
UnregisterHotkeys();
|
|
||||||
|
|
||||||
var globalHotkey = settings.Hotkey;
|
|
||||||
if (globalHotkey is not null)
|
|
||||||
{
|
|
||||||
if (settings.UseLowLevelGlobalHotkey)
|
|
||||||
{
|
|
||||||
// _keyboardListener.SetHotkeyAction(globalHotkey.Win, globalHotkey.Ctrl, globalHotkey.Shift, globalHotkey.Alt, (byte)globalHotkey.Code, string.Empty);
|
|
||||||
// _hotkeys.Add(new(globalHotkey, string.Empty));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var vk = globalHotkey.Code;
|
|
||||||
var modifiers =
|
|
||||||
(globalHotkey.Alt ? HOT_KEY_MODIFIERS.MOD_ALT : 0) |
|
|
||||||
(globalHotkey.Ctrl ? HOT_KEY_MODIFIERS.MOD_CONTROL : 0) |
|
|
||||||
(globalHotkey.Shift ? HOT_KEY_MODIFIERS.MOD_SHIFT : 0) |
|
|
||||||
(globalHotkey.Win ? HOT_KEY_MODIFIERS.MOD_WIN : 0)
|
|
||||||
;
|
|
||||||
|
|
||||||
// var success = PInvoke.RegisterHotKey(_hwnd, _hotkeys.Count, modifiers, (uint)vk);
|
|
||||||
// if (success)
|
|
||||||
// {
|
|
||||||
// _hotkeys.Add(new(globalHotkey, string.Empty));
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// foreach (var commandHotkey in settings.CommandHotkeys)
|
|
||||||
// {
|
|
||||||
// var key = commandHotkey.Hotkey;
|
|
||||||
// if (key is not null)
|
|
||||||
// {
|
|
||||||
// if (settings.UseLowLevelGlobalHotkey)
|
|
||||||
// {
|
|
||||||
// _keyboardListener.SetHotkeyAction(key.Win, key.Ctrl, key.Shift, key.Alt, (byte)key.Code, commandHotkey.CommandId);
|
|
||||||
// _hotkeys.Add(new(globalHotkey, string.Empty));
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// var vk = key.Code;
|
|
||||||
// var modifiers =
|
|
||||||
// (key.Alt ? HOT_KEY_MODIFIERS.MOD_ALT : 0) |
|
|
||||||
// (key.Ctrl ? HOT_KEY_MODIFIERS.MOD_CONTROL : 0) |
|
|
||||||
// (key.Shift ? HOT_KEY_MODIFIERS.MOD_SHIFT : 0) |
|
|
||||||
// (key.Win ? HOT_KEY_MODIFIERS.MOD_WIN : 0)
|
|
||||||
// ;
|
|
||||||
// var success = PInvoke.RegisterHotKey(_hwnd, _hotkeys.Count, modifiers, (uint)vk);
|
|
||||||
// if (success)
|
|
||||||
// {
|
|
||||||
// _hotkeys.Add(commandHotkey);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HandleSummon(string commandId)
|
private void HandleSummon(string commandId)
|
||||||
{
|
{
|
||||||
if (_ignoreHotKeyWhenFullScreen)
|
if (_ignoreHotKeyWhenFullScreen)
|
||||||
@@ -982,7 +913,7 @@ public sealed partial class MainWindow : WindowEx,
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
// _localKeyboardListener.Dispose();
|
_keyboardService.Dispose();
|
||||||
DisposeAcrylic();
|
DisposeAcrylic();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -161,6 +161,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
<ProjectReference Include="..\..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||||
|
<ProjectReference Include="..\Microsoft.CommandPalette.UI.Models\Microsoft.CommandPalette.UI.Models.csproj" />
|
||||||
<ProjectReference Include="..\Microsoft.CommandPalette.UI.Services\Microsoft.CommandPalette.UI.Services.csproj" />
|
<ProjectReference Include="..\Microsoft.CommandPalette.UI.Services\Microsoft.CommandPalette.UI.Services.csproj" />
|
||||||
<ProjectReference Include="..\Microsoft.CommandPalette.UI.ViewModels\Microsoft.CommandPalette.UI.ViewModels.csproj" />
|
<ProjectReference Include="..\Microsoft.CommandPalette.UI.ViewModels\Microsoft.CommandPalette.UI.ViewModels.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -2,24 +2,45 @@
|
|||||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
using Microsoft.CommandPalette.UI.Models;
|
using CommunityToolkit.WinUI;
|
||||||
using Microsoft.CommandPalette.UI.Models.Helpers;
|
using ManagedCommon;
|
||||||
|
using Microsoft.CommandPalette.Extensions;
|
||||||
|
using Microsoft.CommandPalette.UI.Models.Events;
|
||||||
using Microsoft.CommandPalette.UI.Models.Messages;
|
using Microsoft.CommandPalette.UI.Models.Messages;
|
||||||
|
using Microsoft.CommandPalette.UI.Services;
|
||||||
using Microsoft.CommandPalette.UI.ViewModels;
|
using Microsoft.CommandPalette.UI.ViewModels;
|
||||||
using Microsoft.CommandPalette.ViewModels;
|
using Microsoft.CommandPalette.ViewModels;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.PowerToys.Telemetry;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Microsoft.UI.Xaml.Media.Animation;
|
using Microsoft.UI.Xaml.Media.Animation;
|
||||||
using Microsoft.UI.Xaml.Navigation;
|
using Microsoft.UI.Xaml.Navigation;
|
||||||
using DispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue;
|
using DispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue;
|
||||||
|
|
||||||
namespace Microsoft.CommandPalette.UI.Pages;
|
namespace Microsoft.CommandPalette.UI.Pages;
|
||||||
|
|
||||||
public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page
|
public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
|
||||||
|
IRecipient<NavigateBackMessage>,
|
||||||
|
IRecipient<OpenSettingsMessage>,
|
||||||
|
IRecipient<HotkeySummonMessage>,
|
||||||
|
IRecipient<ShowDetailsMessage>,
|
||||||
|
IRecipient<HideDetailsMessage>,
|
||||||
|
IRecipient<ClearSearchMessage>,
|
||||||
|
IRecipient<LaunchUriMessage>,
|
||||||
|
IRecipient<SettingsWindowClosedMessage>,
|
||||||
|
IRecipient<GoHomeMessage>,
|
||||||
|
IRecipient<GoBackMessage>,
|
||||||
|
IRecipient<ShowConfirmationMessage>,
|
||||||
|
IRecipient<ShowToastMessage>,
|
||||||
|
IRecipient<NavigateToPageMessage>,
|
||||||
|
INotifyPropertyChanged,
|
||||||
|
IDisposable
|
||||||
{
|
{
|
||||||
private readonly ShellViewModel viewModel;
|
private readonly ShellViewModel viewModel;
|
||||||
private readonly SettingsModel _settingsModel;
|
private readonly SettingsService _settingsService;
|
||||||
private readonly ILogger logger;
|
private readonly ILogger logger;
|
||||||
private readonly DispatcherQueue _queue = DispatcherQueue.GetForCurrentThread();
|
private readonly DispatcherQueue _queue = DispatcherQueue.GetForCurrentThread();
|
||||||
private readonly Microsoft.UI.Dispatching.DispatcherQueueTimer _debounceTimer = DispatcherQueue.GetForCurrentThread().CreateTimer();
|
private readonly Microsoft.UI.Dispatching.DispatcherQueueTimer _debounceTimer = DispatcherQueue.GetForCurrentThread().CreateTimer();
|
||||||
@@ -30,13 +51,31 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page
|
|||||||
|
|
||||||
private readonly CompositeFormat _pageNavigatedAnnouncement;
|
private readonly CompositeFormat _pageNavigatedAnnouncement;
|
||||||
|
|
||||||
public ShellPage(ShellViewModel viewModel, SettingsModel settingsModel, ILogger logger)
|
public ShellPage(ShellViewModel viewModel, SettingsService settingsService, ILogger logger)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
this.viewModel = viewModel;
|
this.viewModel = viewModel;
|
||||||
_settingsModel = settingsModel;
|
_settingsService = settingsService;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
|
|
||||||
|
// how we are doing navigation around
|
||||||
|
WeakReferenceMessenger.Default.Register<NavigateBackMessage>(this);
|
||||||
|
WeakReferenceMessenger.Default.Register<OpenSettingsMessage>(this);
|
||||||
|
WeakReferenceMessenger.Default.Register<HotkeySummonMessage>(this);
|
||||||
|
WeakReferenceMessenger.Default.Register<SettingsWindowClosedMessage>(this);
|
||||||
|
|
||||||
|
WeakReferenceMessenger.Default.Register<ShowDetailsMessage>(this);
|
||||||
|
WeakReferenceMessenger.Default.Register<HideDetailsMessage>(this);
|
||||||
|
|
||||||
|
WeakReferenceMessenger.Default.Register<ClearSearchMessage>(this);
|
||||||
|
WeakReferenceMessenger.Default.Register<LaunchUriMessage>(this);
|
||||||
|
|
||||||
|
WeakReferenceMessenger.Default.Register<GoHomeMessage>(this);
|
||||||
|
WeakReferenceMessenger.Default.Register<GoBackMessage>(this);
|
||||||
|
WeakReferenceMessenger.Default.Register<ShowConfirmationMessage>(this);
|
||||||
|
WeakReferenceMessenger.Default.Register<ShowToastMessage>(this);
|
||||||
|
WeakReferenceMessenger.Default.Register<NavigateToPageMessage>(this);
|
||||||
|
|
||||||
// AddHandler(PreviewKeyDownEvent, new KeyEventHandler(ShellPage_OnPreviewKeyDown), true);
|
// AddHandler(PreviewKeyDownEvent, new KeyEventHandler(ShellPage_OnPreviewKeyDown), true);
|
||||||
// AddHandler(KeyDownEvent, new KeyEventHandler(ShellPage_OnKeyDown), false);
|
// AddHandler(KeyDownEvent, new KeyEventHandler(ShellPage_OnKeyDown), false);
|
||||||
// AddHandler(PointerPressedEvent, new PointerEventHandler(ShellPage_OnPointerPressed), true);
|
// AddHandler(PointerPressedEvent, new PointerEventHandler(ShellPage_OnPointerPressed), true);
|
||||||
@@ -53,10 +92,218 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _settingsModel.DisableAnimations ? _noAnimation : _slideRightTransition;
|
return _settingsService.CurrentSettings.DisableAnimations ? _noAnimation : _slideRightTransition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Receive(NavigateBackMessage message)
|
||||||
|
{
|
||||||
|
if (RootFrame.CanGoBack)
|
||||||
|
{
|
||||||
|
if (!message.FromBackspace ||
|
||||||
|
_settingsService.CurrentSettings.BackspaceGoesBack)
|
||||||
|
{
|
||||||
|
GoBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!message.FromBackspace)
|
||||||
|
{
|
||||||
|
// If we can't go back then we must be at the top and thus escape again should quit.
|
||||||
|
WeakReferenceMessenger.Default.Send<DismissMessage>();
|
||||||
|
|
||||||
|
PowerToysTelemetry.Log.WriteEvent(new DismissedOnEscEvent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Receive(NavigateToPageMessage message)
|
||||||
|
{
|
||||||
|
// TODO GH #526 This needs more better locking too
|
||||||
|
_ = _queue.TryEnqueue(() =>
|
||||||
|
{
|
||||||
|
// Also hide our details pane about here, if we had one
|
||||||
|
// HideDetails();
|
||||||
|
|
||||||
|
// Navigate to the appropriate host page for that VM
|
||||||
|
// RootFrame.Navigate(
|
||||||
|
// message.Page switch
|
||||||
|
// {
|
||||||
|
// ListViewModel => typeof(ListPage),
|
||||||
|
// ContentPageViewModel => typeof(ContentPage),
|
||||||
|
// _ => throw new NotSupportedException(),
|
||||||
|
// },
|
||||||
|
// new AsyncNavigationRequest(message.Page, message.CancellationToken),
|
||||||
|
// message.WithAnimation ? DefaultPageAnimation : _noAnimation);
|
||||||
|
// PowerToysTelemetry.Log.WriteEvent(new OpenPageEvent(RootFrame.BackStackDepth, message.Page.Id));
|
||||||
|
// if (!viewModel.IsNested)
|
||||||
|
// {
|
||||||
|
// // todo BODGY
|
||||||
|
// RootFrame.BackStack.Clear();
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Receive(ShowConfirmationMessage message)
|
||||||
|
{
|
||||||
|
DispatcherQueue.TryEnqueue(async () =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await HandleConfirmArgsOnUiThread(message.Args);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError(ex.ToString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Receive(ShowToastMessage message)
|
||||||
|
{
|
||||||
|
DispatcherQueue.TryEnqueue(() =>
|
||||||
|
{
|
||||||
|
// _toast.ShowToast(message.Message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// This gets called from the UI thread
|
||||||
|
private async Task HandleConfirmArgsOnUiThread(IConfirmationArgs? args)
|
||||||
|
{
|
||||||
|
if (args is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfirmResultViewModel vm = new(args, new(ViewModel.CurrentPage));
|
||||||
|
var initializeDialogTask = Task.Run(() => { InitializeConfirmationDialog(vm); });
|
||||||
|
await initializeDialogTask;
|
||||||
|
|
||||||
|
var resourceLoader = Microsoft.CmdPal.UI.Helpers.ResourceLoaderInstance.ResourceLoader;
|
||||||
|
var confirmText = resourceLoader.GetString("ConfirmationDialog_ConfirmButtonText");
|
||||||
|
var cancelText = resourceLoader.GetString("ConfirmationDialog_CancelButtonText");
|
||||||
|
|
||||||
|
var name = string.IsNullOrEmpty(vm.PrimaryCommand.Name) ? confirmText : vm.PrimaryCommand.Name;
|
||||||
|
ContentDialog dialog = new()
|
||||||
|
{
|
||||||
|
Title = vm.Title,
|
||||||
|
Content = vm.Description,
|
||||||
|
PrimaryButtonText = name,
|
||||||
|
CloseButtonText = cancelText,
|
||||||
|
XamlRoot = this.XamlRoot,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (vm.IsPrimaryCommandCritical)
|
||||||
|
{
|
||||||
|
dialog.DefaultButton = ContentDialogButton.Close;
|
||||||
|
|
||||||
|
// TODO: Maybe we need to style the primary button to be red?
|
||||||
|
// dialog.PrimaryButtonStyle = new Style(typeof(Button))
|
||||||
|
// {
|
||||||
|
// Setters =
|
||||||
|
// {
|
||||||
|
// new Setter(Button.ForegroundProperty, new SolidColorBrush(Colors.Red)),
|
||||||
|
// new Setter(Button.BackgroundProperty, new SolidColorBrush(Colors.Red)),
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = await dialog.ShowAsync();
|
||||||
|
if (result == ContentDialogResult.Primary)
|
||||||
|
{
|
||||||
|
var performMessage = new PerformCommandMessage(vm);
|
||||||
|
WeakReferenceMessenger.Default.Send(performMessage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// cancel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Receive(OpenSettingsMessage message)
|
||||||
|
{
|
||||||
|
_ = DispatcherQueue.TryEnqueue(() =>
|
||||||
|
{
|
||||||
|
OpenSettings();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenSettings()
|
||||||
|
{
|
||||||
|
if (_settingsWindow is null)
|
||||||
|
{
|
||||||
|
_settingsWindow = new SettingsWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
_settingsWindow.Activate();
|
||||||
|
_settingsWindow.BringToFront();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Receive(ShowDetailsMessage message)
|
||||||
|
{
|
||||||
|
if (ViewModel is not null &&
|
||||||
|
ViewModel.CurrentPage is not null)
|
||||||
|
{
|
||||||
|
if (ViewModel.CurrentPage.PageContext.TryGetTarget(out var pageContext))
|
||||||
|
{
|
||||||
|
Task.Factory.StartNew(
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
// TERRIBLE HACK TODO GH #245
|
||||||
|
// There's weird wacky bugs with debounce currently.
|
||||||
|
if (!ViewModel.IsDetailsVisible)
|
||||||
|
{
|
||||||
|
ViewModel.Details = message.Details;
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(HasHeroImage)));
|
||||||
|
ViewModel.IsDetailsVisible = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GH #322:
|
||||||
|
// For inexplicable reasons, if you try to change the details too fast,
|
||||||
|
// we'll explode. This seemingly only happens if you change the details
|
||||||
|
// while we're also scrolling a new list view item into view.
|
||||||
|
_debounceTimer.Debounce(
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
ViewModel.Details = message.Details;
|
||||||
|
|
||||||
|
// Trigger a re-evaluation of whether we have a hero image based on
|
||||||
|
// the current theme
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(HasHeroImage)));
|
||||||
|
},
|
||||||
|
interval: TimeSpan.FromMilliseconds(50),
|
||||||
|
immediate: ViewModel.IsDetailsVisible == false);
|
||||||
|
ViewModel.IsDetailsVisible = true;
|
||||||
|
},
|
||||||
|
CancellationToken.None,
|
||||||
|
TaskCreationOptions.None,
|
||||||
|
pageContext.Scheduler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Receive(HideDetailsMessage message) => HideDetails();
|
||||||
|
|
||||||
|
public void Receive(LaunchUriMessage message) => _ = global::Windows.System.Launcher.LaunchUriAsync(message.Uri);
|
||||||
|
|
||||||
|
private void HideDetails()
|
||||||
|
{
|
||||||
|
ViewModel.Details = null;
|
||||||
|
ViewModel.IsDetailsVisible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Receive(ClearSearchMessage message) => SearchBox.ClearSearch();
|
||||||
|
|
||||||
|
public void Receive(HotkeySummonMessage message)
|
||||||
|
{
|
||||||
|
_ = DispatcherQueue.TryEnqueue(() => SummonOnUiThread(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Receive(SettingsWindowClosedMessage message) => _settingsWindow = null;
|
||||||
|
|
||||||
|
|
||||||
private void SummonOnUiThread(HotkeySummonMessage message)
|
private void SummonOnUiThread(HotkeySummonMessage message)
|
||||||
{
|
{
|
||||||
var commandId = message.CommandId;
|
var commandId = message.CommandId;
|
||||||
@@ -69,11 +316,11 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page
|
|||||||
// Depending on the settings, either
|
// Depending on the settings, either
|
||||||
// * Go home, or
|
// * Go home, or
|
||||||
// * Select the search text (if we should remain open on this page)
|
// * Select the search text (if we should remain open on this page)
|
||||||
if (_settingsModel.AutoGoHomeInterval == TimeSpan.Zero)
|
if (_settingsService.CurrentSettings.AutoGoHomeInterval == TimeSpan.Zero)
|
||||||
{
|
{
|
||||||
// GoHome(false);
|
GoHome(false);
|
||||||
}
|
}
|
||||||
else if (_settingsModel.HighlightSearchOnActivate)
|
else if (_settingsService.CurrentSettings.HighlightSearchOnActivate)
|
||||||
{
|
{
|
||||||
// SearchBox.SelectSearch();
|
// SearchBox.SelectSearch();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,17 +7,11 @@ using System.Globalization;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
using CommunityToolkit.WinUI;
|
using CommunityToolkit.WinUI;
|
||||||
using ManagedCommon;
|
|
||||||
using Microsoft.CmdPal.Core.ViewModels;
|
|
||||||
using Microsoft.CmdPal.Core.ViewModels.Messages;
|
|
||||||
using Microsoft.CmdPal.UI.Events;
|
using Microsoft.CmdPal.UI.Events;
|
||||||
using Microsoft.CmdPal.UI.Helpers;
|
using Microsoft.CmdPal.UI.Helpers;
|
||||||
using Microsoft.CmdPal.UI.Messages;
|
using Microsoft.CmdPal.UI.Messages;
|
||||||
using Microsoft.CmdPal.UI.Settings;
|
using Microsoft.CmdPal.UI.Settings;
|
||||||
using Microsoft.CmdPal.UI.ViewModels;
|
|
||||||
using Microsoft.CommandPalette.Extensions;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.PowerToys.Telemetry;
|
|
||||||
using Microsoft.UI.Dispatching;
|
using Microsoft.UI.Dispatching;
|
||||||
using Microsoft.UI.Input;
|
using Microsoft.UI.Input;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
|
|||||||
Reference in New Issue
Block a user