Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>
This commit is contained in:
Shawn Yuan (from Dev Box)
2025-11-05 11:59:08 +08:00
parent 229bedd09f
commit 709ceed137
14 changed files with 761 additions and 1 deletions

View File

@@ -394,6 +394,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Plugin.WindowWalk
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerToys.Settings", "src\settings-ui\Settings.UI\PowerToys.Settings.csproj", "{020A7474-3601-4160-A159-D7B70B77B15F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerToys.QuickAccess", "src\settings-ui\QuickAccess.UI\PowerToys.QuickAccess.csproj", "{A7C9C9C6-BA80-4CF3-9DB0-6DBBB4148F60}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameUI", "src\modules\powerrename\PowerRenameUILib\PowerRenameUI.vcxproj", "{27718999-C175-450A-861C-89F911E16A88}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameContextMenu", "src\modules\powerrename\PowerRenameContextMenu\PowerRenameContextMenu.vcxproj", "{1DBBB112-4BB1-444B-8EBB-E66555C76BA6}"
@@ -1686,6 +1688,14 @@ Global
{020A7474-3601-4160-A159-D7B70B77B15F}.Release|ARM64.Build.0 = Release|ARM64
{020A7474-3601-4160-A159-D7B70B77B15F}.Release|x64.ActiveCfg = Release|x64
{020A7474-3601-4160-A159-D7B70B77B15F}.Release|x64.Build.0 = Release|x64
{A7C9C9C6-BA80-4CF3-9DB0-6DBBB4148F60}.Debug|ARM64.ActiveCfg = Debug|ARM64
{A7C9C9C6-BA80-4CF3-9DB0-6DBBB4148F60}.Debug|ARM64.Build.0 = Debug|ARM64
{A7C9C9C6-BA80-4CF3-9DB0-6DBBB4148F60}.Debug|x64.ActiveCfg = Debug|x64
{A7C9C9C6-BA80-4CF3-9DB0-6DBBB4148F60}.Debug|x64.Build.0 = Debug|x64
{A7C9C9C6-BA80-4CF3-9DB0-6DBBB4148F60}.Release|ARM64.ActiveCfg = Release|ARM64
{A7C9C9C6-BA80-4CF3-9DB0-6DBBB4148F60}.Release|ARM64.Build.0 = Release|ARM64
{A7C9C9C6-BA80-4CF3-9DB0-6DBBB4148F60}.Release|x64.ActiveCfg = Release|x64
{A7C9C9C6-BA80-4CF3-9DB0-6DBBB4148F60}.Release|x64.Build.0 = Release|x64
{27718999-C175-450A-861C-89F911E16A88}.Debug|ARM64.ActiveCfg = Debug|ARM64
{27718999-C175-450A-861C-89F911E16A88}.Debug|ARM64.Build.0 = Debug|ARM64
{27718999-C175-450A-861C-89F911E16A88}.Debug|x64.ActiveCfg = Debug|x64
@@ -3140,6 +3150,7 @@ Global
{FD464B4C-2F68-4D06-91E7-4208146C41F5} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F}
{8FE5A5EE-1B59-401C-9FB3-B04ECD3E29C1} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F}
{020A7474-3601-4160-A159-D7B70B77B15F} = {C3081D9A-1586-441A-B5F4-ED815B3719C1}
{A7C9C9C6-BA80-4CF3-9DB0-6DBBB4148F60} = {C3081D9A-1586-441A-B5F4-ED815B3719C1}
{27718999-C175-450A-861C-89F911E16A88} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{1DBBB112-4BB1-444B-8EBB-E66555C76BA6} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{5A1DB2F0-0715-4B3B-98E6-79BC41540045} = {4AFC9975-2456-4C70-94A4-84073C1CED93}

View File

