More deux, two

This commit is contained in:
Michael Jolley
2025-12-11 19:08:35 -06:00
parent 4c1b822948
commit 69d706560f
24 changed files with 1515 additions and 110 deletions

View File

@@ -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" />

View File

@@ -0,0 +1,3 @@
EXPORTS
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE

View File

@@ -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>

View File

@@ -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>

View 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);
}
}

View 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>
{
};
}

View File

@@ -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);
}
}

View 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__

View 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>

View 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>

View File

@@ -0,0 +1 @@
#include "pch.h"

View File

@@ -0,0 +1,4 @@
#pragma once
#include <Unknwn.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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; } = [];
} }

View File

@@ -6,5 +6,4 @@ namespace Microsoft.CommandPalette.UI.Services.Extensions;
public interface IExtensionService public interface IExtensionService
{ {
CommandViewModel
} }

View File

@@ -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);
}

View File

@@ -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>

View File

@@ -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

View File

@@ -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();
} }

View File

@@ -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>

View File

@@ -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();
} }

View File

@@ -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;