mirror of
https://github.com/microsoft/PowerToys
synced 2025-09-03 16:05:12 +00:00
CmdPal: Add low-level keyboard hook for global hotkey (#38250)
Adds the ability to make the global CmdPal hotkey a low-level hook. This is needed for `win+space`, `win+r`, et al. I've only added this to the root hotkey. Other hotkeys will still use the normal `RegisterHotkey` ones. We can re-evaluate this for 0.2+. Originally: https://github.com/zadjii-msft/PowerToys/issues/349 Solves: https://github.com/microsoft/PowerToys/issues/38297 --------- Co-authored-by: Mike Griese <migrie@microsoft.com>
This commit is contained in:
@@ -706,6 +706,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RegistryPreview.FuzzTests",
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.System", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.System\Microsoft.CmdPal.Ext.System.csproj", "{64B88F02-CD88-4ED8-9624-989A800230F9}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.System", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.System\Microsoft.CmdPal.Ext.System.csproj", "{64B88F02-CD88-4ED8-9624-989A800230F9}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdPalKeyboardService", "src\modules\cmdpal\CmdPalKeyboardService\CmdPalKeyboardService.vcxproj", "{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|ARM64 = Debug|ARM64
|
Debug|ARM64 = Debug|ARM64
|
||||||
@@ -2574,14 +2576,18 @@ Global
|
|||||||
{64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|ARM64.Build.0 = Debug|ARM64
|
{64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||||
{64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|x64.ActiveCfg = Debug|x64
|
{64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|x64.Build.0 = Debug|x64
|
{64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|x64.Build.0 = Debug|x64
|
||||||
{64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|x86.ActiveCfg = Debug|x64
|
|
||||||
{64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|x86.Build.0 = Debug|x64
|
|
||||||
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|ARM64.ActiveCfg = Release|ARM64
|
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||||
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|ARM64.Build.0 = Release|ARM64
|
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|ARM64.Build.0 = Release|ARM64
|
||||||
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x64.ActiveCfg = Release|x64
|
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x64.ActiveCfg = Release|x64
|
||||||
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x64.Build.0 = Release|x64
|
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x64.Build.0 = Release|x64
|
||||||
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x86.ActiveCfg = Release|x64
|
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||||
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x86.Build.0 = Release|x64
|
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||||
|
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||||
|
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|ARM64.Build.0 = Release|ARM64
|
||||||
|
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|x64.Build.0 = Release|x64
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@@ -2852,6 +2858,7 @@ Global
|
|||||||
{4E0AE3A4-2EE0-44D7-A2D0-8769977254A0} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}
|
{4E0AE3A4-2EE0-44D7-A2D0-8769977254A0} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}
|
||||||
{5702B3CC-8575-48D5-83D8-15BB42269CD3} = {929C1324-22E8-4412-A9A8-80E85F3985A5}
|
{5702B3CC-8575-48D5-83D8-15BB42269CD3} = {929C1324-22E8-4412-A9A8-80E85F3985A5}
|
||||||
{64B88F02-CD88-4ED8-9624-989A800230F9} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2}
|
{64B88F02-CD88-4ED8-9624-989A800230F9} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2}
|
||||||
|
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2} = {3846508C-77EB-4034-A702-F8BB263C4F79}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
|
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
|
||||||
|
@@ -0,0 +1,3 @@
|
|||||||
|
EXPORTS
|
||||||
|
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
|
||||||
|
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
|
@@ -0,0 +1,40 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
#include "resource.h"
|
||||||
|
#include "../../../common/version/version.h"
|
||||||
|
|
||||||
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
|
#include "winres.h"
|
||||||
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
|
1 VERSIONINFO
|
||||||
|
FILEVERSION FILE_VERSION
|
||||||
|
PRODUCTVERSION PRODUCT_VERSION
|
||||||
|
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS VS_FF_DEBUG
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS VOS_NT_WINDOWS32
|
||||||
|
FILETYPE VFT_DLL
|
||||||
|
FILESUBTYPE VFT2_UNKNOWN
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0" // US English (0x0409), Unicode (0x04B0) charset
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", COMPANY_NAME
|
||||||
|
VALUE "FileDescription", FILE_DESCRIPTION
|
||||||
|
VALUE "FileVersion", FILE_VERSION_STRING
|
||||||
|
VALUE "InternalName", INTERNAL_NAME
|
||||||
|
VALUE "LegalCopyright", COPYRIGHT_NOTE
|
||||||
|
VALUE "OriginalFilename", ORIGINAL_FILENAME
|
||||||
|
VALUE "ProductName", PRODUCT_NAME
|
||||||
|
VALUE "ProductVersion", PRODUCT_VERSION_STRING
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200 // US English (0x0409), Unicode (1200) charset
|
||||||
|
END
|
||||||
|
END
|
@@ -0,0 +1,187 @@
|
|||||||
|
<?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>{5f63c743-f6ce-4dba-a200-2b3f8a14e8c2}</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>
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
|
</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>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="CmdPalKeyboardService.rc" />
|
||||||
|
</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,36 @@
|
|||||||
|
<?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" />
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Midl Include="KeyboardListener.idl" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="CmdPalKeyboardService.def" />
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="PropertySheet.props" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="CmdPalKeyboardService.rc">
|
||||||
|
<Filter>Resources</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
165
src/modules/cmdpal/CmdPalKeyboardService/KeyboardListener.cpp
Normal file
165
src/modules/cmdpal/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/cmdpal/CmdPalKeyboardService/KeyboardListener.h
Normal file
67
src/modules/cmdpal/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);
|
||||||
|
}
|
||||||
|
}
|
17
src/modules/cmdpal/CmdPalKeyboardService/PropertySheet.props
Normal file
17
src/modules/cmdpal/CmdPalKeyboardService/PropertySheet.props
Normal file
@@ -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>
|
4
src/modules/cmdpal/CmdPalKeyboardService/packages.config
Normal file
4
src/modules/cmdpal/CmdPalKeyboardService/packages.config
Normal file
@@ -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/cmdpal/CmdPalKeyboardService/pch.cpp
Normal file
1
src/modules/cmdpal/CmdPalKeyboardService/pch.cpp
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#include "pch.h"
|
4
src/modules/cmdpal/CmdPalKeyboardService/pch.h
Normal file
4
src/modules/cmdpal/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>
|
13
src/modules/cmdpal/CmdPalKeyboardService/resource.h
Normal file
13
src/modules/cmdpal/CmdPalKeyboardService/resource.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
//{{NO_DEPENDENCIES}}
|
||||||
|
// Microsoft Visual C++ generated include file.
|
||||||
|
// Used by PowerToys.MeasureToolCore.rc
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// Non-localizable
|
||||||
|
|
||||||
|
#define FILE_DESCRIPTION "CmdPalKeyboardService"
|
||||||
|
#define INTERNAL_NAME "CmdPalKeyboardService"
|
||||||
|
#define ORIGINAL_FILENAME "CmdPalKeyboardService.dll"
|
||||||
|
|
||||||
|
// Non-localizable
|
||||||
|
//////////////////////////////
|
@@ -26,6 +26,8 @@ public partial class SettingsModel : ObservableObject
|
|||||||
|
|
||||||
public HotkeySettings? Hotkey { get; set; } = DefaultActivationShortcut;
|
public HotkeySettings? Hotkey { get; set; } = DefaultActivationShortcut;
|
||||||
|
|
||||||
|
public bool UseLowLevelGlobalHotkey { get; set; }
|
||||||
|
|
||||||
public bool ShowAppDetails { get; set; }
|
public bool ShowAppDetails { get; set; }
|
||||||
|
|
||||||
public bool HotkeyGoesHome { get; set; }
|
public bool HotkeyGoesHome { get; set; }
|
||||||
|
@@ -27,6 +27,17 @@ public partial class SettingsViewModel : INotifyPropertyChanged
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool UseLowLevelGlobalHotkey
|
||||||
|
{
|
||||||
|
get => _settings.UseLowLevelGlobalHotkey;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_settings.UseLowLevelGlobalHotkey = value;
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Hotkey)));
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool ShowAppDetails
|
public bool ShowAppDetails
|
||||||
{
|
{
|
||||||
get => _settings.ShowAppDetails;
|
get => _settings.ShowAppDetails;
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using CmdPalKeyboardService;
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
using Microsoft.CmdPal.Common.Helpers;
|
using Microsoft.CmdPal.Common.Helpers;
|
||||||
using Microsoft.CmdPal.Common.Messages;
|
using Microsoft.CmdPal.Common.Messages;
|
||||||
@@ -52,6 +53,8 @@ public sealed partial class MainWindow : Window,
|
|||||||
#pragma warning restore SA1306 // Field names should begin with lower-case letter
|
#pragma warning restore SA1306 // Field names should begin with lower-case letter
|
||||||
#pragma warning restore SA1310 // Field names should not contain underscore
|
#pragma warning restore SA1310 // Field names should not contain underscore
|
||||||
|
|
||||||
|
private readonly KeyboardListener _keyboardListener;
|
||||||
|
|
||||||
// Notification Area ("Tray") icon data
|
// Notification Area ("Tray") icon data
|
||||||
private NOTIFYICONDATAW? _trayIconData;
|
private NOTIFYICONDATAW? _trayIconData;
|
||||||
private DestroyIconSafeHandle? _largeIcon;
|
private DestroyIconSafeHandle? _largeIcon;
|
||||||
@@ -66,6 +69,11 @@ public sealed partial class MainWindow : Window,
|
|||||||
_hwnd = new HWND(WinRT.Interop.WindowNative.GetWindowHandle(this).ToInt32());
|
_hwnd = new HWND(WinRT.Interop.WindowNative.GetWindowHandle(this).ToInt32());
|
||||||
CommandPaletteHost.SetHostHwnd((ulong)_hwnd.Value);
|
CommandPaletteHost.SetHostHwnd((ulong)_hwnd.Value);
|
||||||
|
|
||||||
|
_keyboardListener = new KeyboardListener();
|
||||||
|
_keyboardListener.Start();
|
||||||
|
|
||||||
|
_keyboardListener.SetProcessCommand(new CmdPalKeyboardService.ProcessCommand(HandleSummon));
|
||||||
|
|
||||||
// TaskbarCreated is the message that's broadcast when explorer.exe
|
// TaskbarCreated is the message that's broadcast when explorer.exe
|
||||||
// restarts. We need to know when that happens to be able to bring our
|
// restarts. We need to know when that happens to be able to bring our
|
||||||
// notification area icon back
|
// notification area icon back
|
||||||
@@ -304,6 +312,8 @@ public sealed partial class MainWindow : Window,
|
|||||||
// Workaround by turning it off before shutdown.
|
// Workaround by turning it off before shutdown.
|
||||||
App.Current.DebugSettings.FailFastOnErrors = false;
|
App.Current.DebugSettings.FailFastOnErrors = false;
|
||||||
DisposeAcrylic();
|
DisposeAcrylic();
|
||||||
|
|
||||||
|
_keyboardListener.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisposeAcrylic()
|
private void DisposeAcrylic()
|
||||||
@@ -398,6 +408,8 @@ public sealed partial class MainWindow : Window,
|
|||||||
|
|
||||||
private void UnregisterHotkeys()
|
private void UnregisterHotkeys()
|
||||||
{
|
{
|
||||||
|
_keyboardListener.ClearHotkeys();
|
||||||
|
|
||||||
while (_hotkeys.Count > 0)
|
while (_hotkeys.Count > 0)
|
||||||
{
|
{
|
||||||
PInvoke.UnregisterHotKey(_hwnd, _hotkeys.Count - 1);
|
PInvoke.UnregisterHotKey(_hwnd, _hotkeys.Count - 1);
|
||||||
@@ -412,19 +424,28 @@ public sealed partial class MainWindow : Window,
|
|||||||
var globalHotkey = settings.Hotkey;
|
var globalHotkey = settings.Hotkey;
|
||||||
if (globalHotkey != null)
|
if (globalHotkey != null)
|
||||||
{
|
{
|
||||||
var vk = globalHotkey.Code;
|
if (settings.UseLowLevelGlobalHotkey)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
|
_keyboardListener.SetHotkeyAction(globalHotkey.Win, globalHotkey.Ctrl, globalHotkey.Shift, globalHotkey.Alt, (byte)globalHotkey.Code, string.Empty);
|
||||||
|
|
||||||
_hotkeys.Add(new(globalHotkey, 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)
|
foreach (var commandHotkey in settings.CommandHotkeys)
|
||||||
@@ -450,6 +471,26 @@ public sealed partial class MainWindow : Window,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleSummon(string commandId)
|
||||||
|
{
|
||||||
|
var isRootHotkey = string.IsNullOrEmpty(commandId);
|
||||||
|
PowerToysTelemetry.Log.WriteEvent(new CmdPalHotkeySummoned(isRootHotkey));
|
||||||
|
|
||||||
|
// Note to future us: the wParam will have the index of the hotkey we registered.
|
||||||
|
// We can use that in the future to differentiate the hotkeys we've pressed
|
||||||
|
// so that we can bind hotkeys to individual commands
|
||||||
|
if (!this.Visible || !isRootHotkey)
|
||||||
|
{
|
||||||
|
Activate();
|
||||||
|
|
||||||
|
Summon(commandId);
|
||||||
|
}
|
||||||
|
else if (isRootHotkey)
|
||||||
|
{
|
||||||
|
PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_HIDE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private LRESULT HotKeyPrc(
|
private LRESULT HotKeyPrc(
|
||||||
HWND hwnd,
|
HWND hwnd,
|
||||||
uint uMsg,
|
uint uMsg,
|
||||||
@@ -464,22 +505,23 @@ public sealed partial class MainWindow : Window,
|
|||||||
if (hotkeyIndex < _hotkeys.Count)
|
if (hotkeyIndex < _hotkeys.Count)
|
||||||
{
|
{
|
||||||
var hotkey = _hotkeys[hotkeyIndex];
|
var hotkey = _hotkeys[hotkeyIndex];
|
||||||
var isRootHotkey = string.IsNullOrEmpty(hotkey.CommandId);
|
HandleSummon(hotkey.CommandId);
|
||||||
PowerToysTelemetry.Log.WriteEvent(new CmdPalHotkeySummoned(isRootHotkey));
|
|
||||||
|
|
||||||
// Note to future us: the wParam will have the index of the hotkey we registered.
|
// var isRootHotkey = string.IsNullOrEmpty(hotkey.CommandId);
|
||||||
// We can use that in the future to differentiate the hotkeys we've pressed
|
|
||||||
// so that we can bind hotkeys to individual commands
|
|
||||||
if (!this.Visible || !isRootHotkey)
|
|
||||||
{
|
|
||||||
Activate();
|
|
||||||
|
|
||||||
Summon(hotkey.CommandId);
|
// // Note to future us: the wParam will have the index of the hotkey we registered.
|
||||||
}
|
// // We can use that in the future to differentiate the hotkeys we've pressed
|
||||||
else if (isRootHotkey)
|
// // so that we can bind hotkeys to individual commands
|
||||||
{
|
// if (!this.Visible || !isRootHotkey)
|
||||||
PInvoke.ShowWindow(hwnd, SHOW_WINDOW_CMD.SW_HIDE);
|
// {
|
||||||
}
|
// Activate();
|
||||||
|
|
||||||
|
// Summon(hotkey.CommandId);
|
||||||
|
// }
|
||||||
|
// else if (isRootHotkey)
|
||||||
|
// {
|
||||||
|
// PInvoke.ShowWindow(hwnd, SHOW_WINDOW_CMD.SW_HIDE);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
return (LRESULT)IntPtr.Zero;
|
return (LRESULT)IntPtr.Zero;
|
||||||
|
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- This lets us actually reference types from Microsoft.Terminal.UI -->
|
<!-- This lets us actually reference types from Microsoft.Terminal.UI -->
|
||||||
<CsWinRTIncludes>Microsoft.Terminal.UI</CsWinRTIncludes>
|
<CsWinRTIncludes>Microsoft.Terminal.UI;CmdPalKeyboardService</CsWinRTIncludes>
|
||||||
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
|
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
@@ -123,6 +123,12 @@
|
|||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
<CopyLocalSatelliteAssemblies>True</CopyLocalSatelliteAssemblies>
|
<CopyLocalSatelliteAssemblies>True</CopyLocalSatelliteAssemblies>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
|
||||||
|
<ProjectReference Include="..\CmdPalKeyboardService\CmdPalKeyboardService.vcxproj">
|
||||||
|
<ReferenceOutputAssembly>True</ReferenceOutputAssembly>
|
||||||
|
<Private>True</Private>
|
||||||
|
<CopyLocalSatelliteAssemblies>True</CopyLocalSatelliteAssemblies>
|
||||||
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@@ -36,9 +36,18 @@
|
|||||||
|
|
||||||
<TextBlock x:Uid="ActivationSettingsHeader" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
<TextBlock x:Uid="ActivationSettingsHeader" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||||
|
|
||||||
<controls:SettingsCard x:Uid="Settings_GeneralPage_ActivationKey_SettingsExpander" HeaderIcon="{ui:FontIcon Glyph=}">
|
<controls:SettingsExpander
|
||||||
|
x:Uid="Settings_GeneralPage_ActivationKey_SettingsExpander"
|
||||||
|
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||||
|
IsExpanded="True">
|
||||||
<ptControls:ShortcutControl HotkeySettings="{x:Bind viewModel.Hotkey, Mode=TwoWay}" />
|
<ptControls:ShortcutControl HotkeySettings="{x:Bind viewModel.Hotkey, Mode=TwoWay}" />
|
||||||
</controls:SettingsCard>
|
|
||||||
|
<controls:SettingsExpander.Items>
|
||||||
|
<controls:SettingsCard x:Uid="Settings_GeneralPage_LowLevelHook_SettingsCard">
|
||||||
|
<ToggleSwitch IsOn="{x:Bind viewModel.UseLowLevelGlobalHotkey, Mode=TwoWay}" />
|
||||||
|
</controls:SettingsCard>
|
||||||
|
</controls:SettingsExpander.Items>
|
||||||
|
</controls:SettingsExpander>
|
||||||
<controls:SettingsCard x:Uid="Settings_GeneralPage_GoHome_SettingsCard" HeaderIcon="{ui:FontIcon Glyph=}">
|
<controls:SettingsCard x:Uid="Settings_GeneralPage_GoHome_SettingsCard" HeaderIcon="{ui:FontIcon Glyph=}">
|
||||||
<ToggleSwitch IsOn="{x:Bind viewModel.HotkeyGoesHome, Mode=TwoWay}" />
|
<ToggleSwitch IsOn="{x:Bind viewModel.HotkeyGoesHome, Mode=TwoWay}" />
|
||||||
</controls:SettingsCard>
|
</controls:SettingsCard>
|
||||||
|
@@ -322,6 +322,12 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
|||||||
<data name="Settings_GeneralPage_ActivationKey_SettingsExpander.Description" xml:space="preserve">
|
<data name="Settings_GeneralPage_ActivationKey_SettingsExpander.Description" xml:space="preserve">
|
||||||
<value>This key will open the Command Palette.</value>
|
<value>This key will open the Command Palette.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Settings_GeneralPage_LowLevelHook_SettingsCard.Header" xml:space="preserve">
|
||||||
|
<value>Use low-level keyboard hook</value>
|
||||||
|
</data>
|
||||||
|
<data name="Settings_GeneralPage_LowLevelHook_SettingsCard.Description" xml:space="preserve">
|
||||||
|
<value>Try this if there are issues with the shortcut (Command Palette might not get focus when triggered from an elevated window)</value>
|
||||||
|
</data>
|
||||||
<data name="Settings_GeneralPage_GoHome_SettingsCard.Header" xml:space="preserve">
|
<data name="Settings_GeneralPage_GoHome_SettingsCard.Header" xml:space="preserve">
|
||||||
<value>Go home when activated</value>
|
<value>Go home when activated</value>
|
||||||
</data>
|
</data>
|
||||||
|
Reference in New Issue
Block a user