@@ -36,6 +36,7 @@
#include <RestartManager.h>
#include "centralized_kb_hook.h"
#include "centralized_hotkeys.h"
#include "quick_access_host.h"
#if _DEBUG && _WIN64
#include "unhandled_exception_handler.h"
@@ -105,6 +106,7 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow
#endif
Trace::RegisterProvider();
start_tray_icon(isProcessElevated);
QuickAccessHost::start();
set_tray_icon_visible(get_general_settings().showSystemTrayIcon);
CentralizedKeyboardHook::Start();
@@ -242,6 +244,7 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow
result = -1;
}
Trace::UnregisterProvider();
QuickAccessHost::stop();
return result;
}

View File

@@ -0,0 +1,157 @@
#include "pch.h"
#include "quick_access_host.h"
#include <mutex>
#include <string>
#include <vector>
#include <common/logger/logger.h>
#include <common/utils/process_path.h>
#include <wil/resource.h>
namespace
{
wil::unique_handle quick_access_process;
wil::unique_handle show_event;
wil::unique_handle exit_event;
std::wstring show_event_name;
std::wstring exit_event_name;
std::mutex quick_access_mutex;
bool is_process_active_locked()
{
if (!quick_access_process)
{
return false;
}
DWORD exit_code = 0;
if (!GetExitCodeProcess(quick_access_process.get(), &exit_code))
{
Logger::warn(L"QuickAccessHost: failed to read Quick Access process exit code. error={}.", GetLastError());
return false;
}
return exit_code == STILL_ACTIVE;
}
void reset_state_locked()
{
quick_access_process.reset();
show_event.reset();
exit_event.reset();
show_event_name.clear();
exit_event_name.clear();
}
std::wstring build_event_name(const wchar_t* suffix)
{
return L"Local\\PowerToysQuickAccess_" + std::to_wstring(GetCurrentProcessId()) + suffix;
}
std::wstring build_command_line(const std::wstring& exe_path)
{
std::wstring command_line = L"\"";
command_line += exe_path;
command_line += L"\" --show-event=\"";
command_line += show_event_name;
command_line += L"\" --exit-event=\"";
command_line += exit_event_name;
command_line += L"\"";
return command_line;
}
}
namespace QuickAccessHost
{
bool is_running()
{
std::scoped_lock lock(quick_access_mutex);
return is_process_active_locked();
}
void start()
{
std::scoped_lock lock(quick_access_mutex);
if (is_process_active_locked())
{
return;
}
reset_state_locked();
show_event_name = build_event_name(L"_Show");
exit_event_name = build_event_name(L"_Exit");
show_event.reset(CreateEventW(nullptr, FALSE, FALSE, show_event_name.c_str()));
if (!show_event)
{
Logger::error(L"QuickAccessHost: failed to create show event. error={}.", GetLastError());
reset_state_locked();
return;
}
exit_event.reset(CreateEventW(nullptr, FALSE, FALSE, exit_event_name.c_str()));
if (!exit_event)
{
Logger::error(L"QuickAccessHost: failed to create exit event. error={}.", GetLastError());
reset_state_locked();
return;
}
const std::wstring exe_path = get_module_folderpath() + L"\\WinUI3Apps\\PowerToys.QuickAccess.exe";
if (GetFileAttributesW(exe_path.c_str()) == INVALID_FILE_ATTRIBUTES)
{
Logger::warn(L"QuickAccessHost: missing Quick Access executable at {}", exe_path);
reset_state_locked();
return;
}
const std::wstring command_line = build_command_line(exe_path);
std::vector<wchar_t> command_line_buffer(command_line.begin(), command_line.end());
command_line_buffer.push_back(L'\0');
STARTUPINFOW startup_info{};
startup_info.cb = sizeof(startup_info);
PROCESS_INFORMATION process_info{};
BOOL created = CreateProcessW(exe_path.c_str(), command_line_buffer.data(), nullptr, nullptr, FALSE, 0, nullptr, nullptr, &startup_info, &process_info);
if (!created)
{
Logger::error(L"QuickAccessHost: failed to launch Quick Access host. error={}.", GetLastError());
reset_state_locked();
return;
}
quick_access_process.reset(process_info.hProcess);
CloseHandle(process_info.hThread);
}
void show()
{
start();
std::scoped_lock lock(quick_access_mutex);
if (show_event)
{
if (!SetEvent(show_event.get()))
{
Logger::warn(L"QuickAccessHost: failed to signal show event. error={}.", GetLastError());
}
}
}
void stop()
{
std::unique_lock lock(quick_access_mutex);
if (exit_event)
{
SetEvent(exit_event.get());
}
if (quick_access_process)
{
WaitForSingleObject(quick_access_process.get(), 2000);
}
reset_state_locked();
}
}

