mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-09-02 20:18:53 +02:00
Shortcut Guide: Replace dual windows with single transparent overlay and add holding windows button (#48683)
## Summary Refactors Shortcut Guide from two separate `WindowEx` instances (`MainWindow` + `TaskbarWindow`) into a single full-monitor transparent `OverlayWindow` that hosts both surfaces as XAML UserControls. This enables shared animations and a more polished visual experience, and makes the taskbar shortcut indicators **edge-aware** for Windows 11's top/bottom/left/right taskbar positioning. https://github.com/user-attachments/assets/e40a25f6-4ab3-4073-b1a8-906ef7782877 <img width="507" height="968" alt="image" src="https://github.com/user-attachments/assets/2e06a3d9-32d9-482e-90fe-1f0f8a7d7598" /> ## Changes Closes: #48435 Closes #48491 Closes: #49200 Closes: #48552 (theme flash on Light/System theme + shortcut-list scroll flutter) Closes: #48773 ### Architecture - **OverlayWindow**: Single transparent host covering the full monitor work area, using `TransparentTintBackdrop` - **MainPaneControl**: The shortcut list pseudo-window, reusing the shared `TransientSurface` control for chrome (acrylic backdrop, theme shadow, rounded corners) - **TaskbarPaneControl + TaskbarIndicator**: Tooltip-style indicators with triangle tails, positioned above taskbar buttons ### Edge-aware taskbar indicators (Windows 11 top/bottom/left/right) - Detects the taskbar edge via the public, documented `SHAppBarMessage` / `ABM_GETTASKBARPOS` API (the same API CmdPal Dock uses) - Indicators lay out along the correct axis — horizontally for a top/bottom taskbar, vertically for a left/right taskbar — with the triangle tail always pointing toward the taskbar (4-direction tail + per-edge slide-in animation) - For a left/right taskbar, the main pane is inset so the order reads **taskbar | indicators | pane** - **Adaptive sizing**: each indicator's body size is derived from the actual measured UIA taskbar button rect, so the bubbles shrink when Windows uses small icons or combines buttons (many apps open). Uses the smallest button slot (clamped to a readable range) so neighbouring bubbles never overlap; the font scales with it ### Visual polish - Windows 11 system flyout entry/exit animations (slide + fade, ~367ms entrance / ~200ms exit with cubic easing) - Animation direction is position-aware (slides from left when left-aligned, from right when right-aligned) - Taskbar indicators slide in from the taskbar edge with the same timing - Close button on the main flyout title bar ### Robustness - Multi-monitor DPI handling via WM_DPICHANGED suppression (prevents double-scaling on cross-monitor moves) - Win11 phantom border elimination (comprehensive DWM/style stripping) - Click-outside-to-close with animated exit transition - Process lifetime fix (`Application.Current.Exit()` on close) ## Validation - Build clean (x64 Debug, exit 0, empty errors log) - Tested on multi-monitor mixed-DPI setup (150% + 100%) - Tested with the taskbar docked to each edge (top/bottom/left/right) and with small/combined taskbar icons --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Noraa Junker <noraa.junker@outlook.com> Co-authored-by: Clint Rutkas <clint@rutkas.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -10,7 +10,6 @@
|
||||
#include "../interface/powertoy_module_interface.h"
|
||||
#include "Generated Files/resource.h"
|
||||
#include <common/SettingsAPI/settings_objects.h>
|
||||
#include <common/utils/EventWaiter.h>
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD /*ul_reason_for_call*/, LPVOID /*lpReserved*/)
|
||||
{
|
||||
@@ -37,9 +36,10 @@ public:
|
||||
}
|
||||
|
||||
triggerEvent = CreateEvent(nullptr, false, false, CommonSharedConstants::SHORTCUT_GUIDE_TRIGGER_EVENT);
|
||||
triggerEventWaiter.start(CommonSharedConstants::SHORTCUT_GUIDE_TRIGGER_EVENT, [this](DWORD) {
|
||||
OnHotkeyEx();
|
||||
});
|
||||
if (!triggerEvent)
|
||||
{
|
||||
Logger::warn(L"Failed to create {} event. {}", CommonSharedConstants::SHORTCUT_GUIDE_TRIGGER_EVENT, get_last_error_or_default(GetLastError()));
|
||||
}
|
||||
|
||||
InitSettings();
|
||||
}
|
||||
@@ -91,6 +91,7 @@ public:
|
||||
if (!_enabled)
|
||||
{
|
||||
_enabled = true;
|
||||
StartProcess();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -127,6 +128,10 @@ public:
|
||||
{
|
||||
CloseHandle(exitEvent);
|
||||
}
|
||||
if (triggerEvent)
|
||||
{
|
||||
CloseHandle(triggerEvent);
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
@@ -145,19 +150,12 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsProcessActive())
|
||||
if (!IsProcessActive())
|
||||
{
|
||||
TerminateProcess(m_hProcess, 0);
|
||||
return;
|
||||
StartProcess();
|
||||
}
|
||||
|
||||
if (m_hProcess)
|
||||
{
|
||||
CloseHandle(m_hProcess);
|
||||
m_hProcess = nullptr;
|
||||
}
|
||||
|
||||
StartProcess();
|
||||
SetEvent(triggerEvent);
|
||||
}
|
||||
|
||||
virtual void send_settings_telemetry() override
|
||||
@@ -168,6 +166,8 @@ public:
|
||||
Logger::error("Failed to create a process to send settings telemetry");
|
||||
}
|
||||
}
|
||||
virtual bool keep_track_of_pressed_win_key() override { return true; }
|
||||
virtual UINT milliseconds_win_key_must_be_pressed() override { return 900; }
|
||||
|
||||
private:
|
||||
std::wstring app_name;
|
||||
@@ -187,7 +187,6 @@ private:
|
||||
|
||||
HANDLE triggerEvent;
|
||||
HANDLE exitEvent;
|
||||
EventWaiter triggerEventWaiter;
|
||||
|
||||
bool StartProcess(std::wstring args = L"")
|
||||
{
|
||||
@@ -196,6 +195,11 @@ private:
|
||||
ResetEvent(exitEvent);
|
||||
}
|
||||
|
||||
if (triggerEvent)
|
||||
{
|
||||
ResetEvent(triggerEvent);
|
||||
}
|
||||
|
||||
unsigned long powertoys_pid = GetCurrentProcessId();
|
||||
std::wstring executable_args = L"";
|
||||
executable_args.append(std::to_wstring(powertoys_pid));
|
||||
@@ -310,6 +314,14 @@ private:
|
||||
m_hotkey.vkCode = VK_OEM_2;
|
||||
}
|
||||
}
|
||||
|
||||
void WindowsKeyPressBehavior()
|
||||
{
|
||||
if (IsProcessActive())
|
||||
{
|
||||
TerminateProcess(m_hProcess, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
|
||||
|
||||
Reference in New Issue
Block a user