Shortcut Guide V2 (#40834)

## Summary of the Pull Request


https://github.com/user-attachments/assets/f4afdaf8-2830-4993-82ea-1ee9a6978e4c


<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [x] Closes: Status: #890 #15405 #179 #129 #22419 #31289 #47297 #47464
#44816
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [x] **Localization:** All end-user-facing strings can be localized
- [x] **Dev docs:** Added/updated
- [x] **New binaries:** Added on the required places
- [x] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [x] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [x] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here:
https://github.com/MicrosoftDocs/windows-dev-docs/pull/5717

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

Work for future PRs:

- [ ] Localization of built-in shortcut files
- [ ] Further customization (we can wait on user feedback for that)
- [ ] Reimplement holding windows key
- [ ] Search bar

<details>
<summary>Images</summary>


https://github.com/user-attachments/assets/f923daa4-d713-463b-ba33-ede72b986c12

<img width="726" height="1388" alt="image"
src="https://github.com/user-attachments/assets/781eff9a-2863-44be-bbe2-25371ef8838e"
/>
<img width="624" height="351" alt="image"
src="https://github.com/user-attachments/assets/ec8a44db-afbc-4e28-8285-ba2a9e345fb9"
/>
<img width="712" height="1086" alt="image"
src="https://github.com/user-attachments/assets/5a3775fc-36e9-4971-8d3f-491e8f8da45a"
/>
<img width="726" height="134" alt="image"
src="https://github.com/user-attachments/assets/7d0a8b1f-d10e-4466-820c-b3efdc5f3c84"
/>


</details>




<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed

---------

Co-authored-by: Gordon Lam (SH) <yeelam@microsoft.com>
Co-authored-by: Niels Laute <niels.laute@live.nl>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Muyuan Li <116717757+MuyuanMS@users.noreply.github.com>
Co-authored-by: Muyuan Li (from Dev Box) <muyuanli@microsoft.com>
This commit is contained in:
Noraa Junker
2026-05-21 17:27:52 +02:00
committed by GitHub
parent 5b16a8c945
commit 9699d8a802
164 changed files with 28640 additions and 4235 deletions

View File

@@ -104,7 +104,10 @@ public:
if (_enabled)
{
_enabled = false;
TerminateProcess();
if (IsProcessActive())
{
TerminateProcess(m_hProcess, 0);
}
}
else
{
@@ -131,10 +134,6 @@ public:
virtual std::optional<HotkeyEx> GetHotkeyEx() override
{
Logger::trace("GetHotkeyEx()");
if (m_shouldReactToPressedWinKey)
{
return std::nullopt;
}
return m_hotkey;
}
@@ -148,7 +147,7 @@ public:
if (IsProcessActive())
{
TerminateProcess();
TerminateProcess(m_hProcess, 0);
return;
}
@@ -170,16 +169,6 @@ public:
}
}
virtual bool keep_track_of_pressed_win_key() override
{
return m_shouldReactToPressedWinKey;
}
virtual UINT milliseconds_win_key_must_be_pressed() override
{
return std::min(m_millisecondsWinKeyPressTimeForGlobalWindowsShortcuts, m_millisecondsWinKeyPressTimeForTaskbarIconShortcuts);
}
private:
std::wstring app_name;
//contains the non localized key of the powertoy
@@ -193,7 +182,6 @@ private:
// If the module should be activated through the legacy pressing windows key behavior.
const UINT DEFAULT_MILLISECONDS_WIN_KEY_PRESS_TIME_FOR_GLOBAL_WINDOWS_SHORTCUTS = 900;
const UINT DEFAULT_MILLISECONDS_WIN_KEY_PRESS_TIME_FOR_TASKBAR_ICON_SHORTCUTS = 900;
bool m_shouldReactToPressedWinKey = false;
UINT m_millisecondsWinKeyPressTimeForGlobalWindowsShortcuts = DEFAULT_MILLISECONDS_WIN_KEY_PRESS_TIME_FOR_GLOBAL_WINDOWS_SHORTCUTS;
UINT m_millisecondsWinKeyPressTimeForTaskbarIconShortcuts = DEFAULT_MILLISECONDS_WIN_KEY_PRESS_TIME_FOR_TASKBAR_ICON_SHORTCUTS;
@@ -219,7 +207,7 @@ private:
SHELLEXECUTEINFOW sei{ sizeof(sei) };
sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI };
sei.lpFile = L"PowerToys.ShortcutGuide.exe";
sei.lpFile = L"WinUI3Apps\\PowerToys.ShortcutGuide.exe";
sei.nShow = SW_SHOWNORMAL;
sei.lpParameters = executable_args.data();
if (ShellExecuteExW(&sei) == false)
@@ -239,33 +227,18 @@ private:
return true;
}
void TerminateProcess()
{
if (m_hProcess)
{
if (WaitForSingleObject(m_hProcess, 0) != WAIT_OBJECT_0)
{
if (exitEvent && SetEvent(exitEvent))
{
Logger::trace(L"Signaled {}", CommonSharedConstants::SHORTCUT_GUIDE_EXIT_EVENT);
}
else
{
Logger::warn(L"Failed to signal {}", CommonSharedConstants::SHORTCUT_GUIDE_EXIT_EVENT);
}
}
else
{
CloseHandle(m_hProcess);
m_hProcess = nullptr;
Logger::trace("SG process was already terminated");
}
}
}
bool IsProcessActive()
{
return m_hProcess && WaitForSingleObject(m_hProcess, 0) != WAIT_OBJECT_0;
if (!m_hProcess)
{
return false;
}
auto result = WaitForSingleObject(m_hProcess, 0);
if (result == WAIT_FAILED)
{
Logger::error("Failed to wait for SG process.");
}
return result == WAIT_TIMEOUT;
}
void InitSettings()
@@ -289,10 +262,6 @@ private:
void ParseSettings(PowerToysSettings::PowerToyValues& settings)
{
m_shouldReactToPressedWinKey = false;
m_millisecondsWinKeyPressTimeForGlobalWindowsShortcuts = DEFAULT_MILLISECONDS_WIN_KEY_PRESS_TIME_FOR_GLOBAL_WINDOWS_SHORTCUTS;
m_millisecondsWinKeyPressTimeForTaskbarIconShortcuts = DEFAULT_MILLISECONDS_WIN_KEY_PRESS_TIME_FOR_TASKBAR_ICON_SHORTCUTS;
auto settingsObject = settings.get_raw_json();
if (settingsObject.GetView().Size())
{
@@ -328,36 +297,6 @@ private:
{
Logger::warn("Failed to initialize Shortcut Guide start shortcut");
}
try
{
// Parse Legacy windows key press behavior settings
auto jsonUseLegacyWinKeyBehaviorObject = settingsObject.GetNamedObject(L"properties").GetNamedObject(L"use_legacy_press_win_key_behavior");
m_shouldReactToPressedWinKey = jsonUseLegacyWinKeyBehaviorObject.GetNamedBoolean(L"value");
auto jsonPressTimeForGlobalWindowsShortcutsObject = settingsObject.GetNamedObject(L"properties").GetNamedObject(L"press_time");
auto jsonPressTimeForTaskbarIconShortcutsObject = settingsObject.GetNamedObject(L"properties").GetNamedObject(L"press_time_for_taskbar_icon_shortcuts");
int value = static_cast<int>(jsonPressTimeForGlobalWindowsShortcutsObject.GetNamedNumber(L"value"));
if (value >= 0)
{
m_millisecondsWinKeyPressTimeForGlobalWindowsShortcuts = value;
}
else
{
throw std::runtime_error("Invalid Press Time Windows Shortcuts value");
}
value = static_cast<int>(jsonPressTimeForTaskbarIconShortcutsObject.GetNamedNumber(L"value"));
if (value >= 0)
{
m_millisecondsWinKeyPressTimeForTaskbarIconShortcuts = value;
}
else
{
throw std::runtime_error("Invalid Press Time Taskbar Shortcuts value");
}
}
catch (...)
{
Logger::warn("Failed to get legacy win key behavior settings");
}
}
else
{