View File

@@ -0,0 +1,12 @@
#pragma once
#include <Windows.h>
#include <optional>
namespace QuickAccessHost
{
void start();
void show();
void stop();
bool is_running();
}

View File

@@ -66,6 +66,7 @@
</ClCompile>
<ClCompile Include="powertoy_module.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="quick_access_host.cpp" />
<ClCompile Include="restart_elevated.cpp" />
<ClCompile Include="centralized_kb_hook.cpp" />
<ClCompile Include="settings_telemetry.cpp" />
@@ -80,6 +81,7 @@
<ClInclude Include="auto_start_helper.h" />
<ClInclude Include="bug_report.h" />
<ClInclude Include="centralized_hotkeys.h" />
<ClInclude Include="quick_access_host.h" />
<ClInclude Include="general_settings.h" />
<ClInclude Include="hotkey_conflict_detector.h" />
<ClInclude Include="pch.h" />

View File

@@ -48,6 +48,9 @@
<ClCompile Include="hotkey_conflict_detector.cpp">
<Filter>Utils</Filter>
</ClCompile>
<ClCompile Include="quick_access_host.cpp">
<Filter>Utils</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
@@ -99,6 +102,9 @@
<ClInclude Include="hotkey_conflict_detector.h">
<Filter>Utils</Filter>
</ClInclude>
<ClInclude Include="quick_access_host.h">
<Filter>Utils</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Utils">

View File

@@ -5,6 +5,7 @@
#include "general_settings.h"
#include "centralized_hotkeys.h"
#include "centralized_kb_hook.h"
#include "quick_access_host.h"
#include <Windows.h>
#include <common/utils/resources.h>
@@ -71,7 +72,8 @@ void change_menu_item_text(const UINT item_id, wchar_t* new_text)
void open_quick_access_flyout_window(const POINT flyout_position)
{
open_settings_window(std::nullopt, true, flyout_position);
UNREFERENCED_PARAMETER(flyout_position);
QuickAccessHost::show();
}
void handle_tray_command(HWND window, const WPARAM command_id, LPARAM lparam)

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Application
x:Class="Microsoft.PowerToys.QuickAccess.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.PowerToys.QuickAccess">
<Application.Resources>
</Application.Resources>
</Application>

View File

@@ -0,0 +1,20 @@
// 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 System;
using Microsoft.UI.Xaml;
namespace Microsoft.PowerToys.QuickAccess;
public partial class App : Application
{
private MainWindow? _window;
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
var launchContext = QuickAccessLaunchContext.Parse(Environment.GetCommandLineArgs());
_window = new MainWindow(launchContext);
_window.Activate();
}
}

View File

@@ -0,0 +1,16 @@
<Window
x:Class="Microsoft.PowerToys.QuickAccess.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="PowerToys Quick Access (Preview)">
<Grid>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Spacing="12">
<TextBlock Text="PowerToys Quick Access placeholder" HorizontalAlignment="Center" />
<TextBlock Text="This window stays resident to simulate a dedicated flyout host." TextWrapping="Wrap" Width="250" TextAlignment="Center" />
</StackPanel>
</Grid>
</Window>

View File

@@ -0,0 +1,418 @@
// 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 System;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Windows.Graphics;
using WinRT.Interop;
namespace Microsoft.PowerToys.QuickAccess;
public sealed partial class MainWindow : Window
{
private readonly QuickAccessLaunchContext _launchContext;
private readonly DispatcherQueue _dispatcherQueue;
private readonly IntPtr _hwnd;
private readonly AppWindow? _appWindow;
private EventWaitHandle? _showEvent;
private EventWaitHandle? _exitEvent;
private ManualResetEventSlim? _listenerShutdownEvent;
private Thread? _showListenerThread;
private Thread? _exitListenerThread;
private bool _isWindowCloaked;
private bool _initialActivationHandled;
private bool _isPrimed;
private const int DefaultWidth = 320;
private const int DefaultHeight = 480;
private const int DwmWaCloak = 13;
private const int GwlStyle = -16;
private const int SwHide = 0;
private const int SwShow = 5;
private const int SwShowNoActivate = 8;
private const uint SwpShowWindow = 0x0040;
private const uint SwpNoZorder = 0x0004;
private const uint SwpNoSize = 0x0001;
private const uint SwpNoMove = 0x0002;
private const uint SwpNoActivate = 0x0010;
private const uint SwpFrameChanged = 0x0020;
private const long WsSysmenu = 0x00080000L;
private const long WsMinimizeBox = 0x00020000L;
private const long WsMaximizeBox = 0x00010000L;
private static readonly IntPtr HwndTopmost = new(-1);
private static readonly IntPtr HwndBottom = new(1);
public MainWindow(QuickAccessLaunchContext launchContext)
{
InitializeComponent();
_launchContext = launchContext;
_dispatcherQueue = DispatcherQueue.GetForCurrentThread();
_hwnd = WindowNative.GetWindowHandle(this);
_appWindow = InitializeAppWindow(_hwnd);
Title = "PowerToys Quick Access (Preview)";
CustomizeWindowChrome();
HideWindow();
InitializeEventListeners();
Closed += OnClosed;
Activated += OnActivated;
}
private AppWindow? InitializeAppWindow(IntPtr hwnd)
{
var windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hwnd);
return AppWindow.GetFromWindowId(windowId);
}
private void HideWindow()
{
if (_hwnd != IntPtr.Zero)
{
var cloaked = CloakWindow();
if (!ShowWindowNative(_hwnd, SwHide) && _appWindow != null)
{
_appWindow.Hide();
}
if (cloaked)
{
ShowWindowNative(_hwnd, SwShowNoActivate);
}
else
{
SetWindowPosNative(_hwnd, HwndBottom, 0, 0, 0, 0, SwpNoMove | SwpNoSize | SwpNoActivate);
}
}
else if (_appWindow != null)
{
_appWindow.Hide();
}
}
private void InitializeEventListeners()
{
if (!string.IsNullOrEmpty(_launchContext.ShowEventName))
{
try
{
_showEvent = EventWaitHandle.OpenExisting(_launchContext.ShowEventName!);
EnsureListenerInfrastructure();
StartShowListenerThread();
}
catch (WaitHandleCannotBeOpenedException)
{
}
}
if (!string.IsNullOrEmpty(_launchContext.ExitEventName))
{
try
{
_exitEvent = EventWaitHandle.OpenExisting(_launchContext.ExitEventName!);
EnsureListenerInfrastructure();
StartExitListenerThread();
}
catch (WaitHandleCannotBeOpenedException)
{
}
}
}
private void ShowWindow()
{
if (_hwnd != IntPtr.Zero)
{
UncloakWindow();
ShowWindowNative(_hwnd, SwShow);
SetWindowPosNative(_hwnd, HwndTopmost, 0, 0, 0, 0, SwpNoMove | SwpNoSize | SwpShowWindow);
SetForegroundWindowNative(_hwnd);
}
Activate();
}
private void OnActivated(object sender, WindowActivatedEventArgs args)
{
if (args.WindowActivationState == WindowActivationState.Deactivated)
{
HideWindow();
return;
}
if (_initialActivationHandled)
{
return;
}
_initialActivationHandled = true;
PrimeWindow();
HideWindow();
}
private void OnClosed(object sender, WindowEventArgs e)
{
StopEventListeners();
_showEvent?.Dispose();
_showEvent = null;
_exitEvent?.Dispose();
_exitEvent = null;
if (_hwnd != IntPtr.Zero)
{
UncloakWindow();
}
}
private void PrimeWindow()
{
if (_isPrimed || _hwnd == IntPtr.Zero)
{
return;
}
_isPrimed = true;
if (_appWindow != null)
{
var currentPosition = _appWindow.Position;
_appWindow.MoveAndResize(new RectInt32(currentPosition.X, currentPosition.Y, DefaultWidth, DefaultHeight));
}
// Warm up the window while cloaked so the first summon does not pay XAML initialization cost.
var cloaked = CloakWindow();
if (cloaked)
{
ShowWindowNative(_hwnd, SwShowNoActivate);
}
}
private bool CloakWindow()
{
if (_hwnd == IntPtr.Zero)
{
return false;
}
if (_isWindowCloaked)
{
return true;
}
int cloak = 1;
var result = DwmSetWindowAttribute(_hwnd, DwmWaCloak, ref cloak, sizeof(int));
if (result == 0)
{
_isWindowCloaked = true;
SetWindowPosNative(_hwnd, HwndBottom, 0, 0, 0, 0, SwpNoMove | SwpNoSize | SwpNoActivate);
return true;
}
return false;
}
private void UncloakWindow()
{
if (_hwnd == IntPtr.Zero || !_isWindowCloaked)
{
return;
}
int cloak = 0;
var result = DwmSetWindowAttribute(_hwnd, DwmWaCloak, ref cloak, sizeof(int));
if (result == 0)
{
_isWindowCloaked = false;
}
}
[DllImport("user32.dll", EntryPoint = "ShowWindow", SetLastError = true)]
private static extern bool ShowWindowNative(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr", SetLastError = true)]
private static extern nint GetWindowLongPtrNative(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", SetLastError = true)]
private static extern nint SetWindowLongPtrNative(IntPtr hWnd, int nIndex, nint dwNewLong);
[DllImport("user32.dll", EntryPoint = "SetWindowPos", SetLastError = true)]
private static extern bool SetWindowPosNative(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
[DllImport("user32.dll", EntryPoint = "SetForegroundWindow", SetLastError = true)]
private static extern bool SetForegroundWindowNative(IntPtr hWnd);
[DllImport("dwmapi.dll", EntryPoint = "DwmSetWindowAttribute", SetLastError = true)]
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
private void EnsureListenerInfrastructure()
{
_listenerShutdownEvent ??= new ManualResetEventSlim(false);
}
private void StartShowListenerThread()
{
if (_showEvent == null || _listenerShutdownEvent == null || _showListenerThread != null)
{
return;
}
_showListenerThread = new Thread(ListenForShowEvents)
{
IsBackground = true,
Name = "QuickAccess-ShowEventListener",
};
_showListenerThread.Start();
}
private void StartExitListenerThread()
{
if (_exitEvent == null || _listenerShutdownEvent == null || _exitListenerThread != null)
{
return;
}
_exitListenerThread = new Thread(ListenForExitEvents)
{
IsBackground = true,
Name = "QuickAccess-ExitEventListener",
};
_exitListenerThread.Start();
}
private void ListenForShowEvents()
{
if (_showEvent == null || _listenerShutdownEvent == null)
{
return;
}
var handles = new WaitHandle[] { _showEvent, _listenerShutdownEvent.WaitHandle };
try
{
while (true)
{
var index = WaitHandle.WaitAny(handles);
if (index == 0)
{
_dispatcherQueue.TryEnqueue(ShowWindow);
}
else
{
break;
}
}
}
catch (ObjectDisposedException)
{
}
catch (ThreadInterruptedException)
{
}
}
private void ListenForExitEvents()
{
if (_exitEvent == null || _listenerShutdownEvent == null)
{
return;
}
var handles = new WaitHandle[] { _exitEvent, _listenerShutdownEvent.WaitHandle };
try
{
while (true)
{
var index = WaitHandle.WaitAny(handles);
if (index == 0)
{
_dispatcherQueue.TryEnqueue(Close);
break;
}
if (index == 1)
{
break;
}
}
}
catch (ObjectDisposedException)
{
}
catch (ThreadInterruptedException)
{
}
}
private void StopEventListeners()
{
if (_listenerShutdownEvent == null)
{
return;
}
_listenerShutdownEvent.Set();
JoinListenerThread(ref _showListenerThread);
JoinListenerThread(ref _exitListenerThread);
_listenerShutdownEvent.Dispose();
_listenerShutdownEvent = null;
}
private static void JoinListenerThread(ref Thread? thread)
{
if (thread == null)
{
return;
}
try
{
if (!thread.Join(TimeSpan.FromMilliseconds(250)))
{
thread.Interrupt();
thread.Join(TimeSpan.FromMilliseconds(250));
}
}
catch (ThreadInterruptedException)
{
}
catch (ThreadStateException)
{
}
thread = null;
}
private void CustomizeWindowChrome()
{
if (_hwnd == IntPtr.Zero)
{
return;
}
var stylePtr = GetWindowLongPtrNative(_hwnd, GwlStyle);
var lastError = Marshal.GetLastWin32Error();
if (stylePtr == nint.Zero && lastError != 0)
{
return;
}
var styleValue = (long)stylePtr;
var newStyleValue = styleValue & ~(WsSysmenu | WsMinimizeBox | WsMaximizeBox);
if (newStyleValue == styleValue)
{
return;
}
SetWindowLongPtrNative(_hwnd, GwlStyle, (nint)newStyleValue);
// Apply the new chrome immediately so caption buttons disappear right away.
SetWindowPosNative(_hwnd, IntPtr.Zero, 0, 0, 0, 0, SwpNoMove | SwpNoSize | SwpNoZorder | SwpNoActivate | SwpFrameChanged);
}
}

View File

@@ -0,0 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\Common.Dotnet.CsWinRT.props" />
<Import Project="..\..\Common.SelfContained.props" />
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net9.0-windows10.0.19041.0</TargetFramework>
<RootNamespace>Microsoft.PowerToys.QuickAccess</RootNamespace>
<AssemblyName>PowerToys.QuickAccess</AssemblyName>
<UseWinUI>true</UseWinUI>
<WindowsPackageType>None</WindowsPackageType>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<ApplicationManifest>app.manifest</ApplicationManifest>
<OutputPath>..\..\..\$(Platform)\$(Configuration)\WinUI3Apps</OutputPath>
<EnableDefaultPageItems>false</EnableDefaultPageItems>
<EnableDefaultApplicationDefinition>false</EnableDefaultApplicationDefinition>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml" />
<Page Include="MainWindow.xaml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.WindowsAppSDK" />
<PackageReference Include="WinUIEx" />
</ItemGroup>
<ItemGroup>
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,52 @@
// 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 System;
using System.Diagnostics.CodeAnalysis;
namespace Microsoft.PowerToys.QuickAccess;
public sealed record QuickAccessLaunchContext(string? ShowEventName, string? ExitEventName)
{
public static QuickAccessLaunchContext Parse(string[] args)
{
string? showEvent = null;
string? exitEvent = null;
foreach (var arg in args)
{
if (TryReadValue(arg, "--show-event", out var value))
{
showEvent = value;
}
else if (TryReadValue(arg, "--exit-event", out value))
{
exitEvent = value;
}
}
return new QuickAccessLaunchContext(showEvent, exitEvent);
}
private static bool TryReadValue(string candidate, string key, [NotNullWhen(true)] out string? value)
{
if (candidate.StartsWith(key, StringComparison.OrdinalIgnoreCase))
{
if (candidate.Length == key.Length)
{
value = null;
return false;
}
if (candidate[key.Length] == '=')
{
value = candidate[(key.Length + 1)..].Trim('"');
return true;
}
}
value = null;
return false;
}
}

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="PowerToys.QuickAccess.app" />
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</windowsSettings>
</application>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>