Compare commits

..

306 Commits

Author SHA1 Message Date
Michael Jolley
1d11b732b7 [CmdPal] Fix memory leak in PerformanceWidgetsPage network band items (#48880)
## Summary

Fixes a memory leak in the Performance Monitor dock extension where
`GetItems()` created **new** `ListItem` instances for `_networkUpItem`
and `_networkDownItem` on every call.

## Problem

When the dock subscribes to `ItemsChanged` and calls `GetItems()` to
refresh, the band page path allocates 2 new `ListItem` objects each time
— the old ones are replaced in the fields but never collected (they
remain referenced by the `DockItemViewModel` wrappers until the next
refresh cycle). Under normal operation this leaks ~2 objects/second
indefinitely.

## Fix

Move `_networkUpItem`/`_networkDownItem` creation into the constructor
(matching the pattern used by CPU, Memory, GPU, and Battery items).
`GetItems()` now returns stable references. The `Updated` event handler
already updates their `.Title` properties, which propagates to the UI
via `PropChanged` → `CommandItemViewModel.Model_PropChanged`.

## Validation

- Build succeeds (`Microsoft.CmdPal.Ext.PerformanceMonitor.csproj`)
- Network up/down band items still receive title updates via the
existing `Updated` handler
- No `RaiseItemsChanged()` needed — `ListItem.Title` setter fires
`PropChanged`, which `DockItemViewModel` already observes

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit 28e078897a)
2026-06-26 13:35:45 +08:00
Mike Griese
ab4792a4b8 Revert "[CmdPal][Dock] Fix performance meter showing '???' after restart" (#48835)
Reverts microsoft/PowerToys#48682

I'm quite sure that OP did not build or test these changes, and they
should not have merged.

(cherry picked from commit 386a16ff94)
2026-06-26 13:35:45 +08:00
Niels Laute
dc3a9da968 [Shortcut Guide] Prevent overlay crash on section navigation (#48448) (#48481)
## Summary of the Pull Request

Shortcut Guide overlay crashes and closes when navigating between
sidebar sections (e.g. clicking PowerToys, then clicking the Windows
icon to come back). Repro and crash logs in #48448. Crash logs in #48441
show the same propagation path plus a follow-up access violation in
coreclr, indicating exceptions that escape local catches.

This PR fixes the immediate navigation race and adds broader crash
hardening so future exceptions on the UI/background threads are logged
instead of tearing down the overlay.

### Navigation-race fix (commit 1)

Root cause: `WindowSelector_SelectionChanged` calls
`App.TaskBarWindow.Activate()` and then `SetWindowPosition()`
synchronously. `Activate()` runs a reentrant `Window_Activated` →
`BringToFront` → `TaskbarWindow.Activated` chain that can leave
`App.TaskBarWindow.AppWindow` momentarily null, so `SetWindowPosition`
throws `NullReferenceException`.

Because the initial `SelectedItem = MenuItems[0]` is set from
`SetNavItems`, the NRE bubbles up into `InitializeNavItemsAsync`'s catch
block — which sets `_closeType = "InitializationFailed"` and closes the
window. That matches both user-visible symptoms: the overlay "flashes
and disappears" (#48441) on open and "closes when clicking the Windows
icon" (#48448).

Edits in
`src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs`:

- **`SetWindowPosition`**: null-guard `App.TaskBarWindow?.AppWindow` and
skip the taskbar-overlap height adjustment when it is not currently
observable. Wrap the body in `try`/`catch` with `Logger.LogError` so any
future positioning hiccup keeps the previous layout instead of taking
down the overlay.
- **`WindowSelector_SelectionChanged`**: null-guard
`App.TaskBarWindow?.Hide()` / `Activate()` and wrap the body in
`try`/`catch`. This breaks the propagation path that lets a navigation
exception reach `InitializeNavItemsAsync`'s "fatal init failure" branch.

### Crash hardening (commit 2)

Additional defensive changes to cover other unguarded paths surfaced
while reviewing #48441:

- **`App.xaml.cs`**: register `App.UnhandledException`,
`AppDomain.CurrentDomain.UnhandledException`, and
`TaskScheduler.UnobservedTaskException` so a stray exception (e.g. an IO
failure during a fire-and-forget UI handler, or a background `Task`
fault) gets logged instead of tearing the process down with an access
violation in coreclr. Mirrors what Peek, AdvancedPaste, and CmdPal
already do.
- **`App.OnLaunched`**: wrap the launch sequence in `try`/`catch` and
exit cleanly with an error log on failure (`LoadData` / `MainWindow` /
`TaskbarWindow` ctors and `Activate` are all reachable failure points).
- **`App.LoadData`**: broaden the `Pinned.json` deserialize catch to
also handle `IOException` / `UnauthorizedAccessException`, and guard the
round-trip `SaveSettings` call as best-effort with a warning log.
- **`PinnedShortcutsHelper.Save`**: catch `IOException` /
`UnauthorizedAccessException` / `JsonException` and log; `Pin` / `Unpin`
runs from a synchronous UI handler so an unguarded `File.WriteAllText`
would tear down the overlay on any disk hiccup.
- **`TaskbarWindow.UpdateTasklistButtons`**: move the `AppWindow.Move`
calls inside the existing `try` block, null-guard
`App.MainWindow?.AppWindow` up front, and wrap the whole body so the
method (which runs from the ctor and from `Activated`) cannot tear the
overlay down when `MainWindow` is in a transient state.

## PR Checklist

- [x] Closes: #48448
- [x] Likely also fixes: #48441
- [x] **Communication:** Defensive fix to known crash paths; no API
change.
- [ ] **Tests:** No automated tests added — the failures are reentrancy
/ timing races that are hard to deterministically trigger in CI.
Validated with a synthetic repro (see below).
- [x] **Localization:** N/A — only logger strings.
- [x] **Dev docs:** N/A
- [x] **New binaries:** N/A

## Detailed Description of the Pull Request / Additional comments

The fix is intentionally defensive (rather than restructuring the
reentrant activation flow) because the legacy taskbar UIA enumeration
(`TasklistPositions.GetButtons`) on Windows 10 is what most reliably
widens the race window and is out of scope to redesign for a hotfix.

## Validation Steps Performed

- Build: `tools\build\build.cmd` from
`src\modules\ShortcutGuide\ShortcutGuide.Ui` — exit 0, errors log empty
for both commits.
- Synthetic repro: temporarily injected `throw new
NullReferenceException()` at the top of `SetWindowPosition` to exercise
the exact propagation path the reporter's log shows (`SetWindowPosition`
→ `SelectionChanged` → `set_SelectedItem` →
`InitializeNavItemsAsync.catch` → `Close("InitializationFailed")`).
- Before fix: overlay flashes and closes, log shows `Failed to
initialize navigation items.` with the NRE.
- After fix: overlay stays open, page navigates, log shows `Failed to
set Shortcut Guide window position; keeping previous layout.` from the
new `catch`.
- Did not reproduce the live race on a Win11 dev box; the reporter's
repro is Windows 10 19045 / Microsoft Store install where the legacy
taskbar UIA timing makes the reentrant chain more likely to expose the
null.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit 502dc40aa4)
2026-06-22 17:15:23 +08:00
moooyo
baee472288 [PowerDisplay] Detect built-in panel when driven by the discrete GPU (#48637)
On dual-GPU laptops, Power Display stopped detecting the built-in panel
(and adjusting its brightness) when the **discrete GPU** drives the
display — it showed "can't detect the display". This fixes that by
classifying displays by **capability** (does WMI brightness work on it?)
instead of by the nominal `OutputTechnology` value, which the discrete
GPU misreports for the internal panel.

- [x] Closes: #48587
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** All end-user-facing strings can be localized (no
new user-facing strings added)
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places

On a hybrid / MUX laptop, when the **discrete GPU** drives the built-in
eDP panel, `QueryDisplayConfig` reports the panel's
`DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY` as `DISPLAYPORT_EXTERNAL` (`10`)
instead of the `INTERNAL` flag (`0x80000000`) it reports under the
integrated GPU. It is the *same physical panel* (same EDID) — only the
reported connector type changes with the active GPU.

PR #47740 introduced a strict classifier: `OutputTechnology` →
internal/external, then **internal → WMI-only, external → DDC/CI-only,
with no fallback**. So under the discrete GPU the built-in panel was
classified *external* and sent to DDC/CI only — but a laptop eDP panel
does not speak DDC/CI, so it was dropped and Power Display reported it
couldn't detect any monitor. (`WmiMonitorBrightness` still exposes that
panel regardless of which GPU drives it, so the panel was actually
controllable — it just never got routed to WMI.)

- **`MonitorManager`** now runs **WMI discovery first** over the full
`QueryDisplayConfig` inventory. Every display `WmiMonitorBrightness`
exposes is treated as internal (WMI-controlled); whatever WMI does
**not** claim is routed to DDC/CI. The `OutputTechnology`-based
classifier is gone.
- **`WmiController`** matches the system-wide `WmiMonitorBrightness`
results against the full inventory by `Monitor.Id`. The persisted
`Monitor.Id` is still taken from the matched `DevicePath`
(byte-identical to the DDC route and to prior releases), so saved
brightness/per-monitor settings survive upgrades.
- New **`MonitorIdentity.FromInstanceName`** reduces a WMI
`InstanceName` to the same canonical `Monitor.Id` as `FromDevicePath`;
the separate `PnpHardwareKey` helper is removed.
- **Deleted** `DisplayClassifier` and `MonitorDisplayInfo.IsInternal`
(net ~150 fewer lines).

A monitor that exposes **both** `WmiMonitorBrightness` **and** DDC/CI is
now controlled via WMI only and won't get DDC-only features (contrast /
volume / input source / color temperature / power). This is uncommon
(typical laptop panels are WMI-only; typical external monitors are
DDC-only) and is a deliberate decision: it removes the entire class of
`OutputTechnology` misclassification bugs while keeping the performance
win of not DDC-probing internal panels.

- Built the Power Display app (`PowerDisplay.csproj`) and
`PowerDisplay.Lib.UnitTests` (x64 / Debug) with MSBuild — both succeed,
including after merging latest `main` (Windows App SDK 2.2.0).
- Ran the unit test suite: **128/128 pass**, including new
`FromInstanceName` tests — the `FromInstanceName == FromDevicePath`
equivalence invariant and a concrete #48587 regression case (the BOE
panel reported as `OutputTechnology=10`).
- Traced the fix against the reporter's diagnostic logs: the panel that
previously went `OutputTechnology=10 → External → DDC → dropped` is now
claimed by WMI and controllable.
- Reviewed the diff for regressions (Monitor.Id persistence, monitor
blacklist, mirror mode, dual-internal-panel devices, external-only
desktops).

---------

Co-authored-by: Yu Leng <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
(cherry picked from commit 32ad98a0dd)
2026-06-22 16:30:19 +08:00
Bryce Cindrich
142833d49a fix(shortcut-guide): use <N> token for literal digit keys in manifests (#48757)
## Summary of the Pull Request

Converts the literal-digit shortcut keys in the bundled Shortcut Guide
manifests to the `<N>` special-key convention, so they render as the
correct number.

Per the manifest spec, a bare number in `Keys:` is a virtual-key code. A
literal digit key authored as a bare number is therefore misread (VK `9`
is Tab, VK `1` is the left mouse button, VK `0` is undefined) and
renders incorrectly. The fix authors these as the `<N>` token (for
example `"<9>"`), which `KeyVisual` strips to display the digit.

This is a data-only change: **91 literal-digit keys across 14
manifests** become `<N>` tokens. No code or doc changes; the renderer
and converter already support `<N>`, and the convention is documented in
the spec.

Follow-up to #48461, which introduced and documented the `<N>`
convention (per @noraa-junker's request for a separate PR to fix the
remaining manifests). Together with #48461 this resolves the rendering
reported in #48460.

Files touched (all under
`src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/Manifests/`):
Adobe.Illustrator (18), Adobe.Photoshop (17), SlackTechnologies.Slack
(13), Adobe.InDesign (11), JetBrains.IntelliJIDEA.Community (11),
BlenderFoundation.Blender (3), Figma.Figma (3), Google.Chrome (3),
Microsoft.Edge (3), Microsoft.VisualStudioCode (3), Mozilla.Firefox (3),
+WindowsNT.Notepad (1), Adobe.AfterEffects (1), GIMP.GIMP (1).

## PR Checklist

- [ ] **Closes:** N/A (follow-up to #48461; contributes to #48460)
- [ ] **Communication:** discussed in #48461; @noraa-junker requested
this separate PR.
- [ ] **Tests:** N/A for data; the converter and `<N>` convention are
unit-tested in #48461. Validated here by deserializing every manifest
with YamlDotNet (see below).
- [x] **Localization:** unchanged; these are per-language manifest
files.
- [ ] **Dev docs:** N/A (the `<N>` convention is documented in the spec
via #48461).
- [ ] **New binaries:** N/A.
- [ ] **Documentation updated:** N/A.

## Detailed Description of the Pull Request / Additional comments

Each change wraps a single bare digit in angle brackets, for example:

```yaml
          Keys:
-            - 9
+            - "<9>"
```

Quoted tokens (`"<9>"`) are used to match the dominant special-token
style already in the manifests (`"<Enter>"`, `"<Down>"`, etc.).

Note (out of scope): `Adobe.Photoshop.en-US.yml` has a shortcut with an
empty `Name: ""` (around line 799). That is a pre-existing data issue
unrelated to digit rendering; the digit is still converted, and the
empty name is left as-is.

## Validation Steps Performed

- Confirmed the diff touches only the 14 manifests, 91 insertions and 91
deletions, with each changed line being a digit wrapped as `"<N>"` (no
whitespace, indentation, or encoding churn).
- Confirmed zero bare-digit `Keys` entries remain and exactly 91 new
`"<N>"` tokens exist.
- Deserialized all 32 manifests with YamlDotNet (the same library the
app uses at runtime): 0 parse errors.
- Rendering behavior for `<N>` is already verified in #48461 (the
renderer strips the brackets to show the digit).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit cabb71108a)
2026-06-22 16:29:53 +08:00
Bryce Cindrich
46d594a7f5 feat(shortcut-guide): add Postman manifest and fix numbered-key display (#48461)
## Summary of the Pull Request

Adds a Shortcut Guide manifest for **Postman** and fixes a rendering bug
where single-digit keys in manifests displayed incorrectly.

- **Fix numbered-key rendering** —
`src/modules/ShortcutGuide/ShortcutGuide.Ui/Converters/ShortcutDescriptionToKeysConverter.cs`:
a single digit (`0`–`9`) in a manifest's `Keys` was treated as a Windows
virtual-key code instead of the literal digit. Since VK `1` is the left
mouse button, VK `9` is Tab, and VK `0` is undefined, shortcuts such as
`Ctrl+0` (reset zoom) and `Ctrl+9` (last tab) rendered as
blank/incorrect glyphs. Single digits are now rendered as the literal
character.
- **Add Postman shortcuts** —
`src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/Manifests/Postman.Postman.en-US.yml`:
new manifest for `Postman.exe` covering Tabs, Sidebar, Request,
Interface, Window and modals, and Console. Auto-included via the
existing `Manifests/*.yml` glob in `ShortcutGuide.Ui.csproj`.
- **Show tab-number ranges** — Edge, Chrome, Firefox, and Postman
manifests: the "switch to a specific tab" entry used the literal key
`1`, which (after the fix above) read as `Ctrl + 1`. It now uses a `1 -
8` range so the keycap conveys "any tab number 1 through 8". The
separate "last tab" (`9`) and "reset zoom" (`0`) entries remain literal
single keys.
- **Add unit tests** — new `ShortcutGuide.UnitTests` (MSTest) project
covering `ShortcutDescriptionToKeysConverter.GetKeysList`, including the
single-digit regression.

## PR Checklist

- [x] Closes: #48460
- [ ] **Communication:** I've discussed this with core contributors
already. <!-- Filed #48460; the v0.100 announcement invites app-shortcut
contributions via PR. -->
- [x] **Tests:** Added/updated and all pass <!-- New
ShortcutGuide.UnitTests (MSTest); 8 tests pass locally via
vstest.console. -->
- [x] **Localization:** All end-user-facing strings can be localized
<!-- Shortcut names live in per-language manifest files (`*.en-US.yml`);
other locales fall back to en-US, consistent with existing manifests.
-->
- [ ] **Dev docs:** Added/updated <!-- N/A: no behavior requiring
dev-doc changes. -->
- [ ] **New binaries:** Added on the required places <!-- N/A: the new
manifest is a data asset under an already-shipped, globbed folder. The
new test project is auto-discovered by the existing `**\*UnitTest*.dll`
VSTest glob, so no CI pipeline change is required. -->
- [ ] **Documentation updated:** <!-- N/A -->

## Detailed Description of the Pull Request / Additional comments

The Shortcut Guide displays per-app shortcuts from YAML manifests,
matched to the foreground window via `WindowFilter`. Keys are converted
to keycaps by `ShortcutDescriptionToKeysConverter`. Numeric key strings
were unconditionally parsed as virtual-key codes, so literal-digit
shortcuts rendered wrong. The fix adds a `>= 0 and <= 9` case that emits
the digit character as-is; non-digit numeric codes (arrows, etc.) are
unchanged.

The new Postman manifest exercises this with `Ctrl+0` / `Ctrl+9`. The
browser/Postman "specific tab" entries were updated from the literal `1`
to the `1 - 8` range string, rendered verbatim by `KeyVisual` (the same
path used by the existing `Number (1-9)` key in the Windows Explorer
manifest).

A new `ShortcutGuide.UnitTests` (MSTest) project covers the converter:
single digits render literally (regression test), modifier ordering,
non-numeric passthrough (e.g. `1 - 8`), and arrow-key VK mapping.

## Validation Steps Performed

Built and ran locally (x64 Debug):

- Built `ShortcutGuideModuleInterface`, `ShortcutGuide.Ui`, and
`ShortcutGuide.IndexYmlGenerator`; launched the Debug `PowerToys.exe`.
- Triggered Shortcut Guide (`Win+Shift+/`) with **Postman** focused: the
Postman section renders with all categories, and `Ctrl+1` / `Ctrl+9` /
`Ctrl+0` display correctly (previously blank/incorrect).
- Verified the "specific tab" entry renders as `Ctrl + 1 - 8` in
**Edge**, **Chrome**, **Firefox**, and **Postman**.
- Built `ShortcutGuide.UnitTests` and ran via `vstest.console.exe`:
**8/8 tests pass**.

<img width="845" height="1432" alt="PowerToys Shortcut Guide Running
Postman"
src="https://github.com/user-attachments/assets/6359617e-3e2c-48b0-8005-b3684594ec94"
/>

Co-Authored-By: Claude Opus 4.8

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit a0e53de825)
2026-06-22 16:29:52 +08:00
Dave Rayment
673a41512c [ColorPicker] Fix the main window UI appearing in the zoomed-in view (#48762)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [x] Closes: #37801
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

<!-- 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
This uses `SetWindowAffinity()` with the `WDA_EXCLUDEFROMCAPTURE`
constant on the main Color Picker window to ensure the ZoomWindow bitmap
creation excludes the corner of the picker UI. The ability to capture
the picker window is restored immediately after, so it's still visible
in Snipping Tool, Remote Desktop and other tools.

The fix uses a new helper with simple `Include()` / `Exclude()` methods
as an adapter to the native code. This may potentially be included in
Common if other utilities needed it.

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
1. Repro'd the original issue on the current Color Picker release:
<img width="262" height="263" alt="image"
src="https://github.com/user-attachments/assets/bc12b2f8-b67f-4b56-a803-57ab2fe0fa17"
/>

2. Confirmed that the fix worked and normal window affinity was restored
(otherwise I would not have been able to snip this):
<img width="262" height="262" alt="image"
src="https://github.com/user-attachments/assets/bc336ad0-4114-49fa-8440-b78466de363f"
/>

3. Repeated zooming in and out over a normal session.

(cherry picked from commit eab305334b)
2026-06-22 16:29:52 +08:00
Eymard Silva
f57062c206 Fix VS Code Workspaces shared storage lookup (#47505)
## Summary

Fixes VS Code Workspaces recent entries discovery after VS Code 1.118
moved `history.recentlyOpenedPathsList` to the shared application
storage database.

The plugin now probes both the legacy `User/globalStorage/state.vscdb`
database and the new shared storage database for VS Code Stable,
Insiders, Exploration, VSCodium, VSCodium Insiders, and portable
installs.

It also deduplicates results that may appear in both locations.

Fixes #47445

## Validation

- Reviewed the change against the issue's documented VS Code 1.118
storage paths.
- Attempted local focused build from
`src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces`
with `tools/build/build.cmd -Platform x64 -Configuration Debug`.
- Build was blocked by local environment/tooling issues unrelated to
this C# change: missing/invalid VC tooling/Windows SDK.

(cherry picked from commit e1b1a8d7ed)
2026-06-22 16:29:52 +08:00
Mike Griese
f339b48324 CmdPal: Only list available docks when pinning (#48723)
This is a totally minor nitpick.

I don't have the dock enabled on all my displays. But the current "pin
to dock" dialog lets me pin it to a display I don't have the dock on.
When that happens, it effectively results in _nothing_ happening. Not
great.

This PR mitigates that situation, but only listing the enabled docks
when pinning.

(cherry picked from commit 6dcda8a6aa)
2026-06-22 16:29:52 +08:00
ABHIJEET KALE
f590871d6d [CmdPal][Dock] Fix performance meter showing '???' after restart (#48682)
This PR fixes Issue #48680 where the CmdPal dock performance meter shows
'???' after restart.

**Root cause**: The PerformanceWidgetsPage initially returns items with
a placeholder title ('???') because ContentData hasn't loaded yet. The
DataManager timer starts when the dock subscribes to ItemsChanged, and
the Updated event fires 1 second later with real data. However, the
Updated event handlers were updating ListItem.Title directly without
calling RaiseItemsChanged() on the page, so the dock was never notified
that the items had changed and continued to display the stale '???'
title.

**Fix**: Added a RaiseItemsChanged() call to each of the 5 Updated event
handlers (CPU, Memory, Network, GPU, Battery) after the item titles are
updated. This causes the dock to re-call GetItems() and refresh the
displayed titles.

Fixes #48680

(cherry picked from commit 0d12a62abb)
2026-06-22 16:29:52 +08:00
William
bdcedb142e Changed sleep icon to hibernation icon in Command Palette (#48689)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Changed the icon from the sleep icon to the hibernate icon, which fixes
the issue in #48535

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

- [x] Closes: #48535
## Detailed Description of the Pull Request / Additional comments
The icon was previously the sleep icon, and I have changed it to the
hibernate icon.

## Validation Steps Performed
I have visually checked that the icon is now updated to the correct
icon.

(cherry picked from commit 2125d739a3)
2026-06-22 16:29:52 +08:00
Mike Griese
7da85cac40 CmdPal: fix initializing the Run history in AOT builds (#48463)
Regressed in one of the last two releases.

The problem was that `history.ToImmutableList()` ran on the projected
`IVector<string>`. `ImmutableList.CreateRange` checks for
`IReadOnlyCollection<string>`, and resolving that interface on a WinRT
object requires a helper type that AOT can't generate.

So we have to just _not do that_.

Closes #48445

(cherry picked from commit fb0f4292eb)
2026-06-22 16:29:52 +08:00
Clint Rutkas
750ef385b8 [QuickAccess] Suppress unhandled XAML exceptions in flyout host (#48457)
## Summary

Adds the two missing top-level exception handlers in the QuickAccess
(Preview) flyout host so that an unhandled XAML exception during launch
or page navigation no longer FailFasts `PowerToys.QuickAccess.exe`.

Spotted while reading through `App.OnLaunched` and `ShellPage` for an
unrelated review of the flyout startup path — none of the existing
handlers exist yet, so any throw during `MainWindow` construction,
`ShellHost.Initialize`, or `ContentFrame.Navigate(typeof(LaunchPage) |
typeof(AppsListPage), …)` bubbles all the way out to the Windows App SDK
runtime and is stowed as a XAML failure. Compare with
`src\settings-ui\Settings.UI\SettingsXAML\App.xaml.cs`, which already
wires `UnhandledException += App_UnhandledException`.

## Changes

**`src\settings-ui\QuickAccess.UI\QuickAccessXAML\App.xaml.cs`**

- Hook `Application.UnhandledException` in the constructor. The handler
logs the exception via `ManagedCommon.Logger.LogError` (same logger
Settings uses) and sets `e.Handled = true`. QuickAccess is a transient
launcher flyout owned by the runner, so swallowing a stray XAML error
and keeping the host alive for the next summon is the correct trade-off
— the failure is still recorded for diagnostics.
- Wrap the body of `OnLaunched` in a try/catch. If `MainWindow` (which
sets up window chrome, listener threads, the IPC coordinator, and the
XAML shell) fails to construct, log the exception and call `Exit()`
cleanly rather than letting the throw escape into the Windows App SDK
launch path.

**`src\settings-ui\QuickAccess.UI\QuickAccessXAML\Flyout\ShellPage.xaml.cs`**

- Subscribe to `ContentFrame.NavigationFailed` after
`InitializeComponent`. A page constructor or XAML-load failure in
`LaunchPage` / `AppsListPage` would otherwise bubble out of the `Frame`
and crash the launcher. The handler logs the failure
(`SourcePageType.FullName` + the exception) and marks it handled so the
next summon retries navigation.

No production behaviour changes when things work — only the failure
paths are different. No public API surface changes.

## Why both handlers, not just one

- `Application.UnhandledException` does not fire for
`Frame.NavigationFailed`. The Frame raises its own event first and, if
no handler runs or `e.Handled` is left `false`, then it rethrows on the
dispatcher.
- Conversely, `Frame.NavigationFailed` only fires for navigation
failures — not for an exception thrown directly in `OnLaunched` before
any navigation happens.

The two events are complementary, so both need a handler to fully cover
the launch + navigation paths.

## Testing

- The local NuGet feed on my dev box currently can't restore
`Microsoft.NETCore.App.Runtime.win-x64 = 10.0.9` (the feed only has
`11.0.0-preview.1.26104.118`), which fails the project restore for every
WinUI project including this one. That's the same environment issue I
called out on #48414 — pipeline restore uses a different feed and is
fine.
- All three patterns added here are copy-paste analogues of code that
already exists in `Settings.UI` (`App.xaml.cs:96, 106-109`,
`ShellViewModel.cs:86, 136`), so namespace and signature drift risk is
minimal. The only behavioural difference is `e.Handled = true`, which is
the actual goal of this PR.

## Risk

- Low. Two new event handlers and one try/catch. No behaviour change on
the success path.
- Worst-case regression is that a real, repeatable XAML failure becomes
silent in the runner's eyes (no process crash) instead of loud — but
it's logged via `Logger.LogError` so the user can still find the trace
in `%LOCALAPPDATA%\Microsoft\PowerToys\Logs\`.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---

ADO:
https://microsoft.visualstudio.com/DefaultCollection/OS/_workitems/edit/61258633/

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit ab4947579b)
2026-06-22 16:29:51 +08:00
Matheus Mol
7279bfd9ec [KBM] Fix modifier key remapped to non-modifier delivering WM_SYSKEYDOWN (#47192)
## Summary of the Pull Request

When a modifier key (Ctrl/Alt/Shift) is remapped to a non-modifier key
using
Keyboard Manager, the injected key event is delivered to applications as
WM_SYSKEYDOWN instead of WM_KEYDOWN. This causes unexpected behavior —
for
example, remapping Left Alt to Backspace results in whole words being
deleted
instead of single characters, because applications interpret
WM_SYSKEYDOWN +
VK_BACK as Alt+Backspace.

The fix resets the modifier state with a suppress-flag key-up event
before
injecting the target key, consistent with the existing approach used for
the
Caps Lock remapping scenario.

## PR Checklist

- [ ] Closes: #47191
- [ ] Communication: I've discussed this with core contributors already.
If the work hasn't been agreed, this work might be rejected
- [x] Tests: Added/updated and all pass
- [ ] Localization: All end-user-facing strings can be localized
- [ ] Dev docs: Added/updated
- [ ] New binaries: Added on the required places

## Detailed Description of the Pull Request / Additional comments

The root cause is that SendInput is called inside the low-level keyboard
hook
callback before the original modifier event is suppressed. At that point
the
modifier state is still active, so the OS delivers the injected key as
WM_SYSKEYDOWN (system key with Alt context) rather than WM_KEYDOWN.

This is the same mechanism that was already fixed for the Ctrl/Alt/Shift
↔
Caps Lock case. This PR extends the fix to cover modifier → non-modifier
remaps.

## Validation Steps Performed

1. Remapped Left Alt → Backspace in Keyboard Manager
2. Opened a text editor, typed text, pressed the remapped key
3. Confirmed single characters are deleted instead of whole words
4. All 93 unit tests pass (KeyboardManager.Engine.UnitTests)

(cherry picked from commit 5688441127)
2026-06-22 16:29:51 +08:00
Mario Hewardt
8d6bb43c26 ZoomIt - Fix race condition in audio init (#48685)
It was a race condition.

(cherry picked from commit d9216f0fc7)
2026-06-22 16:29:51 +08:00
moooyo
b82e3535da [PowerDisplay] Allow waking a monitor from standby via power-state On (#48628)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

Power Display could put a monitor to sleep but never wake it back up.
Selecting **On** in the per-monitor power-state list was a hard-coded
no-op, so the DDC/CI wake command (VCP `0xD6` = `0x01`) was never sent.
This removes that guard so selecting **On** wakes the display, and
cleans up the dead code/comment left behind by the original
one-directional design.

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

- [x] Closes: #48428
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [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
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

`MonitorViewModel.HandlePowerStateSelectionChanged` early-returned when
the selected power state was **On** (`0x01`), so `SetPowerStateAsync`
was never called for On and the wake write never reached the monitor. As
a result Power Display's power control was one-directional: it could
send Standby/Suspend/Off but could never turn a monitor back on.

The guard dates back to the very first power-state commit and was paired
with a single-monitor assumption — *"the monitor must be on to see the
UI"*, so On was treated as the always-current state and skipped. A later
change made the selection reflect the monitor's real power state (so a
monitor in the list can legitimately be asleep), and multi-monitor
support means the flyout can be shown on monitor A while the user wants
to wake monitor B. Those changes invalidated the assumption, but the
action-side guard survived a subsequent refactor.

The lower layers already do the right thing:
`MonitorManager.SetPowerStateAsync` →
`DdcCiController.SetPowerStateAsync` → `SetVcpFeatureAsync(monitor,
0xD6, value)` passes the value through unchanged, so the fix is purely
removing the UI-layer guard. DDC/CI stays reachable while the panel is
in Standby/Suspend/Off(DPM), so writing `0x01` turns it back on (this is
the same mechanism Twinkle Tray uses). `Off (Hard)` / `0x05` may still
require a physical wake on some monitors, since that state can cut the
DDC command channel.

Cleanup included in this PR:
- Removed the now-unused `PowerStateItem.PowerStateOn` constant (its
only consumer was the deleted guard).
- Removed the dead `SetPowerState` `[RelayCommand]` (the generated
`SetPowerStateCommand` had zero references — the XAML wires
`SelectionChanged`, not a command).
- Updated the `SetPowerStateAsync` doc comment from the one-directional
framing to a neutral bidirectional description.

Net change: 2 files, +5 / −24.

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

- **Build:** `MSBuild PowerDisplay.csproj -p:Platform=x64
-p:Configuration=Debug` (CoreCompile) — **0 errors / 0 warnings**.
- **Static check:** repo-wide grep confirms no remaining references to
`PowerStateOn` or `SetPowerStateCommand`; the power-state ListView binds
only `ItemsSource` + `SelectionChanged` (no `SelectedItem` binding), so
opening the flyout cannot spuriously re-fire a selection.
- **Manual (requires a DDC/CI monitor):** enable *Power state control*
for a monitor → open its flyout and select **Standby** or **Off (DPM)**
(screen blanks) → reopen the flyout and select **On** → the display
wakes.

No automated test was added: with the guard removed the handler is an
unconditional pass-through (identical in shape to
`HandleInputSourceSelectionChanged`), and it is an `async void` WinUI
event handler over real DDC/CI hardware, which is outside the
`PowerDisplay.Lib` unit-test seam.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Yu Leng <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
(cherry picked from commit ff3c1f9252)
2026-06-22 16:29:13 +08:00
Boliang Zhang (from Dev Box)
d81186267d Merge main into stable for 0.100 release (rev 14) 2026-06-09 23:45:55 +08:00
Alex Mihaiuc
d57096af20 Fix broken hotkeys condition (#48401)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

This fixes a bug introduced by
`ba68b88ca1617e52647c6dde467c56f53ca2422a` in the hotkey processing
logic.

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

A complex condition ended up being incorrectly broken into 2 conditions,
leading to a missed `else` execution. This led to the mishandling of
keyboard shortcuts especially during reassignment in the standalone mode
for ZoomIt.

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-06-09 15:44:08 +02:00
Noraa Junker
f136a4fe04 [Shortcut Guide] Fix foreground window detection (#48386)
## Summary of the Pull Request

This PR fixes Shortcut Guide foreground app detection by resolving app
IDs from the window that was in the foreground before the Shortcut Guide
UI takes focus.

Based on review feedback, it also adds the missing XML `<param>`
documentation for `foregroundWindowHandle` in
`ManifestInterpreter.GetAllCurrentApplicationIds(...)` to satisfy
documentation/style requirements.

## PR Checklist

- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

### Functional change
- Capture and reuse the foreground window handle taken before Shortcut
Guide UI activation.
- Use that captured handle for current-application ID resolution instead
of querying foreground window later, improving app-specific shortcut
matching reliability.

### Follow-up feedback fix
- Added missing XML parameter documentation:
-
`src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/ManifestInterpreter.cs`
  - Added `<param name="foregroundWindowHandle">...</param>`

## Validation Steps Performed

- Ran `parallel_validation` (Code Review: no issues; CodeQL: skipped as
trivial doc-only follow-up).
- Attempted local `dotnet build` for `ShortcutGuide.Ui.csproj`; blocked
by transient external package feed/network failure while restoring
`Microsoft.Build.CopyOnWrite/1.0.282`.

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-06-09 20:00:46 +08:00
Niels Laute
87fa204fd6 Disable Shortcut Guide by default on clean installs (#48383)
## Summary

Flips the default for the `Shortcut Guide` entry in `enabledModules`
from `true` to `false`. New PowerToys installs (no prior
`settings.json`) will start with Shortcut Guide disabled, matching how
other newer modules (PowerToys Run, MouseJump, AdvancedPaste,
MouseWithoutBorders, CropAndLock, QuickAccent, TextExtractor,
MousePointerCrosshairs, KeyboardManager) already ship off-by-default in
`EnabledModules.cs`.

## Why

Shortcut Guide has been on-by-default since the early days, but it is an
opt-in style utility (overlay launched on hotkey). It should not be
active for users who never asked for it on a fresh install.

## Changes

- `src/settings-ui/Settings.UI.Library/EnabledModules.cs` -- flip
`shortcutGuide` backing field from `= true` to bare declaration with the
file's `// defaulting to off` comment convention.
- `src/settings-ui/Settings.UI.UnitTests/ViewModelTests/General.cs` --
update the corresponding `AllModulesAreEnabledByDefault` assertion.

## Compatibility

Existing installs are unaffected: their `settings.json` already persists
the user's prior value (`true`), so anyone who has it on today keeps it
on. Only freshly created `EnabledModules` instances pick up the new
default.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-09 17:06:40 +08:00
Niels Laute
6ebfac8eab [Shortcut Guide] Settings footer icon clip fix and vector nav icons (#48390)
## Summary of the Pull Request

Visual polish for the Shortcut Guide UI, follow-up to #48383 and #48384.

- Fixes the Settings footer icon being clipped in the rail at startup.
Root cause: the icon `RowDefinition` in `CustomNavigationViewStyle.xaml`
was `*`, so the rail's `MinHeight` constraint compressed the 20px icon
down. Changing it to `Auto` lets the row size to its content. This also
removes the need for the `FakeSettingsButton` workaround.
- Replaces the laptop `FontIcon` used for the `Windows` nav entry with a
4-square Windows logo rendered as a `PathIcon`.
- Replaces the bitmap PowerToys app icon with a theme-aware vector
`PathIcon` (rounded square frame + menu bar + three dots) so it matches
the rest of the icons.
- Path data for both icons lives as `x:String` resources in `App.xaml`.
- Tunes the rail item `Row 0` height so the icon vertically aligns with
the selection pill center.

<img width="681" height="1405" alt="image"
src="https://github.com/user-attachments/assets/10787087-e32f-4018-b004-3f824648b962"
/>

## PR Checklist

- [x] **Closes:** part of the Shortcut Guide 0.100 polish set
- [x] **Communication:** internal only
- [x] **Tests:** manual verification
- [x] **Localization:** no new strings
- [x] **Dev docs:** N/A

## Validation Steps Performed

- Built locally and verified the Settings footer icon is no longer
clipped on first show.
- Verified the Windows nav entry now uses the Windows logo PathIcon and
renders correctly in light and dark.
- Verified the PowerToys entry now renders as a vector and follows the
theme foreground.
- Verified the selection pill aligns vertically with the icon center.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-09 17:06:17 +08:00
Jessica Dene Earley-Cha
582f3eb5c3 Move from testing to final for telemetry PR detection workflow (#47993)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

Transitions the telemetry PR detection workflow from testing phase to
ready status. All components are now fully functional and automatically
triggered on every new PR.

- Skips checks on draft PRs to avoid noise
- Prevents multiple concurrent runs per PR
- Safely requests `@chatasweetie` as reviewer on telemetry changes
- update commit messages

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Carlos Zamora <carlos.zamora@microsoft.com>
2026-06-08 22:56:09 +02:00
Boliang Zhang (from Dev Box)
d22589bcf6 Revert "Add copy monitor diagnostics button to Power Display (#48209)"
This reverts commit 76eb6eaac5.
2026-06-05 15:42:28 +08:00
Boliang Zhang (from Dev Box)
0aed70cc87 Merge main into stable for 0.100 release (rev 13) 2026-06-05 11:33:54 +08:00
Mike Griese
4f14070a1a cmdpal: blindly try to fix dock usage data (#48283)
We have no idea why this event isn't flowing in 0.99. We fixed the other
"new" event, `CmdPal_ExtensionInvoked`, when we merged #47121. But this
event didn't show up.

So, as a blind experiment, we're removing the potentially long payload.
Just to see if something happens.
2026-06-05 11:31:00 +08:00
Shinpache Shimura
76eb6eaac5 Add copy monitor diagnostics button to Power Display (#48209)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [x] Closes: #47572 
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

In the powerdisplay tool, Added a new button, that allows to copy the
current display configuration, to allow to share for troubleshooting, or
just sharing.

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-06-05 01:14:09 +08:00
Boliang Zhang (from Dev Box)
ba70becdef Merge main into stable for 0.100 release (rev 12) 2026-06-03 17:43:12 +08:00
Jessica Dene Earley-Cha
97f2868481 Fix: Narrator announces checkbox labels in CmdPal Extensions > Installed Apps page (#48135)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

Fixes labels not associated with controls in Installed Apps pane.
Narrator only announces "space, checkbox, checked/unchecked" for
Extensions > Installed Apps page checkboxes instead of reading the label
too.

this is an a11y internal bug

The Adaptive Cards renderer (`AdaptiveCards.Rendering.WinUI3` v2.x)
renders `Input.Toggle` as a CheckBox whose `Content` is a TextBlock
containing just `" "`. Without an AutomationProperties.Name`, Narrator
reads the CheckBox.Content (a space character), making the settings
inaccessible to screen reader users.

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Michael Jolley <mike@baldbeardedbuilder.com>
2026-06-03 07:50:35 +02:00
Pranshu Namdeo
f3d3abc552 Fix Performance Monitor settings file path collision (#48251)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Fixes #48224

The Performance Monitor extension was still storing its settings in the
shared settings.json file. Since Command Palette built-in extensions now
use extension-specific sibling settings files, the extension's settings
could be overwritten when Command Palette personalization settings were
saved.

This change updates SettingsJsonPath() to store Performance Monitor
settings in an extension-specific settings file
(performanceMonitor.settings.json), ensuring the network speed unit
setting persists correctly.

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

- [x] Closes: #48224 
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

The Performance Monitor extension had not been migrated to the newer
extension-specific settings file architecture. As a result, its settings
were stored in the shared settings.json file and could be lost when the
Command Palette host rewrote its configuration.

Following @zadjii-msft's guidance in the issue, this PR updates
SettingsManager.cs to store Performance Monitor settings in an
extension-specific settings file:

performanceMonitor.settings.json

instead of the shared:

settings.json

This aligns the extension with the current Command Palette settings
architecture and prevents the network speed unit setting from being
overwritten.


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

* Changed Network Speed Unit to "Binary bytes per second" in Performance
Monitor settings.
* Verified the setting was successfully saved to the newly created
`performanceMonitor.settings.json` file.
* Modified core Command Palette personalization settings.
* Verified the Performance Monitor setting was preserved and not
overwritten.
* Restarted PowerToys and verified the setting persisted correctly.

**Note to reviewers:** I left the "Tests" box unchecked because this is
a single-line file path configuration change. I did not add an automated
test, but I have thoroughly verified the fix manually as described in
the Validation steps above.
2026-06-02 16:33:17 +00:00
Michael Jolley
0a64561ed5 CmdPal: Allow connecting to arbitrary hostnames in Remote Desktop list page (#48069)
## Summary of the Pull Request

Fixes #48053 — Remote Desktop extension now allows connecting to
arbitrary hostnames when navigated into the extension's list page.

Previously, `RemoteDesktopListPage` only displayed previously saved
connections. This converts it from `ListPage` to `DynamicListPage`,
adding search-driven behavior:

- Typing a valid hostname/IP that **doesn't** match an existing saved
connection shows a **"Connect to {hostname}"** item at the top of the
list
- Typing something that **exactly matches** a saved connection shows
only the normal results (no duplicate arbitrary-host item)
- Typing an invalid string (not a valid hostname/IP) shows no
arbitrary-host item

The hostname validation reuses the same logic as
`FallbackRemoteDesktopItem`: strip the port suffix (e.g. `myhost:3389` →
`myhost`), then check `Uri.CheckHostName` against `IPv4`, `IPv6`, `Dns`.

## PR Checklist
- [x] Closes: #48053
- [ ] **Communication:** I've discussed this with core contributors
already.
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized

---------

Co-authored-by: root <root@io.bbq>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-02 10:47:25 -05:00
Mike Griese
820d98cb43 cmdpal: fix the dock window border being visible, redux (#48180)
Addenda to #47187

that fix only works if the _hwnd is already set. Actually it's crazy it
ever worked.

Tested by disconnecting and reconnecting RDP a couple times, which
pretty consistently reproduces the problem.

(cherry picked from commit c6a9ad2ad0)
2026-06-02 21:41:29 +08:00
Dustin L. Howett
cbeeefcaf9 Remove our dependency on expected-lite (#48159)
This removes our last git submodule dependency!

We were using `expected-lite` in one place, which was being compiled out
_anyway_ in favor of using `std::expected`.

(cherry picked from commit 109c63ba33)
2026-06-02 21:41:29 +08:00
Boliang Zhang
6ceb53336f Migrate spdlog from submodule to vcpkg (#48039)
## Summary

Migrate `deps/spdlog` from a git submodule to **vcpkg manifest mode**
with an overlay port pinned to the **exact same commit**
(`gabime/spdlog@616866fc`). Replaces the polyfill shim added in #47910
with a proper port-level patch.

This is the follow-up to PR #47928, which I closed after @zadjii-msft /
@DHowett clarified that the intended direction was a single combined
"move to vcpkg **and** apply a patch file" (one change, not two stepping
stones).

## Guidance honored

Per @zadjii-msft (offline):
-  Convert each submodule to vcpkg **one at a time** — this PR is
**spdlog only**. `deps/expected-lite` stays a submodule (separate PR
next).
-  Atomic commit per dep (multiple commits on the branch for review
traceability; squash on merge gives the requested single commit).
-  **Don't bump the version.** Only variable changed: submodule →
vcpkg. Same commit (`616866fc`, v1.8.5 + 38) the submodule pointed at.

Per @DHowett
([review](https://github.com/microsoft/PowerToys/pull/48039#pullrequestreview-4338835150)):
-  No vcpkg submodule — vswhere-first detection via a Terminal-style
`steps-install-vcpkg.yml` template; three-tier `VcpkgRoot` fallback (env
var → VS-shipped → runtime clone pinned to manifest baseline).

## Design

- **Repo-root manifest**: `vcpkg.json` declares only `spdlog`, with
`builtin-baseline` pinned. `vcpkg-configuration.json` registers
`deps/vcpkg-overlays/` as overlay-ports.
- **Overlay port** `deps/vcpkg-overlays/spdlog/`: `vcpkg_from_github(REF
616866fc...)` with bundled fmt preserved (`-DSPDLOG_FMT_EXTERNAL=OFF`);
the MSVC 14.51 fix from #47910 carried as a proper vcpkg patch on
`include/spdlog/fmt/bundled/format.h`.
- **vcpkg integration is global** (set in `Cpp.Build.props`, imported
via `ForceImportBeforeCppProps` for every `.vcxproj`). An earlier
attempt to make vcpkg per-project-opt-in via `deps/spdlog.props` failed
because ~85 PowerToys `.vcxproj` files import `spdlog.props` AFTER
`Microsoft.Cpp.targets`, by which point `vcpkg.props`' `ClCompile` hook
is dead-on-arrival. The trade-off (every C++ project invokes `vcpkg
install` once at build time, ~0.5 s on cache hits, manifest declares
only spdlog so install set is fixed) is documented in the expanded
`Cpp.Build.props` comment.
- **`deps/spdlog.props`** is now a thin shim that only sets the
historical `SPDLOG_*` preprocessor defines for source-compat.
- **`Cpp.Build.targets`** is a new file imported via
`ForceImportAfterCppTargets` to load `vcpkg.targets` after
`Microsoft.Cpp.targets`. A fail-fast `<Target>` errors with a clear
message if `vcpkg.props` can't be found at the resolved `VcpkgRoot`.
- **Removes** `deps/spdlog-msvc-fix/` polyfill, in-tree wrapper
`src/logging/`, spdlog submodule, the single `<ProjectReference>` in
`logger.vcxproj`, plus 3 `.slnf` refs and 2 `.slnx` refs
(`PowerToys.slnx` + `installer/PowerToysSetup.slnx`), plus 3 hard-coded
`..\deps\spdlog\include` entries in `<AdditionalIncludeDirectories>`.
- **CI**: new reusable `.pipelines/v2/templates/steps-install-vcpkg.yml`
(vswhere-first, manifest-baseline-pinned fallback clone, respects
`useVSPreview`). Gated `Cache@2` for `%LOCALAPPDATA%\vcpkg\archives`
keyed on overlay-port contents. Same vcpkg detection added to
`tools\build\build-essentials.ps1` for local devs.

## Verification

Local build matrix (all 4 configs of `logger.vcxproj` and a
representative late-import consumer):

| Config | Result | Notes |
|--------|--------|-------|
| Release \| x64    |  | vcpkg install ~21 s, `logger.lib` produced |
| Debug \| x64 |  | **Validates patch fixes the actual MSVC 14.51 bug**
(`_ITERATOR_DEBUG_LEVEL > 0` → `_SECURE_SCL`) |
| Release \| ARM64 |  | vcpkg cross-installs `arm64-windows-static`
spdlog in ~16 s |
| Debug \| ARM64 |  | **Previously DISABLED for the in-tree spdlog**
(per `<Build Solution="Debug\|ARM64" Project="false" />` in
`PowerToysSetup.slnx`); this migration FIXES that latent gap |
| FancyZonesLib (Release \| x64) |  | Late-import-pattern consumer;
previously broke in v2 |

Full PowerToys CI (x64 + arm64 + CmdPal SDK + all GitHub Actions checks)
green.

**Consumer audit**: 72 `.vcxproj` files reference `logger.vcxproj`; all
72 also import `deps/spdlog.props`. No transitive-link breakage.

## Out of scope (intentional)

- `deps/expected-lite` migration — next PR per "one-at-a-time" rule.
- Remote vcpkg binary cache (Azure Artifacts NuGet feed). Local pipeline
`Cache@2` works for now, but a remote feed survives across pipelines and
is the long-term answer. Happy to split this into a follow-up.

## Notes for review

- Patch in the overlay port is identical content to PR #47928's patch
but regenerated with LF line endings (vcpkg's `vcpkg_apply_patches` is
strict; no `--ignore-whitespace`).
- Once PowerToys eventually bumps spdlog past v1.14 (which ships fmt
10.2 and drops the affected code path), the overlay port can be deleted
and we can use upstream vcpkg's `spdlog` directly.
- Re. official-release pipelines and terrapin / less-restricted network
isolation: VS-shipped vcpkg is the primary path (no network); the
fallback clone is only exercised when VS doesn't ship vcpkg. Happy to
wire terrapin into the fallback as a follow-up if the official build
template needs it.

Closes the work tracked in #47928 (which was closed unmerged).

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Dustin L. Howett <dustin@howett.net>
(cherry picked from commit 8a7933c0b2)
2026-06-02 21:41:29 +08:00
Niels Laute
5812b55710 Rework Power Display warning dialog (#48249)
## Summary of the Pull Request

Rework the confirmation dialog shown when enabling Power Display (and
its potentially-destructive sub-features) so it is shorter, friendlier,
and consistent across all entry points. The five separate prefix-driven
variants are now a single `PowerDisplayWarningDialog` user control
selected via an enum, sharing the title, learn-more link, and
Enable/Cancel buttons. The previous hand-rolled red warning text is
replaced with a Fluent `InfoBar Severity=""Warning""`.

## PR Checklist

- [ ] Closes: #xxx
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places

## Detailed Description of the Pull Request / Additional comments

### Before
- `DangerousFeatureWarningDialog` took a resource-key prefix string and
probed up to five optional keys per variant (`_WarningHeader`,
`_WarningConfirm`, `_WarningList_Item1/2`, etc.).
- Each of the five flows (EnableModule, ColorTemperature, PowerState,
InputSource, MaxCompatibility) had a slightly different title (some
questions, some statements, mixed `Warning:` prefixes) and a hand-rolled
red `TextBlock` warning header with a `⚠️` emoji and
`SystemFillColorCriticalBrush`.
- ~30 fragmented `PowerDisplay_*_Warning*` resw keys.

### After
- New `PowerDisplayWarningDialog` selected via `PowerDisplayWarningKind`
enum (`EnableModule`, `ColorTemperature`, `PowerState`, `InputSource`,
`MaxCompatibility`).
- Shared chrome lives in the control:
  - Single title `Before you continue` for every variant.
  - `InfoBar Severity=""Warning""` replaces the hand-rolled red header.
- Learn-more `HyperlinkButton` pointing at
`aka.ms/powerToysOverview_PowerDisplay_Note` (URL is a `private const`
so translators don't see it).
  - Consistent Enable / Cancel buttons.
- Per-variant content collapses to one InfoBar message + one body
paragraph in resw (12 keys total, down from ~30). Bullets are inlined as
`• ` + newlines with `xml:space=""preserve""`.
- `PowerDisplayViewModel.ConfirmDangerousFeatureAsync` and
`TryCommitDangerousChangeAsync` now take the enum instead of a magic
string.

### Files
- **Added:** `ViewModels/PowerDisplayWarningKind.cs`,
`SettingsXAML/Views/PowerDisplayWarningDialog.xaml{,.cs}`
- **Removed:**
`SettingsXAML/Views/DangerousFeatureWarningDialog.xaml{,.cs}`
- **Updated:** `Strings/en-us/Resources.resw`,
`ViewModels/PowerDisplayViewModel.cs`,
`SettingsXAML/Views/PowerDisplayPage.xaml.cs`

## Validation Steps Performed

- Built `PowerToys.Settings.csproj` (Debug arm64) — clean.
- Manually exercised the EnableModule and MaxCompatibility flows;
verified the new title, InfoBar, body paragraph, learn-more link, and
Enable/Cancel button behavior.
- Verified `aka.ms/powerToysOverview_PowerDisplay_Note` opens in the
default browser.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit 7f19817182)
2026-06-02 15:34:10 +08:00
Niels Laute
1be856c573 [KBM] Enable new editor by default (#48245)
## Summary

Make the new WinUI 3 Keyboard Manager editor the default by flipping
`useNewEditor` from `false` to `true` everywhere a default is supplied.

## Behavior

- **New installs / new `settings.json`** → new editor enabled
- **Upgrades from a version before the `useNewEditor` key existed** →
new editor enabled (the key is missing, so the default kicks in)
- **Users who have explicitly toggled the setting** → unchanged (we only
change the default, not stored values)
- The "Go back to classic" button in the KBM settings page is untouched

## Changes

- `src/settings-ui/Settings.UI.Library/KeyboardManagerProperties.cs` —
`UseNewEditor` property initializer now `true`
- `src/modules/keyboardmanager/dll/dllmain.cpp` — `m_useNewEditor`
member init + `GetNamedBoolean` fallback now `true`; warn-log message
updated to match
-
`src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Modules/KeyboardManagerModuleCommandProvider.cs`
— both fallback paths in `IsUseNewEditorEnabled` (file missing /
unreadable) now return `true`, so the "Open New Editor" CmdPal command
surfaces by default

## Validation

Built locally on ARM64 Debug (exit code 0):
- `src/modules/keyboardmanager/dll`
- `src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys`
- `src/settings-ui/Settings.UI.Library`

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit a33fd3c474)
2026-06-02 15:34:09 +08:00
Niels Laute
c356d65e0d Reword Shortcut Guide module and OOBE descriptions (#48248)
## Summary of the Pull Request

Reword the Shortcut Guide module description and OOBE description so
they describe the feature without referring to `your apps`. The module
description now reads as a single sentence covering Windows and the
active app; the OOBE description is shortened to one paragraph and
refers to `various applications` instead of enumerating the bundled
apps.

## PR Checklist

- [ ] Closes: #xxx
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places

## Detailed Description of the Pull Request / Additional comments

Two strings in
`src/settings-ui/Settings.UI/Strings/en-us/Resources.resw` changed:

- `ShortcutGuide.ModuleDescription` — now: `Shows an on-screen overlay
of keyboard shortcuts for Windows and the active application.`
- `Oobe_ShortcutGuide.Description` — collapsed to one sentence
describing Windows + various applications, no longer enumerating bundled
apps or mentioning future additions.

No code or behavioral changes.

## Validation Steps Performed

- Built Settings.UI (Debug arm64) – clean.
- Verified the Shortcut Guide module card in Settings UI shows the new
description and the OOBE Shortcut Guide page shows the new paragraph.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
(cherry picked from commit b712fa4d85)
2026-06-02 15:34:09 +08:00
Niels Laute
7f19817182 Rework Power Display warning dialog (#48249)
## Summary of the Pull Request

Rework the confirmation dialog shown when enabling Power Display (and
its potentially-destructive sub-features) so it is shorter, friendlier,
and consistent across all entry points. The five separate prefix-driven
variants are now a single `PowerDisplayWarningDialog` user control
selected via an enum, sharing the title, learn-more link, and
Enable/Cancel buttons. The previous hand-rolled red warning text is
replaced with a Fluent `InfoBar Severity=""Warning""`.

## PR Checklist

- [ ] Closes: #xxx
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places

## Detailed Description of the Pull Request / Additional comments

### Before
- `DangerousFeatureWarningDialog` took a resource-key prefix string and
probed up to five optional keys per variant (`_WarningHeader`,
`_WarningConfirm`, `_WarningList_Item1/2`, etc.).
- Each of the five flows (EnableModule, ColorTemperature, PowerState,
InputSource, MaxCompatibility) had a slightly different title (some
questions, some statements, mixed `Warning:` prefixes) and a hand-rolled
red `TextBlock` warning header with a `⚠️` emoji and
`SystemFillColorCriticalBrush`.
- ~30 fragmented `PowerDisplay_*_Warning*` resw keys.

### After
- New `PowerDisplayWarningDialog` selected via `PowerDisplayWarningKind`
enum (`EnableModule`, `ColorTemperature`, `PowerState`, `InputSource`,
`MaxCompatibility`).
- Shared chrome lives in the control:
  - Single title `Before you continue` for every variant.
  - `InfoBar Severity=""Warning""` replaces the hand-rolled red header.
- Learn-more `HyperlinkButton` pointing at
`aka.ms/powerToysOverview_PowerDisplay_Note` (URL is a `private const`
so translators don't see it).
  - Consistent Enable / Cancel buttons.
- Per-variant content collapses to one InfoBar message + one body
paragraph in resw (12 keys total, down from ~30). Bullets are inlined as
`• ` + newlines with `xml:space=""preserve""`.
- `PowerDisplayViewModel.ConfirmDangerousFeatureAsync` and
`TryCommitDangerousChangeAsync` now take the enum instead of a magic
string.

### Files
- **Added:** `ViewModels/PowerDisplayWarningKind.cs`,
`SettingsXAML/Views/PowerDisplayWarningDialog.xaml{,.cs}`
- **Removed:**
`SettingsXAML/Views/DangerousFeatureWarningDialog.xaml{,.cs}`
- **Updated:** `Strings/en-us/Resources.resw`,
`ViewModels/PowerDisplayViewModel.cs`,
`SettingsXAML/Views/PowerDisplayPage.xaml.cs`

## Validation Steps Performed

- Built `PowerToys.Settings.csproj` (Debug arm64) — clean.
- Manually exercised the EnableModule and MaxCompatibility flows;
verified the new title, InfoBar, body paragraph, learn-more link, and
Enable/Cancel button behavior.
- Verified `aka.ms/powerToysOverview_PowerDisplay_Note` opens in the
default browser.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-02 14:57:43 +08:00
Niels Laute
a33fd3c474 [KBM] Enable new editor by default (#48245)
## Summary

Make the new WinUI 3 Keyboard Manager editor the default by flipping
`useNewEditor` from `false` to `true` everywhere a default is supplied.

## Behavior

- **New installs / new `settings.json`** → new editor enabled
- **Upgrades from a version before the `useNewEditor` key existed** →
new editor enabled (the key is missing, so the default kicks in)
- **Users who have explicitly toggled the setting** → unchanged (we only
change the default, not stored values)
- The "Go back to classic" button in the KBM settings page is untouched

## Changes

- `src/settings-ui/Settings.UI.Library/KeyboardManagerProperties.cs` —
`UseNewEditor` property initializer now `true`
- `src/modules/keyboardmanager/dll/dllmain.cpp` — `m_useNewEditor`
member init + `GetNamedBoolean` fallback now `true`; warn-log message
updated to match
-
`src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Modules/KeyboardManagerModuleCommandProvider.cs`
— both fallback paths in `IsUseNewEditorEnabled` (file missing /
unreadable) now return `true`, so the "Open New Editor" CmdPal command
surfaces by default

## Validation

Built locally on ARM64 Debug (exit code 0):
- `src/modules/keyboardmanager/dll`
- `src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys`
- `src/settings-ui/Settings.UI.Library`

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-02 14:57:02 +08:00
Niels Laute
b712fa4d85 Reword Shortcut Guide module and OOBE descriptions (#48248)
## Summary of the Pull Request

Reword the Shortcut Guide module description and OOBE description so
they describe the feature without referring to `your apps`. The module
description now reads as a single sentence covering Windows and the
active app; the OOBE description is shortened to one paragraph and
refers to `various applications` instead of enumerating the bundled
apps.

## PR Checklist

- [ ] Closes: #xxx
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places

## Detailed Description of the Pull Request / Additional comments

Two strings in
`src/settings-ui/Settings.UI/Strings/en-us/Resources.resw` changed:

- `ShortcutGuide.ModuleDescription` — now: `Shows an on-screen overlay
of keyboard shortcuts for Windows and the active application.`
- `Oobe_ShortcutGuide.Description` — collapsed to one sentence
describing Windows + various applications, no longer enumerating bundled
apps or mentioning future additions.

No code or behavioral changes.

## Validation Steps Performed

- Built Settings.UI (Debug arm64) – clean.
- Verified the Shortcut Guide module card in Settings UI shows the new
description and the OOBE Shortcut Guide page shows the new paragraph.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-02 14:39:52 +08:00
Michael Jolley
2dd1d457eb CmdPal: Synchronize fallback title/subtitle format for consistent scoring (#48085)
## Summary

Fixes #46055 — Standardizes built-in fallback title/subtitle format so
scoring is consistent across all action fallbacks.

## Problem

`MainListPage.cs` scores fallback items by fuzzy-matching the query
against both Title and Subtitle, but with different weights:
- `nameScore = FuzzyScore(query, Title)`
- `descriptionScore = (FuzzyScore(query, Subtitle) - 4) / 2`

Fallbacks that embedded the raw query in Title got artificially higher
scores than those using Subtitle. This made ranking unpredictable.

## Fix

All "action" fallbacks now follow a consistent pattern:
- **Title** = static action description (no query text)
- **Subtitle** = raw query string (unquoted)

"Result" fallbacks (that found a specific matched item) are left
unchanged — they correctly show the matched item name in Title.

## Full Fallback Audit (example query: `notepad`)

| Fallback | Title | Subtitle | Status |
|---|---|---|---|
| WebSearch: Search | "Search the web with Edge" | `Search for notepad`
| **Changed** — was `Search for "notepad"` in subtitle |
| WebSearch: Open URL | "Open in Microsoft Edge" | `Open notepad.com` |
**Changed** — was `Open "notepad.com"` in title |
| Shell: Run | "Run" | `notepad` | Unchanged — already correct |
| Calculator | "3" (result) | `1+2` (query) | Unchanged — intentional
exception |
| Indexer: single result | "notepad.exe" | `C:\Windows\notepad.exe` |
Unchanged — result fallback |
| Indexer: multiple results | "File search" | `Search for notepad in
files` | **Changed** — was `Search for "notepad" in files` in title |
| Windows Settings: single | "Notepad settings" | `Settings > Apps` |
Unchanged — result fallback |
| Windows Settings: multiple | "Search Windows settings..." | `Search
for notepad` | **Changed** — was `Search for "notepad" in Windows
settings` in title |
| Remote Desktop: exact match | "MyPC" (connection) | "Connect to MyPC"
| Unchanged — result fallback |
| Remote Desktop: arbitrary host | "Remote Desktop" | `Connect to
notepad-host` | **Changed** — was `Connect to notepad-host` in title |
| TimeDate | "Monday, May 23" (result) | "Current date" | Unchanged —
result fallback |
| System | "Shut down" (result) | "Shuts down the computer" | Unchanged
— result fallback |
| PowerToys | "Color Picker" (static) | "Pick a color..." | Unchanged —
result fallback |

## Changes

- `FallbackExecuteSearchItem.cs` — Subtitle uses raw query instead of
`"Search for \"{query}\""` format
- `FallbackOpenURLItem.cs` — Title shows browser name (was query),
Subtitle shows raw query (was browser)
- `FallbackOpenFileItem.cs` — Multi-result: Title is static display
name, Subtitle is raw query
- `FallbackWindowsSettingsItem.cs` — Multi-result: Title is static
description, Subtitle is raw query
- `FallbackRemoteDesktopItem.cs` — Arbitrary host: Title is static
"Remote Desktop", Subtitle is raw query

---------

Co-authored-by: root <root@io.bbq>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit b66b044210)
2026-06-02 11:42:13 +08:00
Michael Jolley
bb276d3be9 CmdPal: Fix dock subtitle visibility in compact mode after async update (#48088)
## Summary

When an extension updates its `Subtitle` property asynchronously after
initial render, the `TextVisibilityStates` visual state group
transitions from `TitleOnly` → `TextVisible`. This transition sets
`SubtitleText.Visibility = Visible`, overriding the `CompactStates`
setter that had hidden it.

## Fix

Added `control.UpdateCompactState()` to `OnTextPropertyChanged` in
`DockItemControl.xaml.cs`. This re-applies the compact state after any
text property change. When `IsCompact` is `false`, `UpdateCompactState`
is a no-op — no behavior change for the non-compact path.

Fixes #47980

Co-authored-by: root <root@io.bbq>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit 18919eaa40)
2026-06-02 11:42:12 +08:00
Michael Jolley
b7aca7c3fc CmdPal: Reorder dock network stats to match Task Manager order (#48098)
## Summary

Fixes #47939

The Performance Monitor dock band displayed network stats as Receive →
Send, but Task Manager shows Send → Receive. This swaps the order to
match Task Manager.

## Changes

- `PerformanceWidgetsPage.cs`: Swap `_networkUpItem` (Send) before
`_networkDownItem` (Receive) in the band items array.

Co-authored-by: root <root@io.bbq>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit e0854fbaf3)
2026-06-02 11:42:12 +08:00
Michael Jolley
8e3a88df2c CmdPal: Fix hotkey navigation when palette is showing transient dock page (#48089)
## Summary

When a keyboard shortcut opens CmdPal to an extension while the palette
is already showing a dock-launched transient page, `GoHome(false)`
cannot restore the root page — the frame's back stack is empty because
the transient dock page was never pushed on top of root. The user ends
up with only the hotkey-target page in the frame with no way to navigate
back to the main list.

## Root Cause

In `ShellPage.SummonOnUiThread()`, the hotkey-to-page branch called
`GoHome(false)` before sending `ShowWindowMessage`. But when the active
page is a transient dock page, `_currentlyTransient` is still `true` and
the frame back stack is empty, so `GoHome` can't re-establish the root
page as the frame base.

## Fix

Added `ResetToHome()` to `ShellViewModel`, mirroring the pattern already
used in `WindowHiddenMessage` handling:
1. Clears `_currentlyTransient`
2. Calls `_rootPageService.GoHome()` to reset extension state
3. Sends `PerformCommandMessage` for `_rootPage` — navigating
MainListPage into the frame as the base

In `ShellPage.SummonOnUiThread()`, the `GoHome(false)` call in the
`isPage` branch is replaced with `ViewModel.ResetToHome()`. The root
page is then cleanly in the frame before the hotkey target's
`PerformCommandMessage` navigates on top of it.

Fixes #47994

Co-authored-by: root <root@io.bbq>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit ba20da1611)
2026-06-02 11:42:12 +08:00
Niels Laute
fb028e8fdc CmdPal: Reorder Pin to Dock dialog so controls precede the preview (#48250)
## Summary of the Pull Request

Reorder the Pin to Dock dialog content so the configuration controls
(monitor selector, dock section, label options) appear at the top and
the live preview is shown below them. The user now configures the pin
first and sees the resulting preview directly underneath, instead of
staring at the preview and having to scan past it to find the controls.

<img width="515" height="440" alt="image"
src="https://github.com/user-attachments/assets/0d1d0543-2b30-48f5-a1aa-676a165870f5"
/>

## PR Checklist

- [ ] Closes: #xxx
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places

## Detailed Description of the Pull Request / Additional comments

XAML-only change to
`src/modules/cmdpal/Microsoft.CmdPal.UI/Dock/PinToDockDialogContent.xaml`.
The new visual order inside the `ScrollViewer`/`StackPanel` is:

1. Monitor selector (still `Visibility=""Collapsed""` by default; shown
when more than one monitor is available)
2. Dock section `Segmented` (Start / Center / End)
3. Label options (`Show title` / `Show subtitle` checkboxes)
4. Divider `Rectangle`
5. Preview `Border`

No logic, bindings, `x:Name` identifiers, event handlers, or `x:Uid`
keys are changed.

## Validation Steps Performed

- Built `Microsoft.CmdPal.UI` (Debug arm64) — clean.
- Verified the Pin to Dock dialog renders with controls on top and the
preview underneath; segmented selection, label-option checkboxes, and
the multi-monitor combo still behave as before.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit 35f2ed839e)
2026-06-02 11:42:12 +08:00
Michael Jolley
d980697849 CmdPal: Fix GPU index out of range crash in PerfMon widget (#48103)
## Summary

Fixes #47821

The GPU Performance Monitor widget crashes with
`IndexOutOfRangeException` on systems where GPU performance counters
fail to enumerate (common on Intel Arc and hybrid GPU configurations).
The dock band shows `???` and opening the flyout causes an error.

## Root Cause

`GPUStats.CreateGPUImageUrl()` accessed `_stats[index]` without bounds
checking. When `GetGPUPerfCounters()` finds no matching counter
instances, `_stats` remains empty but callers still pass index 0.

`GetGPUName()`, `GetGPUUsage()`, and `GetGPUTemperature()` already have
proper guards (`if (_stats.Count <= index) return ...`) — this fix adds
the same pattern to the one remaining unguarded method.

## Changes

- `GPUStats.cs`: Add bounds check to `CreateGPUImageUrl()` — return
empty string if index out of range

Co-authored-by: root <root@io.bbq>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit e20b5b9c51)
2026-06-02 11:42:12 +08:00
Mike Griese
d42b15f380 cmdpal: fix the dock window border being visible, redux (#48180)
Addenda to #47187

that fix only works if the _hwnd is already set. Actually it's crazy it
ever worked.

Tested by disconnecting and reconnecting RDP a couple times, which
pretty consistently reproduces the problem.

(cherry picked from commit c6a9ad2ad0)
2026-06-02 11:41:59 +08:00
Michael Jolley
b66b044210 CmdPal: Synchronize fallback title/subtitle format for consistent scoring (#48085)
## Summary

Fixes #46055 — Standardizes built-in fallback title/subtitle format so
scoring is consistent across all action fallbacks.

## Problem

`MainListPage.cs` scores fallback items by fuzzy-matching the query
against both Title and Subtitle, but with different weights:
- `nameScore = FuzzyScore(query, Title)`
- `descriptionScore = (FuzzyScore(query, Subtitle) - 4) / 2`

Fallbacks that embedded the raw query in Title got artificially higher
scores than those using Subtitle. This made ranking unpredictable.

## Fix

All "action" fallbacks now follow a consistent pattern:
- **Title** = static action description (no query text)
- **Subtitle** = raw query string (unquoted)

"Result" fallbacks (that found a specific matched item) are left
unchanged — they correctly show the matched item name in Title.

## Full Fallback Audit (example query: `notepad`)

| Fallback | Title | Subtitle | Status |
|---|---|---|---|
| WebSearch: Search | "Search the web with Edge" | `Search for notepad`
| **Changed** — was `Search for "notepad"` in subtitle |
| WebSearch: Open URL | "Open in Microsoft Edge" | `Open notepad.com` |
**Changed** — was `Open "notepad.com"` in title |
| Shell: Run | "Run" | `notepad` | Unchanged — already correct |
| Calculator | "3" (result) | `1+2` (query) | Unchanged — intentional
exception |
| Indexer: single result | "notepad.exe" | `C:\Windows\notepad.exe` |
Unchanged — result fallback |
| Indexer: multiple results | "File search" | `Search for notepad in
files` | **Changed** — was `Search for "notepad" in files` in title |
| Windows Settings: single | "Notepad settings" | `Settings > Apps` |
Unchanged — result fallback |
| Windows Settings: multiple | "Search Windows settings..." | `Search
for notepad` | **Changed** — was `Search for "notepad" in Windows
settings` in title |
| Remote Desktop: exact match | "MyPC" (connection) | "Connect to MyPC"
| Unchanged — result fallback |
| Remote Desktop: arbitrary host | "Remote Desktop" | `Connect to
notepad-host` | **Changed** — was `Connect to notepad-host` in title |
| TimeDate | "Monday, May 23" (result) | "Current date" | Unchanged —
result fallback |
| System | "Shut down" (result) | "Shuts down the computer" | Unchanged
— result fallback |
| PowerToys | "Color Picker" (static) | "Pick a color..." | Unchanged —
result fallback |

## Changes

- `FallbackExecuteSearchItem.cs` — Subtitle uses raw query instead of
`"Search for \"{query}\""` format
- `FallbackOpenURLItem.cs` — Title shows browser name (was query),
Subtitle shows raw query (was browser)
- `FallbackOpenFileItem.cs` — Multi-result: Title is static display
name, Subtitle is raw query
- `FallbackWindowsSettingsItem.cs` — Multi-result: Title is static
description, Subtitle is raw query
- `FallbackRemoteDesktopItem.cs` — Arbitrary host: Title is static
"Remote Desktop", Subtitle is raw query

---------

Co-authored-by: root <root@io.bbq>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-01 16:57:30 -05:00
Michael Jolley
18919eaa40 CmdPal: Fix dock subtitle visibility in compact mode after async update (#48088)
## Summary

When an extension updates its `Subtitle` property asynchronously after
initial render, the `TextVisibilityStates` visual state group
transitions from `TitleOnly` → `TextVisible`. This transition sets
`SubtitleText.Visibility = Visible`, overriding the `CompactStates`
setter that had hidden it.

## Fix

Added `control.UpdateCompactState()` to `OnTextPropertyChanged` in
`DockItemControl.xaml.cs`. This re-applies the compact state after any
text property change. When `IsCompact` is `false`, `UpdateCompactState`
is a no-op — no behavior change for the non-compact path.

Fixes #47980

Co-authored-by: root <root@io.bbq>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-01 16:56:33 -05:00
Michael Jolley
e0854fbaf3 CmdPal: Reorder dock network stats to match Task Manager order (#48098)
## Summary

Fixes #47939

The Performance Monitor dock band displayed network stats as Receive →
Send, but Task Manager shows Send → Receive. This swaps the order to
match Task Manager.

## Changes

- `PerformanceWidgetsPage.cs`: Swap `_networkUpItem` (Send) before
`_networkDownItem` (Receive) in the band items array.

Co-authored-by: root <root@io.bbq>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-01 16:55:41 -05:00
Michael Jolley
ba20da1611 CmdPal: Fix hotkey navigation when palette is showing transient dock page (#48089)
## Summary

When a keyboard shortcut opens CmdPal to an extension while the palette
is already showing a dock-launched transient page, `GoHome(false)`
cannot restore the root page — the frame's back stack is empty because
the transient dock page was never pushed on top of root. The user ends
up with only the hotkey-target page in the frame with no way to navigate
back to the main list.

## Root Cause

In `ShellPage.SummonOnUiThread()`, the hotkey-to-page branch called
`GoHome(false)` before sending `ShowWindowMessage`. But when the active
page is a transient dock page, `_currentlyTransient` is still `true` and
the frame back stack is empty, so `GoHome` can't re-establish the root
page as the frame base.

## Fix

Added `ResetToHome()` to `ShellViewModel`, mirroring the pattern already
used in `WindowHiddenMessage` handling:
1. Clears `_currentlyTransient`
2. Calls `_rootPageService.GoHome()` to reset extension state
3. Sends `PerformCommandMessage` for `_rootPage` — navigating
MainListPage into the frame as the base

In `ShellPage.SummonOnUiThread()`, the `GoHome(false)` call in the
`isPage` branch is replaced with `ViewModel.ResetToHome()`. The root
page is then cleanly in the frame before the hotkey target's
`PerformCommandMessage` navigates on top of it.

Fixes #47994

Co-authored-by: root <root@io.bbq>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-01 16:29:53 -05:00
Niels Laute
35f2ed839e CmdPal: Reorder Pin to Dock dialog so controls precede the preview (#48250)
## Summary of the Pull Request

Reorder the Pin to Dock dialog content so the configuration controls
(monitor selector, dock section, label options) appear at the top and
the live preview is shown below them. The user now configures the pin
first and sees the resulting preview directly underneath, instead of
staring at the preview and having to scan past it to find the controls.

<img width="515" height="440" alt="image"
src="https://github.com/user-attachments/assets/0d1d0543-2b30-48f5-a1aa-676a165870f5"
/>

## PR Checklist

- [ ] Closes: #xxx
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places

## Detailed Description of the Pull Request / Additional comments

XAML-only change to
`src/modules/cmdpal/Microsoft.CmdPal.UI/Dock/PinToDockDialogContent.xaml`.
The new visual order inside the `ScrollViewer`/`StackPanel` is:

1. Monitor selector (still `Visibility=""Collapsed""` by default; shown
when more than one monitor is available)
2. Dock section `Segmented` (Start / Center / End)
3. Label options (`Show title` / `Show subtitle` checkboxes)
4. Divider `Rectangle`
5. Preview `Border`

No logic, bindings, `x:Name` identifiers, event handlers, or `x:Uid`
keys are changed.

## Validation Steps Performed

- Built `Microsoft.CmdPal.UI` (Debug arm64) — clean.
- Verified the Pin to Dock dialog renders with controls on top and the
preview underneath; segmented selection, label-option checkboxes, and
the multi-monitor combo still behave as before.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-01 15:43:46 -05:00
Michael Jolley
e20b5b9c51 CmdPal: Fix GPU index out of range crash in PerfMon widget (#48103)
## Summary

Fixes #47821

The GPU Performance Monitor widget crashes with
`IndexOutOfRangeException` on systems where GPU performance counters
fail to enumerate (common on Intel Arc and hybrid GPU configurations).
The dock band shows `???` and opening the flyout causes an error.

## Root Cause

`GPUStats.CreateGPUImageUrl()` accessed `_stats[index]` without bounds
checking. When `GetGPUPerfCounters()` finds no matching counter
instances, `_stats` remains empty but callers still pass index 0.

`GetGPUName()`, `GetGPUUsage()`, and `GetGPUTemperature()` already have
proper guards (`if (_stats.Count <= index) return ...`) — this fix adds
the same pattern to the one remaining unguarded method.

## Changes

- `GPUStats.cs`: Add bounds check to `CreateGPUImageUrl()` — return
empty string if index out of range

Co-authored-by: root <root@io.bbq>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-01 20:59:57 +02:00
Mike Griese
c6a9ad2ad0 cmdpal: fix the dock window border being visible, redux (#48180)
Addenda to #47187

that fix only works if the _hwnd is already set. Actually it's crazy it
ever worked.

Tested by disconnecting and reconnecting RDP a couple times, which
pretty consistently reproduces the problem.
2026-06-01 11:33:17 +00:00
Muyuan Li
b49f722e88 Fix ShortcutGuide v2 crash when Manifests directory is missing (#48171)
## Summary

Fixes #48170 — ShortcutGuide v2 crashes on launch when the bundled
`Manifests` directory is absent from the install path.

### Root Cause

The `Assets\ShortcutGuide\Manifests\*.yml` files were never reaching the
build output directory during the CI solution-level build (`msbuild
PowerToys.slnx /t:Build -graph`). The `CopyToOutputDirectory` metadata
on `<Content>` items does not reliably copy files to a shared
`OutputPath` in this build configuration. As a result, the WiX installer
generator found no yml files to package, and the installed product was
missing the Manifests directory entirely.

At runtime, `PowerToysShortcutsPopulator.Populate()` threw an unhandled
`FileNotFoundException` causing a crash loop.

### Fix (3 layers)

1. **Code resilience** (`Program.cs`, `PowerToysShortcutsPopulator.cs`):
- Wrap `Populate()` in try/catch so a missing manifest degrades
gracefully instead of crashing
   - Add `File.Exists` guard before `File.ReadAllText`

2. **Build output** (`ShortcutGuide.Ui.csproj`):
- Add explicit `CopyManifestsToOutputDir` MSBuild target
(`AfterTargets="Build"`) that copies yml files to
`$(OutDir)Assets\ShortcutGuide\Manifests\` — same pattern as the
existing `CopyPRIFileToOutputDir` target
- Keep `<Content Include>` with `CopyToOutputDirectory` as a fallback
for publish scenarios

3. **Installer packaging** (`generateAllFileComponents.ps1`,
`ShortcutGuide.wxs`):
   - Add `*.yml` to the file inclusion list
- Add `Generate-FileList` / `Generate-FileComponents` calls for
`ShortcutGuideManifestsFiles`
- Add WiX directory definition and `RemoveFolder` component for the
Manifests directory

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit a67fc2d9b7)
2026-06-01 16:32:35 +08:00
Jessica Dene Earley-Cha
c2ea654b3c [CmdPal] Toggle "Show details" / "Hide details" with icon in context menu (#48140)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

Converts the "Show details" context menu command into a toggle that
switches between "Show details" and "Hide details" with appropriate
icons, and fixes the icon not rendering in the context menu.

Address internal a11y bug.

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

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

(cherry picked from commit c78f6e52a0)
2026-06-01 16:32:35 +08:00
Muyuan Li
a67fc2d9b7 Fix ShortcutGuide v2 crash when Manifests directory is missing (#48171)
## Summary

Fixes #48170 — ShortcutGuide v2 crashes on launch when the bundled
`Manifests` directory is absent from the install path.

### Root Cause

The `Assets\ShortcutGuide\Manifests\*.yml` files were never reaching the
build output directory during the CI solution-level build (`msbuild
PowerToys.slnx /t:Build -graph`). The `CopyToOutputDirectory` metadata
on `<Content>` items does not reliably copy files to a shared
`OutputPath` in this build configuration. As a result, the WiX installer
generator found no yml files to package, and the installed product was
missing the Manifests directory entirely.

At runtime, `PowerToysShortcutsPopulator.Populate()` threw an unhandled
`FileNotFoundException` causing a crash loop.

### Fix (3 layers)

1. **Code resilience** (`Program.cs`, `PowerToysShortcutsPopulator.cs`):
- Wrap `Populate()` in try/catch so a missing manifest degrades
gracefully instead of crashing
   - Add `File.Exists` guard before `File.ReadAllText`

2. **Build output** (`ShortcutGuide.Ui.csproj`):
- Add explicit `CopyManifestsToOutputDir` MSBuild target
(`AfterTargets="Build"`) that copies yml files to
`$(OutDir)Assets\ShortcutGuide\Manifests\` — same pattern as the
existing `CopyPRIFileToOutputDir` target
- Keep `<Content Include>` with `CopyToOutputDirectory` as a fallback
for publish scenarios

3. **Installer packaging** (`generateAllFileComponents.ps1`,
`ShortcutGuide.wxs`):
   - Add `*.yml` to the file inclusion list
- Add `Generate-FileList` / `Generate-FileComponents` calls for
`ShortcutGuideManifestsFiles`
- Add WiX directory definition and `RemoveFolder` component for the
Manifests directory

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-01 16:28:08 +08:00
Jessica Dene Earley-Cha
c78f6e52a0 [CmdPal] Toggle "Show details" / "Hide details" with icon in context menu (#48140)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

Converts the "Show details" context menu command into a toggle that
switches between "Show details" and "Hide details" with appropriate
icons, and fixes the icon not rendering in the context menu.

Address internal a11y bug.



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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-06-01 13:19:38 +08:00
thetsaw
80e0a4d09e Add DiskAnalyzer to third-party Run plugins list (#48106)
## Summary of the Pull Request

Adds **DiskAnalyzer** to the General plugins table in
`doc/thirdPartyRunPlugins.md`.

- **Plugin:**
[Community.PowerToys.Run.Plugin.DiskAnalyzer](https://github.com/thetsaw/PowerToys.Plugin)
- - **Author:** thetsaw
- - **Keyword:** `ds`
- - **License:** MIT
- - **Platforms:** x64 and ARM64
### What it does
Scan any folder or drive to find the largest files and subfolders, view
drive usage with visual progress bars, and navigate your filesystem all
from PowerToys Run.

## PR Checklist

- [x] Plugin has been publicly available
- [ ] - [x] MIT licensed
- [ ] - [x] Releases include x64 and ARM64 zips
- [ ] - [x] plugin.json is correctly formatted
- [ ] - [x] README includes install instructions
## Detailed Description

This is a documentation-only change adding one row to the third-party
plugins table. No source code, binaries, or build files are modified.

(cherry picked from commit 9a55209d13)
2026-05-29 12:49:14 +08:00
Copilot
8c93854bbb Rename Settings UI label from “Shortcut Guide V2” to “Shortcut Guide” (#48151)
## Summary of the Pull Request

This updates PowerToys Settings to remove the obsolete “V2” suffix from
the Shortcut Guide module name. The UI now consistently shows **Shortcut
Guide**.

## PR Checklist

- [ ] **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
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

- **Settings navigation label**
  - Updated `Shell_ShortcutGuide.Content` to `Shortcut Guide`.
- **Module title**
  - Updated `ShortcutGuide.ModuleTitle` to `Shortcut Guide`.
- **OOBE title**
  - Updated `Oobe_ShortcutGuide.Title` to `Shortcut Guide`.

```xml
<data name="Shell_ShortcutGuide.Content" xml:space="preserve">
  <value>Shortcut Guide</value>
</data>
```

## Validation Steps Performed

- N/A for behavior-level validation in this description (change is
limited to localized display strings).

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
(cherry picked from commit 0cb6fe250b)
2026-05-29 12:49:14 +08:00
moooyo
1aba1e170c Remove "NEW" tag from Power Display and Grab and Move (#48174)
## Summary of the Pull Request
Both Power Display and Grab and Move have matured beyond their initial
release phase. This removes the "NEW" `InfoBadge` from their navigation
items in Settings, the two parent navigation groups (Windowing &
Layouts, Input / Output) that surfaced the badge when collapsed, and
clears the `IsNew` flag for Power Display in the OOBE shell.

<img width="1867" height="973" alt="image"
src="https://github.com/user-attachments/assets/533f271c-c70f-414f-a76a-43fd9ffbbd44"
/>
<img width="497" height="575" alt="image"
src="https://github.com/user-attachments/assets/fe1e97c3-c806-4f42-a836-76e042630d61"
/>
<img width="1619" height="1027" alt="image"
src="https://github.com/user-attachments/assets/f5db715b-bc69-4505-803a-18a9b2716280"
/>

## PR Checklist

- [x] Closes: #48153
- [x] **Communication:** Tracked by the linked issue
- [x] **Tests:** Markup-only change; Settings.UI builds clean with WinUI
markup compiler (no XAML errors)
- [x] **Localization:** No end-user-facing strings changed
- [ ] **Dev docs:** N/A
- [ ] **New binaries:** N/A
- [ ] **Documentation updated:** N/A

## Detailed Description of the Pull Request / Additional comments
Files touched:
- `src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml` —
removed four `<InfoBadge Style="{StaticResource NewInfoBadge}" />`
blocks on `GrabAndMoveNavigationItem`, `PowerDisplayNavigationItem`, and
on the two parent group headers `WindowingAndLayoutsNavigationItem` and
`InputOutputNavigationItem` (the parent badges existed only to surface a
NEW child when the group was collapsed; with no NEW children left in
those groups, the parent badges are now stale).
- `src/settings-ui/Settings.UI/OOBE/ViewModel/OobeShellViewModel.cs` —
flipped `(PowerToysModules.PowerDisplay, true)` to
`(PowerToysModules.PowerDisplay, false)`. Grab and Move was already
`false`.

No other modules or strings affected.

## Validation Steps Performed
- Built `src\settings-ui\Settings.UI\PowerToys.Settings.csproj`
(Release|x64) with MSBuild from VS 18 Enterprise;
`PowerToys.Settings.dll` produced with 0 errors related to this change.
WinUI markup compiler would have aborted before producing the DLL if the
XAML had syntax issues.
- Diff inspected: only the five intended deletions/edits, no collateral
changes.
- Visual run-time verification of the Settings navigation pane is
recommended before merge.

Co-authored-by: Yu Leng <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
(cherry picked from commit c0cb9417ad)
2026-05-29 12:49:14 +08:00
moooyo
c5a18aa488 [PowerDisplay] Fix false-positive crash detection on cooperative shutdown (#48173)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

Cooperative shutdowns of `PowerDisplay.exe` — Runner's `TerminateApp`
NamedPipe message, the `Terminate` named event, tray-quit, Runner-exit
detection, and PowerToys upgrades — all call `Environment.Exit(0)`
immediately. If DDC/CI discovery is mid-flight, that path skips the
`try/finally` that owns `CrashDetectionScope`, leaving `discovery.lock`
on disk. Phase 0 at the next `PowerDisplay.exe` startup then treats this
orphan as evidence of a real crash and auto-disables the module,
surfacing the "PowerDisplay has crashed" InfoBar in Settings UI.

This PR adds an `AppDomain.ProcessExit` safety-net inside
`CrashDetectionScope`. ProcessExit fires for `Environment.Exit` but
**not** for `FailFast` / BSOD / external `TerminateProcess` — exactly
the partition we need: cooperative exit → best-effort delete the lock;
involuntary kill → leave the lock for Phase 0 to detect (original design
intent preserved).

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

- [x] Closes: #48169
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** All end-user-facing strings can be localized
<!-- no user-facing strings changed -->
- [x] **Dev docs:** Added/updated <!-- inline XML doc on
CrashDetectionScope explains the ProcessExit partition -->
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

### Root cause

`CrashDetectionScope.Begin()` writes `discovery.lock` before DDC/CI
capability fetch and `Dispose()` deletes it when the `using` block
exits. The lock is intentionally designed to survive any code path that
cannot run user-mode cleanup (BSOD, kernel OOM, `TerminateProcess`), so
that the next `PowerDisplay.exe` start can see it and run Phase 0 (write
`crash_detected.flag`, set `enabled.PowerDisplay=false` in global
`settings.json`, signal `AutoDisablePowerDisplayEvent`).

The bug is that several **cooperative** shutdown paths route to
`Environment.Exit(0)` immediately:

| Path | Code |
|---|---|
| Runner's `TerminateApp` NamedPipe | `App.xaml.cs::OnNamedPipeMessage`
→ `Shutdown()` → `Environment.Exit(0)` |
| `Terminate` named event | `App.xaml.cs::OnLaunched` →
`RegisterEvent(..., () => Environment.Exit(0), "Terminate")` |
| Tray-quit | `TrayIconService` callback → `Environment.Exit(0)` |
| Runner-exit detection | `RunnerHelper.WaitForPowerToysRunner` callback
→ `Environment.Exit(0)` |

`Environment.Exit` calls `ExitProcess` under the hood, which terminates
all threads abruptly. Background `Task.WhenAll` doing DDC capability
fetch is killed mid-flight; the `finally` block that calls
`scope.Dispose()` never runs; `discovery.lock` orphans; Phase 0 next
time false-positives.

Concrete repro from logs:
- `15:08:42.510` lock written
- `15:08:42.79` probe monitor #1
- `15:08:46.92` probe monitor #2 (started, not finished — typical probe
takes ~5s)
- `15:08:49.03` `TerminateApp` received → `Environment.Exit(0)` → no
`Dispose` log line
- `15:10:10.03` next startup: Phase 0 sees orphan lock with `pid:17712,
startedAt:2026-05-28T07:08:42Z` → writes `crash_detected.flag` →
auto-disables

### Fix

`CrashDetectionScope.Begin()` now also subscribes to
`AppDomain.CurrentDomain.ProcessExit`. The handler does a best-effort
`File.Delete(_lockPath)` (swallowing exceptions, as required for
ProcessExit handlers). `Dispose()` unsubscribes before deleting. An
`Interlocked.Exchange` guards the race between Dispose and ProcessExit
so only one of the two performs the delete.

ProcessExit's semantics match the cooperative/involuntary partition
exactly:

| Shutdown path | ProcessExit fires? | Behavior after this PR |
|---|---|---|
| `Environment.Exit(code)` (all 4 paths above) | yes | lock deleted by
handler |
| `Environment.FailFast` | no | lock survives → Phase 0 catches it
(correct: explicit FailFast = real failure) |
| BSOD / external `TerminateProcess` / kernel OOM | no | lock survives →
Phase 0 catches it (correct: original design) |
| Discovery completes normally / throws | n/a | `try/finally` calls
`Dispose()` as before; handler unsubscribed first |

### Testability

A new `IProcessExitHook` interface abstracts the subscription so unit
tests can simulate ProcessExit without terminating the test runner.
Production code uses the default `AppDomainProcessExitHook` singleton;
tests inject a fake whose `RaiseExit()` invokes subscribed handlers
synchronously.

### Files touched

-
`src/modules/powerdisplay/PowerDisplay.Lib/Services/IProcessExitHook.cs`
*(new)* — interface + production singleton
-
`src/modules/powerdisplay/PowerDisplay.Lib/Services/CrashDetectionScope.cs`
— subscribe in `Begin`, unsubscribe in `Dispose`, add `OnProcessExit`
handler, expanded class doc
-
`src/modules/powerdisplay/PowerDisplay.Lib.UnitTests/CrashDetectionScopeTests.cs`
*(new)* — 10 unit tests

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

### Automated

10 new unit tests in `CrashDetectionScopeTests`, all passing:

```
Passed Begin_WritesLockFileAtomically
Passed Begin_SubscribesToProcessExit
Passed Dispose_UnsubscribesFromProcessExit
Passed Dispose_DeletesLockFile
Passed ProcessExitFired_BeforeDispose_DeletesLock      (core scenario)
Passed ProcessExitFired_AfterDispose_DoesNothing
Passed Dispose_AfterProcessExit_DoesNotThrow
Passed ProcessExitFired_LockFileMissing_DoesNotThrow
Passed Dispose_IsIdempotent
Passed MultipleScopes_DoNotShareState
```

Full `PowerDisplay.Lib.UnitTests` suite: **129 / 132 passing**. The 3
failures (`DetectOrphanAndDisable_RunsFullSequenceWhenOrphanPresent`,
`DetectOrphanAndDisable_HandlesUnknownVersionAsOrphan`,
`DetectOrphanAndDisable_LeavesLockIntactOnSignalFailure`) are
**pre-existing on `main`** — they fail with `REGDB_E_CLASSNOTREG` from
`Constants.AutoDisablePowerDisplayEvent()` (WinRT activation factory not
COM-registered in the test environment). Verified by stashing this PR's
changes and re-running the same 3 tests on baseline `main` — same
failures, same cause, unrelated to this change.

### Manual

1. Reproduced the original false-positive on `main`:
- Enable PowerDisplay → open Settings UI → quickly toggle PowerDisplay
off
- Observe `discovery.lock` left in
`%LOCALAPPDATA%\Microsoft\PowerToys\PowerDisplay\`
- Re-enable PowerDisplay → Phase 0 writes `crash_detected.flag` →
InfoBar appears
2. Repeated the same steps with this branch:
- Toggling PowerDisplay off cleanly deletes `discovery.lock`
(ProcessExit handler ran)
- Re-enabling PowerDisplay shows no InfoBar, no `crash_detected.flag`
created
3. BSOD path is unchanged (verified by inspecting the conditional logic
— `AppDomain.ProcessExit` does not fire for involuntary terminations;
the lock survives just as before).

---------

Co-authored-by: Yu Leng <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
(cherry picked from commit cd5027fa1a)
2026-05-29 12:49:14 +08:00
Copilot
df019c09e6 Rename OOBE overview Learn link label to “Documentation” (#48155)
## Summary of the Pull Request

Renames the OOBE welcome/overview hyperlink label from **“Documentation
on Microsoft Learn”** to **“Documentation”** for brevity and
consistency.
Scope is limited to the localized string resource used by the OOBE
overview page.

## PR Checklist

- [ ] **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
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

- **Resource update (OOBE Overview)**
- Updated `Oobe_Overview_DescriptionLinkText.Text` in
`src/settings-ui/Settings.UI/Strings/en-us/Resources.resw`.

```xml
<data name="Oobe_Overview_DescriptionLinkText.Text" xml:space="preserve">
  <value>Documentation</value>
</data>
```

## Validation Steps Performed

- Confirmed the OOBE overview string key now resolves to
**“Documentation”**.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
(cherry picked from commit 7da62cdb0a)
2026-05-29 12:49:14 +08:00
Eymard Silva
d97301f06f Handle complex calculator results (#47506)
## Summary of the Pull Request

Return a friendly calculator error when Mages evaluates an expression to
a complex number instead of letting decimal conversion throw.

This fixes the PowerToys Run Calculator result for expressions such as
`sqrt(-1)` by detecting `System.Numerics.Complex` results before decimal
conversion and showing a localized error message instead.

Fixes #43937

## PR Checklist

- [x] Closes: #43937
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **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
- [x] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [x] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [x] **Documentation updated:** Not required for this bug fix.

## Detailed Description of the Pull Request / Additional comments

The Calculator plugin previously passed complex results from Mages into
`Convert.ToDecimal`, which caused an exception for expressions like
`sqrt(-1)`.

This PR updates the calculator result transformation logic to detect
`System.Numerics.Complex` and return a localized user-facing error
message: `Complex numbers are not supported`.

It also updates calculator query tests to cover both direct keyword and
global query behavior.

## Validation Steps Performed

- Added unit test coverage for `=sqrt(-1)` returning `Complex numbers
are not supported`.
- Added unit test coverage for global query `sqrt(-1)` returning no
result instead of surfacing an unhandled exception.
- Ran `git diff --check`.
- Attempted local build/test with the PowerToys build scripts, but local
validation was blocked by Visual Studio/VC tooling configuration issues
unrelated to this change: `PlatformToolsetVersion` resolves to an empty
value during restore/build.

(cherry picked from commit c46083dd8d)
2026-05-29 12:49:13 +08:00
Mike Griese
86ca7c5661 Move CmdPal API spec back to cmdpal/ directory (#48160)
Reverts 0819a62 / #46926

The cmdpal API is literally generated from this spec document. It needs
to live with the rest of the code to work correctly.

Docs for authoring cmdpal extensions are on
https://learn.microsoft.com/en-us/windows/powertoys/command-palette/extension-development,
and we should direct docs commentary there.

(cherry picked from commit 65112a7b05)
2026-05-29 12:49:13 +08:00
🄂ʏᴇᴅ 🄰ʙᴅᴜʟ 🄰ᴍᴀ🄝 ✧
e37d1d5d04 Fix project template settings heading (#48148)
## Summary
- Fix a grammar typo in the PowerToy project template README heading.
- Change "Settings Informations" to "Settings Information".

## Validation
- Ran `git diff --check`.

(cherry picked from commit 6be6509c46)
2026-05-29 12:48:44 +08:00
thetsaw
9a55209d13 Add DiskAnalyzer to third-party Run plugins list (#48106)
## Summary of the Pull Request

Adds **DiskAnalyzer** to the General plugins table in
`doc/thirdPartyRunPlugins.md`.

- **Plugin:**
[Community.PowerToys.Run.Plugin.DiskAnalyzer](https://github.com/thetsaw/PowerToys.Plugin)
- - **Author:** thetsaw
- - **Keyword:** `ds`
- - **License:** MIT
- - **Platforms:** x64 and ARM64
### What it does
Scan any folder or drive to find the largest files and subfolders, view
drive usage with visual progress bars, and navigate your filesystem all
from PowerToys Run.

## PR Checklist

- [x] Plugin has been publicly available
- [ ] - [x] MIT licensed
- [ ] - [x] Releases include x64 and ARM64 zips
- [ ] - [x] plugin.json is correctly formatted
- [ ] - [x] README includes install instructions
## Detailed Description

This is a documentation-only change adding one row to the third-party
plugins table. No source code, binaries, or build files are modified.
2026-05-28 17:46:23 +00:00
Copilot
0cb6fe250b Rename Settings UI label from “Shortcut Guide V2” to “Shortcut Guide” (#48151)
## Summary of the Pull Request

This updates PowerToys Settings to remove the obsolete “V2” suffix from
the Shortcut Guide module name. The UI now consistently shows **Shortcut
Guide**.

## PR Checklist

- [ ] **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
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

- **Settings navigation label**
  - Updated `Shell_ShortcutGuide.Content` to `Shortcut Guide`.
- **Module title**
  - Updated `ShortcutGuide.ModuleTitle` to `Shortcut Guide`.
- **OOBE title**
  - Updated `Oobe_ShortcutGuide.Title` to `Shortcut Guide`.

```xml
<data name="Shell_ShortcutGuide.Content" xml:space="preserve">
  <value>Shortcut Guide</value>
</data>
```

## Validation Steps Performed

- N/A for behavior-level validation in this description (change is
limited to localized display strings).

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-05-28 17:46:17 +08:00
moooyo
c0cb9417ad Remove "NEW" tag from Power Display and Grab and Move (#48174)
## Summary of the Pull Request
Both Power Display and Grab and Move have matured beyond their initial
release phase. This removes the "NEW" `InfoBadge` from their navigation
items in Settings, the two parent navigation groups (Windowing &
Layouts, Input / Output) that surfaced the badge when collapsed, and
clears the `IsNew` flag for Power Display in the OOBE shell.

<img width="1867" height="973" alt="image"
src="https://github.com/user-attachments/assets/533f271c-c70f-414f-a76a-43fd9ffbbd44"
/>
<img width="497" height="575" alt="image"
src="https://github.com/user-attachments/assets/fe1e97c3-c806-4f42-a836-76e042630d61"
/>
<img width="1619" height="1027" alt="image"
src="https://github.com/user-attachments/assets/f5db715b-bc69-4505-803a-18a9b2716280"
/>


## PR Checklist

- [x] Closes: #48153
- [x] **Communication:** Tracked by the linked issue
- [x] **Tests:** Markup-only change; Settings.UI builds clean with WinUI
markup compiler (no XAML errors)
- [x] **Localization:** No end-user-facing strings changed
- [ ] **Dev docs:** N/A
- [ ] **New binaries:** N/A
- [ ] **Documentation updated:** N/A

## Detailed Description of the Pull Request / Additional comments
Files touched:
- `src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml` —
removed four `<InfoBadge Style="{StaticResource NewInfoBadge}" />`
blocks on `GrabAndMoveNavigationItem`, `PowerDisplayNavigationItem`, and
on the two parent group headers `WindowingAndLayoutsNavigationItem` and
`InputOutputNavigationItem` (the parent badges existed only to surface a
NEW child when the group was collapsed; with no NEW children left in
those groups, the parent badges are now stale).
- `src/settings-ui/Settings.UI/OOBE/ViewModel/OobeShellViewModel.cs` —
flipped `(PowerToysModules.PowerDisplay, true)` to
`(PowerToysModules.PowerDisplay, false)`. Grab and Move was already
`false`.

No other modules or strings affected.

## Validation Steps Performed
- Built `src\settings-ui\Settings.UI\PowerToys.Settings.csproj`
(Release|x64) with MSBuild from VS 18 Enterprise;
`PowerToys.Settings.dll` produced with 0 errors related to this change.
WinUI markup compiler would have aborted before producing the DLL if the
XAML had syntax issues.
- Diff inspected: only the five intended deletions/edits, no collateral
changes.
- Visual run-time verification of the Settings navigation pane is
recommended before merge.

Co-authored-by: Yu Leng <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 09:28:31 +00:00
moooyo
cd5027fa1a [PowerDisplay] Fix false-positive crash detection on cooperative shutdown (#48173)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

Cooperative shutdowns of `PowerDisplay.exe` — Runner's `TerminateApp`
NamedPipe message, the `Terminate` named event, tray-quit, Runner-exit
detection, and PowerToys upgrades — all call `Environment.Exit(0)`
immediately. If DDC/CI discovery is mid-flight, that path skips the
`try/finally` that owns `CrashDetectionScope`, leaving `discovery.lock`
on disk. Phase 0 at the next `PowerDisplay.exe` startup then treats this
orphan as evidence of a real crash and auto-disables the module,
surfacing the "PowerDisplay has crashed" InfoBar in Settings UI.

This PR adds an `AppDomain.ProcessExit` safety-net inside
`CrashDetectionScope`. ProcessExit fires for `Environment.Exit` but
**not** for `FailFast` / BSOD / external `TerminateProcess` — exactly
the partition we need: cooperative exit → best-effort delete the lock;
involuntary kill → leave the lock for Phase 0 to detect (original design
intent preserved).

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

- [x] Closes: #48169
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** All end-user-facing strings can be localized
<!-- no user-facing strings changed -->
- [x] **Dev docs:** Added/updated <!-- inline XML doc on
CrashDetectionScope explains the ProcessExit partition -->
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

### Root cause

`CrashDetectionScope.Begin()` writes `discovery.lock` before DDC/CI
capability fetch and `Dispose()` deletes it when the `using` block
exits. The lock is intentionally designed to survive any code path that
cannot run user-mode cleanup (BSOD, kernel OOM, `TerminateProcess`), so
that the next `PowerDisplay.exe` start can see it and run Phase 0 (write
`crash_detected.flag`, set `enabled.PowerDisplay=false` in global
`settings.json`, signal `AutoDisablePowerDisplayEvent`).

The bug is that several **cooperative** shutdown paths route to
`Environment.Exit(0)` immediately:

| Path | Code |
|---|---|
| Runner's `TerminateApp` NamedPipe | `App.xaml.cs::OnNamedPipeMessage`
→ `Shutdown()` → `Environment.Exit(0)` |
| `Terminate` named event | `App.xaml.cs::OnLaunched` →
`RegisterEvent(..., () => Environment.Exit(0), "Terminate")` |
| Tray-quit | `TrayIconService` callback → `Environment.Exit(0)` |
| Runner-exit detection | `RunnerHelper.WaitForPowerToysRunner` callback
→ `Environment.Exit(0)` |

`Environment.Exit` calls `ExitProcess` under the hood, which terminates
all threads abruptly. Background `Task.WhenAll` doing DDC capability
fetch is killed mid-flight; the `finally` block that calls
`scope.Dispose()` never runs; `discovery.lock` orphans; Phase 0 next
time false-positives.

Concrete repro from logs:
- `15:08:42.510` lock written
- `15:08:42.79` probe monitor #1
- `15:08:46.92` probe monitor #2 (started, not finished — typical probe
takes ~5s)
- `15:08:49.03` `TerminateApp` received → `Environment.Exit(0)` → no
`Dispose` log line
- `15:10:10.03` next startup: Phase 0 sees orphan lock with `pid:17712,
startedAt:2026-05-28T07:08:42Z` → writes `crash_detected.flag` →
auto-disables

### Fix

`CrashDetectionScope.Begin()` now also subscribes to
`AppDomain.CurrentDomain.ProcessExit`. The handler does a best-effort
`File.Delete(_lockPath)` (swallowing exceptions, as required for
ProcessExit handlers). `Dispose()` unsubscribes before deleting. An
`Interlocked.Exchange` guards the race between Dispose and ProcessExit
so only one of the two performs the delete.

ProcessExit's semantics match the cooperative/involuntary partition
exactly:

| Shutdown path | ProcessExit fires? | Behavior after this PR |
|---|---|---|
| `Environment.Exit(code)` (all 4 paths above) | yes | lock deleted by
handler |
| `Environment.FailFast` | no | lock survives → Phase 0 catches it
(correct: explicit FailFast = real failure) |
| BSOD / external `TerminateProcess` / kernel OOM | no | lock survives →
Phase 0 catches it (correct: original design) |
| Discovery completes normally / throws | n/a | `try/finally` calls
`Dispose()` as before; handler unsubscribed first |

### Testability

A new `IProcessExitHook` interface abstracts the subscription so unit
tests can simulate ProcessExit without terminating the test runner.
Production code uses the default `AppDomainProcessExitHook` singleton;
tests inject a fake whose `RaiseExit()` invokes subscribed handlers
synchronously.

### Files touched

-
`src/modules/powerdisplay/PowerDisplay.Lib/Services/IProcessExitHook.cs`
*(new)* — interface + production singleton
-
`src/modules/powerdisplay/PowerDisplay.Lib/Services/CrashDetectionScope.cs`
— subscribe in `Begin`, unsubscribe in `Dispose`, add `OnProcessExit`
handler, expanded class doc
-
`src/modules/powerdisplay/PowerDisplay.Lib.UnitTests/CrashDetectionScopeTests.cs`
*(new)* — 10 unit tests

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

### Automated

10 new unit tests in `CrashDetectionScopeTests`, all passing:

```
Passed Begin_WritesLockFileAtomically
Passed Begin_SubscribesToProcessExit
Passed Dispose_UnsubscribesFromProcessExit
Passed Dispose_DeletesLockFile
Passed ProcessExitFired_BeforeDispose_DeletesLock      (core scenario)
Passed ProcessExitFired_AfterDispose_DoesNothing
Passed Dispose_AfterProcessExit_DoesNotThrow
Passed ProcessExitFired_LockFileMissing_DoesNotThrow
Passed Dispose_IsIdempotent
Passed MultipleScopes_DoNotShareState
```

Full `PowerDisplay.Lib.UnitTests` suite: **129 / 132 passing**. The 3
failures (`DetectOrphanAndDisable_RunsFullSequenceWhenOrphanPresent`,
`DetectOrphanAndDisable_HandlesUnknownVersionAsOrphan`,
`DetectOrphanAndDisable_LeavesLockIntactOnSignalFailure`) are
**pre-existing on `main`** — they fail with `REGDB_E_CLASSNOTREG` from
`Constants.AutoDisablePowerDisplayEvent()` (WinRT activation factory not
COM-registered in the test environment). Verified by stashing this PR's
changes and re-running the same 3 tests on baseline `main` — same
failures, same cause, unrelated to this change.

### Manual

1. Reproduced the original false-positive on `main`:
- Enable PowerDisplay → open Settings UI → quickly toggle PowerDisplay
off
- Observe `discovery.lock` left in
`%LOCALAPPDATA%\Microsoft\PowerToys\PowerDisplay\`
- Re-enable PowerDisplay → Phase 0 writes `crash_detected.flag` →
InfoBar appears
2. Repeated the same steps with this branch:
- Toggling PowerDisplay off cleanly deletes `discovery.lock`
(ProcessExit handler ran)
- Re-enabling PowerDisplay shows no InfoBar, no `crash_detected.flag`
created
3. BSOD path is unchanged (verified by inspecting the conditional logic
— `AppDomain.ProcessExit` does not fire for involuntary terminations;
the lock survives just as before).

---------

Co-authored-by: Yu Leng <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 09:02:14 +00:00
Copilot
7da62cdb0a Rename OOBE overview Learn link label to “Documentation” (#48155)
## Summary of the Pull Request

Renames the OOBE welcome/overview hyperlink label from **“Documentation
on Microsoft Learn”** to **“Documentation”** for brevity and
consistency.
Scope is limited to the localized string resource used by the OOBE
overview page.

## PR Checklist

- [ ] **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
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

- **Resource update (OOBE Overview)**
- Updated `Oobe_Overview_DescriptionLinkText.Text` in
`src/settings-ui/Settings.UI/Strings/en-us/Resources.resw`.

```xml
<data name="Oobe_Overview_DescriptionLinkText.Text" xml:space="preserve">
  <value>Documentation</value>
</data>
```

## Validation Steps Performed

- Confirmed the OOBE overview string key now resolves to
**“Documentation”**.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-05-28 15:26:02 +08:00
Eymard Silva
c46083dd8d Handle complex calculator results (#47506)
## Summary of the Pull Request

Return a friendly calculator error when Mages evaluates an expression to
a complex number instead of letting decimal conversion throw.

This fixes the PowerToys Run Calculator result for expressions such as
`sqrt(-1)` by detecting `System.Numerics.Complex` results before decimal
conversion and showing a localized error message instead.

Fixes #43937

## PR Checklist

- [x] Closes: #43937
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **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
- [x] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [x] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [x] **Documentation updated:** Not required for this bug fix.

## Detailed Description of the Pull Request / Additional comments

The Calculator plugin previously passed complex results from Mages into
`Convert.ToDecimal`, which caused an exception for expressions like
`sqrt(-1)`.

This PR updates the calculator result transformation logic to detect
`System.Numerics.Complex` and return a localized user-facing error
message: `Complex numbers are not supported`.

It also updates calculator query tests to cover both direct keyword and
global query behavior.

## Validation Steps Performed

- Added unit test coverage for `=sqrt(-1)` returning `Complex numbers
are not supported`.
- Added unit test coverage for global query `sqrt(-1)` returning no
result instead of surfacing an unhandled exception.
- Ran `git diff --check`.
- Attempted local build/test with the PowerToys build scripts, but local
validation was blocked by Visual Studio/VC tooling configuration issues
unrelated to this change: `PlatformToolsetVersion` resolves to an empty
value during restore/build.
2026-05-28 15:06:22 +08:00
Mike Griese
65112a7b05 Move CmdPal API spec back to cmdpal/ directory (#48160)
Reverts 0819a62 / #46926

The cmdpal API is literally generated from this spec document. It needs
to live with the rest of the code to work correctly.

Docs for authoring cmdpal extensions are on
https://learn.microsoft.com/en-us/windows/powertoys/command-palette/extension-development,
and we should direct docs commentary there.
2026-05-28 00:05:12 +02:00
Dustin L. Howett
109c63ba33 Remove our dependency on expected-lite (#48159)
This removes our last git submodule dependency!

We were using `expected-lite` in one place, which was being compiled out
_anyway_ in favor of using `std::expected`.
2026-05-27 14:58:27 -07:00
🄂ʏᴇᴅ 🄰ʙᴅᴜʟ 🄰ᴍᴀ🄝 ✧
6be6509c46 Fix project template settings heading (#48148)
## Summary
- Fix a grammar typo in the PowerToy project template README heading.
- Change "Settings Informations" to "Settings Information".

## Validation
- Ran `git diff --check`.
2026-05-27 17:31:03 +00:00
Boliang Zhang
8a7933c0b2 Migrate spdlog from submodule to vcpkg (#48039)
## Summary

Migrate `deps/spdlog` from a git submodule to **vcpkg manifest mode**
with an overlay port pinned to the **exact same commit**
(`gabime/spdlog@616866fc`). Replaces the polyfill shim added in #47910
with a proper port-level patch.

This is the follow-up to PR #47928, which I closed after @zadjii-msft /
@DHowett clarified that the intended direction was a single combined
"move to vcpkg **and** apply a patch file" (one change, not two stepping
stones).

## Guidance honored

Per @zadjii-msft (offline):
-  Convert each submodule to vcpkg **one at a time** — this PR is
**spdlog only**. `deps/expected-lite` stays a submodule (separate PR
next).
-  Atomic commit per dep (multiple commits on the branch for review
traceability; squash on merge gives the requested single commit).
-  **Don't bump the version.** Only variable changed: submodule →
vcpkg. Same commit (`616866fc`, v1.8.5 + 38) the submodule pointed at.

Per @DHowett
([review](https://github.com/microsoft/PowerToys/pull/48039#pullrequestreview-4338835150)):
-  No vcpkg submodule — vswhere-first detection via a Terminal-style
`steps-install-vcpkg.yml` template; three-tier `VcpkgRoot` fallback (env
var → VS-shipped → runtime clone pinned to manifest baseline).

## Design

- **Repo-root manifest**: `vcpkg.json` declares only `spdlog`, with
`builtin-baseline` pinned. `vcpkg-configuration.json` registers
`deps/vcpkg-overlays/` as overlay-ports.
- **Overlay port** `deps/vcpkg-overlays/spdlog/`: `vcpkg_from_github(REF
616866fc...)` with bundled fmt preserved (`-DSPDLOG_FMT_EXTERNAL=OFF`);
the MSVC 14.51 fix from #47910 carried as a proper vcpkg patch on
`include/spdlog/fmt/bundled/format.h`.
- **vcpkg integration is global** (set in `Cpp.Build.props`, imported
via `ForceImportBeforeCppProps` for every `.vcxproj`). An earlier
attempt to make vcpkg per-project-opt-in via `deps/spdlog.props` failed
because ~85 PowerToys `.vcxproj` files import `spdlog.props` AFTER
`Microsoft.Cpp.targets`, by which point `vcpkg.props`' `ClCompile` hook
is dead-on-arrival. The trade-off (every C++ project invokes `vcpkg
install` once at build time, ~0.5 s on cache hits, manifest declares
only spdlog so install set is fixed) is documented in the expanded
`Cpp.Build.props` comment.
- **`deps/spdlog.props`** is now a thin shim that only sets the
historical `SPDLOG_*` preprocessor defines for source-compat.
- **`Cpp.Build.targets`** is a new file imported via
`ForceImportAfterCppTargets` to load `vcpkg.targets` after
`Microsoft.Cpp.targets`. A fail-fast `<Target>` errors with a clear
message if `vcpkg.props` can't be found at the resolved `VcpkgRoot`.
- **Removes** `deps/spdlog-msvc-fix/` polyfill, in-tree wrapper
`src/logging/`, spdlog submodule, the single `<ProjectReference>` in
`logger.vcxproj`, plus 3 `.slnf` refs and 2 `.slnx` refs
(`PowerToys.slnx` + `installer/PowerToysSetup.slnx`), plus 3 hard-coded
`..\deps\spdlog\include` entries in `<AdditionalIncludeDirectories>`.
- **CI**: new reusable `.pipelines/v2/templates/steps-install-vcpkg.yml`
(vswhere-first, manifest-baseline-pinned fallback clone, respects
`useVSPreview`). Gated `Cache@2` for `%LOCALAPPDATA%\vcpkg\archives`
keyed on overlay-port contents. Same vcpkg detection added to
`tools\build\build-essentials.ps1` for local devs.

## Verification

Local build matrix (all 4 configs of `logger.vcxproj` and a
representative late-import consumer):

| Config | Result | Notes |
|--------|--------|-------|
| Release \| x64    |  | vcpkg install ~21 s, `logger.lib` produced |
| Debug \| x64 |  | **Validates patch fixes the actual MSVC 14.51 bug**
(`_ITERATOR_DEBUG_LEVEL > 0` → `_SECURE_SCL`) |
| Release \| ARM64 |  | vcpkg cross-installs `arm64-windows-static`
spdlog in ~16 s |
| Debug \| ARM64 |  | **Previously DISABLED for the in-tree spdlog**
(per `<Build Solution="Debug\|ARM64" Project="false" />` in
`PowerToysSetup.slnx`); this migration FIXES that latent gap |
| FancyZonesLib (Release \| x64) |  | Late-import-pattern consumer;
previously broke in v2 |

Full PowerToys CI (x64 + arm64 + CmdPal SDK + all GitHub Actions checks)
green.

**Consumer audit**: 72 `.vcxproj` files reference `logger.vcxproj`; all
72 also import `deps/spdlog.props`. No transitive-link breakage.

## Out of scope (intentional)

- `deps/expected-lite` migration — next PR per "one-at-a-time" rule.
- Remote vcpkg binary cache (Azure Artifacts NuGet feed). Local pipeline
`Cache@2` works for now, but a remote feed survives across pipelines and
is the long-term answer. Happy to split this into a follow-up.

## Notes for review

- Patch in the overlay port is identical content to PR #47928's patch
but regenerated with LF line endings (vcpkg's `vcpkg_apply_patches` is
strict; no `--ignore-whitespace`).
- Once PowerToys eventually bumps spdlog past v1.14 (which ships fmt
10.2 and drops the affected code path), the overlay port can be deleted
and we can use upstream vcpkg's `spdlog` directly.
- Re. official-release pipelines and terrapin / less-restricted network
isolation: VS-shipped vcpkg is the primary path (no network); the
fallback clone is only exercised when VS doesn't ship vcpkg. Happy to
wire terrapin into the fallback as a follow-up if the official build
template needs it.

Closes the work tracked in #47928 (which was closed unmerged).

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Dustin L. Howett <dustin@howett.net>
2026-05-27 15:45:24 +08:00
Boliang Zhang (from Dev Box)
ac6aa80401 Merge main into stable for 0.100 release (rev 6) 2026-05-26 15:19:20 +08:00
Jeremy Sinclair
6f5ea3bb95 [Deps] Upgrade .NET Runtime package versions to 10.0.8 (#48010)
## Summary of the Pull Request

Updates .NET 10 Runtime / Library packages to the latest 10.0.8
servicing release for security fixes.

## PR Checklist

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

Updates the runtime-related package versions in
`Directory.Packages.props` from `10.0.7` to `10.0.8`.

## Validation Steps Performed

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Niels Laute <niels.laute@live.nl>
2026-05-26 14:57:35 +08:00
Michael Clayton
fe985e7eea Ready To Review - [MouseWithoutBorders] - incremental code cleanup / refactor (#44553)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

Some focussed refactoring / simplifying / cleanup / delinting on the
Mouse Without Borders codebase (see [#44508 - [Mouse Without Borders] -
de-linting
codebase](https://github.com/microsoft/PowerToys/issues/44508)) now that
the Common class has been broken down.

This PR does some cleaning up on the ```Logger``` class:

* Uplifting coding style (string interpolation, pattern matching,
```var```, etc)
* Rationalising and simplifying code
* Relocating e.g. IO and UI side effects (writing to disk, displaying
dialog boxes) outside of Logger class
* Removing dead code, tightening visibility of existing code
* Added / updated tests to try to cover as much of the refactoring as
possible to prevent regressions

I've split the changes into lots of small commits - it might be easier
to review the individual commits rather than the whole PR in one go.

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

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

### Run manual tests from [Test Checklist
Template](5bc7201ae2/doc/releases/tests-checklist-template.md (mouse-without-borders)):

* Install PowerToys on two PCs in the same local network:
   - [x]     Verify that PowerToys is properly installed on both PCs.
   - [x]     Configure Windows Firewall Rules
- ```netsh advfirewall firewall add rule
name="PowerToys.MouseWithoutBorders - mc" dir=in action=allow
program="C:\src\mc\PowerToys\x64\Debug\PowerToys.exe" enable=yes
remoteip=any profile=any protocol=tcp```
   
 * Setup Connection:
- [x] Open MWB's settings on the first PC and click the "New Key"
button. Verify that a new security key is generated.
- [x] Copy the generated security key and paste it in the corresponding
input field in the settings of MWB on the second PC. Also enter the name
of the first PC in the required field.
- [x] Press "Connect" and verify that the machine layout now includes
two PC tiles, each displaying their respective PC names.
   
 * Verify Connection Status:
- [x] Ensure that the border of the remote PC turns green, indicating a
successful connection.
- [x] Enter an incorrect security key and verify that the border of the
remote PC turns red, indicating a failed connection.
   
 * Test Remote Mouse/Keyboard Control:
- [x] With the PCs connected, test the mouse/keyboard control from one
PC to another. Verify that the mouse/keyboard inputs are correctly
registered on the other PC.
- [ ] Test remote mouse/keyboard control across all four PCs, if
available. Verify that inputs are correctly registered on each connected
PC when the mouse is active there.
     - unable to test - only 2 machines available
   
 * Test Remote Control with Elevated Apps:
- note - the main PowerToys.exe must be running as a **non**-admin for
these tests
- [x] Open an elevated app on one of the PCs. Verify that without "Use
Service" enabled, PowerToys does not control the elevated app.
- [x] Enable "Use Service" in MWB's settings (need to run PowerToys.exe
as admin to enable "Use Service", then restart PowerToys.exe as
non-admin). Verify that PowerToys can now control the elevated app
remotely. Verify that MWB processes are running as LocalSystem, while
the MWB helper process is running non-elevated.
- ```get-process -Name "PowerToys.MouseWithoutBorders*" -IncludeUserName
| format-table Id, ProcessName, UserName```
- [x] Process: ```PowerToys.MouseWithoutBorders.exe``` - running as
```SYSTEM```
- [x] Process: ```PowerToys.MouseWithoutBorders.Helper.exe``` - running
as current user
- ```get-service -Name "PowerToys.*" | ft Status, Name, UserName;
get-ciminstance -Class "Win32_Service" -Filter "Name like 'PowerToys%'"
| ft ProcessId, Name```
- [ ] Service: ```PowerToys.MWB.Service``` - running as ```Local
System```
- [x] Toggle "Use Service" again, verify that each time you do that, the
MWB processes are restarted.
- [ ] Run PowerToys elevated on one of the machines, verify that you can
control elevated apps remotely now on that machine.

* Test Module Enable Status:
- [ ] For all combinations of "Use Service"/"Run PowerToys as admin",
try enabling/disabling MWB module and verify that it's indeed being
toggled using task manager.
   
 * Test Disconnection/Reconnection:
- [ ] Disconnect one of the PCs from network. Verify that the machine
layout updates to reflect the disconnection.
   - [ ]     Do the same, but now by exiting PowerToys.
   - [ ]     Start PowerToys again, verify that the PCs are reconnected.
  
 * Test Various Local Network Conditions:
- [ ] Test MWB performance under various network conditions (e.g., low
bandwidth, high latency). Verify that the tool maintains a stable
connection and functions correctly.

 * Clipboard Sharing:
- [ ] Copy some text on one PC and verify that the same text can be
pasted on another PC.
- [ ] Use the screenshot key and Win+Shift+S to take a screenshot on one
PC and verify that the screenshot can be pasted on another PC.
- [ ] Copy a file in Windows Explorer and verify that the file can be
pasted on another PC. Make sure the file size is below 100MB.
- [ ] Try to copy multiple files and directories and verify that it's
not possible (only the first selected file is being copied).
 
 * Drag and Drop:
- [ ] Drag a file from Windows Explorer on one PC, cross the screen
border onto another PC, and release it there. Verify that the file is
copied to the other PC. Make sure the file size is below 100MB.
- [ ] While dragging the file, verify that a corresponding icon is
displayed under the mouse cursor.
- [ ] Without moving the mouse from one PC to the target PC, press
CTRL+ALT+F1/2/3/4 hotkey to switch to the target PC directly and verify
that file sharing/dropping is not working.

 * Lock and Unlock with "Use Service" Enabled:
   - [ ]     Enable "Use Service" in MWB's settings.
- [ ] Lock a remote PC using Win+L, move the mouse to it remotely, and
try to unlock it. Verify that you can unlock the remote PC.
- [ ] Disable "Use Service" in MWB's settings, lock the remote PC, move
the mouse to it remotely, and try to unlock it. Verify that you can't
unlock the remote PC.

 * Test Settings:
- [ ] Change the rest of available settings on MWB page and verify that
each setting works as described.

### Group Policy Tests

See https://learn.microsoft.com/en-us/windows/powertoys/grouppolicy

- [ ] Install *.admx / *.adml and check settings behave as expected
  - [ ] I'll expand the list of settings here when I get this far :-)
- [ ] HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys
  - [x]     ConfigureEnabledUtilityMouseWithoutBorders
- [x] ```[missing]``` - "Activation -> Enable Mouse Without Borders"
enabled, with GPO warning hidden
- ```reg delete HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v
ConfigureEnabledUtilityMouseWithoutBorders /f```
- [x] ```0``` - "Activation -> Enable Mouse Without Borders" set to
"off" and disabled, with GPO warning visible
- ```reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v
ConfigureEnabledUtilityMouseWithoutBorders /t REG_DWORD /d 0 /f```
- [x] ```1``` - "Activation -> Enable Mouse Without Borders" set to "on"
and disabled, with GPO warning visible
- ```reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v
ConfigureEnabledUtilityMouseWithoutBorders /t REG_DWORD /d 1 /f```
  - [ ] MwbClipboardSharingEnabled
  - [ ] MwbFileTransferEnabled
  - [ ] MwbUseOriginalUserInterface
  - [ ] MwbDisallowBlockingScreensaver
  - [ ] MwbSameSubnetOnly
  - [ ] MwbValidateRemoteIp
  - [x]     MwbDisableUserDefinedIpMappingRules
- [x] ```[missing]``` - "Advanced Settings -> IP address mapping"
enabled, with GPO warning hidden
- ```reg delete HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v
MwbDisableUserDefinedIpMappingRules /f```
- [x] ```0``` - "Advanced Settings -> IP address mapping" enabled, with
GPO warning hidden
- ```reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v
MwbDisableUserDefinedIpMappingRules /t REG_DWORD /d 0 /f```
- [x] ```1``` - "Advanced Settings -> IP address mapping" disabled, with
GPO warning visible
- ```reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v
MwbDisableUserDefinedIpMappingRules /t REG_DWORD /d 1 /f```
  - [x]     MwbPolicyDefinedIpMappingRules
- [x] ```[missing]``` - "Advanced Settings -> IP address mapping"
enabled, with GPO warning and GPO values hidden
- ```reg delete HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v
MwbPolicyDefinedIpMappingRules /f```
- [x] ```[empty value]``` - "Advanced Settings -> IP address mapping"
enabled, with GPO warning hidden and GPO values hidden
- ```reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v
MwbPolicyDefinedIpMappingRules /t REG_MULTI_SZ /d "" /f```
- [x] ```[non-empty value]``` - "Advanced Settings -> IP address
mapping" enabled, with GPO warning visible and GPO values visible
- ```reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v
MwbPolicyDefinedIpMappingRules /t REG_MULTI_SZ /d "aaa 10.0.0.1\0bbb
10.0.0.2" /f```
2026-05-26 14:54:15 +08:00
Niels Laute
b3bf154fa5 [General] Update issue tracker's duplicate resolution message (#47981)
Reopens the change from #46743 (which appears to be broken) on a fresh
branch.

Original author: @daverayment

## Summary

GitHub newcomers can be confused by the current duplicate resolution
message, as it doesn't clearly point to the original referenced issue -
see
https://github.com/microsoft/PowerToys/issues/46347#issuecomment-4103681050.
They may not realise that the #12345 in the duplicate comment is the
relevant link.

This small wording update to the duplicate resolution message tightens
up wording slightly and includes reference to the prior `/dup #nnn`
comment so newcomers don't miss it.

### Before
> Hi! We've identified this issue as a duplicate of another one that
already exists on this Issue Tracker. This specific instance is being
closed in favor of tracking the concern over on the referenced thread.
Thanks for your report!

### After
> We've identified this issue as a duplicate of an existing one and are
closing this thread so discussion stays in one place.<br/><br/>Please
see the comment above for the link to the original tracking issue, and
feel free to subscribe there for updates.

## Validation Steps Performed
N/A - bot reply text change only.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 13:44:34 +08:00
Niels Laute
ab553f9930 [CmdPal][PerfMon] Use distinct up/down arrow icons for network Send/Receive (#48118)
## Summary of the Pull Request

On the Command Palette Performance Monitor extension's Network widget
page, the **Send** and **Receive** list items both used the generic
`NetworkIcon` (`\uEC05`), making them visually indistinguishable at a
glance.

This PR gives each direction its own glyph:
- Send → up arrow `\uE74A`
- Receive → down arrow `\uE74B`

The redundant `↑`/`↓` characters are removed from the Send/Receive
subtitles since the icons now carry that meaning.

Before vs after:

<img width="918" height="122" alt="image"
src="https://github.com/user-attachments/assets/4af3a2fc-d5a7-4fb5-98c6-f1889c7e80f2"
/>


## PR Checklist

- [x] **Closes:** N/A (no existing issue found)
- [x] **Communication:** I've discussed this with collaborators
- [x] **Tests:** Manually verified
- [x] **Localization:** Updated en-US resw (other locales still contain
the arrow characters and can be translated/updated by the loc pipeline)

## Detailed Description of the Pull Request / Additional comments

Files changed:
- `Icons.cs` – added `NetworkUpIcon` and `NetworkDownIcon`
- `PerformanceWidgetsPage.cs` – set `Icon` on `_networkUpItem` and
`_networkDownItem`
- `Strings/en-US/Resources.resw` – `Send ↑` → `Send`, `Receive ↓` →
`Receive`

## Validation Steps Performed

Local visual verification in Command Palette.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 06:29:00 +02:00
Boliang Zhang (from Dev Box)
c4a83be733 Merge main into stable for 0.100 release (rev 5) 2026-05-26 11:28:54 +08:00
Gordon Lam
85b9191b7c [AdvancedPaste] Harden ToJsonFromXmlOrCsvAsync against clipboard read failures (#48124)
## Summary

`ToJsonFromXmlOrCsvAsync` in `AdvancedPaste/Helpers/JsonHelper.cs`
documents that it never throws and returns an empty string on any
failure. The clipboard read at the top of the method
(`clipboardData.GetTextAsync()`) was not wrapped, so a transient
clipboard failure could surface as an exception to callers, contrary to
the documented contract.

This PR:

- Wraps `GetTextAsync()` in a try/catch and returns `string.Empty` on
failure, matching the pattern already used by the JSON/XML/CSV parsing
branches further down in the same method.
- Updates the matching unit test to decode input bytes as UTF-8
(`Encoding.UTF8.GetString(input)`) and consume the awaited task via
`GetAwaiter().GetResult()`, for consistency with sibling tests elsewhere
in the solution.

## Validation

- Local build of `AdvancedPaste.sln`. (Note: my machine has a
pre-existing NuGet SDK resolver issue unrelated to this change — the
same baseline fails on `main` for me. CI should be the source of truth.)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 10:59:24 +08:00
Marcello Morena
cb174210cb Add CmdPal debugging information (#48108)
## Summary of the Pull Request
Adding information about using the Command Palette Visual Studio
solution filter based on
https://github.com/microsoft/PowerToys/issues/47997#issuecomment-4524045763.

## PR Checklist

- [ ] Closes: #47997 

## Detailed Description of the Pull Request / Additional comments
I found this really useful and couldn't see a reference to it anywhere
else in the devdocs. Not sure if this is the best way to describe the
process, but I think adding this information somewhere in the debugging
doc would really help newcomers to CmdPal development!
2026-05-25 17:32:57 +00:00
moooyo
f175a9c96a [PowerDisplay] Confirm before enabling module; log EdidId in Phase 0 (#48111)
## Summary of the Pull Request

Two crash-correlation aids for the kernel-side DDC/CI BSOD mitigated by
#47734:

1. Log EDID hardware ID (manufacturer + product code, e.g. `DELD1A8`)
during Phase 0 monitor classification, before any DDC/CI capability
fetch enters the BSOD risk window.
2. Show a confirmation dialog before turning the Power Display module on
from the Settings page, so the user understands the BSOD risk before the
first capability fetch runs.

## PR Checklist

- [ ] Closes: #xxx
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

### 1. Phase 0 EdidId logging

`MonitorIdentity.EdidIdFromDevicePath` parses the EDID hardware ID
segment from a DevicePath of the form
``\?\DISPLAY#DELD1A8#5&abc&0&UID12345#{guid}`` and returns ``DELD1A8``.
The 3-letter PNP manufacturer code + 4-hex product code is identical for
every physical unit of the same model, so it identifies the *model*
without leaking per-unit identifiers.

`MonitorManager` logs the EdidId on the existing Phase 0 classification
line. Phase 0 uses `QueryDisplayConfig`, which reads OS-cached EDID and
cannot BSOD, so this line is guaranteed on disk before the crash-prone
Phase 2 capability fetch starts. If a machine crashes during
enumeration, the recovered log identifies every attached model
(including same-model duplicates), which makes it possible to correlate
crash reports to specific monitor models even when the user can't tell
us which monitor caused the crash.

### 2. Enable-module confirmation dialog

`PowerDisplayViewModel.IsEnabled` setter is refactored to follow the
same two-phase pattern already used by `MaxCompatibilityMode`:

- `false → true` does not commit immediately; it kicks off
`ConfirmAndEnableModuleAsync`, which awaits the existing
`DangerousFeatureWarningDialog` (resource prefix
`PowerDisplay_EnableModule`) and either commits or reverts the
ToggleSwitch via `OnPropertyChanged`.
- `true → false` commits unconditionally — we never block a user who
wants to turn the module off.
- App-startup loads via `InitializeEnabledValue()` /
`RefreshEnabledState()` assign the `_isEnabled` field directly,
bypassing the setter, so the dialog never fires on settings restore or
GPO refresh.
- GPO-configured state still short-circuits before any dialog logic.

The dialog reuses the existing `DangerousFeatureWarningDialog` injected
by `PowerDisplayPage.xaml.cs`. The 5 new `PowerDisplay_EnableModule_*`
strings explain that the BSOD is in Windows (not Power Display), that
Power Display will auto-disable itself after a detected crash, and that
the user has to re-enable + dismiss the warning each time.

## Validation Steps Performed

- Built `src/settings-ui` and `src/modules/powerdisplay` locally.
- Unit tests: added `EdidIdFromDevicePath_*` cases to
`MonitorIdentityTests`, all green.
- Settings UI manual: toggling Power Display ON now shows the warning
dialog. Pressing Cancel reverts the ToggleSwitch visually; pressing
Enable commits and the module starts. Toggling OFF does not prompt.
Restarting Settings UI with PowerDisplay enabled does not prompt.
GPO-disabled state still locks the toggle.
- Log inspection: `MonitorManager` Phase 0 log now shows `EdidId=...`
for each path before any capability fetch.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 09:08:26 +00:00
moooyo
273d735a8b [PowerDisplay] Confirm before enabling module; log EdidId in Phase 0 (#48111)
## Summary of the Pull Request

Two crash-correlation aids for the kernel-side DDC/CI BSOD mitigated by
#47734:

1. Log EDID hardware ID (manufacturer + product code, e.g. `DELD1A8`)
during Phase 0 monitor classification, before any DDC/CI capability
fetch enters the BSOD risk window.
2. Show a confirmation dialog before turning the Power Display module on
from the Settings page, so the user understands the BSOD risk before the
first capability fetch runs.

## PR Checklist

- [ ] Closes: #xxx
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

### 1. Phase 0 EdidId logging

`MonitorIdentity.EdidIdFromDevicePath` parses the EDID hardware ID
segment from a DevicePath of the form
``\?\DISPLAY#DELD1A8#5&abc&0&UID12345#{guid}`` and returns ``DELD1A8``.
The 3-letter PNP manufacturer code + 4-hex product code is identical for
every physical unit of the same model, so it identifies the *model*
without leaking per-unit identifiers.

`MonitorManager` logs the EdidId on the existing Phase 0 classification
line. Phase 0 uses `QueryDisplayConfig`, which reads OS-cached EDID and
cannot BSOD, so this line is guaranteed on disk before the crash-prone
Phase 2 capability fetch starts. If a machine crashes during
enumeration, the recovered log identifies every attached model
(including same-model duplicates), which makes it possible to correlate
crash reports to specific monitor models even when the user can't tell
us which monitor caused the crash.

### 2. Enable-module confirmation dialog

`PowerDisplayViewModel.IsEnabled` setter is refactored to follow the
same two-phase pattern already used by `MaxCompatibilityMode`:

- `false → true` does not commit immediately; it kicks off
`ConfirmAndEnableModuleAsync`, which awaits the existing
`DangerousFeatureWarningDialog` (resource prefix
`PowerDisplay_EnableModule`) and either commits or reverts the
ToggleSwitch via `OnPropertyChanged`.
- `true → false` commits unconditionally — we never block a user who
wants to turn the module off.
- App-startup loads via `InitializeEnabledValue()` /
`RefreshEnabledState()` assign the `_isEnabled` field directly,
bypassing the setter, so the dialog never fires on settings restore or
GPO refresh.
- GPO-configured state still short-circuits before any dialog logic.

The dialog reuses the existing `DangerousFeatureWarningDialog` injected
by `PowerDisplayPage.xaml.cs`. The 5 new `PowerDisplay_EnableModule_*`
strings explain that the BSOD is in Windows (not Power Display), that
Power Display will auto-disable itself after a detected crash, and that
the user has to re-enable + dismiss the warning each time.

## Validation Steps Performed

- Built `src/settings-ui` and `src/modules/powerdisplay` locally.
- Unit tests: added `EdidIdFromDevicePath_*` cases to
`MonitorIdentityTests`, all green.
- Settings UI manual: toggling Power Display ON now shows the warning
dialog. Pressing Cancel reverts the ToggleSwitch visually; pressing
Enable commits and the module starts. Toggling OFF does not prompt.
Restarting Settings UI with PowerDisplay enabled does not prompt.
GPO-disabled state still locks the toggle.
- Log inspection: `MonitorManager` Phase 0 log now shows `EdidId=...`
for each path before any capability fetch.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 09:08:06 +00:00
Copilot
bcf0b685ac [File Locksmith] Fix IPC text-mode file I/O corrupting Unicode paths (#47361)
## Summary of the Pull Request

The File Locksmith IPC layer reads and writes raw UTF-16 (WCHAR) bytes
to `last-run.log`, but all three stream opens were using the default
text mode. On Windows, the CRT translates `0x0A` bytes to `0x0D 0x0A` on
write and collapses `0x0D 0x0A` back to `0x0A` on read. Because each
WCHAR is 2 bytes, any code unit whose little-endian byte pair contains
`0x0A` in the low position (e.g. `U+010A`, `U+0A0D`) is silently
corrupted. The fix opens all three streams in binary mode and adds an
explicit open-failure guard.

```cpp
// IPC.cpp — Writer::start()
// Before
m_stream = std::ofstream(path);
// After
m_stream = std::ofstream(path, std::ios::binary);
// + is_open() guard returning E_FAIL on failure

// NativeMethods.cpp — StartAsElevated() writer
// Before
std::ofstream stream(paths_file());
// After
std::ofstream stream(paths_file(), std::ios::binary);

// NativeMethods.cpp — ReadPathsFromFile() reader
// Before
std::ifstream stream(paths_file());
// After
std::ifstream stream(paths_file(), std::ios::binary);
```

## PR Checklist

- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

Three targeted changes across two files:

1. **`FileLocksmithLib/IPC.cpp` — `Writer::start()`**: switched
`std::ofstream` from text to binary mode and added an `is_open()` check
that returns `E_FAIL` immediately when the file cannot be opened
(previously the try/catch did not catch a silent open failure because
`std::ofstream` does not throw by default).

2. **`FileLocksmithLibInterop/NativeMethods.cpp` —
`StartAsElevated()`**: switched `std::ofstream` from text to binary
mode. This is the elevated-restart writer path; without this fix,
Unicode corruption persisted when File Locksmith relaunched as
administrator.

3. **`FileLocksmithLibInterop/NativeMethods.cpp` —
`ReadPathsFromFile()`**: switched `std::ifstream` from text to binary
mode. This is the symmetric reader-side bug — even with both writers
corrected, the CRT text-mode reader could collapse a `0x0D 0x0A` byte
pair (a valid UTF-16 LE code unit, e.g. U+0A0D GURMUKHI EK ONKAR) into a
single byte, desynchronising the 2-bytes-at-a-time read loop and
corrupting all subsequent path data.

No behaviour change for purely ASCII paths. Paths containing Unicode
code points whose little-endian UTF-16 byte pair spans `0x0D 0x0A` were
silently corrupted in all three code paths before this fix.

## Validation Steps Performed

- Code review: no issues flagged.
- Full diff reviewed: all three stream opens (`ofstream` writer in
`IPC.cpp`, `ofstream` writer in `NativeMethods.cpp`, `ifstream` reader
in `NativeMethods.cpp`) now use `std::ios::binary`, making write and
read paths byte-exact and symmetric.
- Mechanically correct: `std::ios::binary` suppresses Windows CRT
`\n`↔`\r\n` translation; the delimiter `L'\n'` (LE bytes `0x0A 0x00`) is
unambiguous in binary mode and is handled correctly by the existing read
loop.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: MuyuanMS <116717757+MuyuanMS@users.noreply.github.com>
Co-authored-by: Muyuan Li (from Dev Box) <muyuanli@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-25 16:30:15 +08:00
Boliang Zhang
6a5e320749 [CI] Prune orphan tokens from check-spelling expect.txt (#48110)
## Problem

Since #47119 (`Refresh check-spelling 0.0.26`, merged 2026-04-23)
refreshed the check-spelling tooling and rewrote
`.github/actions/spell-check/expect.txt` (938 lines / 633 deletions),
the check-spelling bot has been leaving a noisy advisory comment on
**every PR**:

> #### These words are not needed and should be removed
> ABlocked AClient AColumn ACR ADate ADifferent AHybrid ALarger
AModifier ANull AOklab APeriod ARandom ARemapped ASingle ASUS bck …

The same ~150-word list is appended verbatim to every PR the bot looks
at (verified against #48058, #48102, #48104 — the list is identical).
These tokens are residual orphans in `expect.txt` from before the 0.0.26
refresh and no longer match anything in source.

## Fix

Removes exactly the 147 orphan tokens that the bot has consistently
flagged as `now absent` from `.github/actions/spell-check/expect.txt`.
The removed tokens are exclusively the ones the bot itself identified.

All uppercase Win32 / DirectWrite identifiers that are still used in
source (`DWRITE`, `LWIN`, `VCENTER`, `VREDRAW`, etc.) are **preserved**.

## Verification

- Diff is a single file, deletions only: `expect.txt` shrinks from 2343
→ 2196 lines.
- Each of the 4 uppercase Win32 tokens (`DWRITE` line 514, `LWIN` 1074,
`VCENTER` 2105, `VREDRAW` 2144 in the original) remains in the file.
- The check-spelling job on this PR should now post a clean report (no
`should be removed` block).

## Background — which PR introduced the drift

| PR | Date | What it changed |
|----|------|-----------------|
| **#47119** | 2026-04-23 | Refreshed check-spelling to 0.0.26; rewrote
`expect.txt` with 938 line-changes (633 deletions, 305 additions). The
duplicated lowercase/uppercase entries and many obsolete tokens
originate here. |

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <Copilot@users.noreply.github.com>
2026-05-25 16:29:42 +08:00
Michael Jolley
83285e929a CmdPal: Enable entrance animation for End dock bands (#48099)
## Summary

Fixes #46767

Items pinned to the End section of the dock did not animate on startup,
while Start and Center items did. The EndListView had an explicit empty
`ItemContainerTransitions` collection that suppressed all container
transitions. Removing it allows the default WinUI entrance animations to
play, matching Start and Center behavior.

## Changes

- `DockControl.xaml`: Remove empty `TransitionCollection` override from
EndListView

---------

Co-authored-by: root <root@io.bbq>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-25 08:31:09 +02:00
Boliang Zhang (from Dev Box)
34d01e998c Merge main into stable for 0.100 release (rev 4) 2026-05-25 13:03:13 +08:00
Boliang Zhang
26108ff04b [CI] Sign PowerAccent.Common.dll (new managed library from #47211) (#48058)
## Summary

Fixes the **stable** signed release pipeline failure (Dart build
[`147621162`](https://microsoft.visualstudio.com/Dart/_build/results?buildId=147621162))
at the *"Verify all binaries are signed and versioned"* task:

```
Not Signed: + …\extractedMachineMsi\File\BaseApplicationsFiles_File_PowerAccent.Common.dll
```

## Root cause

PR #47211 (*"[Quick Accent] Move language data to PowerAccent.Common
library, refactor"*) introduced the new managed library:

- `src/modules/poweraccent/PowerAccent.Common/PowerAccent.Common.csproj`

`PowerAccent.Common.dll` is referenced by both `PowerAccent.Core` (ships
in the installer root) and `PowerToys.Settings` (ships in WinUI3Apps;
deduplicated against root by `generateAllFileComponents.ps1`). The DLL
is harvested into the MSI's `BaseApplicationsFiles` component group, but
the PR did not update `.pipelines/ESRPSigning_core.json`, so ESRP never
signs it and `versionAndSignCheck.ps1` correctly fails the build.

This is the same kind of omission that PR #48050 fixed for
`YamlDotNet.dll` introduced by #40834 — a new managed library shipping
in the MSI without a matching signing config entry.

## Fix

One additive line in `.pipelines/ESRPSigning_core.json`, placing
`"PowerAccent.Common.dll"` inside the existing alphabetized PowerAccent
block (next to `PowerAccent.Core.dll`).

```diff
             "PowerAccent.Core.dll",
+            "PowerAccent.Common.dll",
             "PowerToys.PowerAccent.dll",
```

## Validation

- `git diff` shows exactly one additive line.
- File still parses as valid JSON (`ConvertFrom-Json` round-trip OK).
- Audited the full file list of PR #47211: `PowerAccent.Common.dll` is
the only new shippable assembly it added (the other new project,
`PowerAccent.Common.UnitTests`, is a test project and is not included in
the installer).
- Dedup logic in
`installer/PowerToysSetupVNext/generateAllFileComponents.ps1` keeps only
the root copy when WinUI3Apps and root copies are byte-identical, so a
single root-level entry is sufficient.

## Follow-up

After merge to `main`, cherry-pick / merge into `stable` to unblock the
0.100 release pipeline. This is the third (and hopefully final) PR in
the 0.100 release-pipeline unblock sequence, after #48050 (sign
`YamlDotNet.dll`) and #48054 (remove duplicate
`QuickAccent_SelectedLanguage_Greek_Polytonic` resource).

Co-authored-by: Copilot <Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-25 11:43:17 +08:00
Noraa Junker
fed9e81fdc [Shortcut Guide V2] Fixes (#48043)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

* Fix wrong Shortcut for Shortcut Guide V2 (previously always showed
default)
* Fix outdated OOBE description
* Fix process not stopping when exiting via ESC or close button
* Fixed some missing modules
* Removed regex capability and was able to improve the start up time
through this

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-05-24 18:08:54 +08:00
Mike Griese
f998c38ac8 cmdpal: fix an AOT-only crash loading the extension page (#48065)
Okay I'll admit this is a clanker fix. 

There's currently a crash when you navigate to an individual extension
page, that only repro's in Release/AOT. And because of
release&trimming&AOT reasons, that's very very difficult to diagnose.
But the clanker added a shitload of logging, and was able to figure out
that:

We were binding to this `Screenshots` collection. Problem is that we
can't safely bind to an `IReadOnlyList` in trimmed scenarios. C#/AOT is
a wonderful world of horrors.

Fixing this is as simple as swapping it for a `ObservableCollection`.
2026-05-23 05:56:14 -05:00
Mike Griese
11083c9fb2 CmdPal: Successfully open when opened on other displays (#48061)
When we were docked on a screen other than the primary display, then
clicking on a dock item that was a `IPage` would result in the palette
window just not showing up at all.

The fix is to make sure that we use the actual position of the current
monitor in the calculation of the final position of the palette HWND.
2026-05-23 05:55:51 -05:00
Boliang Zhang
809601a33c [CmdPal] Add stable AutomationIds across XAML for UI testing (#48033)
## Summary

Adds **77 explicit `AutomationProperties.AutomationId`** declarations (4
→ 81, ~20x) to Command Palette XAML so UI-testing tools (WinAppDriver,
FlaUI, winappCli, Appium) can address controls deterministically instead
of falling back to runtime slugs that change every session. Also covers
the `DataTemplate`-generated long tail (search results, file results,
every extension item, every monitor in Dock settings) by binding
`AutomationId` to existing stable model identifiers via `{x:Bind}`.

Headline: a one-line addition to the four CmdPal `ListItem`
`DataTemplate`s now exposes each instance's underlying `Command.Id`
(e.g. `com.microsoft.cmdpal.builtin.calculator`) as its `AutomationId`.
This is the same pattern as web's `<li data-testid={item.id}>`.

## Why

CmdPal today ships with only **4** explicit
`AutomationProperties.AutomationId` declarations across **44** XAML
files (~303 interactive controls). UI tests are forced to fall back to:

- runtime-generated slugs like `itm-12-9dda` that change every CmdPal
restart, or
- regex-parsing the text output of `winappCli ui inspect`, or
- walking the UIA tree client-side and matching by `Name` (localized,
ambiguous when several controls share a label).

## What changed

### Source changes
- **`Microsoft.CmdPal.UI/ExtViews/ListItemsView.xaml`** — bind
`AutomationProperties.AutomationId="{x:Bind Command.Id, Mode=OneWay}"`
on the root of all 4 `ListItem` `DataTemplate`s (single-row, small-grid,
medium-grid, gallery). Covers **every** runtime list item across all
built-in and third-party providers.
- **`Microsoft.CmdPal.UI/Settings/GeneralPage.xaml`** — 14 IDs on
activation hotkey controls, auto-go-home combo, behaviour toggles,
about-section hyperlinks.
- **`Microsoft.CmdPal.UI/Settings/AppearancePage.xaml`** — 19 IDs on
theme/backdrop/colorization, background image controls, 5 sliders,
behaviour toggles.
- **`Microsoft.CmdPal.UI/Settings/DockSettingsPage.xaml`** — 14 IDs on
enable toggle, theme/colorization/backdrop, background image controls,
plus per-monitor data-bound ID using `DisplayName`.
- **`Microsoft.CmdPal.UI/Settings/ExtensionsPage.xaml`** — 4 IDs on
banner/store hyperlinks plus the per-provider `SettingsCard` (data-bound
to the provider's `Id`, e.g. `com.microsoft.cmdpal.builtin.calculator`).
- **`Microsoft.CmdPal.UI/Settings/ExtensionPage.xaml`** — 5 IDs on
provider enable toggle, alias text/activation, fallback rank link.
- **`Microsoft.CmdPal.UI/Settings/ExtensionGalleryItemPage.xaml`** — 5
IDs on install/cancel/copy-command buttons and author/repo/uninstall
links.
- **`Microsoft.CmdPal.UI/Settings/InternalPage.xaml`** — 7 IDs on the
dev-only "Throw exception" and folder/log-opening buttons.
- **`Microsoft.CmdPal.UI/Pages/ShellPage.xaml`** — 1 data-bound ID on
the `CommandTemplate` button (binds to `CommandViewModel.Id`).
- **`Microsoft.CmdPal.UI.ViewModels/ProviderSettingsViewModel.cs`** —
single-line addition exposing the underlying `CommandProviderWrapper.Id`
so the ExtensionsPage template can bind to it.

### Naming convention applied

`CmdPal_<Page>_<Semantic>` PascalCase, with the existing well-known IDs
left untouched to avoid breaking the `modules/cmdpal/*` checklist tests
already referencing them. `Id` / `TestId` suffixes deliberately omitted
(the attribute is already `AutomationId`); control-type suffixes
(`Toggle` / `Button` / `ComboBox`) omitted because the type lives on the
UIA `type` field already.

### Files NOT touched (deferred)

About 5–7 secondary files (`SettingsWindow.xaml`,
`ExtensionGalleryPage.xaml`, `DockControl.xaml`, `DevRibbon.xaml`, deep
style/viewer XAML) — their interactive controls already carry `x:Name`,
which WinUI auto-promotes to `AutomationId` at runtime, so practical
testability is mostly already there. Can be tightened up in a follow-up
PR.

## Risk

-  Zero runtime cost (`AutomationProperties.AutomationId` is metadata
only)
-  Does not affect localization (`AutomationId` is non-localized by
design)
-  Does not affect user-facing accessibility (screen readers consume
`Name` / `AutomationProperties.Name`, untouched)
-  Does not rename any existing ID; `modules/cmdpal/*` tests
referencing `MainSearchBox` / `PrimaryCommandButton` / `ItemsList` /
etc. remain valid
-  All 51 CmdPal XAML files parse as valid XML (PowerShell `[xml]`
round-trip)
-  All `x:Bind` paths verified against the relevant ViewModel types
(`CommandViewModel.Id`, `DockMonitorConfigViewModel.DisplayName`,
`ProviderSettingsViewModel.Id`)

## Validation requested before merge

XAML compilation was attempted locally but blocked by a missing native
NuGet package (`Microsoft.Windows.ImplementationLibrary`) — needs
`tools\build\build-essentials.cmd` to fully restore first. **Reviewer
please run a clean local build of `Microsoft.CmdPal.UI` (or rely on CI)
to confirm the XAML compiler is happy.**

Once built, a quick smoke check:

```powershell
# After CmdPal restart with the new bits installed:
winapp ui search 'CmdPal_'           -w <hwnd> --json  # should list all the new IDs
winapp ui invoke 'CmdPal_AppearancePage_OpenCommandPalette' -w <hwnd>
winapp ui invoke 'com.microsoft.cmdpal.builtin.calculator' -w <hwnd>   # ListItem template binding
```

## Why this matters beyond our tools

This is the same pattern Microsoft's accessibility and WinUI teams
already recommend for any XAML app intended to be automated. It's the
WinUI equivalent of adding `data-testid` in a web app — universally
accepted as low-risk, high-leverage. WinAppDriver, FlaUI, Appium and any
future automation framework all benefit from the same change.
2026-05-22 21:42:19 -05:00
Mike Griese
2c9481e69a cmdpal: update template project to 0.11 SDK (#48066)
title
2026-05-22 21:09:06 -05:00
Boliang Zhang (from Dev Box)
b1adc8548f Merge main into stable for 0.100 release (rev 3) 2026-05-23 00:06:56 +08:00
Boliang Zhang
1d0917d06f [CI] Sign YamlDotNet.dll (ShortcutGuide V2 dependency) (#48050)
## Summary

Fixes the **stable** signed release pipeline failure (Dart build
[`147590319`](https://microsoft.visualstudio.com/Dart/_build/results?buildId=147590319))
at the *"Verify all binaries are signed and versioned"* task on both
`Build Release_x64` and `Build Release_arm64`:

```
Not Signed: + …\extractedMachineMsi\File\WinUI3ApplicationsFiles_File_YamlDotNet.dll
```

## Root cause

PR #40834 (*Shortcut Guide V2*) added a `YamlDotNet` `PackageReference`
to:

- `src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj`
-
`src/modules/ShortcutGuide/ShortcutGuide.IndexYmlGenerator/ShortcutGuide.IndexYmlGenerator.csproj`

Both projects publish into `WinUI3Apps\`, so `YamlDotNet.dll` is
harvested into the MSI by
`installer/PowerToysSetupVNext/generateAllFileComponents.ps1`. The PR
updated `ESRPSigning_core.json` for its own new binaries but missed this
3rd-party transitive dependency, so ESRP never signs it and
`.pipelines/versionAndSignCheck.ps1` correctly fails the build.

## Fix

One additive line to `.pipelines/ESRPSigning_core.json`, placing
`WinUI3Apps\YamlDotNet.dll` next to the other 3rd-party `WinUI3Apps\`
entries (`Google.Apis.*`, `Google.GenAI.dll`, `ReverseMarkdown.dll`,
`SharpCompress.dll`, …).

## Validation

- `git diff` shows exactly one additive line.
- File still parses as valid JSON (`ConvertFrom-Json` round-trip OK).
- Both ShortcutGuide csprojs target
`$(Platform)\$(Configuration)\WinUI3Apps`, so a single
`WinUI3Apps\YamlDotNet.dll` entry covers all uses.

## Follow-up

After merge to `main`, cherry-pick / merge into `stable` so build
`147590319` can be re-queued and the 0.100 release pipeline can proceed.

Co-authored-by: Copilot <Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-22 15:43:42 +00:00
moooyo
4edfcee87e [Power Display] Built-in monitor blacklist to mitigate DDC/CI BSOD (#47556, #47968) (#48051)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

Adds a built-in monitor blacklist that skips known-bad monitor models at
the DDC/CI discovery stage — before PowerDisplay sends any capabilities
request to the firmware. Matches by EdidId (the PnP manufacturer +
product code from EDID). Two entries pre-populated from existing crash
reports:

| EdidId | Reported in | Notes |

|-----------|-------------|------------------------------------------------------------------------|
| `LTM2C02` | #47556 | Counterfeit-EDID LG 27MR400 (PnP claims Litemax
40" 2011, actual hw is LG 27" 2024) |
| `GSM7714` | #47968 | LG UltraWide HDR WFHD |

Also logs `[EdidId=…] [FriendlyName=…] [DevicePath=…]` immediately
before each `GetCapabilitiesString*` syscall in `DdcCiController`. If
the kernel call BSODs (`win32kfull` stack-cookie overrun), that is the
last log line that survives — adding a new blacklist entry then takes
one PR to `BuiltInMonitorBlacklist.json` instead of a memory-dump
triage.

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

- [x] Mitigates: #47556
- [x] Mitigates: #47968
- [x] **Communication:** This is the "Add blacklist and prevent the API
call on broken monitor" mitigation outlined in [#47556
(comment)](https://github.com/microsoft/PowerToys/issues/47556#issuecomment-4505498427).
The underlying `win32kfull!DdcciGetCapabilitiesStringFromMonitor` stack
overrun is tracked separately by the Windows team.
- [x] **Tests:** 6 new MSTest unit tests under
`PowerDisplay.Lib.UnitTests`. All 120 PowerDisplay tests pass on x64
Debug.
- [ ] **Localization:** N/A — this PR ships no end-user-facing strings
(no UI surface).
- [ ] **Dev docs:** N/A.
- [ ] **New binaries:** N/A. Data ships as an `<EmbeddedResource>`
inside the existing `PowerDisplay.Models.dll`; no new .dll, no installer
change.
- [ ] **Documentation updated:** N/A.

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

### Threat model

Some retail monitor firmwares ship non-conformant DDC/CI capabilities
strings — typically oversized, not NUL-terminated, or otherwise
malformed. When PowerDisplay calls `GetCapabilitiesStringLength` /
`CapabilitiesRequestAndCapabilitiesReply` on these monitors, the request
flows into
`win32kfull!CPhysicalMonitorHandle::DdcciGetCapabilitiesStringFromMonitor`,
which copies the reply into a stack buffer without bounding the length.
The kernel detects its own stack cookie corruption on the epilogue check
and `__fastfail`s with `BUGCHECK 0x139 / 2
(STACK_COOKIE_CHECK_FAILURE)`.

The kernel-side overrun is a Windows defect, not PowerDisplay's, but
PowerDisplay is currently the most widely deployed consumer of this API
on hot-plug. Until the Windows team fixes the kernel, the only safe
mitigation in user space is to **never call** the capabilities API on
monitor models known to trigger it.

### Architecture

| File | Role |
|---|---|
| `PowerDisplay.Models/MonitorBlacklistEntry.cs` | POCO: `{ edidId,
comments }` |
| `PowerDisplay.Models/BuiltInMonitorBlacklist.json` | Data file
(embedded resource) |
| `PowerDisplay.Models/BuiltInMonitorBlacklist.cs` | Lazy-loaded reader,
AOT-safe (source-gen `JsonSerializerContext`); silent fallback to empty
list on any IO/parse failure |
| `PowerDisplay.Lib/Services/MonitorBlacklistService.cs` |
`IsBlocked(monitorId)` — extracts EdidId via
`MonitorIdentity.EdidIdFromMonitorId`, checks a `HashSet<string>` with
`OrdinalIgnoreCase` |
| `PowerDisplay/Helpers/MonitorManager.cs` | Filters QueryDisplayConfig
inventory by EdidId **before** any controller (DDC/CI or WMI) is
dispatched; logs each skip with `[MonitorBlacklist] Skipping ...` |
| `PowerDisplay.Lib/Drivers/DDC/DdcCiController.cs` | Logs EdidId +
FriendlyName + DevicePath immediately before the first capabilities
syscall per-monitor |

Matching is **model-level granularity** (EdidId, e.g. `GSM7714`) rather
than device-level (full DevicePath). One entry covers every physical
port and every machine with the same monitor model.

### Adding new entries

Once the kernel overrun is fixed this list can shrink. Until then, when
a new BSOD surfaces:

1. User reports BSOD, attaches PowerDisplay log
2. The last line before the crash now reads `DDC: probing capabilities
[EdidId=XXXXXX] [FriendlyName='...'] [DevicePath=...]`
3. Add `{ "edidId": "XXXXXX", "comments": "See #issue" }` to
`BuiltInMonitorBlacklist.json`
4. Submit PR, ship in next release

### Scoped out (deliberate)

A user-customized blacklist surface (Settings UI dialog) was prototyped
and hit multiple WinUI 3 dialog parse / measure crashes inside a
`ContentDialog`. The custom-list code path was reverted in favor of
"built-in only" for v1 reliability. UI can be re-added later on top of
this foundation if needed — the data model and service already support
it.

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

1. **Unit tests:** `dotnet test` on `PowerDisplay.Lib.UnitTests` →
**120/120 pass** (including 6 new tests for loader + service: built-in
JSON loads, EdidIds are normalized to upper-case, no blank entries,
`Lazy<>` cache returns same instance, `IsBlocked` returns `false` for
empty built-in list and for unidentifiable monitor IDs).
2. **Clean x64 Debug build** via `tools\build\build-essentials.cmd` +
per-project `tools\build\build.cmd`:
   - `PowerDisplay.Models` — 0 warning, 0 error
   - `PowerDisplay.Lib` — 0 warning, 0 error
   - `PowerDisplay` (app) — 0 warning, 0 error
3. **Smoke test (manual):** launched PowerDisplay, confirmed every
connected monitor produces a `DDC: probing capabilities [EdidId=…]
[FriendlyName=…] [DevicePath=…]` log line right before its caps request.
4. **Empty-list case:** `BuiltInMonitorBlacklist.json` with no entries →
`IsBlocked` returns `false` for any input (verified via unit test).
5. **Non-empty case (manual):** temporarily added a connected monitor's
EdidId to the built-in JSON → that monitor disappears from
`MonitorManager.Monitors` and `[MonitorBlacklist] Skipping ...` log line
appears; removed the entry → monitor reappears, all per-monitor settings
intact.

---------

Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com>
2026-05-22 23:18:13 +08:00
Boliang Zhang
33cf6995fc [Settings UI] Remove duplicate QuickAccent_SelectedLanguage_Greek_Polytonic resource (#48054)
## Summary

Fixes the **"Build PowerToys main project"** failure on every PR/CI
build off current `main` (e.g. Dart build
[`147597426`](https://microsoft.visualstudio.com/Dart/_build/results?buildId=147597426)):

```
WINAPPSDKGENERATEPROJECTPRIFILE: Error PRI175: Processing Resources failed with error: Duplicate Entry.
WINAPPSDKGENERATEPROJECTPRIFILE: Error PRI277: Conflicting values for resource
                                  'Resources/QuickAccent_SelectedLanguage_Greek_Polytonic'
```

## Root cause

`src/settings-ui/Settings.UI/Strings/en-us/Resources.resw` contained two
`<data name="QuickAccent_SelectedLanguage_Greek_Polytonic">` entries:

- Line 3597 — original, added by #47021 (*"[PowerAccent] adding greek
polytonic"*), placed in the alphabetized QuickAccent block.
- Line 6175 — duplicate, appended at the file tail by #47211 (*"[Quick
Accent] Move language data to PowerAccent.Common library, refactor"*).

The two entries are byte-identical (same value `Greek Polytonic`, same
`xml:space="preserve"`). The WinAppSDK PRI generator (`MakePri`) rejects
duplicates, so every build off current `main` fails before reaching the
compile step.

## Fix

Remove the tail duplicate (3-line block right before `</root>`). Keeps
the original entry in its alphabetized location.

## Validation

- `git diff` shows exactly 3 deleted lines.
- `[xml](Get-Content … -Raw)` round-trip succeeds — file is still
well-formed XML.
- `Select-String` count of
`QuickAccent_SelectedLanguage_Greek_Polytonic` in the file is now **1**
(was 2).
- Only `en-us` has this key (other localized `.resw` files are populated
later via Touchdown), so no other file needs touching.

## Note

Discovered while investigating a CI failure unrelated to my other PR
#48050 (signing of `WinUI3Apps\YamlDotNet.dll`). Both fixes are needed
for the 0.100 release pipeline; this PR unblocks PR builds off `main`,
and #48050 unblocks the signed release pipeline once both are merged to
`main` and the next `main → stable` sync happens.

Co-authored-by: Copilot <Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-22 15:42:56 +02:00
Dave Rayment
81e251c2de [Quick Accent] Move language data to PowerAccent.Common library, refactor (#47211)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Language data for Quick Accent was previously defined in
**PowerAccent.Core/Languages.cs**, internal to the Quick Accent
application itself. The Settings application had no access to the list
and had to maintain a parallel, manually-synchronised list of the
language names and groups, and there was no single place to look up the
complete set of languages.

This PR resolves this and extracts the language data into a new
**PowerAccent.Common** project with no external or UI dependencies,
making it the single source of truth for both the character popup and
Settings UI.

The implicit and non-obvious ordering of the old **Languages.cs** has
been replaced with explicit ordering of the language groups and
languages list.

A new unit test project for the application has also been added.

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

- [x] Closes: #47159
- [x] Closes: #30000
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

The following changes and additions have been made:

New project **PowerAccent.Common** contains:

- **Language.cs** - an enum of Quick Accent's pseudo-ISO identifiers for
each of the supported languages
- **LetterKey.cs** - mirrors the LetterKey enum defined in the
KeyboardListener.idl, and must be kept in sync with that. This exposes
the VK_* data to the Settings UI without it having to reference the
PowerAccentKeyboardService project
- **LanguageGroup.cs** - classifies languages as `Language` (for spoken
languages), `Special` (for sets like Currency and International Phonetic
Alphabet), or `UserDefined` (reserved for future work)
- **LanguageInfo.cs** - a record which combines a language's identity,
group, resource identifier, and character mappings
- **CharacterMappings.cs** - a new version of the old **Languages.cs**,
providing:
    - `All` - the canonical registry of every `LanguageInfo` entry
- `DisplayOrder` - the explicit within-group ordering for languages, for
the default popup ordering, i.e. when the user has not got
frequency-based ordering enabled. This is a culturally-neutral
alphabetical ordering by our pseudo-ISO language IDs, and close to the
previous order, minimising any impact to users' muscle memory
- `GroupDisplayOrder` - the explicit ordering of language groups for
both the popup and the Settings UI
- `LanguageLookup` - new _O(1)_ `Language` to `LanguageInfo` dictionary
- `GetCharacters(LetterKey, Language[])` - a deduplicating character
collector and sorter

A significant improvement over the old **Languages.cs** is that language
ordering is now explicit and in one place. Previously, popup ordering
was an implicit side-effect of a large Union chain across all language
mappings, with the enum, the language mapping declarations and the union
all carrying different orderings. This was a source of confusion and
made adding new languages fragile.

The original **Languages.cs** has been deleted. There's now a thin
`CharacterMappings` adapter that casts the `LetterKey` to the managed
equivalent by numeric value. This is another effort to decouple the
Settings UI and Quick Accent and only share the required elements.

In Settings, the `PowerAccentViewModel` class has been updated. It now
derives the language list directly from `CharacterMappings.All`; the
`InitializeLanguages()` call handles localisation, sorting and grouping
in a single place using `GroupDisplayOrder`.

A new unit test project covers `CharacterMappings`, the `LetterKey`
IDL-to-managed code bridge and general language declaration checks. The
application is now much more robust against changes which alter the
declared order, introduce empty/null elements, and so on. It is now
impossible to add a new language and forget a constituent part (the enum
entry, its place in the display order, the character mappings
themselves) without a test failing.

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

See new unit test project for comprehensive tests.

Manually confirmed:

- Triggering Quick Accent with no language selected does not report an
error
- Language order is consistent in the popup, no matter what order the
languages are selected in Settings
- The order of languages in Settings is consistent, alphabetically by
localised name
- All declared languages are present in Settings and no resource IDs
were missed

---------

Co-authored-by: Muyuan Li (from Dev Box) <muyuanli@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-22 15:24:26 +08:00
Boliang Zhang (from Dev Box)
0e71f616de Merge main into stable for 0.100 release (rev 2) 2026-05-22 14:04:49 +08:00
Clint Rutkas
f02b66c88d Fix auto-update relaunch, add config backup, enable auto-download by default (#46889)
## Summary

Addresses three critical issues with the PowerToys update experience
that cause user fragmentation across old versions.

### Changes

**1. Fix relaunch after update (Fixes #42004, #43011, #44071)**
- Stage 1 now passes the PowerToys install directory to Stage 2 as an
argument
- After successful install, Stage 2 relaunches `PowerToys.exe` with
`-report_update_success`
- Users will see a 'successfully updated' toast and PT resumes
automatically

**2. Config backup/restore (Fixes #46179)**
- `BackupConfigFiles()` snapshots all JSON configs to `ConfigBackup/`
before update begins
- `RestoreCorruptedConfigs()` checks for null-byte corruption after
install and auto-restores
- Protects Workspaces, FancyZones, Keyboard Manager, and all other
module settings

**3. Enable auto-download by default**
- New installations default `AutoDownloadUpdates` to `true` (was
`false`)
- Existing users' preferences are preserved — this only affects
first-run defaults
- The runner already defaulted to `true`; this aligns the C# settings
model

### Why this matters

The current updater kills all PowerToys processes, runs the installer,
then **exits without relaunching**. Users lose keyboard remappings,
FancyZones layouts, and Awake settings with no indication why. Combined
with auto-download being off by default, most users are multiple
versions behind.

### Testing

- Verified update flow: Stage 1 → Stage 2 → PT relaunches with success
toast
- Config backup creates mirror of all JSON settings before update
- Corruption detection catches null-byte pattern from #46179
- Graceful fallback: if install dir not provided (old Stage 1), logs
warning but doesn't crash

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Muyuan Li (from Dev Box) <muyuanli@microsoft.com>
Co-authored-by: Niels Laute <niels.laute@live.nl>
2026-05-22 14:01:56 +08:00
Copilot
386fdcb1e9 [Shortcut Guide] Render key names instead of raw numeric key codes (#48037)
## Summary of the Pull Request

Shortcut Guide was rendering raw numeric key codes in key visuals for
some shortcuts (notably generated PowerToys shortcuts), showing numbers
where key characters/names were expected. This change normalizes numeric
key handling so display output matches actual key labels.

## PR Checklist

- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

- **Scope**
- Updated `ShortcutDescriptionToKeysConverter` in `ShortcutGuide.Ui`
only.

- **Behavior change**
- Numeric key codes are no longer passed through as raw integers by
default.
- Arrow keys (`37/38/39/40`) remain numeric to preserve existing glyph
rendering behavior.
- All other numeric key codes are converted to display names via
`Helper.GetKeyName(...)`.

- **Result**
- Shortcut Guide key caps now show expected characters/key names instead
of numeric values for manifest-provided numeric keys.

```csharp
if (int.TryParse(key, out int keyCode))
{
    switch (keyCode)
    {
        case 38:
        case 40:
        case 37:
        case 39:
            shortcutList.Add(keyCode); // keep glyph path
            break;
        default:
            shortcutList.Add(Helper.GetKeyName((uint)keyCode)); // show key label
            break;
    }
}
```

## Validation Steps Performed

No additional validation details are included in this description.

> [!WARNING]
>
> <details>
> <summary>Firewall rules blocked me from connecting to one or more
addresses (expand for details)</summary>
>
> #### I tried to connect to the following addresses, but was blocked by
firewall rules:
>
> - `o3svsblobprodcus318.vsblob.vsassets.io`
> - Triggering command: `/usr/bin/dotnet dotnet build
/home/REDACTED/work/PowerToys/PowerToys/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj
-v minimal` (dns block)
>
> If you need me to access, download, or install something from one of
these locations, you can either:
>
> - Configure [Actions setup
steps](https://gh.io/copilot/actions-setup-steps) to set up my
environment, which run before the firewall is enabled
> - Add the appropriate URLs or hosts to the custom allowlist in this
repository's [Copilot coding agent
settings](https://github.com/microsoft/PowerToys/settings/copilot/coding_agent)
(admins only)
>
> </details>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
Co-authored-by: Noraa Junker <noraa.junker@outlook.com>
2026-05-22 11:08:32 +08:00
Niels Laute
8af6a99136 Settings UX tweaks (#48024)
This PR:

- Adds a MaxWidth to the SCOOBE and OOBE pages, inline with Fluent
design guidance
- Updates the imagery for PowerToys
- Tweaks some small nits in the General settings page: re-ordering,
adding icons, replacing a ToggleSwitch with a CheckBox

<img width="1774" height="1325" alt="image"
src="https://github.com/user-attachments/assets/d825047a-27be-4e8b-a6ce-7f1a71f39dfe"
/>
2026-05-21 17:28:40 +02:00
Noraa Junker
9699d8a802 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>
2026-05-21 17:27:52 +02:00
moooyo
5b16a8c945 fix(PowerDisplay): close window on Escape key (#48016) (#48026)
The PowerDisplay flyout had no keyboard close path: pressing Tab kept
focus inside the window so it never deactivated, and there was no
KeyDown / KeyboardAccelerator wired up. Handle Escape on RootGrid to
hide the window, matching the behavior of other PowerToys flyouts.

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [x] Closes: #48016
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Yu Leng (from Dev Box) <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 12:59:07 +02:00
Muyuan Li
fa2b7f6e5f Fix VALID_LABELS mismatches in auto-label-issues workflow (#48027)
## Summary

Corrects four label names in the \VALID_LABELS\ allow-list of the
\uto-label-issues.yml\ workflow to match existing repository labels
exactly.

## Root Cause

The GitHub Actions \ddLabels\ API creates a brand-new label when the
name doesn't exactly match an existing one. The hardcoded list had
typos/mismatches:

| Workflow had | Repo actually has |
|---|---|
| \Product-Power Display\ | \Product-PowerDisplay\ |
| \Product-ColorPicker\ | \Product-Color Picker\ |
| \Product-Command Not Found\ | \Product-CommandNotFound\ |
| \Product-Hosts\ | \Product-Hosts File Editor\ |

## Changes

- Fixed all 4 label strings in \VALID_LABELS\ array
- Deleted the spurious \Product-Power Display\ label that was created by
the mismatch

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-21 12:58:46 +02:00
moooyo
f117bfc64e feat(PowerDisplay): migrate legacy "{Source}_{EdidId}_{N}" Ids to new stable ID (#47977)
Carry per-monitor user preferences from the pre-#47712 Id format onto
the current DevicePath-based Ids by matching on EdidId. Without this,
every upgrade silently resets Enable* toggles (input source, color
temperature, power state) for monitors users had already opted in on,
because the direct-Id lookup in ApplyPreservedUserSettings can never
match the old "DDC_DELD1A8_1" / "WMI_BOE0900_2" keys.

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Yu Leng (from Dev Box) <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 14:21:20 +08:00
Boliang Zhang (from Dev Box)
4f0f614f67 Merge main into stable for 0.100 release 2026-05-21 13:58:32 +08:00
Niels Laute
52bf042df2 [Workspaces] Move to WPF Fluent and tweak overall UX (#46172)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

This PR includes the following changes:
- Remove the dependency of ControlzEx and ModernWpf, and instead uses
the default WPF Fluent theming. No more third-party packages.
- A lot of UI design refinements: using the proper fontweights, spacing,
Mica background, and default Fluent styles.
- Usability improvements: action buttons are at the top, full width
scrolling.

Related: #46220

<img width="1209" height="879" alt="image"
src="https://github.com/user-attachments/assets/132cdb9a-aa73-4aa2-88b0-c36031b4aea3"
/>


<img width="1060" height="980" alt="image"
src="https://github.com/user-attachments/assets/a04f83d4-74d3-466c-9d5c-f193f436337b"
/>



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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Jay <65828559+Jay-o-Way@users.noreply.github.com>
Co-authored-by: Muyuan Li (from Dev Box) <muyuanli@microsoft.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
2026-05-21 07:54:19 +02:00
Mike Griese
2fc27b13b6 CmdPal: Fix opening a IPage from a context menu on a dock item (#47991)
Currently, if the user clicks on a dock item which is a Page command,
then we'll attempt to show the cmdpal where the user clicked on a dock
item. This works great. However, if the user right-clicks a dock item to
invoke the context menu, then from that menu clicks on a Page command,
then nothing happens - we don't show the cmdpal window.

Similarly - IInvokableCommand's that return a CommandResult.Confirm - we
never show the cmdpal window so that the confirmation ContentDialog is
shown to the user.

Yes in the long run, these will make more sense to have a better UI for
the "dock flyout" (see #45861). But until then, this fixes these
scenarios.

Closes #45963

very relevant for #47989
2026-05-20 16:03:07 -05:00
Dave Rayment
94b7e3eea2 [Image Resizer] Automatically reload settings changes (#45266)
## Summary of the Pull Request

This PR introduces real-time settings synchronisation for Image Resizer.
External changes to `settings.json` (via the Settings application or
manual edits to the file) are detected and reloaded immediately without
requiring a restart.

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

- [x] Closes: #36943
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

### Reload updates
The reload detection is via an `IFileSystemWatcher` (as file system
operations are abstracted in Image Resizer), which monitors the
`settings.json` file for creation and changes. There is a half second
debounce for changes, as the settings file can rapidly change when the
user is editing the preset name field.

Hot reloading of the properties required refactoring `ReloadCore`, which
replaces the `Sizes` preset collection and updates the Custom and AI
presets, in addition to the application-wide properties like compression
options and the fallback encoder choice.

I changed the combo box data binding from the `SelectedSize` object to
the int `SelectedSizeIndex`. This was required to resolve a specific WPF
issue where reloading the `Sizes` collection would cause issues with
restoring the current combo box selection to the prior value. Binding to
the index decouples the selection state from the object lifecycle during
the reload process.

Selection preservation is based on the preset ID (for user presets) and
preset type (for Custom and AI presets). This ensures that matches are
robust even if the user is in the process of renaming an entry in the
Settings application. If the preset cannot be matched (for example, if
the user deletes the item or changes the ID manually in the file), the
Custom preset is selected.

Selection range checks are maintained from the old code, and additional
checks have been added to ensure that Custom and AI presets will be
present even if they're deleted from the settings file.

The AI preset check from before has been inlined; this guarantees that
the AI resize option will not display if the facility is unavailable on
the current PC, even if it's present in the settings file.

The reload routine is dispatched to the UI thread, as changes involve
updates to the combo box.

### ID recovery
Preset IDs are key to preserving the combo box selection between
reloads, and a couple of changes were necessary to ensure round-tripping
changes were robust.

1. IDs are not reused. The old code could reuse IDs under certain
circumstances, for example if a preset was deleted and re-added via
Settings.
2. The ID Recovery Helper routine sorted the supplied presets by ID
before performing duplicate conflict resolution. This is not required
and it is more natural to assume that the order in the settings file and
the client UI is the source of truth.

New ID assignment is now based on a monotonically increasing ID (seeded
at application start) rather than `Current Maximum ID + 1`. This means
that IDs cannot be reused in the same Settings application session. This
makes the matching process in the client application more reliable.

A small update was made to the ID Recovery Helper to use `HashSet.Add()`
instead of splitting up the check and addition steps (`Add` will return
false if the value already exists), which saves a massive one line of
code.

There were comments about the ID Recovery Helper resolving "empty" or
"invalid" entries; this was inaccurate, as IDs are ints, which must by
definition always have a valid value. The routine only guards against
duplicates, so the comments have been updated to reflect this.

### Miscellaneous
The `Default` Settings property getter previously called `Reload` every
time it was accessed. This is fine when the file is only read at
application startup, but I changed this to lazily instantiate and call
`Reload` a single time.

I refactored duplicate code related to settings file/folder strings, and
also the creation of the Custom and AI size instances.

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

Manual testing:
1. Add new preset in the Settings application. The new entry is
reflected in the client application as it is running.
2. Delete new preset. The entry is removed in the client application
list.
3. Edit an existing preset. The property change is reflected in the
client application.
4. Add new preset in the Settings application. Select the new preset in
the client application. Edit the properties of the new preset in the
Settings application and confirm that the updates appear in the client
application.
5. Add new preset in the Settings application. Select the new preset in
the client application. Delete the new preset in Settings. Confirm that
the current preset is removed and the selection changes to the default
in the client application.
6. Change one or more application-wide properties in the settings file
which are represented in the client application, too, e.g. "Make
pictures smaller but not larger" (`imageresizer_shrinkOnly`) or
"Overwrite files" (`imageresizer_replace`). Upon saving, confirm the
checkbox changes immediately in the client application.
7. Edit the `settings.json` file manually by e.g. adding a new Size
preset or editing the width or height property of an existing preset.
Upon saving, the change(s) should be reflected in the client
application.
8. Make a change to an existing or new preset which affects the resize
operation itself, e.g. the dimensions or the "Make pictures smaller but
not larger" setting. Proceed with the resize operation and confirm that
the new changes have been applied.

14 new unit tests have been added to `SetingsTests.cs` to exercise the
`Settings` and `IDRecoveryHelper` functionality.

---------

Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 12:18:12 +00:00
Gordon Lam
c334f1d997 [CI] Sign Google.Apis.* and Google.GenAI DLLs (AdvancedPaste Gemini deps) (#48001)
## Summary

Adds the four Google.* DLLs shipped by AdvancedPaste (via
`Microsoft.SemanticKernel.Connectors.Google` for Gemini support) to the
ESRP sign list.

## Problem

The `Verify all binaries are signed and versioned` pipeline step
(`.pipelines/versionAndSignCheck.ps1`) was failing with:

```
Not Signed:  + ...\extractedMachineMsi\File\WinUI3ApplicationsFiles_File_Google.Apis.Auth.dll
Not Signed:  + ...\extractedMachineMsi\File\WinUI3ApplicationsFiles_File_Google.Apis.Core.dll
Not Signed:  + ...\extractedMachineMsi\File\WinUI3ApplicationsFiles_File_Google.Apis.dll
Not Signed:  + ...\extractedMachineMsi\File\WinUI3ApplicationsFiles_File_Google.GenAI.dll
```

These DLLs are transitive NuGet dependencies of
`Microsoft.SemanticKernel.Connectors.Google` (referenced by
`src/modules/AdvancedPaste/AdvancedPaste/AdvancedPaste.csproj`) and
deploy to `WinUI3Apps\`, but were never added to
`.pipelines/ESRPSigning_core.json`.

## Fix

Added the four DLLs to the second `SignBatch` (`CP-231522`, the
third-party / OSS-library identity) — same batch used for other
connector DLLs like `OpenAI.dll`, `OllamaSharp.dll` and
`Microsoft.SemanticKernel.Connectors.Ollama.dll`.

## Validation

- `ConvertFrom-Json` on the modified file confirms valid JSON.
- Sign-list entries match the actual deploy paths flagged by
`versionAndSignCheck.ps1`.
- The next ESRP signing run will pick them up; the verify step should
pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-20 17:45:56 +08:00
moooyo
8e74eb2ba8 [PowerDisplay] Auto-disable on detected DDC/CI capability fetch crash (#47556) (#47734)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary

Mitigation for issue #47556 — `KERNEL_SECURITY_CHECK_FAILURE` BSOD
originating in `win32kfull!DdcciGetCapabilitiesStringFromMonitor` when
PowerDisplay calls DDC/CI capability APIs against monitors with
malformed capability strings.

After a detected crash, PowerDisplay auto-disables itself via
`settings.json`, shows an error InfoBar at the top of the PowerDisplay
settings page (page is locked except the Ignore button), so users can
avoid getting stuck in an infinite reboot loop after a crash. And the
user must explicitly dismiss the warning before re-enabling the module.

The actual kernel-side fix is the Windows team's responsibility — this
PR only prevents users from BSOD-ing repeatedly on the same monitor
without warning.

settings page:
<img width="1743" height="1475" alt="image"
src="https://github.com/user-attachments/assets/8cf1b72f-c51a-4955-82d7-213cae49fd4e"
/>


## Mechanism

1. `CrashDetectionScope` IDisposable wraps Phase 2 capability fetch in
`DdcCiController.DiscoverMonitorsAsync`, writing `discovery.lock`
(`WriteThrough` + `Flush(flushToDisk: true)`) before, deleting it on
Dispose.
2. If the process is killed externally (BSOD, FailFast), the lock
survives.
3. On next PowerDisplay.exe startup (Phase 0), `CrashRecovery` detects
the orphan lock and runs a strict fail-fast sequence: write
`crash_detected.flag` → set `enabled.PowerDisplay=false` in global
`settings.json` → signal the new `POWER_DISPLAY_AUTO_DISABLE_EVENT` →
delete the lock (commit point).
4. The runner-loaded `PowerDisplayModuleInterface.dll` runs a one-shot
listener thread that wakes on the event and calls `disable()` to sync
`m_enabled`.
5. `PowerDisplayViewModel` reads the flag at construction and binds
`IsCrashLockActive` to lock the page.

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

- [x] Closes: #47556 
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Yu Leng <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 16:13:16 +08:00
Mike Griese
da9a08aa92 CmdPal: Add support for drag-drop bookmarking to the dock (#47989)
This allows users to drag files & URLS to the dock, to immediately
create a bookmark, and pin that bookmark to the dock.

It also updates the bookmark provider's dock bands. If you bookmark a
folder, then pin that to the dock, when you click it on the dock, we'll
default to the "browse" experience, which will open the list of files in
cmdpal, rather than open in explorer.

Had to make miscellaneous changes to make this all a bit faster:
* DirectoryPage didn't load icons smartly, like we do for bookmarks
* I added a different "observable" collection for dock top-level items,
because it caused a flippin CollectionChanged cascade any time a single
provider had more than one item pinned in the dock. Each item from each
provider would cause us to recreate all the dock view models (???) crazy
* I alas had to make `IBookmarksManager` public, so that the UI could
use it. I hate it, but I couldn't figure out a better way. Bookmarks are
a pretty built-in part, so it's _fine i guess_

re: #45584
2026-05-19 16:49:33 -05:00
Jessica Dene Earley-Cha
b893d633d9 [TEST Version] Event PR Check (#47889)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

This PR checks if future PRs has added or refines telemetry events, if
so, the bot will add a message to the PR about the needed steps
depending on the PR.

**NOTE**: This PR is submitting a test version, which is only manually
triggered, once tested and confirmed then will move to it being
automatic


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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-05-19 17:28:57 +00:00
Dave Rayment
a7bc09a87a [QuickAccent] Fix UI glitches, DPI-related issues, selection bugs, and add hardware shift key state fallback (#46593)
## Summary of the Pull Request
This PR fixes several issues around the popup selection window's size
and position, selection-related issues which result in flashing or
glitching, and includes more reliable detection of the Shift key.

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

- [x] Closes: #44332
- [x] Closes: #44980
- [x] Closes: #35094 
- [x] Closes: #40498
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

This PR includes fixes for the Quick Accent's selection window position,
its width measurement, and letter selection-related issues. In addition,
glitches such as the window flashing the selection colour and the window
appearing blank should be reduced or eliminated entirely.

### Popup width bug

When opening Quick Accent from a letter with many mappings, it would
appear too wide for the display. Even though letters could be selected,
they may be entirely off-screen:

<img width="1578" height="134" alt="image"
src="https://github.com/user-attachments/assets/cfcb2ddb-3cf3-47d5-9386-133a2fc70550"
/>

This was because of this flaw in `GetDisplayMaxWidth`, which is used
directly by the popup to set the maximum width of the characters area:

```csharp
    // In Selector.xaml.cs
    private void SetWindowsSize()
    {
        this.characters.MaxWidth = _powerAccent.GetDisplayMaxWidth();
    }

...
    // In PowerAccent.cs
    public double GetDisplayMaxWidth()
    {
        return WindowsFunctions.GetActiveDisplay().Size.Width - ScreenMinPadding;
    }
```

`GetActiveDisplay` uses the `GetMonitorInfo` API, which exposes the
working area of the display. It returns its values in _raw unscaled
pixel_ values:

```csharp
    public static (Point Location, Size Size, double Dpi) GetActiveDisplay()
    {
        ...
        var res = PInvoke.MonitorFromWindow(guiInfo.hwndActive, MONITOR_FROM_FLAGS.MONITOR_DEFAULTTONEAREST);
        MONITORINFO monitorInfo = default;
        monitorInfo.cbSize = (uint)Marshal.SizeOf(monitorInfo);
        PInvoke.GetMonitorInfo(res, ref monitorInfo);

        ...

        return (location, monitorInfo.rcWork.Size, dpi);
    }
```

However, the `MaxWidth` property must be a _pre-scaled_ value, i.e. in
logical WPF units not physical pixels. The fix is straightforward:

```csharp
    public double GetDisplayMaxWidth()
    {
        var activeDisplay = WindowsFunctions.GetActiveDisplay();
        return (activeDisplay.Size.Width / activeDisplay.Dpi) - ScreenMinPadding;
    }
```

### Popup positioning bug

This is related to a subtle DPI issue in `GetActiveDisplay()`:

```csharp
    public static (Point Location, Size Size, double Dpi) GetActiveDisplay()
    {
        GUITHREADINFO guiInfo = default;
        guiInfo.cbSize = (uint)Marshal.SizeOf(guiInfo);
        PInvoke.GetGUIThreadInfo(0, ref guiInfo);
        var res = PInvoke.MonitorFromWindow(guiInfo.hwndActive, MONITOR_FROM_FLAGS.MONITOR_DEFAULTTONEAREST);

        MONITORINFO monitorInfo = default;
        monitorInfo.cbSize = (uint)Marshal.SizeOf(monitorInfo);
        PInvoke.GetMonitorInfo(res, ref monitorInfo);

        double dpi = PInvoke.GetDpiForWindow(guiInfo.hwndActive) / 96d;
        var location = new Point(monitorInfo.rcWork.left, monitorInfo.rcWork.top);
        return (location, monitorInfo.rcWork.Size, dpi);
    }
```

Here, the application window's DPI is returned. Unfortunately, the
window may report a value which is different from the monitor's own DPI
value. This will consistently happen if the application is not
Per-Monitor DPI-Aware, and the monitor is not at 100% Scale. The effects
are that the Quick Accent popup can appear misaligned or even off-screen
entirely. Quick Accent can still be used, but the user may not be able
to see what they are selecting.

As Quick Accent is using monitor coordinates for setting its location,
the solution is to use the monitor's own DPI value. The fix is to add
this in place of the `GetDpiForWindow` line:

```csharp
        uint dpiRaw = 96; // Safe default
        if (PInvoke.GetDpiForMonitor(res, MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI, out uint dpiX, out _) == 0)
        {
            dpiRaw = dpiX;
        }

        double dpi = dpiRaw / 96d;
```

### Selection bugs

After dismissing the Quick Accent window, the `_selectedIndex` state was
not properly reset. The next time the window opened, it could attempt to
scroll to or highlight an index that was out-of-bounds for the new
character set. This could result in glitching, such as the window
flashing the selection colour or the initial selection being incorrect.
In this fix, I:

1. Explicitly set `_selectedIndex` to `-1` when the UI hides.
2. Reset the `SelectedIndex` inside Selector.xaml.cs before updating the
`ItemsSource`.

### Shift key activation

In certain cases, a quick press of Shift could fail to move back through
the character list. In this fix, I:

1. Added a native fallback usign GetAsyncKeyState(VK_SHIFT).
2. Updated `ProcessNextChar()` to evaluate `shiftPressed ||
WindowsFunctions.IsShiftState()`.
3. Updated the multiple `if`s in `ProcessNextChar` to be an if/else
structure, to prevent bugs when more than one trigger key is pressed.

### Support added for multi-codepoint graphemes

The current code loops through each `char` of a mapping, calling
`SendInput` multiple times for multi-char sequences. This will fail for
multi-codepoint graphemes, i.e. where the mapping 'letter' is more than
one UTF-16 codepoint. Those characters may appear as `[]`. The amended
`Insert()` in `WindowsFunctions` appends all characters before calling
`SendInput`.

### Miscelleneous

- Added an `OnDpiChanged` handler for the Selector control, so changing
the DPI of the screen should be picked up automatically. (It's
questionable whether this is essential, as the DPI would have to change
while the control was displayed, but it's worth having for robustness.)
- Now using `SetWindowPos` instead of setting the `Left` and `Top` of
the popup control. Also now initialising the popup offscreen to attempt
to reduce flicker and the occurrence of blank window flashes.
- Changed the `Focusable` property of the characters `ListBox` to
`False`, to attempt to reduce flicker and the window flashing the
selector colour.
- Removed `Width` and added `MinWidth` to the letter control in
Selector.xaml. This allows for wider letters or longer multi-letter
mappings.
- Changed the `VirtualizingStackPanel` to a regular `StackPanel`. We do
not have mappings with enough entries for a virtual control to be
necessary, and using StackPanel seemed to have a positive effect on the
appearance of blank window glitches.
- Added `TextTrimming`, `TextWrapping` and `MaxHeight` to the unicode
description `TextBlock`. This helps support extremely long unicode
descriptions. Again, this will enable us to support longer
multi-character mappings in the future.
- Added CsWin32 to the PowerAccent.UI project, to support the
`SetWindowPos` call.

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

See separate doc for full test details:


https://docs.google.com/document/d/19uClcUiv7RUDRlbFhazG-Cmu46oNmrAVoJf9bHSjSJU/edit?usp=sharing

---------

Co-authored-by: Muyuan Li (from Dev Box) <muyuanli@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Niels Laute <niels.laute@live.nl>
2026-05-20 00:20:03 +08:00
Marco Guido
6e9b3b1536 [PowerAccent] adding greek polytonic (#47021)
Adds Greek Polytonic characters set to power accent, based on
https://github.com/microsoft/PowerToys/pull/29709
### PR Checklist

- [x]  Closes #46941
- [x] Communication: I've discussed this with core contributors already.
- [ ] Tests: Not sure if there are specific tests for this
- [ ] Documentation updated: Power accent docs

### Detailed Description of the Pull Request / Additional comments
Added all greek polytonic letters to their corresponding english letter
(some duplicated)
(if you wondered about GRC -> ISO 639-3)

### Validation Steps Performed
Compiled and Observed Power Accent

---------

Co-authored-by: Niels Laute <niels.laute@live.nl>
Co-authored-by: Dave Rayment <dave.rayment@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-20 00:19:06 +08:00
Gordon Lam
d973bcbcaa Update Microsoft.SemanticKernel packages from 1.66.0 to 1.71.0 (#47819)
## Summary

Updates the `Microsoft.SemanticKernel` package family from 1.66.0 to
1.71.0 to pick up upstream improvements and bug fixes from the Semantic
Kernel project.

> Note: the `Connectors.AzureAIInference` (`-beta`), `Connectors.Google`
/ `Connectors.MistralAI` / `Connectors.Ollama` (`-alpha`) packages have
no stable upstream release yet, but are required to keep the existing
Advanced Paste AI provider options working.


## Packages updated

**SemanticKernel family:**

| Package | From | To |
|---------|------|----|
| `Microsoft.SemanticKernel` | 1.66.0 | 1.71.0 |
| `Microsoft.SemanticKernel.Connectors.OpenAI` | 1.66.0 | 1.71.0 |
| `Microsoft.SemanticKernel.Connectors.AzureAIInference` | 1.66.0-beta |
1.71.0-beta |
| `Microsoft.SemanticKernel.Connectors.Google` | 1.66.0-alpha |
1.71.0-alpha |
| `Microsoft.SemanticKernel.Connectors.MistralAI` | 1.66.0-alpha |
1.71.0-alpha |
| `Microsoft.SemanticKernel.Connectors.Ollama` | 1.66.0-alpha |
1.71.0-alpha |

**Transitive dependencies bumped to satisfy SK 1.71's resolution
constraints:**

| Package | From | To |
|---------|------|----|
| `Microsoft.Extensions.AI` | 9.9.1 | 10.2.0 |
| `Microsoft.Extensions.AI.OpenAI` | 9.9.1-preview.1.25474.6 |
10.0.1-preview.1.25571.5 |
| `System.Numerics.Tensors` | 9.0.11 | 10.0.2 |
| `Newtonsoft.Json` | 13.0.3 | 13.0.4 |
| `OpenAI` | 2.5.0 | 2.7.0 |
| `System.ClientModel` | 1.7.0 | 1.8.0 |

These transitive bumps were required to avoid `NU1109` package-downgrade
errors after the SK upgrade.

## Scope

- `Directory.Packages.props` only  central package version bumps.
- No source-code changes.

## Consumers

- AdvancedPaste uses the SK `Kernel` / `IChatCompletionService` /
connector surfaces unchanged.
- `LanguageModelProvider` and `FoundryLocalPasteProvider` use the stable
`Microsoft.Extensions.AI` `IChatClient` / `ChatMessage` / `ChatRole` /
`ChatResponse` / `AsIChatClient()` types unchanged across 9.x to 10.x.

## Validation

- Static API-surface review of all SK / `Microsoft.Extensions.AI` call
sites only stable types in use.
- CI build pipeline will provide the full restore + compile verification
across the solution.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-19 10:25:41 +02:00
Niels Laute
02fbb916a7 [Quick Accent] Remove wpfui (#46604)
## Summary of the Pull Request

<img
src="https://github.com/user-attachments/assets/8756671f-642a-4bbd-a174-eb13b02cfe59">

This PR removes the dependency on the WpfUI library and uses plain WPF.

## PR Checklist

- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

- Replaced `ui:FluentWindow` with a standard WPF `Window` and removed
the `xmlns:ui` WpfUI namespace
- Replaced `<Rectangle.Fill><SolidColorBrush /></Rectangle.Fill>` with
an inline `Fill=` attribute on the selection indicator rectangle
- Simplified `App.xaml` by removing WpfUI theme/controls resource
dictionaries and using `ThemeMode="System"` instead
- Fixed XAML formatting: converted empty `<Application>` to a
self-closing tag, removed extra blank lines in `Window.Resources` and
inside `ControlTemplate`

## Validation Steps Performed

- Manually verified the Quick Accent overlay renders correctly with
accent character selection and character name display

<!-- START COPILOT CODING AGENT TIPS -->
---

 Let Copilot coding agent [set things up for
you](https://github.com/microsoft/PowerToys/issues/new?title=+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-19 08:13:00 +00:00
Copilot
9dff42627a Rename issue triage workflow, remove legacy product auto-label action, and sync with main (#47911)
## Summary of the Pull Request

Renames the issue-triage GitHub Action to **Automatic Triaging on Issue
Creation** and removes the redundant `auto-label-product.yml` workflow.
This consolidates issue labeling/triage under a single workflow surface.

Also syncs this PR branch with the latest `main` via a merge commit to
keep it up to date with upstream.

## PR Checklist

- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

- **Workflow rename**
  - Updated `.github/workflows/auto-label-issues.yml`:
- `name: Auto-label Issues by Area` → `name: Automatic Triaging on Issue
Creation`
- Updated the manual-trigger comment to reference the new action name.

- **Workflow cleanup**
- Removed `.github/workflows/auto-label-product.yml` to eliminate
overlapping automation.

- **Branch sync requested in PR comments**
- Merged latest `origin/main` into this branch (`4f831bc`) to keep the
PR current.

```yaml
# .github/workflows/auto-label-issues.yml
name: Automatic Triaging on Issue Creation
```

## Validation Steps Performed

- Verified clean merge of `origin/main` into this PR branch (no merge
conflicts).
- Confirmed targeted workflow changes remain present after merge.
- Ran PR validation tooling:
  - Code Review completed successfully.
  - CodeQL scan timed out in validation tooling.

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
2026-05-19 05:40:18 +00:00
Boliang Zhang (from Dev Box)
ddf9815613 Merge remote-tracking branch 'origin/main' into stable 2026-05-19 10:55:40 +08:00
Mike Griese
df4f130023 CmdPal: allow users to pin individual perf metrics (#47967)
title.

Basically just exposes bands that have each perf metric as the only
item.

Built on top of https://github.com/microsoft/PowerToys/pull/47870

Closes #46200
2026-05-18 19:31:10 -05:00
Jiří Polášek
2d0aadee9c Revert "Move storyboards used to show/hide breadcrumbs to XAML" (#47971)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

This PR reverts #47900: it causes an exception in the Release+AOT build
configuration when retrieving a storyboard from XAML resources and
casting it to a local field.

- [x] Closes: #47970 
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-05-18 22:24:37 +00:00
Mike Griese
b02e53dda5 CmdPal: Update the shell provider to be run (#47642)
This PR updates the shell command provider to work (almost) exactly like
run. The current shell provider is close, but not technically correct.
It does enumerate files. Sure. But as it turns out, it doesn't enumerate
things **exactly** correctly. It doesn't handle network paths super
well. It doesn't handle NTFS file paths. Basically, there's a lot of
weird edge cases in the way the run dialog enumerates file paths for
suggestions. And the only way to match that is to just use the code from
the old run dialog.

This is code that is taken pretty verbatim from the new run dialog.
Instead of trying to enumerate paths manually and shellexecuting command
lines, We're using the actual APIs that the original run dialog used,
more or less. They've been pretty much ported to C#.

This should make us feel just as correct as the original run dialog did.
And exactly the same as the new Run dialog.

The one major change is the introduction of a static item at the top of
the list for running the command that the user typed. This command is
used to just immediately take whatever is in the search box and fire it
off as the command the user typed. This is essentially what happens with
the run dialog. When you press the button, we run the command in the
text box.

See: [The new Run dialog: faster, cleaner, and more capable - Windows
Command
Line](https://devblogs.microsoft.com/commandline/the-new-run-dialog-faster-cleaner-and-more-capable/)

Honestly, most of this PR is just deleting the files we no longer need
from the shell list provider and adding the tests from the OS side here.

I also had to update CsWinRT for this.
2026-05-18 12:59:51 -05:00
Knyrps
95ef94d35f [CmdPal][PerfMon] Add battery widget (charge, status, time remaining) (#47870)
## Summary

Adds a Battery widget to the CmdPal Performance Monitor dock, exposing
live charge percentage, charging/AC status, and estimated time
remaining. The dock-band icon updates each tick to reflect the current
charge level and charging state, matching the existing
CPU/RAM/GPU/Network widget pattern.

Closes #47218

## Detail

- New `SystemBatteryUsageWidgetPage` in `PerformanceWidgetsPage.cs`,
mirroring the existing widget pattern.
- Data source: `GetSystemPowerStatus` via CsWin32 (AOT-safe), wrapped in
`BatteryStats` and surfaced through `SystemData` / `DataManager` on the
shared 1 s timer.
- Live dock-band icon: `Icons.cs` caches 23 `IconInfo` instances
(`BatteryIcons[0..10]`, `BatteryChargingIcons[0..10]`,
`BatteryUnknownIcon`); alloc-free `BatteryGlyph()` selects the glyph per
tick. Codepoints `0xEBA0`–`0xEBB5` / `0xEC02` (Segoe Fluent Icons
MobBattery family).
- Adaptive card template `SystemBatteryTemplate.json` registered as
`<None Update … PreserveNewest>`, consistent with the other PerfMon
templates.
- New `Battery_*` strings under `Strings\en-US\Resources.resw`.
- Handles `GetSystemPowerStatus` sentinels: `BatteryLifePercent == 255`,
`BatteryLifeTime == 0xFFFFFFFF`, `BatteryFlag == 0xFF`, `0x80` (no
battery), `0x08` (charging).

## Screenshots

<img width="1660" height="401" alt="image"
src="https://github.com/user-attachments/assets/6e26f10a-267b-4f6b-b43a-b2c63c092a6d"
/>

When the battery is at 100%, the widget will always show the "full" icon
(`MobBatteryCharging10`).
<img width="537" height="37" alt="image"
src="https://github.com/user-attachments/assets/d925a328-b9b6-4760-a488-f936910a1715"
/>
Otherwise and when on AC, it will show the "charging" variant of the
icon:
<img width="85" height="61" alt="image"
src="https://github.com/user-attachments/assets/065e3a53-c210-4d65-8ca2-02dccf63edf6"
/>
The icon also always reflects the current charging state: It resolves to
the correct glyph in both charging and discharging states, rounded to
the nearest 10% (so 0%, 10%, … 100%).

## How tested

- `MSBuild CommandPalette.slnf /p:Configuration=Release /p:Platform=x64
/m /restore` — green, 0 errors, 0 warnings.
- Launched dev `Microsoft.CmdPal.UI.exe`, opened PerfMon dock, confirmed
Battery widget renders charge %, status, time remaining, and that the
dock-band glyph matches the current charge level (verified on AC, on
battery, and while charging).
2026-05-18 17:07:25 +00:00
Michael Jolley
8da01581f6 CmdPal: Cap visible tags at 3 with +N overflow badge (#47140)
## Summary

Fixes #38317 — "Too many tags on a list item looks hilarious"

When CmdPal list items have many tags (e.g., GitHub issue labels), the
tag pills dominated the row and pushed the title text out of view.

### Changes

**Two-pronged fix:**

1. **Cap visible tags at 3** — ViewModel exposes `VisibleTags` (first 3)
and `OverflowTagText` (`+N`) properties. Original `Tags`/`HasTags`
bindings are preserved (no contract breaks).

2. **Overflow badge** — A `[+N]` badge appears when more than 3 tags
exist, reusing existing `Tag*` theme resources for visual consistency.
Includes `AutomationProperties.Name` for accessibility.

### Files Changed

| File | Change |
|------|--------|
| `ListItemViewModel.cs` | Added `MaxVisibleTags`, `VisibleTags`,
`OverflowTagCount`, `HasOverflowTags`, `OverflowTagText` properties and
`UpdateVisibleTags()` |
| `ListPage.xaml` | `ItemsRepeater` binds `VisibleTags`, wrapped in
`StackPanel` with overflow `Border` badge |

### Validation

- [x] Build clean (`Microsoft.CmdPal.UI.ViewModels` +
`Microsoft.CmdPal.UI`)
- [x] Handles 0, 1-3, and 4+ tags correctly
- [x] No ABI/contract breaks (original `Tags`/`HasTags` preserved)
- [x] Overflow badge reuses existing theme resources
- [x] Accessibility: `AutomationProperties.Name` on overflow badge

### Follow-up

- Overflow badge accessible name could be enriched (e.g., "+3 more tags"
instead of "+3")

### Screenshots

<img width="972" height="545" alt="image"
src="https://github.com/user-attachments/assets/327dcdd0-2e62-435a-9b07-0432189cc947"
/>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-18 11:40:32 -05:00
Michael Jolley
c7bb7f7e79 CmdPal: Set IsLoading in Window Walker during search (#47919)
## Summary of the Pull Request
Sets `IsLoading = true` before querying open windows in
`WindowWalkerListPage.GetItems()` and resets it in a `finally` block, so
the UI shows a loading indicator while Window Walker results are being
fetched.

Closes #38314

## PR Checklist
- [x] Closes: #38314
- [ ] **Communication:** I've discussed this with core contributors
already.
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized

## Detailed Description
The Window Walker extension was not setting `IsLoading` during its
search operation. This meant users got no visual feedback that a search
was in progress. This follows the same pattern used by other extensions
(AllAppsPage, IndexerPage, etc.).

## Validation Steps Performed
- Verified the change follows existing patterns in AllAppsPage.cs and
IndexerPage.cs
- The try/finally ensures IsLoading is always reset even if Query throws

Co-authored-by: root <root@io.bbq>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-18 11:38:50 -05:00
Michael Jolley
d9725649bc CmdPal: Enable cross-monitor drag-and-drop in dock edit mode (#47921)
## Summary of the Pull Request
Enables dragging dock bands between monitors in edit mode. Previously,
drag-and-drop only worked within bands on the same monitor's dock.

Closes #47920

## PR Checklist
- [x] Closes: #47920
- [ ] **Communication:** I've discussed this with core contributors
already.
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized

## Detailed Description
The existing drag-and-drop implementation used a local `_draggedBand`
field per `DockControl` instance, which meant the target DockControl on
another monitor had no reference to the dragged band. This PR fixes that
by:

1. **DataPackage properties** — `DragItemsStarting` now stores the band
ID and source monitor device ID in `DataPackage.Properties`, making the
identity available to any drop target in the same process.

2. **Cross-window drop acceptance** — `DragOver` and `DragEnter` now
check for `DockBandId` in `DataView.Properties` in addition to the local
`_draggedBand` field.

3. **CrossMonitorBandDropMessage** — A new `WeakReferenceMessenger`
message coordinates removal from the source dock after a successful
cross-monitor drop.

4. **ViewModel methods** — `DockViewModel.AcceptBandFromMonitor()`
creates a new band ViewModel on the target dock using the same factory
pattern as `AddBandToSection`. `RemoveBandById()` handles cleanup on the
source dock.

Both methods call `EnsureMonitorForked()` to fork per-monitor band
settings from global when needed, maintaining the existing customization
model.

## Validation Steps Performed
- Verified existing same-monitor drag-and-drop behavior is preserved
(local path unchanged)
- Verified cross-monitor handler properly stores/retrieves DataPackage
properties
- Reviewed against existing patterns in DockControl (AddBandToSection,
MoveBandWithoutSaving)

---------

Co-authored-by: root <root@io.bbq>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-18 06:46:21 -05:00
Copilot
4e8c7aa3a6 Fix: Quick Access flyout shortcut editor crashes on Reset (#47407)
## Summary of the Pull Request

Clicking **Reset** in the Quick Access hotkey shortcut dialog crashes
PowerToys Settings. The root cause is that `C_ResetClick` sets the
`HotkeySettingsProperty` DependencyProperty to `null`, which causes the
WinUI3 XAML runtime to dereference a null pointer during two-way binding
property-change notification — a native E_POINTER crash (0x80004003).

## PR Checklist

- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

### Root Cause

`C_ResetClick` previously did:

```csharp
hotkeySettings = null;
SetValue(HotkeySettingsProperty, null);
```

The `HotkeySettingsProperty` is bound two-way (`{x:Bind Mode=TwoWay}`)
to the ViewModel. `SetValue(null)` synchronously triggers the binding
chain: ViewModel setter → `NotifyPropertyChanged` → XAML runtime reads
back the DP value → null pointer → **native E_POINTER crash** in
`CoreMessagingXP.dll`.

### Fix

Use `new HotkeySettings()` instead of `null` — matching the existing
`C_ClearClick` pattern that never crashes:

```csharp
// C_ResetClick — fixed
hotkeySettings = new HotkeySettings();
SetValue(HotkeySettingsProperty, hotkeySettings);
SetKeys();
lastValidSettings = hotkeySettings;
shortcutDialog.Hide();
```

An empty `HotkeySettings` (`IsEmpty() == true`) semantically means "no
shortcut configured" — the same intent as null, but the XAML binding
chain always has a valid object to dereference.

Also added null-conditional guards in `OpenDialogButton_Click` as
defense-in-depth:
- `HotkeySettings?.GetKeysList() ?? new List<object>()` ensures `c.Keys`
is never null, preventing `{x:Bind Keys.Count}` in
`ShortcutDialogContentControl.xaml` from throwing.
- `hotkeySettings?.HasConflict ?? false` and
`hotkeySettings?.ConflictDescription` guard the remaining property
accesses.
- A null guard in `Hotkey_KeyDown` prevents a crash if the user presses
keys after Reset.

## Validation Steps Performed

- Reproduced crash: Settings → General → Quick Access shortcut → Edit →
Reset → crash (before fix)
- Verified fix: Same steps → no crash, dialog closes cleanly, shortcut
shows as empty
- Verified reopening dialog after Reset works without crash
- Verified pressing keys in dialog after Reset works without crash
- Built and tested with full Runner IPC (debug PowerToys.exe → Settings)

---------

Co-authored-by: Muyuan Li (from Dev Box) <muyuanli@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: MuyuanMS <116717757+MuyuanMS@users.noreply.github.com>
2026-05-18 15:56:26 +08:00
Copilot
49cdb9249d Peek: Add setting to disable file metadata tooltip (#46624)
Adds a **"Show file preview tooltip"** toggle to Peek's Behavior
settings, letting users disable the metadata tooltip (filename, type,
date modified, size) shown on hover over the preview.

## Changes

- **`PeekProperties`** — new `ShowFilePreviewTooltip: BoolProperty`
(default `true`)
- **`IUserSettings` / `UserSettings`** — expose the setting; updated by
the existing file watcher on settings change
- **`FilePreview.xaml`** — `ImagePreview` and `VideoPreview` now bind
`ToolTipService.ToolTip` directly to `InfoTooltip` (the same
attached-property form already used by `AudioControl`). The previous
explicit `<ToolTip Content="{x:Bind InfoTooltip}"/>` element form left a
`ToolTip` instance permanently attached, so nulling the content still
produced an empty popup on hover. With the attached-property form, a
`null` `InfoTooltip` detaches the tooltip entirely and no popup is
shown.
- **`FilePreview.xaml.cs`** — new `ShowFilePreviewTooltip`
DependencyProperty; sets `InfoTooltip = null` when disabled; re-triggers
`UpdateTooltipAsync` when re-enabled with a file loaded; `infoTooltip`
field changed to `string?`
- **`MainWindow.xaml.cs`** — reads setting from `IUserSettings` and
pushes it to `FilePreviewer.ShowFilePreviewTooltip` on each
`Initialize()` call, picking up the latest user preference each time
Peek activates
- **`PeekViewModel`** — `ShowFilePreviewTooltip` property for two-way
Settings UI binding
- **`PeekPage.xaml`** — toggle in the Behavior group, consistent with
existing toggles
- **`Resources.resw`** — localizable strings for header and description

## PR Checklist

- [x] Closes: #46621
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

Setting defaults to `true` — no behavior change for existing users.

The tooltip is suppressed by setting `InfoTooltip` to `null` while bound
through `ToolTipService.ToolTip` as an attached property. A `null` value
on the attached property prevents WinUI from creating a tooltip popup at
all (this is the same pattern `AudioControl` already used and behaves
correctly with null). The earlier explicit `<ToolTip>` element form did
*not* behave this way — the `ToolTip` instance stayed attached and an
empty popup appeared on hover — so the XAML was switched to the
attached-property form on `ImagePreview` and `VideoPreview`. The custom
tooltip placement logic (top/bottom based on cursor Y) is unaffected.

## Validation Steps Performed

- Verified toggle appears in Peek Settings > Behavior
- Toggling off fully suppresses the hover tooltip on image, video, and
audio previews (no empty bubble)
- Toggling back on restores tooltip with file metadata on next file load
- Default `true` preserves existing behavior

<img width="688" height="99" alt="image"
src="https://github.com/user-attachments/assets/369d0ba7-fc9a-495e-9603-f4b2b95ba68e"
/>

<img width="692" height="305" alt="image"
src="https://github.com/user-attachments/assets/cb5dfc69-a445-46b0-9c0a-041fbf4c89c2"
/>

<img width="684" height="73" alt="image"
src="https://github.com/user-attachments/assets/8088caa7-9536-4384-91dc-dbdbbe0ae755"
/>

<img width="686" height="430" alt="image"
src="https://github.com/user-attachments/assets/0d9d2d6f-bc42-4497-89c5-06ac9c18a2b7"
/>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
Co-authored-by: Niels Laute <niels.laute@live.nl>
Co-authored-by: Muyuan Li (from Dev Box) <muyuanli@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-18 15:54:04 +08:00
Copilot
fb59905d41 Fix Markdown preview crash on UTF-8 files with >2MB size and <1.5M characters (#47391)
`NavigateToString` throws `ArgumentException` when previewing Markdown
files containing many multi-byte UTF-8 characters (e.g., CJK) — file
size exceeds 2MB but character count stays under 1.5M, bypassing the
guard.

## Summary of the Pull Request

The size guard in `MarkdownPreviewHandlerControl` used
`markdownHTML.Length` (character count / UTF-16 code units), but
WebView2's `NavigateToString` limit is measured in **bytes**. A string
with 700K CJK characters has only 700K `.Length` units but ~2.1MB of
UTF-8 bytes — enough to crash the API while passing the old check.

**Changes:**
- **`MarkdownPreviewHandlerControl.cs`**: Replace character-count guard
with UTF-8 byte count:
  ```csharp
  // Before
  if (markdownHTML.Length > 1_500_000)

  // After
  if (System.Text.Encoding.UTF8.GetByteCount(markdownHTML) > 1_500_000)
  ```
When the byte threshold is exceeded, content is written to a temp file
and loaded via `_browser.Source` instead of `NavigateToString` —
existing fallback path, now correctly triggered.

- **`MarkdownPreviewHandlerTest.cs`**: Added 3 regression tests to
prevent this class of bug from recurring:
1. Multi-byte UTF-8 content (CJK, <1.5M chars but >2MB bytes) →
temp-file navigation path
2. Small ASCII content within both thresholds → `NavigateToString` path
3. Large ASCII content exceeding 1.5M chars → temp-file navigation path

## PR Checklist

- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

The existing fallback (write HTML to a temp file, navigate via
`_browser.Source`) was already correct and handles arbitrarily large
content safely. The only bug was in the guard condition that decides
when to use it — it measured the wrong unit (characters vs. bytes).
Single-byte ASCII content is unaffected; only multi-byte Unicode content
was under-counted.

The tests use reflection to read the private `_localFileURI` field.
Since this field is set synchronously before `Controls.Add(_browser)`,
the check is race-free: once the wait loop exits with `Controls.Count >
0`, `_localFileURI` is guaranteed to have its final value.

## Validation Steps Performed

- Verified the fix by reasoning through the byte math: a file with 700K
CJK characters → `Length` = 700K (passes old check) → UTF-8 bytes ≈
2.1MB (fails new check → uses temp file path, no crash).
- Added 3 targeted unit tests in `UnitTests-MarkdownPreviewHandler`
covering the multi-byte threshold boundary; all 14 tests in the suite
pass (14/14).

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: MuyuanMS <116717757+MuyuanMS@users.noreply.github.com>
Co-authored-by: Muyuan Li (from Dev Box) <muyuanli@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-18 14:30:48 +08:00
moooyo
38882fd392 [PowerDisplay] Rescan monitors on display wake (#47876)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

1. Subscribes to GUID_CONSOLE_DISPLAY_STATE so PowerDisplay rescans
monitors when the console display wakes from sleep — previously, woken
monitors stayed unrecognized until the user manually re-triggered
discovery.
2. Locks the PowerDisplay UI immediately on wake to block stale
interactions before the rescan completes.

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

- [x] Closes: #47951
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Yu Leng <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 14:26:26 +08:00
Jiří Polášek
75ac1521a8 CmdPal: Extension Gallery - Move storyboards used to show/hide breadcrumbs to XAML (#47900)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

This PR moves storyboard that handles showing and hiding breadcrumbs in
Settings windows to a XAML resources.

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-05-17 19:43:12 +02:00
Dave Rayment
e17454b553 [CmdPal Calculator] Add rand() and randi(). Expand result responses to differentiate between NaN and ParseError (#47725)
## Summary of the Pull Request
This adds `rand()` and `randi()` functions to Command Palette's
Calculator, making it consistent with Run.

It also expands upon the return values from `ToWStringFullPrecision()`,
so NaN, ParseError and +/-infinity results are passed back to the
caller, improving the specificity of the error message display.

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

- [x] Closes: #47707
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

<!-- 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
The two new functions have been added to **ExprtkEvaluator.cpp**,
alongside `sign()` and `factorial()`. As they need to handle the state
of the RNG, they're slightly more complex in implementation. I used the
Mersenne Twister RNG with a uniform distribution, and the instances are
marked `static thread_local` in case the engine moves to multithreaded
evaluation in the future.

It's possible for the RNG to return a value out of the range of
`double`, and this is caught and `quiet_NaN()` is returned. To prevent
this being caught as a generic parse error, I updated
`ToWStringFullPrecision()` to distinguish between `NaN`, expression
parsing errors and infinity values. This should improve the accuracy of
error messages for other expressions, too.

Finally, I corrected a comment in **CalculateEngine.cs,** which still
referred to the Mages calculation engine. The log/ln mapping is the same
for both engines, so the comment was still accurate except for this
reference.

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Unit tests were added to exercise the new functions. All Calculator
tests pass:

<img width="375" height="59" alt="image"
src="https://github.com/user-attachments/assets/5a33e1ed-a4fd-4d53-b9ba-6b44000f1bf4"
/>

Confirmed that error messages are displaying correctly for the
newly-exposed result types:

**Not a number**
<img width="787" height="128" alt="image"
src="https://github.com/user-attachments/assets/8c73dcf6-122b-4af8-bf1a-62284842433a"
/>

<img width="786" height="145" alt="image"
src="https://github.com/user-attachments/assets/fe14338c-1160-4aae-83dd-5ca3491ae59e"
/>

**+/- Infinity**
<img width="898" height="137" alt="image"
src="https://github.com/user-attachments/assets/20cfacda-72a7-44bb-a875-af7be39ee7e2"
/>

**Parser failure**
<img width="607" height="139" alt="image"
src="https://github.com/user-attachments/assets/7d7120b2-a2cf-45b6-ab89-79af4051fa50"
/>

<img width="587" height="140" alt="image"
src="https://github.com/user-attachments/assets/2dc7a365-7ee6-4379-8b3f-47b3912e6891"
/>
2026-05-16 19:50:58 +00:00
Dave Rayment
703dc92c04 [CmdPal Calculator] Fix issue for multi-argument functions where comma is both the number group separator and list separator (#47731)
## Summary of the Pull Request
This fixes Calculator functions with multiple arguments in cultures
where the number group separator and list separator are identical, e.g.
**en-US** and **en-GB**.

It maintains existing parsing behaviour for other cultures where the
separators differ, e.g. **de-DE**.

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

- [x] Closes: #47726
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

The root issue was in the number translation step. In cultures such as
en-US, commas were being consumed as part of numeric tokens and were
treated as number group separators, which broke functions whcih took
multiple arguments. For example, `max(1,2)` would be translated as
`max(12)` and `pow(2,3)` as `pow(23)`. The number translator's result
would be passed on to ExprTK, which could sometimes still interpret the
input and would give a result (`12` in the case of `max(1,2)`); for
cases like `pow(2,3)`, it would surface an error, as the expression
`pow(23)` is invalid.

This fix resolves the ambiguity in two ways:
- It uses stricter grouped number matching when the culture's list
separator and number group separator are the same.
- It preserves separator characters for multi-argument functions. This
means that expressions like `max(123,456)` are correctly interpreted as
two arguments inside the function call, while `123,456` outside a
function call is still interpreted as a grouped number.

Care has been taken to preserve grouped numbers inside single-argument
functions, e.g. `ceil(123,456.23)`.

The more permissive parsing for cultures which do not have this
ambiguity has been retained. (Arguably this is too loose, but that's
something to consider separately.)

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Added and updated unit tests, with **en-US** used as the representative
'ambiguous culture'. Coverage includes:

- `max()`, `min()` and `pow()`
- Grouped numbers in single-argument functions like `ceil()`, `floor()`,
`round()`, `log()` and `sin()`.
- Nested expressions
- Spacing around function calls
- Scientific notation
- Hexadecimal, binary and octal literals

All tests pass:

<img width="696" height="52" alt="image"
src="https://github.com/user-attachments/assets/ed89fbb9-70e0-4cf7-8e13-12f1f36b6037"
/>

Manual testing was also performed to confirm:

- Multi-argument functions now evaluate correctly
<img width="243" height="136" alt="image"
src="https://github.com/user-attachments/assets/b5c96954-ee6d-4842-b599-561ccbd10607"
/>

- Grouped numbers inside single-argument functions still work
<img width="356" height="135" alt="image"
src="https://github.com/user-attachments/assets/918425b0-cce4-4708-855b-c8b4916e6a4a"
/>

- Nested expressions and spacing variations are handled correctly
<img width="606" height="137" alt="image"
src="https://github.com/user-attachments/assets/12be5aa9-ba33-4000-96d5-444a2932bbe7"
/>

<img width="482" height="135" alt="image"
src="https://github.com/user-attachments/assets/aea2ebce-7c88-469e-b9e4-bdb7099ef538"
/>
2026-05-16 19:47:41 +00:00
Jiří Polášek
012fb4a5c8 CmdPal: Extension Gallery - Fix WMC1506 warnings (#47899)
## Summary of the Pull Request

This PR fixes WMC1506 warnings introduced by the extension gallery PR.

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-05-16 17:59:22 +00:00
Jiří Polášek
36f172cedf CmdPal: Extension Gallery - Allow only HTTP/HTTPS URIs as links in the UI (#47898)
## Summary of the Pull Request

This PR filters URIs from extension gallery and allows only HTTP/HTTPS
URIs as links for the installation page.

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-05-16 17:51:38 +00:00
Mike Griese
2d3f93537f CmdPal: Move bookmarks with placeholders to be parameters (#47886)
The placeholders page for a bookmark is already goofy. It's a seemingly
simple form, for just filling in something that really should be an
inline value.

So let's do that!

This moves the placeholders out of a whole adaptive card, and into an
inline parameter.

Targets #47885 

<img width="790" height="635" alt="image"
src="https://github.com/user-attachments/assets/d0faa5a2-e967-4860-b3d2-b6bcb0c91c0b"
/>
<img width="787" height="798" alt="image"
src="https://github.com/user-attachments/assets/36ff41c3-8c6e-48bf-a141-9655b463d049"
/>
2026-05-16 02:31:42 +00:00
Michael Jolley
a187bfc2bb CmdPal: Pass extension log messages into logging system (#47896)
This pull request updates the logging behavior in the `LogMessage`
method to ensure that log messages are categorized and logged according
to their severity (Error, Warning, or Info), instead of always using
debug-level logging.

Logging improvements:

* Updated the `LogMessage` method in `AppExtensionHost.cs` to log
messages using `CoreLogger.LogError`, `CoreLogger.LogWarning`, or
`CoreLogger.LogInfo` based on the `MessageState` of the incoming
message, improving log clarity and severity categorization.

Previously, any logging sent to LogMessage (which is exposed in the
toolkit) would only be written when debugging. Any error/warning/info
messages sent as part of the normal operation would be bypassed because
it only used `CoreLogger.LogDebug`

Now extension developers can log errors/warnings and use PowerToys log
export / bug report feature to help their users provide them with
actionable data to make their extensions better.
2026-05-15 20:34:08 -05:00
Mike Griese
42902eeba5 CmdPal: Add support for pages with parameters (redux) (#47826)
(this PR is an updated version of #43784)

This PR adds a new type of page to Command Palette: 
The `ParametersPage`.

This allows extensions to create commands that require a set of
parameters
before invoking the command. Previously, extensions could create
commands with a
form page to use an adaptive card for parameter input, but that was a
relatively
heavyweight UX. 

Instead, the `ParametersPage` allows extensions to define a set of
lightweight
inputs, which allows for a more streamlined experience. 

The parameters page is made up of a set of "runs". Each run represents a
single element in the search box. Runs can be either:
* A label run: a static piece of text
* An value run: some input for the user to provide a value. These fall
into several categories:
  * String input
  * Command Input
    * `IInvokableCommand`s become buttons in the search box
* `IListPage`s become a list input to pick from (**these will be added
in a follow-up PR**)

There are a ton of samples included. 

I also added all my draft notes in the drafts folder, to see how we got
here.
I'd skip reviewing those.

Furthermore, I added the "dumb" token support, where an extension can
opt in to
having tokens in the search box, delimited by ZWSP characters. 

The XAML styling was fixed by Niels a few months back

Closes #40948

---------

Co-authored-by: Niels Laute <niels.laute@live.nl>
2026-05-15 20:31:32 -05:00
Michael Jolley
b99defbc0d CmdPal: Add setting to hide app descriptions in All Apps (#47128)
## Summary

Adds a **Hide app descriptions** toggle setting to the Command Palette
All Apps extension. When enabled, the descriptive subtitle text next to
app results is hidden for a cleaner look.

### Changes

| File | Change |
|------|--------|
| `AllAppsSettings.cs` | New `HideAppDescriptions` `ToggleSetting`
(default: `false`), following the existing `EnableStartMenuSource`
pattern |
| `AllAppsPage.cs` | Conditionally clears `Subtitle` on each
`AppListItem` in `GetPrograms()` when setting is enabled |
| `Resources.resx` / `Resources.Designer.cs` | Resource strings for the
setting label and description |
| `AllAppsPageTests.cs` | Two new tests verifying subtitle visibility
with setting on/off |

### Validation

- [x] Build clean (exit code 0)
- [x] All 14 unit tests pass (including 2 new tests)
- [x] Setting defaults to `false` (preserves current behavior)
- [x] Empty subtitle renders gracefully (no placeholder shown)
- [x] No ABI breaks — all changes scoped to All Apps extension

Closes #46634

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-15 16:15:37 -05:00
Michael Jolley
08caf10d84 CmdPal: Fix CmdPal command bar not refreshing on back navigation (#47126)
## Summary

Fixes #46810 — When navigating backward in CmdPal (Esc/Backspace), the
bottom command bar retained stale commands from the previous page until
the user changed selection.

## Root Cause

In `ListPage.xaml.cs` `OnNavigatedTo()`, the back-navigation path sets
selection using `SuppressSelectionChangedScope()`, which prevents
`Items_SelectionChanged` from firing. This means `PushSelectionToVm()`
is never called, so `UpdateCommandBarMessage` is never sent to
`CommandBarViewModel`, and the command bar displays stale state.

## Fix

Added `PushSelectionToVm()` after the selection restoration block inside
the back-navigation dispatcher callback. This is safe because:
- `PushSelectionToVm()` is idempotent (guards with
`ReferenceEquals(_lastPushedToVm, li)`)
- Handles both selected items (pushes to VM) and no selection (sends
null)
- Triggers `UpdateCommandBarMessage` which refreshes the command bar

## Validation

### Manual Test Steps

| Scenario | Expected |
|----------|----------|
| **Esc navigation** — Navigate into nested page, press Esc | Bottom bar
commands update immediately to parent page |
| **Backspace navigation** — Navigate into nested page, press Backspace
| Bottom bar commands update immediately to parent page |
| **Forward navigation** — Navigate forward into a page | Commands
update (no regression) |
| **Selection change** — Change selection on any page | Commands update
(no regression) |
| **No flicker** — Navigate back and observe command bar | Single clean
update, no double-fire |
| **Empty page** — Navigate back to page with no selectable items |
Graceful handling, no crash |

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-15 16:14:16 -05:00
Michael Jolley
eaaba455dd CmdPal: Fix pluralization in CmdPal Extensions settings page (#47125)
## Summary

Fixes the pluralization bug in Command Palette settings where extensions
with a single command displayed "1 commands" and "1 fallback commands"
instead of the correct singular forms.

### Changes

**`ProviderSettingsViewModel.cs`** — Rewrote the `ExtensionSubtext`
property to use tuple pattern matching that selects the correct
singular/plural format string based on whether command count and
fallback count equal 1.

**`Resources.resx`** — Added 4 new resource strings for singular form
combinations:
- `builtin_extension_subtext_singular` — "{0}, {1} command"
- `builtin_extension_subtext_with_fallback_singular_command` — "{0}, {1}
command, {2} fallback commands"
- `builtin_extension_subtext_with_fallback_singular_fallback` — "{0},
{1} commands, {2} fallback command"
- `builtin_extension_subtext_with_fallback_singular_both` — "{0}, {1}
command, {2} fallback command"

**`ProviderSettingsViewModelPluralizationTests.cs`** — 17 new test cases
covering all singular/plural combinations for command and fallback
command counts.

### Validation

- [x] Matches existing `CompositeFormat` pattern used elsewhere in
CmdPal
- [x] Follows `.editorconfig` and StyleCop conventions
- [x] All files within `CommandPalette.slnf` scope

Closes #47110

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-15 16:09:52 -05:00
Boliang Zhang
b68b2a5583 Fix GrabAndMove LNK2038 C++/WinRT version mismatch (PowerToys CI break) (#47910)
Diagnostic / prototype fix for the LNK2038 C++/WinRT version mismatch
that has been failing PowerToys CI on every batched-CI run since commit
`59eefd9581` (5/14):

`
SettingsAPI.lib(settings_objects.obj): error LNK2038: mismatch detected
for 'C++/WinRT version':
  value '2.0.250303.1' doesn't match value '2.0.250303.5' in main.obj
  [src/modules/GrabAndMove/GrabAndMove/GrabAndMove.vcxproj]
`

## Root cause

GrabAndMove.vcxproj does not import the `Microsoft.Windows.CppWinRT`
NuGet package, so `main.cpp` picks up `<winrt/Windows.Foundation.h>`
(included transitively via `SettingsAPI/settings_objects.h` ->
`common/utils/json.h`) from the **Windows SDK's in-box CppWinRT**
instead of the repo-pinned NuGet version.

After the SHINE-VS18-Latest agent image picked up a newer Windows SDK
shipping `CppWinRT 2.0.250303.5`, `main.obj` began emitting that version
via `#pragma detect_mismatch`, while `SettingsAPI.lib` continued to be
built against the pinned NuGet `2.0.250303.1`. The linker rejects the
mix.

This was masked while the agent SDK happened to ship a matching CppWinRT
version, and surfaced after #47470 (Bump WindowsAppSDK to 2.0.1) plus
the agent image roll.

## Fix

Mirror the canonical CppWinRT NuGet wiring used by every other native
vcxproj in the repo (see `src/common/SettingsAPI/SettingsAPI.vcxproj`
for the reference pattern):

- Add `packages.config` pinning `Microsoft.Windows.CppWinRT
2.0.250303.1`.
- Import the props after `Microsoft.Cpp.Default.props`.
- Import the targets in an `ExtensionTargets` `ImportGroup`.
- Add `EnsureNuGetPackageBuildImports` for restore-time validation.

## Validation

- Local x64/Release build of GrabAndMove.vcxproj clean (linked against
SettingsAPI.lib without LNK2038).
- (Local SDK on the dev box already ships matching CppWinRT
2.0.250303.1, so the LNK2038 cannot reproduce locally; the CI pool agent
has the newer SDK that exposes the latent issue.)
- Awaiting PowerToys CI to confirm fix on the agent image.

## Related

- #47470 (Bump WindowsAppSDK to 2.0.1) — preceded but did not directly
cause this; just changed which CppWinRT was sitting in the include path.
- Failing CI runs: 319304, 319351, 319593 (all on shine-oss PowerToys CI
definition 3).
2026-05-15 14:13:24 -05:00
Copilot
34e78bd8c3 Add validation to prevent empty names in ImageResizer size presets (#45425)
## Summary of the Pull Request

Prevents users from clearing the name field in ImageResizer size preset
edit dialog. Empty names made the UI confusing without causing errors.

## PR Checklist

- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

Added validation guard in `ImageSize.Name` property setter:

```csharp
public string Name
{
    get => _name;
    set
    {
        if (!string.IsNullOrWhiteSpace(value))
        {
            SetProperty(ref _name, value);
        }
    }
}
```

Invalid assignments (empty, null, whitespace) are silently ignored,
preserving the existing value. This matches the existing pattern used
for `FileName` validation in `ImageResizerViewModel`.

TwoWay binding in UI causes the TextBox to revert when users attempt to
clear the field—standard behavior for required fields.

## Validation Steps Performed

- Added unit test `ImageSizeNameShouldNotBeSetToEmptyOrNull()` covering
all rejection and acceptance cases
- Verified silent rejection behavior matches `FileName` property pattern

> [!WARNING]
>
> <details>
> <summary>Firewall rules blocked me from connecting to one or more
addresses (expand for details)</summary>
>
> #### I tried to connect to the following addresses, but was blocked by
firewall rules:
>
> - `i1qvsblobprodcus353.vsblob.vsassets.io`
> - Triggering command: `/usr/bin/dotnet dotnet build
/home/REDACTED/work/PowerToys/PowerToys/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/ResultHelper.cs
/home/REDACTED/work/PowerToys/PowerToys/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/RegistryHelper.cs
/home/REDACTED/work/PowerToys/PowerToys/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Enumerations/TruncateSide.cs
/home/REDACTED/work/PowerToys/PowerToys/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Constants/KeyName.cs
/home/REDACTED/work/PowerToys/PowerToys/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Constants/MaxTextLength.cs
/home/REDACTED/work/PowerToys/PowerToys/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Commands/CopyRegistryInfoCommand.cs
/home/REDACTED/work/PowerToys/PowerToys/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Commands/OpenKeyInEditorCommand.cs
/home/REDACTED/work/PowerToys/PowerToys/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Re
/home/REDACTED/work/PowerToys/PowerToys/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/CopyType.cs
/home/REDACTED/work/PowerToys/PowerToys/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Icons.cs`
(dns block)
>
> If you need me to access, download, or install something from one of
these locations, you can either:
>
> - Configure [Actions setup
steps](https://gh.io/copilot/actions-setup-steps) to set up my
environment, which run before the firewall is enabled
> - Add the appropriate URLs or hosts to the custom allowlist in this
repository's [Copilot coding agent
settings](https://github.com/microsoft/PowerToys/settings/copilot/coding_agent)
(admins only)
>
> </details>

<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

> 
> ----
> 
> *This section details on the original issue you should resolve*
> 
> <issue_title>[Settings: ImageResizer] Edit size dialog: Add validation
against empty name</issue_title>
> <issue_description>There is one small thing we should add. (But I
don't know how.)
> The data in the name field of the edit dialog should be validated
against `.NullOrEmpty`!
> _Originally posted by @htcfreek in
https://github.com/microsoft/PowerToys/pull/13285#issuecomment-924113251_
> 
> **Detailed description:**
> While users edit an image size in the ImageResizer settings on PT's
settings ux they are able to clear the name of the image size. This
doesn't lead to errors/exceptions, but it also doesn't make sense to
have sizes without a name. So we should prevent user from doing this in
the edit dialog.
> 
> _**Note:**_
> This is the second and last change that is needed to prevent the users
from having incorrect image size settings (#8698). But I think this is
not as relevant, because a missing name won't break image resizing._
> 
> ---
> 
> cc: @niels9001 </issue_description>
> 
> <agent_instructions>Implement a proper fix for this issue. Do NOT
create placeholder stub files. Create actual working code that addresses
the issue described. Follow PowerToys coding guidelines and
conventions.</agent_instructions>
> 
> ## Comments on the Issue (you are @copilot in this section)
> 
> <comments>
> <comment_new><author>@TheJoeFin</author><body>
> does this issue still happen with v0.73.0?
/needinfo</body></comment_new>
> </comments>
> 


</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes microsoft/PowerToys#13336

<!-- START COPILOT CODING AGENT TIPS -->
---

 Let Copilot coding agent [set things up for
you](https://github.com/microsoft/PowerToys/issues/new?title=+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: yeelam-gordon <73506701+yeelam-gordon@users.noreply.github.com>
2026-05-15 11:39:01 +02:00
Boliang Zhang
e932fe6e61 Remove unused dependencies and shrink installer size (#47233)
## Summary of the Pull Request

Two related installer changes to (1) eliminate genuinely-unused
dependencies and (2) deduplicate shared WinAppSDK files between
`<install>\` and `<install>\WinUI3Apps\` to shrink the installer
download.

### 1. Remove unused dependencies (~11 MB savings per output location)

- **System.Data.SqlClient**: Removed from MouseWithoutBorders projects
and the central `Directory.Packages.props` pin. It was a transitive
dependency of `Microsoft.Windows.Compatibility` but PowerToys has zero
SQL database usage.
- **Unused `using` import**: Removed `using
System.ServiceModel.Channels` from MouseWithoutBorders `Program.cs` (no
WCF usage).
- **MFC / C++ AMP / OpenMP DLLs**: Added `RemoveUnusedVCRuntimeDlls`
target in `Directory.Build.targets` to clean up `mfc140*`, `mfcm140*`,
`vcamp140*`, and `vcomp140*` DLLs that leak from the VC++
Redistributable tree but are not imported by any PowerToys binary
(verified with `dumpbin /dependents` across all installed binaries).
Also excluded MFC DLLs from installer file collection.

### 2. WinAppSDK file deduplication (build-time only; install-time uses
copy)

**Background**: The `WinUI3Apps` subfolder must remain a real directory
because MSIX sparse package registration applies DACL changes to the
`ExternalLocation` folder (PR #47177). Flattening is not viable.

**Build-time** (`generateAllFileComponents.ps1`): computes the SHA256
intersection of root and `WinUI3Apps` files, and for each file that is
also present in the BaseApplications WXS file list, removes the
duplicate from the WinUI3Apps WXS component list and writes its name to
a `hardlinks.txt` manifest. The BaseApplications cross-check ensures we
never deduplicate a file the MSI does not actually deploy at the install
root, which would otherwise leave both copies missing post-install. The
manifest is written as UTF-8 without BOM (via
`[System.IO.File]::WriteAllLines` with `UTF8Encoding($false)`) so its
encoding is identical regardless of the build host's PowerShell version.
This step produces the **MSI download-size win** (~97 MB smaller cab;
LZX:21 was already deduplicating most byte-identical content
automatically inside the cab).

**Install-time** (`CreateWinAppSDKHardlinksCA` custom action):
- Reads `hardlinks.txt` after `InstallFiles` as a raw byte stream and
converts each line to a `std::wstring` via `MultiByteToWideChar(CP_UTF8,
MB_ERR_INVALID_CHARS, ...)`. Avoids `std::wifstream`'s ANSI-codepage
codecvt so non-ASCII paths can never be silently mangled.
- For each entry, computes `(installDir / fileName).lexically_normal()`
and `(winui3Dir / fileName).lexically_normal()`, then verifies via
`std::mismatch` that each resolved path is still rooted at its
respective folder. Manifest entries containing `..`, absolute paths, or
alternate-stream syntax are logged and skipped.
- Materialises each validated entry from `<install>\<name>` into
`<install>\WinUI3Apps\<name>` via `fs::copy_file` (overwrite_existing).
- Reports the per-file copy / failure counts to the install log. If
every entry failed (`created == 0 && failed > 0`), the CA escalates to
`E_FAIL` so the install does not silently succeed with an unusable
WinUI3Apps tree.

`DeleteWinAppSDKHardlinksCA` removes the materialised copies before
`RemoveFiles` on uninstall, using the same UTF-8 reader and per-entry
containment check.

**WiX sequencing**: `CreateWinAppSDKHardlinks` runs
`After="InstallFiles"` with `Condition="NOT Installed OR
WIX_UPGRADE_DETECTED OR REINSTALL"` so a `msiexec /fa` repair refreshes
the deduplicated copies (otherwise `RemoveFiles` would orphan them).

#### Why copy and not hard-link

A hard-linked variant of this CA was originally proposed but caused a
Monaco preview-handler regression. Hard-links share an NTFS inode (and
therefore one DACL) between `<install>\<file>` and
`<install>\WinUI3Apps\<file>`. The MSIX sparse-package registrations for
PowerRename / ImageResizer / FileLocksmith / NewPlus run after the dedup
CA and propagate the `WinUI3Apps` parent's rich DACL (Capability SID, 5×
Package SIDs, 5× conditional SYSAPPID ACE, RC SID) onto the shared
inode. The root path then also exposes the rich DACL, which trips a
kernel "stricter access evaluation" path that blocks the LOW-IL
`prevhost.exe` from `LoadLibrary`-ing `hostfxr.dll` (and the rest of the
.NET runtime), turning the Monaco preview pane blank for `.json` / `.md`
/ `.cs` / `.xaml` / `.svg` / `.xml` files.

`fs::copy_file` creates a **fresh inode** for the WinUI3Apps copy. The
root inode keeps its simple DACL (`SY:F + BA:F + owner:F` + inherited
`BU:RX`) so LOW-IL `prevhost.exe` can still load it — Monaco preview
works. The WinUI3Apps copy inherits the WinUI3Apps parent's rich DACL
via normal NTFS inheritance (matches 0.99.1 behaviour exactly) — MSIX
context-menu shells continue to work.

#### Trade-off

| Metric | Hard-link variant (rejected) | This PR (file copy) | 0.99.1
(no dedup) |
|---|---|---|---|
| MSI size | ~296 MB | ~296 MB | ~393 MB |
| On-disk after install | ~2,475 MB | ~2,772 MB | ~2,772 MB |
| DACL contamination risk | YES (broke Monaco) | NO | NO |

The on-disk savings (~297 MB) are given up in exchange for eliminating
the DACL contamination risk; the **installer download savings (~97 MB)**
are preserved by the build-time WiX/cab dedup.

#### Edge cases handled

- Empty duplicate list: `hardlinks.txt` always written, CA handles
empty.
- All files duplicated: `Generate-FileComponents` returns early for
empty list.
- File stripped from BaseApplications by an earlier build step:
BaseApplications cross-check skips it during dedup so neither copy goes
missing.
- Manifest entry escapes install root (`..`, absolute path): rejected
per-entry, install continues.
- Manifest line is non-UTF-8: rejected per-entry, install continues.
- Source missing at install time: per-entry skip, install continues.
- All copies fail: install aborts loudly via `E_FAIL` (catastrophic-case
escalation).
- Upgrade or `msiexec /fa` repair: CA fires (`NOT Installed OR
WIX_UPGRADE_DETECTED OR REINSTALL`).

**MSI repair risk**: Burn bundle uses `SuppressRepair=yes` and
`MajorUpgrade` (full uninstall + reinstall) for all version upgrades, so
the standard upgrade path is unaffected. The `OR REINSTALL` clause
covers power users running `msiexec /fa` directly.

## PR Checklist

- [x] **Communication:** Discussed approach via PRs #46866, #47177,
#46745
- [ ] **Tests:** Installer infrastructure only — no runtime behaviour
changes
- [ ] **Localization:** N/A
- [ ] **Dev docs:** N/A
- [ ] **New binaries:** N/A

## Detailed Description of the Pull Request / Additional comments

Based on the approach from PR #46745 by @yeelam-gordon, rebased onto
latest main and switched from hard-links to file copies after the DACL
contamination root cause was identified. Hardening (UTF-8 read, path
containment, catastrophic-case escalation, REINSTALL repair,
BaseApplications-filtered dedup) added in response to review feedback.

These changes are purely build/installer infrastructure — no runtime
behaviour changes to any PowerToys module.

## Validation Steps Performed

Validated on a 0.99.4 / 0.99.5 local install (per-user
`%LocalAppData%\PowerToys`):

-  `dumpbin /dependents` across the installed PowerToys tree confirmed
zero binaries import `mfc140*`, `mfcm140*`, `vcamp140*`, or `vcomp140*`
— the cleanup target removes ~11 MB of genuinely unused VC runtime DLLs.
-  `System.Data.SqlClient` has zero call-sites in PowerToys source.
-  Local installer build produces a 296 MB MSI (down from 393 MB
pre-dedup, ~97 MB cab savings purely from the build-time WiX dedup).
-  MSI table inspection (`wix msi decompile`) confirms the deferred CAs
are present (`CreateWinAppSDKHardlinks`, `DeleteWinAppSDKHardlinks`) and
the `hardlinks.txt` File row is registered.
-  MSI table inspection confirms .NET runtime DLLs (`hostfxr.dll`,
`coreclr.dll`, `hostpolicy.dll`, `clretwrc.dll`, `Accessibility.dll`,
`backup_restore_settings.json`) appear ONLY in
`BaseApplicationsFiles_File_*`, NOT in `WinUI3ApplicationsFiles_File_*`
— proving the build-time dedup worked.
-  Post-install verification: deduplicated files materialised at both
root and WinUI3Apps with byte-identical SHA256 hashes, and `fsutil
hardlink list` returns link-count == 1 for each — proving the
install-time copy approach worked, not hard-link.
-  DACL on root .NET runtime DLLs is clean: no Package SID, no
Capability SID, no SYSAPPID conditional ACE, no `ALL APPLICATION
PACKAGES` ACE — Monaco preview load path is safe.
-  DACL on WinUI3Apps copies has the rich MSIX inheritance —
context-menu shells continue to work (matches 0.99.1).
-  All four MSIX sparse packages (PowerRename, ImageResizer,
FileLocksmith, NewPlus) registered after install.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-15 17:15:11 +08:00
Niels Laute
c7d458b71d Fix auto-label-issues workflow (#47820)
## Summary

Fixes the `Auto-label Issues by Area` workflow, which currently logs
`GITHUB_TOKEN is not set; skipping.` on every run and never applies
labels.

Failing run on issue #47818:
https://github.com/microsoft/PowerToys/actions/runs/25722067064/job/75525452318

## Root cause

`actions/github-script@v7` consumes its `github-token` input only to
authenticate the injected `github` Octokit object. It does **not**
export that value to `process.env.GITHUB_TOKEN`. The inline script reads
`process.env.GITHUB_TOKEN` to authorize a direct `fetch()` against
`https://models.inference.ai.azure.com/chat/completions`, so the token
check at the top of `labelIssue()` always fails and the function returns
early before calling the model.

## Fix

Add a step-level `env:` block exposing `GITHUB_TOKEN` to the Node
process running the inline script. The existing `with.github-token`
input is preserved so the injected `github` Octokit continues to
authenticate.

`yaml
- name: Apply area labels with AI
  uses: actions/github-script@v7
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  with:
    github-token: ${{ secrets.GITHUB_TOKEN }}
`

5 lines added, 0 removed.

## Security

- `secrets.GITHUB_TOKEN` is the workflow's built-in ephemeral token
(auto-issued per run, auto-revoked at job end). Not a PAT.
- Scope is already constrained by `permissions: models: read, issues:
write` at the top of the workflow. No widening.
- Exposure is unchanged: the token is already loaded into the same Node
process by `actions/github-script` via `github-token:`. The `env:`
mapping just lets the script body read what the action already has in
the same process.
- The token is sent only to GitHub's own GitHub Models inference
endpoint, which is the documented use of `models: read`.
- Triggers are safe: `issues: opened/reopened` (issue body is
JSON-encoded into the request body, never interpolated into a shell) and
`workflow_dispatch` (write-access required).
- Token is never logged.

## Validation

After merge, re-run the workflow on issue #47818 via Actions ->
"Auto-label Issues by Area" -> Run workflow, and confirm logs show
`Model response: ...` instead of `GITHUB_TOKEN is not set; skipping.`

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-15 14:39:00 +08:00
Jiří Polášek
c4ff073d01 CmdPal: Extension Gallery (#46636)
## Summary of the Pull Request

Adds the **Extension Gallery** to Command Palette — a built-in page
where users can discover, browse, and install community extensions
without leaving the app.


https://github.com/user-attachments/assets/e4565333-b970-4085-9e40-5cfd207e533b

## How it works

### 1. The extension author's side

Extensions are listed in the external repo
**[`microsoft/CmdPal-Extensions`](https://github.com/microsoft/CmdPal-Extensions)**.
To get an extension into the in-app gallery, an author opens a PR there
that adds a single entry to `extensions.json`. Nothing in PowerToys
itself needs to change. A typical entry looks like:

```json
{
  "id": "contoso.sample",
  "title": "Sample Extension",
  "description": "Short blurb shown in the list and detail view.",
  "author": { "name": "Contoso", "url": "https://github.com/contoso" },
  "homepage": "https://github.com/contoso/sample",
  "iconUrl": "https://.../icon.png",
  "screenshotUrls": ["https://.../screenshot-1.png"],
  "tags": ["sample"],
  "installSources": [
    { "type": "winget",  "id":  "Contoso.SampleExtension" },
    { "type": "msstore", "id":  "9P..." },
    { "type": "url",     "uri": "https://github.com/contoso/sample/releases/latest" }
  ],
  "detection": { "packageFamilyName": "Contoso.SampleExtension_8wekyb..." }
}
```

- `id`, `title`, `description`, `author.name`, and at least one
`installSources` entry are required; everything else is optional.
- `installSources` can mix and match `winget` / `msstore` / `url`. The
gallery shows an install button for the first source it can handle
(WinGet preferred) and exposes any remaining sources as links.
- `detection.packageFamilyName` lets CmdPal recognise an
already-installed packaged extension before any WinGet lookup resolves,
so the "Installed" badge appears instantly.

Once the PR is merged into `CmdPal-Extensions`, every running copy of
CmdPal picks the new entry up the next time its feed cache expires
(within 4 hours) or when the user clicks **Refresh**.

### 2. What CmdPal does with it

`ExtensionGalleryService` (in `Microsoft.CmdPal.Common`) owns the whole
pipeline:

1. **Resolve the feed URL.** Default is
`https://raw.githubusercontent.com/microsoft/CmdPal-Extensions/refs/heads/main/extensions.json`.
A hidden setting (`GalleryFeedUrl`) lets developers point at a custom
URL or a `file://` path for local testing.
2. **Fetch** the feed through `ExtensionGalleryHttpClient`, which wraps
`HttpCachingClient` — a conditional-GET + on-disk cache layer built on
`HttpClient` (ETag / `If-None-Match`, 30 s timeout, UA
`PowerToys-CmdPal/1.0`).
3. **Parse** with the source-generated `GallerySerializationContext`
into a strongly-typed `GalleryRemoteIndex` (`{ "extensions": [ ... ]
}`). Entries without an `id` are dropped.
4. **Normalize** relative `iconUrl` / `screenshotUrls` against the feed
URL (useful for local `file://` feeds).
5. **Localize icons.** Each HTTP icon URL is pulled through the same
cache and rewritten to a local `file://` URI before the view model binds
to it, so the list renders instantly on subsequent loads and works
offline.
6. **Prune** cached resources that are no longer referenced, but only
after a successful forced refresh.

The gallery page itself is built on top of `ExtensionGalleryViewModel`,
with `ExtensionGalleryItemViewModel` handling per-entry concerns —
install/update/uninstall (via the shared WinGet service),
installed-state detection, and joining in-flight install progress so the
global `WinGetOperationsButton` in the top bar stays in sync.

### 3. Caching + offline behaviour

The cache lives under
`ApplicationData.Current.LocalCacheFolder\GalleryCache\` when CmdPal
runs packaged, or
`%LOCALAPPDATA%\Microsoft\PowerToys\Microsoft.CmdPal\Cache\GalleryCache\`
when unpackaged.

| Resource        | TTL      |
|-----------------|----------|
| `extensions.json` feed | 4 hours |
| Icons (per URL) | 24 hours |

Each fetch returns a `GalleryFetchResult` whose flags drive the UI:

- `FromCache` — cache was still fresh, no network call was made.
- `UsedFallbackCache` — network failed; the last-known-good cached copy
was served instead. The page shows a "showing cached data" info bar.
- `RateLimited` — origin returned `429` and no fallback was available.
The page shows a rate-limit error.

`RefreshAsync` (wired up to the gallery's refresh button) forces a fresh
conditional GET, then prunes any cached files that the new feed no
longer references.

### 4. WinGet install flow

- `installSources[type=winget].id` is handed to the shared WinGet
service for install/update/uninstall.
- In-flight operations are surfaced by `WinGetOperationsButton` in the
top bar with per-operation progress.
- `detection.packageFamilyName` is consulted first so that the gallery
can show "Installed" / "Update available" without waiting on WinGet
metadata.

### Top-level command cleanup

- Removed the separate "Find extensions from WinGet" and "Find
extensions from the Store" top-level commands — the gallery replaces
both.
- Renamed the gallery command to **"Find and install Command Palette
extensions"** and gave it the extensions puzzle-piece icon.

## PR Checklist

- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## New projects / areas

| Area | What |
|------|------|
| Microsoft.CmdPal.Common | Gallery models, `ExtensionGalleryService`
(fetch + cache), HTTP caching layer (`HttpCachingClient`,
`FileSystemHttpResourceCacheStore`), WinGet service abstractions and
implementations |
| Microsoft.CmdPal.UI.ViewModels | `ExtensionGalleryViewModel`,
`ExtensionGalleryItemViewModel`, WinGet operation view models, gallery
sort options |
| Microsoft.CmdPal.UI | `ExtensionGalleryPage.xaml`,
`ExtensionGalleryItemPage.xaml`, `IconCarouselControl`,
`WinGetOperationsButton`, service registrations |
| Microsoft.CmdPal.Ext.WinGet | Streamlined — removed the two redundant
"find extensions" top-level commands, kept the general WinGet search
page |
| Tests | Unit tests for gallery service, gallery view models, WinGet
services |
| Docs |
[`doc/devdocs/modules/cmdpal/extension-gallery/extension-gallery.md`](https://github.com/microsoft/PowerToys/blob/dev/jpolasek/f/46628-cmdpal-extension-gallery/doc/devdocs/modules/cmdpal/extension-gallery/extension-gallery.md)
— dev reference for the runtime, caching, and feed shape |

## Validation Steps Performed

- Gallery loads and displays extensions from the remote index
- Search, sort, and filtering work as expected
- WinGet install/update/uninstall flow works end-to-end with progress
tracking
- Loading state correctly hides all content until data is fetched
- Offline / cache-fallback path surfaces the info bar as expected
- Spell-check CI workflow passes

---------

Co-authored-by: Niels Laute <niels.laute@live.nl>
Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
2026-05-14 16:30:20 -05:00
Dave Rayment
59eefd9581 [CmdPal and Run Calculator] Fix issues with log functions and spaces (#47767)
## Summary of the Pull Request

The Calculator components in Command Palette and Run produced incorrect
results or errors for `log` and `ln` inputs where spaces exist between
the function name and the argument list. This is because input
validation allowed for those spaces, but this was not respected in the
log mapping code which transforms user input into a string for
consumption by the expression evaluator engine.

The result of this is discrepancy was that:

- Natural log would be called instead of log base 10 for `log (n)`.
- An error would be shown for `ln (n)`.

For example:
<img width="556" height="166" alt="image"
src="https://github.com/user-attachments/assets/d2110292-ca8f-4635-bdef-9fa4f2211deb"
/>

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

- [x] Closes: #47759
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

<!-- 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
The issue was with this code:


a650504640/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/CalculateEngine.cs (L56-L58)

This maps user input such as `log(10)` or `ln(10)` to the functions the
back-end expression evaluator understands. For Mages and ExprTK, this is
mapped to `log10(n)` for base 10 logs or `log(n)` for natural logs.

Unfortunately, the input validator regex allows for spaces between the
function name and the start of the argument list, and the string replace
does not. When spaces exist:

- For `log (n)` - the log10 match is missed and the expression is
interpreted as a natural log, producing incorrect results.
- For `ln (n)` - the string is passed as-is to the back-end. Neither
Mages nor ExprTK recognise it, so an error is returned.

The fix is to replace the string replacement code with two regexes.
These are both forgiving of spaces between the function name and
argument list:

For log base 10: `"log(?![0-9])\\s*\\("`
For natural log: `"ln\\s*\\("`

Both are culture-agnostic and have `IgnoreCase` set. I took the
opportunity to remove the "en-US" culture from the
`DivisionByZeroRegex`, as it is not required.

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Added unit tests which ensure the log and ln functions perform
identically with or without spaces. Confirmed all unit tests for Command
Palette and Run still pass.

Manually confirmed that `log` and `ln` now produce correct results in
both applications.
2026-05-14 16:16:03 -05:00
Boliang Zhang
42ff04d4bc Fix uitest pipeline install dotnet10 sdk (#47852)
## Problem

The scheduled UI Test Automation pipeline
([Dart/161438](https://microsoft.visualstudio.com/Dart/_build?definitionId=161438))
has been failing daily since 2026-04-30 because PR #41280 (`.NET 10
Upgrade`) updated the main build template (`job-build-project.yml`) for
.NET 10 / VS 2026 but the parallel changes were missed in the UI Test
Automation templates.

Symptoms in recent runs (e.g. build
[#20260512.1](https://microsoft.visualstudio.com/Dart/_build/results?buildId=146803928)):

```
error NETSDK1045: The current .NET SDK does not support targeting .NET 10.0.
   Either target .NET 9.0 or lower, or use a version of the .NET SDK that supports .NET 10.0.
```

…emitted ×179 across every csproj during the *Restore solution-level
NuGet packages* step on both `Build UI Tests Only Release_x64` and
`…_arm64` jobs.

## Changes

This PR mirrors the two pipeline changes that PR #41280 already applied
to the main CI templates.

**1. Install the .NET 10 SDK on the build agent**
- File: `.pipelines/v2/templates/job-build-ui-tests.yml`
- Bump the pinned `steps-ensure-dotnet-version.yml` parameter from
`version: '9.0'` → `'10.0'`.
- Matches `job-build-project.yml`, which already installs the .NET 10
SDK alongside 6.0/8.0.

**2. Pin the build agent image to VS 2026 (MSBuild 18)**
- File: `.pipelines/v2/templates/pipeline-ui-tests-official-build.yml`
- Add `demands: ImageOverride -equals SHINE-VS18-Latest` to the agent
pool spec.
- The .NET 10 SDK (≥ 10.0.300) requires MSBuild 18, which only ships
with VS 2026. Without this demand, the SHINE pool selects a default
image with VS 2022 / MSBuild 17 and restore fails with `MSB4236: The SDK
'Microsoft.NET.Sdk' specified could not be found`.
- Mirrors the unconditional pattern in `pipeline-ci-build.yml` (lines
56–67), which applies the same demand across both `SHINE-INT-L` and
`SHINE-OSS-L` pools.

## Validation

Queued pipeline 161438 against this branch:

| Build | Commit | Result |
| --- | --- | --- |
|
[`146821554`](https://microsoft.visualstudio.com/Dart/_build/results?buildId=146821554)
| `4dd13b9` (SDK fix only) | `NETSDK1045` gone  — exposed VS 2022 /
MSBuild 17 mismatch |
|
[`146825355`](https://microsoft.visualstudio.com/Dart/_build/results?buildId=146825355)
| `97cadbb` (SDK + agent demand) | Both errors gone  — agent now
`Visual Studio\18\Enterprise\` |

After this PR, the pipeline reaches NuGet restore and now hits a
separate, **pre-existing** issue from the April 13–29 failure window:
`401 Unauthorized` on the `shine-oss/PowerToysPublicDependencies`
Artifacts feed for newly-released `Microsoft.NETCore.App.*/8.0.27`
packages. That requires feed-admin action (granting the Dart pipeline
build identity "save from upstream" on the feed, or pre-seeding those
package versions) and is **out of scope for this PR**.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-14 22:08:28 +08:00
Boliang Zhang
3948fcc19d [release-notes skill] Use local agent for PR summaries; vendor prepare-release-assets.ps1 (#47651)
## Summary

Two related changes to the `release-note-generation` agent skill:

### 1. Step 3 reviews: use the local agent instead of
`mcp_github_request_copilot_review`

Step 3.1 previously instructed the agent to call
`mcp_github_request_copilot_review` for every milestone PR so that the
`CopilotSummary` column in `sorted_prs.csv` would be populated by the
GitHub-side Copilot bot.

When this skill is driven from a CLI / coding agent, that request comes
from a bot identity, and the GitHub API rejects it (`Bot reviewers
cannot be requested`). The PR ends up with no Copilot review and
`CopilotSummary` stays empty.

`references/step3-review-grouping.md` has been rewritten to instead have
**the local agent** that is running the skill perform the review itself:

- Fetch each PR's diff with a non-mutating tool
(`mcp_github_pull_request_read` `get_diff` / `get_files`, or `gh pr
diff`).
- Produce a 1-3 sentence user-facing summary in the same style as a
Copilot PR review.
- Write the summary directly into the `CopilotSummary` column of
`Generated Files/ReleaseNotes/sorted_prs.csv`, preserving row order and
skipping rows that already have a non-empty summary.

Step 3.2 (re-run `dump-prs-since-commit.ps1`) is demoted to optional,
with a note that re-running the dump will overwrite the
locally-generated summaries.

`SKILL.md` was updated to match: front-matter description, "When to
Use", workflow diagram, the 3.1-3.3 row in the summary table,
prerequisites (no longer requires "GitHub Copilot code review enabled
for the org/repo"; mentions MCP for fetching diffs), and the
troubleshooting row for empty `CopilotSummary` now points at Step 3.1
with the bot-rejection caveat.

### 2. Vendor `prepare-release-assets.ps1` into the skill

Added `scripts/prepare-release-assets.ps1` -- previously kept in
OneDrive at `Tools/prepare-release.ps1`. Renamed because the script does
more than download installers: it also pulls per-arch symbol archives,
computes SHA256, and emits the **Installer Hashes** markdown table for
the GitHub release page. "Release assets" captures all of that.

Header `.SYNOPSIS` / `.DESCRIPTION` / `.EXAMPLE` blocks were updated to
reflect the new filename and the symbol-archive behavior (the original
synopsis only mentioned installers).

`SKILL.md` registers the new script in the "Available Scripts" table,
lists Azure CLI + the `azure-devops` extension as a prerequisite (only
when running this script), adds a "Prepare GitHub release assets" entry
to "When to Use", and adds a troubleshooting row for the most common
failure (`Failed to acquire ADO access token` -> `az login`).

## Files changed

| File | Change |
|------|--------|
| `.github/skills/release-note-generation/SKILL.md` | Updated
description, prerequisites, workflow, scripts table, troubleshooting |
|
`.github/skills/release-note-generation/references/step3-review-grouping.md`
| Rewritten to use local-agent review; demoted refresh step |
|
`.github/skills/release-note-generation/scripts/prepare-release-assets.ps1`
| New (vendored from OneDrive) |

## Validation

- PowerShell parser ([`Parser]::ParseFile`) reports no errors on the new
script.
- Documentation-only / scripts-only change -- no product code touched,
so the standard PowerToys build / test gates do not apply.
- The change preserves the existing CSV schema (`Id, Title, Labels,
Author, Url, Body, CopilotSummary, NeedThanks`), so downstream Step 3.3
(`group-prs-by-label.ps1`) and Step 4 summarization continue to work
without modification.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-14 22:07:38 +08:00
moooyo
c5d17913e4 [PowerDisplay] Add max compatibility mode setting (#47875)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

1. Adds an opt-in Max compatibility mode in PowerDisplay's Advanced
settings. When enabled, DDC discovery probes monitors that don't
advertise capabilities, picking up displays that would otherwise be
skipped.
2. Toggling the setting triggers an immediate rescan via a new
RescanPowerDisplayMonitorsEvent IPC event from Settings to PowerDisplay.
3. Hides the brightness slider on monitors that lack VCP 0x10.

Also fixed animation issue #47868

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

- [x] Closes: #47878
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Yu Leng <yuleng@microsoft.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-14 07:20:22 +00:00
Jiří Polášek
5715f694ea CmdPal: Add a pinned commands section to the Home page and enable reordering (#45869)
## Summary of the Pull Request

This PR adds a new section for pinned to Home page and commands to
re-order them

- Updates the settings model for pinned command persistence, moving from
per-provider lists to a single ordered list.
- Adds context menu commands for pinned items to reorder them (move up,
move down, move to top).

<img width="902" height="689" alt="image"
src="https://github.com/user-attachments/assets/7d9ef34f-fa00-4155-b62c-2dacc5b85603"
/>


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

- [x] Related to: #45865
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Michael Jolley <mjolley@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-13 20:35:58 -05:00
Michael Jolley
966c1db76a CmdPal Dock: Multi-monitor support (#46915)
This pull request introduces per-monitor dock customization support and
refactors how dock band settings are managed to enable independent
layouts on different monitors. The changes add a new
`DockMonitorConfigViewModel` for monitor-specific configuration, update
`DockViewModel` to handle per-monitor band lists and settings, and
refactor band movement and ordering logic to respect per-monitor
overrides.

**Per-monitor dock customization:**

* Added `DockMonitorConfigViewModel` to encapsulate the configuration
and state for each monitor, exposing properties for binding and
persisting changes using `ISettingsService`.
* Updated `DockViewModel` to track an optional `MonitorDeviceId`,
enabling docks to be associated with a specific monitor and to expose
per-monitor settings and methods.
[[1]](diffhunk://#diff-b661a9311de64dd1123860e858f1f4963f05ccee06b5bd218916635495b2ff06L17-R33)
[[2]](diffhunk://#diff-b661a9311de64dd1123860e858f1f4963f05ccee06b5bd218916635495b2ff06L41-R56)

**Band management refactor for per-monitor settings:**

* Refactored band retrieval and update logic in `DockViewModel` to use
new helper methods (`GetActiveBands`, `WithActiveBands`) that select and
modify either global or per-monitor band lists as appropriate.
* Updated band movement and ordering methods (`SyncBandPosition`,
`MoveBandWithoutSaving`, `SaveBandOrder`) to operate on the correct band
lists for each monitor, ensuring that changes apply to the intended
scope (global or per-monitor).
[[1]](diffhunk://#diff-b661a9311de64dd1123860e858f1f4963f05ccee06b5bd218916635495b2ff06L205-R399)
[[2]](diffhunk://#diff-b661a9311de64dd1123860e858f1f4963f05ccee06b5bd218916635495b2ff06L250-R413)
[[3]](diffhunk://#diff-b661a9311de64dd1123860e858f1f4963f05ccee06b5bd218916635495b2ff06L263-R424)
[[4]](diffhunk://#diff-b661a9311de64dd1123860e858f1f4963f05ccee06b5bd218916635495b2ff06L280-R437)
[[5]](diffhunk://#diff-b661a9311de64dd1123860e858f1f4963f05ccee06b5bd218916635495b2ff06L290-R447)
[[6]](diffhunk://#diff-b661a9311de64dd1123860e858f1f4963f05ccee06b5bd218916635495b2ff06L300-R465)
[[7]](diffhunk://#diff-b661a9311de64dd1123860e858f1f4963f05ccee06b5bd218916635495b2ff06L329-R491)

**Resource management:**

* Implemented `IDisposable` on `DockViewModel` to clean up event
handlers and prevent resource leaks.
[[1]](diffhunk://#diff-b661a9311de64dd1123860e858f1f4963f05ccee06b5bd218916635495b2ff06L17-R33)
[[2]](diffhunk://#diff-b661a9311de64dd1123860e858f1f4963f05ccee06b5bd218916635495b2ff06R85-R235)

Closes #46939

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Niels Laute <niels.laute@live.nl>
Co-authored-by: Mike Griese <migrie@microsoft.com>
2026-05-13 17:37:58 -05:00
Knyrps
34cebb8285 [CmdPal][PerfMon] Use % Processor Time for system CPU dock (#47864)
## Summary of the Pull Request

The system-wide CPU counter in the Command Palette Performance monitor
used `% Processor Utility`, which is scaled by `% Processor Performance`
and is intentionally unbounded above 100% when cores boost above their
nominal base frequency. Under load this produced values like 144% in the
dock, as reported in #46381.

Switch to `% Processor Time` — the same counter Task Manager renders —
which is naturally bounded to 0-100%.

The per-process branch is unaffected; it already divides by
`Environment.ProcessorCount` and continues to use `% Processor Time`, so
individual process readings remain correct.

## PR Checklist

- [x] **Closes:** #46381
- [x] **Communication:** I've discussed this with the team/maintainers
via the linked issue.
- [x] **Tests:** Manually tested locally. Built
`Microsoft.CmdPal.Ext.PerformanceMonitor` and the full
`CommandPalette.slnf` (Debug|x64). Verified the built DLL contains `%
Processor Time` and no longer contains `% Processor Utility`.
- [x] **Manual tests:** Ran the rebuilt dev build under sustained CPU
load; the system CPU figure now stays bounded to 100%.
- [x] **Localization:** Not applicable — counter name is an OS API
string, not user-visible text.

## Detailed Description of the Pull Request / Additional comments

`% Processor Utility` is documented by Microsoft as deliberately
unbounded; it represents an "effective" utilization that accounts for
turbo/boost frequencies. It is well-suited for billing/capacity contexts
but not for a "% of CPU used" UI element where users expect a 0-100%
reading consistent with Task Manager and Resource Monitor.

`_procPerformance` (the `% Processor Performance` counter) is retained
because it is still used by `CpuSpeed` to compute the live frequency
display, so removing it would regress the speed readout.

### Before
System CPU dock showed values >100% under load (reported 144% in the
issue).

### After
System CPU dock is bounded to 0-100%, matching Task Manager.
2026-05-13 16:43:16 -05:00
Mike Griese
9b28e6d5a2 cmdpal: bump to 0.11 (#47841)
title
2026-05-13 10:35:29 +02:00
Copilot
ba68b88ca1 Fix ZoomIt Record hotkey ignoring Alt modifier when Alt is the only modifier key (#47388)
## Summary of the Pull Request

ZoomIt derives three recording hotkeys from one base key via XOR:
fullscreen (base), crop (base XOR Shift), window (base XOR Alt). When
Alt is the sole modifier, `base XOR Alt = 0`, registering a
modifier-less hotkey that captures every bare keypress (e.g., pressing
`5` triggers window recording).

**`Zoomit.cpp`** — 4 hotkey registration sites:
- Guard `RECORD_CROP_HOTKEY` registration behind `(g_RecordToggleMod ^
MOD_SHIFT) != 0`
- Guard `RECORD_WINDOW_HOTKEY` registration behind `(g_RecordToggleMod ^
MOD_ALT) != 0`

```cpp
// Before (all 4 sites):
registerHotkey( RECORD_CROP_HOTKEY, ( g_RecordToggleMod ^ MOD_SHIFT ) | MOD_NOREPEAT, ... );
registerHotkey( RECORD_WINDOW_HOTKEY, ( g_RecordToggleMod ^ MOD_ALT ) | MOD_NOREPEAT, ... );

// After:
if ( g_RecordToggleMod ^ MOD_SHIFT ) {
    registerHotkey( RECORD_CROP_HOTKEY, ( g_RecordToggleMod ^ MOD_SHIFT ) | MOD_NOREPEAT, ... );
}
if ( g_RecordToggleMod ^ MOD_ALT ) {
    registerHotkey( RECORD_WINDOW_HOTKEY, ( g_RecordToggleMod ^ MOD_ALT ) | MOD_NOREPEAT, ... );
}
```

**`ZoomItViewModel.cs`** — `RecordToggleKeyCrop` /
`RecordToggleKeyWindow` computed properties:
- Return `null` when the derived hotkey would have no modifier keys, so
the Settings UI omits the inapplicable shortcut description rather than
displaying a bare-key shortcut.

## PR Checklist

- [ ] Closes: #xxx
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

ZoomIt registers crop and window recording variants by XOR-ing the base
modifier with `MOD_SHIFT` and `MOD_ALT` respectively. This design breaks
when the base modifier equals the XOR target — the result is `0`, and
`RegisterHotKey` with no modifiers intercepts every bare keypress of
that key system-wide.

The fix is symmetric across all 4 registration sites (standalone
`registerHotkey()` in `RegisterAllHotkeys`, the legacy dialog OK path,
and two `WM_CREATE`-adjacent paths): skip the derived hotkey
registration when the computed modifier is zero. The Settings UI
ViewModel mirrors this logic by returning `null` for the affected
computed properties, causing the converter to emit an empty string
instead of a modifier-less shortcut label.

## Validation Steps Performed

- Code review confirmed fix is applied consistently across all 4
`RegisterHotKey` call sites in `Zoomit.cpp`
- Verified `HotkeySettingsToLocalizedStringConverter` returns
`string.Empty` for `null` input — no display regression in Settings UI
- Confirmed the default `Ctrl+5` hotkey is unaffected (`MOD_CONTROL ^
MOD_ALT = MOD_CONTROL | MOD_ALT ≠ 0`)

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: MuyuanMS <116717757+MuyuanMS@users.noreply.github.com>
Co-authored-by: Muyuan Li (from Dev Box) <muyuanli@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-13 15:20:23 +08:00
Copilot
3e60249326 FancyZones Editor: Add translator comments for "Space around zones" and "Highlight distance" (#47226)
Two FancyZones Editor strings have misleading Japanese translations due
to ambiguous English phrasing:

- **"Space around zones"** → 「ゾーン周りのスペース」 (generic space/room) — should
be 「ゾーン周りの余白」 (margin/padding)
- **"Highlight distance"** → 「距離を強調表示」 (distance to visually emphasize)
— should be 「隣接するゾーンの検知距離」 (detection distance for adjacent zones)

## PR Checklist

- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

Changes to `FancyZonesEditor/Properties/Resources.resx`:

- **`Distance_adjacent_zones`** — Rewrote existing comment to explicitly
state this is a *detection/snapping proximity distance* (px at which a
nearby zone activates), not a visual-emphasis concept. Prevents
translators from reaching for 強調表示 ("visually highlight/emphasize").
- **`Space_Around_Zones`** — Added comment clarifying this is
*padding/margin* (empty gap in pixels) between zones, not a generic
space/area. Guides translators toward 余白 over スペース.
- **`Show_Space_Zones`** — Added comment clarifying this is a toggle for
enabling/disabling the padding display.

```xml
<data name="Distance_adjacent_zones" xml:space="preserve">
  <value>Highlight distance</value>
  <comment>The pixel distance at which an adjacent zone highlights (lights up) when a window is dragged near it. This is about detection/snapping range proximity, not about making something visually stand out.</comment>
</data>

<data name="Space_Around_Zones" xml:space="preserve">
  <value>Space around zones</value>
  <comment>The size (in pixels) of the padding or margin (empty gap) surrounding each zone. This is about blank space/whitespace between zones, not an area or region.</comment>
</data>
```

## Validation Steps Performed

Verified `Resources.resx` is well-formed XML and that the modified
entries render correctly in the resource file. No runtime behavior is
changed — comments are translator-only metadata consumed by the
Touchdown Build localization pipeline.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
2026-05-13 14:20:33 +08:00
Copilot
af1c0a313c Fix Korean mistranslation of "Activation modifier key" in Grab And Move settings (#47352)
The Korean translation of "Activation modifier key"
(`GrabAndMove_ModifierKey.Header`) was rendered as "정품인증 보조키" ("product
authentication/genuine certification modifier key") — conflating feature
activation with Windows product licensing. The correct translation is
"활성화 보조 키".

## Change

- **`src/settings-ui/Settings.UI/Strings/en-us/Resources.resw`**:
Expanded the `<comment>` on `GrabAndMove_ModifierKey.Header` to
explicitly disambiguate "Activation" for translators:

```xml
<comment>Drop-down to choose which modifier key (Alt or Win) activates Grab And Move drag and resize.
"Activation" here means to enable/trigger the feature (활성화 in Korean),
NOT product authentication/genuine certification (정품인증 in Korean).</comment>
```

## PR Checklist

- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

The word "Activation" is ambiguous in Korean: it can refer to Windows
product license activation (정품인증) or feature enablement (활성화). The
localization pipeline picked the wrong interpretation. Adding an
explicit in-source comment with both the correct and incorrect Korean
terms guides the translation tooling and human reviewers to use "활성화 보조
키" going forward.

## Validation Steps Performed

- Verified the updated comment appears correctly in the `.resw` file.
- No runtime behavior changes; comment-only modification to the resource
file.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
2026-05-13 14:20:20 +08:00
Copilot
3b76597981 Power Display: Add "do not translate" comments to all product name references (#47351)
The German locale translated the system tray tooltip `AppName` ("Power
Display") to "Leistungsanzeige", despite the Settings UI keeping the
utility name untranslated. The affected resource entries had no
translator guidance, so "Power Display" was treated as a localizable
phrase rather than a fixed product name. This PR adds consistent "do not
translate" comments across all touchpoints in both resource files.

## Summary of the Pull Request

- `src/modules/powerdisplay/PowerDisplay/Strings/en-us/Resources.resw`:
Added `Product name, do not translate.` comment to the `AppName` entry
(system tray tooltip)
- `src/settings-ui/Settings.UI/Strings/en-us/Resources.resw`: Added
`{Locked="Power Display"}` comments to all 15 entries containing "Power
Display" — including the module title, enable/toggle/open/launch
strings, OOBE title/description/activation text, LearnMore link,
QuickProfiles description, group header, and flyout header — following
the same convention already used for FancyZones and other product names
in that file

## PR Checklist

- [ ] **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
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

The system tray tooltip is populated via `GetString("AppName")` in
`TrayIconService.cs`. Because the resource had no comment, translators
localized "Power Display" as a common phrase ("performance display")
rather than treating it as a fixed product name.

To ensure consistency across all touchpoints, `{Locked="Power Display"}`
comments have been added to every entry in the Settings UI resource file
that contains the product name, matching the convention already in use
for `Shell_PowerDisplay.Content` (`Product name: Navigation view item
name for Power Display`) and for other utilities such as FancyZones
(`{Locked="FancyZones"}`).

## Validation Steps Performed

Verified that all `AppName` and Settings UI resource entries containing
"Power Display" now carry the appropriate translator comment. No runtime
behavior changes — the English values are unchanged; the comments solely
guide translators to leave the product name as-is in all locales.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
2026-05-13 14:20:02 +08:00
Dave Rayment
e193509e65 [Settings] Fix double-period suffix for "No shortcuts to show" message (#47287)
The nittiest of nits: "No shortcuts to show.." message should be "No
shortcuts to show." when no modules are enabled.

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

<!-- 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
This one is pretty self-explanatory.

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

<img width="240" height="141" alt="image"
src="https://github.com/user-attachments/assets/a036d345-dc1d-4040-9111-187619453dcd"
/>
2026-05-12 10:19:03 +00:00
Copilot
a33f984027 Add Refresh Connections (Mouse Without Borders) to Quick Access (#46025)
## Summary of the Pull Request

Adds the Mouse Without Borders "Refresh connections" action to both the
Quick Access tray flyout and the Settings Dashboard, so users can
trigger a reconnect without navigating into MWB settings.

## PR Checklist

- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

### Quick Access flyout (`Settings.UI.Controls`)

- **`QuickAccessViewModel`**: Added `MouseWithoutBorders` to
`InitializeItems()`; tooltip shows the configured `ReconnectShortcut`.
- **`QuickAccessLauncher`**: Added `case ModuleType.MouseWithoutBorders`
— signals `MWBReconnectEvent` (same named Windows event used by the
CmdPal `MWBReconnectCommand`).

### Settings Dashboard (`Settings.UI`)

- **`DashboardViewModel`**: Added `GetModuleItemsMouseWithoutBorders()`
returning a `DashboardModuleButtonItem` wired to a new
`MouseWithoutBordersReconnectClicked` handler that fires
`MWBReconnectEvent`. Added the module to the `GetModuleItems()` switch.
Added `using System.Threading` and `using PowerToys.Interop`.

No new strings — reuses existing
`MouseWithoutBorders_ReconnectButton.Text` ("Refresh connections") and
`MouseWithoutBorders_ReconnectTooltip.Text` for the button label and
description.

## Validation Steps Performed

- Verified `MWBReconnectEvent` is the same event used by
`MWBReconnectCommand` in the CmdPal extension.
- Confirmed `MouseWithoutBorders.png` icon exists in
`Assets/Settings/Icons/`.
- Confirmed `PowerToys.Interop` is already referenced by
`PowerToys.Settings.csproj`.

> [!WARNING]
>
> <details>
> <summary>Firewall rules blocked me from connecting to one or more
addresses (expand for details)</summary>
>
> #### I tried to connect to the following addresses, but was blocked by
firewall rules:
>
> - `o3svsblobprodcus318.vsblob.vsassets.io`
> - Triggering command: `/usr/bin/dotnet dotnet build
Settings.UI/PowerToys.Settings.csproj -c Debug` (dns block)
>
> If you need me to access, download, or install something from one of
these locations, you can either:
>
> - Configure [Actions setup
steps](https://gh.io/copilot/actions-setup-steps) to set up my
environment, which run before the firewall is enabled
> - Add the appropriate URLs or hosts to the custom allowlist in this
repository's [Copilot coding agent
settings](https://github.com/microsoft/PowerToys/settings/copilot/coding_agent)
(admins only)
>
> </details>

<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

> 
> ----
> 
> *This section details on the original issue you should resolve*
> 
> <issue_title>Add Refresh Connections (from Mouse Without Borders) to
Quick Access</issue_title>
> <issue_description>### Description of the new feature / enhancement
> 
> As per subject ... add Refresh Connections (_from Mouse Without
Borders_) to Quick Access
> 
> ### Scenario when this would be used?
> 
> There are a number of scenarios (_in my use case_) where I have one of
my machines connected to a business VPN .... which in 90% of the cases
triggers a small network drop resulting in the machine dropping off
mouse w/o borders - a refresh connections fixes it - but is currently a
bit annoying to get to.
> 
> ### Supporting information
> 
> _No response_</issue_description>
> 
> ## Comments on the Issue (you are @copilot in this section)
> 
> <comments>
> </comments>
> 


</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes microsoft/PowerToys#45935

<!-- START COPILOT CODING AGENT TIPS -->
---

🔒 GitHub Advanced Security automatically protects Copilot coding agent
pull requests. You can protect all pull requests by enabling Advanced
Security for your repositories. [Learn more about Advanced
Security.](https://gh.io/cca-advanced-security)

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
Co-authored-by: Niels Laute <niels.laute@live.nl>
2026-05-12 10:08:42 +00:00
Muyuan Li
be1f9dd2d8 Add auto-label-product GitHub Action for issue triage (#47485)
## Summary

Adds a GitHub Action workflow that **automatically applies `Product-*`
labels** to issues, reducing manual triage effort.

### How it works

**Two-tier approach:**
1. **Deterministic mapping** — Parses the structured "Area(s) with
issue?" dropdown from bug report templates and maps selections to the
correct `Product-` label via a hardcoded lookup table.
2. **AI inference (Copilot fallback)** — When no product is resolved
from the structured field (e.g., feature requests without the area
field), calls GitHub Models API (`gpt-4.1-mini`) to infer the product
from issue title + body.

### Trigger modes

| Trigger | Use case |
|---------|----------|
| `issues: [opened]` | Auto-labels every new issue |
| `workflow_dispatch` (single) | Test on one specific issue with dry-run
|
| `workflow_dispatch` (batch) | Process all open issues missing Product-
labels |

### Safety features
- **Label validation** — checks each label exists in the repo before
applying
- **Dry-run mode** — logs what would happen without modifying issues
- **Concurrency control** — prevents duplicate runs
- **Conservative AI prompt** — only labels products the issue is
*primarily* about

### Testing performed

Tested locally against 10 real issues with `Needs-Triage` and no
`Product-*` label:
- **6/10 resolved deterministically** (correct labels applied via `gh
issue edit`)
- **4/10 tested AI inference** via GitHub Models API:
  - #47482 (CmdPal Dock) → `Product-Command Palette` 
  - #47474 (grab and move + fancy zones) → `Product-FancyZones` 
  - #47476 (modular download) → `[]` (correctly abstained) 
- #47478 (Quick Access pinning) → improved prompt to avoid over-labeling

### Files changed

| File | Purpose |
|------|---------|
| `.github/workflows/auto-label-product.yml` | The GitHub Action |
| `.github/policies/resourceManagement.yml` | Removed redundant
Workspaces-only regex rule |
| `tools/Test-AutoLabelProduct.ps1` | Local PowerShell test script for
dry-run testing |

### Mapping validated against actual repo labels
Confirmed all label names in the mapping exist in the repo via `gh label
list --search "Product-"`.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-12 11:36:08 +02:00
Copilot
14f2ac1b78 Add AI-powered recurring workflow to auto-label new issues by area (#47808)
## Summary of the Pull Request

Adds a GitHub Actions workflow that fires on every new/reopened issue
and uses `gpt-4o-mini` (via GitHub Models) to classify the issue and
apply the correct `Product-*` / `Area-*` label(s) automatically. Also
adds a `workflow_dispatch` path so maintainers can manually backfill
labels on existing untriaged issues by supplying a comma-separated list
of issue numbers.

## PR Checklist

- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

**New file:** `.github/workflows/auto-label-issues.yml`

- **Trigger:** `issues: [opened, reopened]` for the automatic path;
`workflow_dispatch` with an `issue_numbers` input (comma-separated) for
manual backfill
- **Model call:** issue title + body (≤4 000 chars) → `gpt-4o-mini` at
the GitHub Models inference endpoint (`models.inference.ai.azure.com`);
uses `GITHUB_TOKEN` — no extra secrets required; `temperature: 0` for
deterministic output
- **Safety:** model output is filtered through a hard-coded allow-list
of 37 `Product-*` / `Area-*` labels before any API call — hallucinated
labels are dropped silently
- **Permissions:** `models: read` + `issues: write` only (same
minimal-permission pattern as the existing dedup workflow)
- **Concurrency:** per-issue group for automatic events; per-run-ID for
manual dispatch — prevents races without blocking unrelated runs

## Validation Steps Performed

- Manually triggered via `workflow_dispatch` against several untriaged
issues; step logs confirmed correct JSON output from the model and
matching labels applied via the GitHub Issues API.
- Verified the allow-list filter correctly discards any label not in the
predefined set.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
Co-authored-by: Niels Laute <niels.laute@live.nl>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-12 10:07:59 +02:00
moooyo
3796b244e5 [PowerDisplay] Pre-classify internal/external displays at discovery (#47740)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

Adds an explicit Phase 0 classification step in `MonitorManager` that
uses `DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY` (from `QueryDisplayConfig`)
to label every connected display as **internal** (built-in) or
**external** before any controller runs. Each controller is then
dispatched a strictly-scoped target list:
- **WMI controller** → only internal displays
- **DDC/CI controller** → only external displays

Two practical wins:
1. **Performance** — DDC/CI's ~4-second I2C capabilities probe (per
monitor) is now skipped entirely for internal laptop panels, which never
respond to DDC/CI in the first place. On a typical laptop with one
built-in panel + one external monitor, discovery is noticeably faster.
2. **Layering** — `WmiController` no longer reaches into the
`Drivers/DDC/` namespace to call
`DdcCiNative.GetAllMonitorDisplayInfo()`. Both controllers receive their
input from `MonitorManager` via a single `QueryDisplayConfig` call.

Strict classification is enforced: a display classified as internal but
not returned by `WmiMonitorBrightness` is dropped + logged (Warning),
with **no fallback to DDC/CI**. This is a deliberate design choice — the
spec discusses the trade-off in detail.

Adds a Phase 0 classification log (Info level) so misclassifications are
diagnosable from logs alone:
```
[DisplayClassification] Found 2 displays:
  [Path 1] \\.\DISPLAY1 / "Built-in display": OutputTechnology=0x80000000 → Internal
  [Path 2] \\.\DISPLAY2 / "Dell U2723QE": OutputTechnology=10 → External
[DisplayClassification] Summary: 1 internal, 1 external
```

The classification rule (in `DisplayClassifier.IsInternal`) is
deliberately conservative — misclassifying an external display as
internal would silently drop it from DDC/CI discovery with no fallback,
so we err on the side of external:
- **Internal**: the bare `INTERNAL` flag (`0x80000000`) alone, the
`INTERNAL` flag combined with a documented embedded subtype
(`DISPLAYPORT_EMBEDDED` 11 or `UDI_EMBEDDED` 13), or one of those
embedded subtypes on its own
- **External**: everything else, including the `INTERNAL` flag combined
with an undocumented subtype (HDMI, DP_EXTERNAL, MIRACAST, etc.)
- LVDS (6) is intentionally **not** classified internal — the [Microsoft
docs](https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ne-wingdi-displayconfig_video_output_technology)
describe it only as a connector type, not as an internal-display marker

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Yu Leng <yuleng@microsoft.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-12 16:07:40 +08:00
Niels Laute
5b981666a9 Adding missing telem events to DATA AND PRIVACY.md (#47228)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

Adding missing Grab And Move and Power Display events

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-05-11 12:16:08 +01:00
Gordon Lam
8864e64c97 Bump WindowsAppSDK to 2.0.1 (#47470)
## Summary of the Pull Request

Bumps `Microsoft.WindowsAppSDK` (and split sub-packages) from
**`1.8.260209005`** to public NuGet''s **`2.0.1`** GA, plus the
centrally-pinned `Microsoft.Web.WebView2` to **`1.0.3719.77`** to
satisfy the new transitive requirement from
`Microsoft.WindowsAppSDK.WinUI 2.0.12`.

This is the minimum mechanical version-bump set required for the
WinAppSDK 2.0 upgrade ΓÇö no API migration or behavioral changes.
Subsequent commits on this branch will address breaking-change
migrations as they surface.

NuGet source-of-truth used to pick sub-package versions: WinAppSDK 2.0.1
catalog `dependencyGroup`
(https://api.nuget.org/v3/catalog0/data/2026.04.29.22.25.36/microsoft.windowsappsdk.2.0.1.json).

## Detailed Description of the Pull Request / Additional comments

### Scope

| Package | Pinned |
|---|---|
| `Microsoft.WindowsAppSDK` | `2.0.1` | 
| `Microsoft.WindowsAppSDK.Foundation` | `2.0.20` | 
| `Microsoft.WindowsAppSDK.AI` | `2.0.185` | 
| `Microsoft.WindowsAppSDK.Runtime` | `2.0.1` | 
| `Microsoft.Web.WebView2` | `1.0.3719.77` | 

## Validation Steps Performed

`tools\build\build-essentials.cmd` results on the temp branch (x64
Debug, VS 2026 Insiders 14.51.36231):

| Stage | Errors | Warnings | Time |
|---|---|---|---|
| `PowerToys.slnx` NuGet restore | **0** | 0 | 1:05 |
| Native C++ `src\runner\runner.vcxproj` | **0** | 0 | 4:08 |
| Managed `src\settings-ui\Settings.UI\PowerToys.Settings.csproj` |
**0** | 0 | 3:35 |

Exit code: **0**. The end-to-end `build-essentials` flow passes locally
ΓÇö the WinAppSDK 2.0 upgrade is verified to compile against the runner
+ Settings.UI projects.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-11 10:36:16 +02:00
Copilot
df41e322d1 README: fix broken Roadmap reference link for v0.100 (#47785)
## Summary of the Pull Request

The Roadmap entry in `README.md` used a reference-style link
(`[v0.100][github-next-release-work]`) without a matching reference
definition, causing it to render as plain text. This change restores the
missing definition so the roadmap item renders as a clickable link.

## PR Checklist
- [ ] Closes: #47668
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

- **Roadmap link fix**
  - Added the missing Markdown reference definition in `README.md`:
    ```md
[github-next-release-work]:
https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.100%22
    ```
- **Rendering impact**
- `Stay tuned for [v0.100][github-next-release-work]!` now resolves to a
proper hyperlink in GitHub-rendered Markdown.

## Validation Steps Performed

Documentation-only change; validation focused on confirming
reference-style links in `README.md` are fully defined.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
2026-05-11 16:22:01 +08:00
Niels Laute
0e766bcafa [PowerDisplay] Debounced + wheel-scrollable brightness/contrast/volume sliders (#47756)
## Summary of the Pull Request

The brightness / contrast / volume sliders in the PowerDisplay flyout
previously committed to hardware (DDC/CI) only on `PointerCaptureLost`
plus arrow-key `KeyUp`. That doesn't work reliably on touchscreens —
tap-on-track issues no pointer capture, and the Slider / Thumb doesn't
always bubble `PointerCaptureLost` on touch — so the value the user
dialed in never reached the monitor.

This PR replaces that wiring with the simpler approach we actually
wanted: a TwoWay `Value` binding plus a debounced commit in the
view-model. `ValueChanged` runs the setter on every move, but a 200 ms
`DispatcherQueueTimer` (restarted on each change) collapses the entire
interaction into a single DDC/CI write once the user stops sliding.
Mouse, touch, tap-on-track, and held arrow keys all use the same code
path.

It also adds a small `SliderExtensions` helper (Toolkit-style attached
properties) so the brightness / contrast / volume sliders can be
adjusted by mouse-wheel scroll. The wheel event is marked handled so the
parent `ScrollViewer` does not also scroll, and the existing 200 ms
debounce coalesces wheel input into a single DDC/CI write.

## PR Checklist

- [x] Closes: #47724
- [x] **Communication:** I've discussed this with core contributors
already.
- [x] **Tests:** Manual smoke; no automated coverage exists for the
slider flyout.
- [x] **Localization:** No new end-user-facing strings.
- [x] **Dev docs:** N/A
- [x] **New binaries:** N/A
- [x] **Documentation updated:** N/A

## Detailed Description of the Pull Request / Additional comments

### Debounced commit

- `MonitorViewModel.Brightness/Contrast/Volume` setters now: assign
field → `OnPropertyChanged()` → `ScheduleCommit(...)` which (re)starts a
per-metric `DispatcherQueueTimer`. On `Tick` the closure calls
`SetBrightnessAsync(_brightness)` (etc.), reading the latest field value
so intermediate drag values are coalesced into one hardware write.
- `SetBrightnessAsync` / `SetContrastAsync` / `SetVolumeAsync` (used by
hotkeys, profile load, hardware refresh) keep their immediate-apply
behavior — they bypass the public setters, so a TwoWay source-update
from one of those paths does **not** reschedule a commit.
- `MonitorViewModel.Dispose()` stops the three timers. Pending writes
are intentionally dropped: `Dispose` only runs when the monitor is gone
(unplug / refresh) or the app is shutting down, in which case a hardware
write would race a half-torn-down `MonitorManager`.
- `AppConstants.UI.SliderCommitDebounceMs = 200` is the single source of
truth for the delay.
- Removed the six
`Handle{Brightness|Contrast|Volume}{PointerCaptureLost|KeyUp}` methods
and the now-unused `IsArrowKey` helper.
- `using DispatcherQueueTimer =
Microsoft.UI.Dispatching.DispatcherQueueTimer;` alias avoids ambiguity
with `Windows.System.DispatcherQueueTimer`.

### Wheel-scrollable sliders

- New `PowerDisplay.Helpers.SliderExtensions` — a Toolkit-style `public
static class <Control>Extensions` with two attached properties:
- `SliderExtensions.IsMouseWheelEnabled` (bool) — opt in to wheel input.
- `SliderExtensions.MouseWheelChange` (double, default `NaN` → falls
back to the slider's own `Slider.SmallChange`) — per-notch delta.
- Handler computes `notches = MouseWheelDelta / 120`, clamps to
`[Minimum, Maximum]`, sets `Value`, and marks `e.Handled = true` so the
enclosing `MainScrollViewer` doesn't also scroll.
- Wired on the brightness, contrast, and volume sliders with
`MouseWheelChange="5"` (20 notches for a full sweep).
- Body has zero PowerDisplay-specific dependencies (only
`Microsoft.UI.Xaml.*`) so the helper is straightforward to lift into the
WinUI Community Toolkit later.

## Validation Steps Performed

- `tools/build/build.cmd` against
`src/modules/powerdisplay/PowerDisplay/PowerDisplay.csproj` — exit code
0.
- Manual smoke on a touchscreen device:
  - Touch drag thumb 50 → 80, lift finger → monitor commits once at 80.
  - Tap on the track at 25 % → monitor commits once at 25 %.
- Manual smoke with mouse:
  - Drag 50 → 80, release → exactly one DDC/CI write at 80.
- Manual smoke with keyboard:
- Hold Right arrow on the brightness slider → repeated nudges collapse
into a single write 200 ms after key release.
- Manual smoke with mouse wheel:
- Hover brightness slider, scroll wheel → value moves by 5 per notch,
monitor commits once after scrolling stops.
- Wheel over a slider does **not** scroll the flyout's
`MainScrollViewer`; wheel outside the sliders still scrolls.
  - Wheel past `Minimum` / `Maximum` clamps at the boundary.
- Hotkey-driven brightness change still applies immediately (regression
check on the `SetBrightnessAsync` path).
- `DisplayChangeWatcher`-driven hardware refresh does not schedule a
spurious commit.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-11 15:15:47 +08:00
Niels Laute
a650504640 [Image Resizer] A11y fixes (#47752)
This PR solves the following issues:

- Narrator announced the Resize button as 'button', now it's 'resize'.
- The app window was still 'WinUI Desktop', it's now 'Image Resizer'
2026-05-08 20:57:02 +02:00
Mike Griese
d6e27ae10b CmdPal: when a band item updates, update the tooltip too (#47557)
Binding is hard.

The tooltip is bound to `.Tooltip`. But we forgot to raise a property
changed event for `Tooltip` when title or subtitle change.

Closes: issue filed on teams
2026-05-08 11:01:02 -05:00
moooyo
3d96d52564 [PowerDisplay] Fix brightness/contrast/volume on monitors with native max != 100 (#47679)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

Fixes #47458 — on monitors that advertise a non-100 raw VCP maximum
(e.g. Samsung S27DG602SN reports 50), the DDC controller was writing the
slider's 0–100 percentage directly as the raw VCP value. Anything above
the device's max was silently clamped, so only the bottom half of the
brightness / contrast / volume sliders had any visible effect.

The same root cause affects all three continuous-range VCPs (0x10
brightness, 0x12 contrast, 0x62 volume).

- Capture the device-reported `max` at discovery into new
  `Monitor.{Brightness,Contrast,Volume}VcpMax` fields.
- Add `VcpFeatureValue.FromPercentage(percent, max, min)` as the
  symmetric inverse of the existing `ToPercentage()`.
- Scale percent → raw inside `DdcCiController.Set{Brightness,Contrast,
  Volume}Async` before each `SetVCPFeature` call.
- WMI is unaffected — Windows already standardises WMI brightness to
  0–100.

The whole stack above the controller (ViewModel, MonitorManager, slider,
settings persistence, IPC) stays in the percent domain. The only place
percent ↔ raw conversion happens is the controller boundary.

#47458

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

- [x] Closes: #
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Yu Leng <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 15:26:07 +08:00
moooyo
95b70555bb [PowerDisplay] Stable monitor Id + survive transient discovery failures (#47712)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

Fixes #47665 — users report the per-monitor "Show input source control"
/ "Show power state control" toggles silently revert to off over time.
Three independent log captures pin the root cause to two layers in
`MainViewModel`:

- **Data-loss layer**: `SaveMonitorsToSettings` rebuilds
`settings.Properties.Monitors` from the currently-discovered list and
only re-adds entries with `IsHidden=true`. Whenever monitor discovery
transiently fails (DDC `GetPhysicalMonitors` NULL handle, DDC `empty
capabilities string`, WMI 4200 — all common in production logs),
affected monitors get **deleted** from settings.json. Next successful
discovery initialises them with the post-#47303 defaults
(`EnableInputSource=false`, `EnableColorTemperature=false`,
`EnablePowerState=false`), and `ApplyPreservedUserSettings` cannot
recover what is no longer there.
- **Identity layer**: `Monitor.Id` is
`{Source}_{EdidId}_{MonitorNumber}` — `EdidId` is not unique for
identical-model monitors, and `MonitorNumber` is OS-assigned and changes
after sleep/wake / GPU reset / display reorder. Even fixing the
data-loss layer would still apply preserved settings to the wrong
physical monitor for users with multiple identical displays.

This PR addresses both layers:
- **30-day retention** — `MonitorSettingsRebuilder` (in
`PowerDisplay.Lib`) replaces the inline `IsHidden`-only loop.
Currently-discovered monitors get a fresh `LastSeenUtc` stamp;
missing-but-recent (< 30 days) entries are preserved with all `Enable*`
flags intact; missing-and-stale entries are dropped with a single info
log. `IsHidden=true` entries are still preserved unconditionally.
- **DevicePath-based Id** — `Monitor.Id` is now the Windows `DevicePath`
minus the trailing device-class GUID (e.g.
`\\?\DISPLAY#DELD1A8#5&abc&0&UID12345`). The middle PnP-instance segment
is unique per (physical device × physical port) and stable across
reboots, sleep/wake, and OS-level reordering —
`MonitorDisplayInfo.DevicePath` already carries this value from
`QueryDisplayConfig`; it just wasn't being used as the Id.

The order of commits keeps the app behaviourally identical to today
through the first 8 commits (only adds dormant helpers / fields /
wiring); the actual ID-format flip is the very last commit.
Bisect-friendly.


#47599


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

- [x] Closes: #
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Yu Leng <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 15:25:40 +08:00
Alex Mihaiuc
2aedb932e5 Add aspect ratio checkbox to ZoomIt UI (#47695)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Exposes the 16:9 aspect ratio toggle for the ZoomIt screen region
recording (default: `Ctrl`+`Shift`+`5`) in the settings UI.

<img width="1047" height="817" alt="image"
src="https://github.com/user-attachments/assets/4117a6a1-9f57-44c5-9a21-1b1b65bc2992"
/>

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Checked that the toggle works and that it's compatible with the
standalone ZoomIt, too.
2026-05-06 10:22:26 -07:00
Gordon Lam
f0c9a17fd1 [GPO]Bump en-US ADML revision to 1.20 to match ADMX (fixes #47645) (#47672)
## Summary

Fixes #47645.

The ADMX policy definition (`src/gpo/assets/PowerToys.admx`) declares
`revision="1.20"` and `<resources minRequiredRevision="1.20"/>`, but the
en-US ADML language resource (`src/gpo/assets/en-US/PowerToys.adml`) was
still at `revision="1.19"`. Group Policy Editor refuses to load the
PowerToys template because the language resource does not meet the
minimum required revision, producing the error reported in the issue.

## Change

Bump `revision` on the `policyDefinitionResources` root element of
`PowerToys.adml` from `1.19` to `1.20` so it matches the ADMX
`minRequiredRevision`.

## Validation

- Diffed against `src/gpo/assets/PowerToys.admx` to confirm the
revisions now align (both `1.20`).
- Documentation/asset-only change; no code build required.

## PR Checklist

- [x] Closes #47645
- [x] Tests added/passed — N/A (asset-only revision bump)
- [x] Requires documentation to be updated — No
- [x] I know how to test these changes — Open `gpedit.msc` and confirm
PowerToys policies load without the resource-version error.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-06 05:33:22 +00:00
Boliang Zhang
a2892cd993 [ZoomIt] Remove stale WIL package import from ZoomItBreak.vcxproj (#47649)
## Summary of the Pull Request
ZoomItBreak.vcxproj contained a leftover Import of
Microsoft.Windows.ImplementationLibrary.targets pinned to version
1.0.231216.1, plus the matching EnsureNuGetPackageBuildImports guard.
The project has no packages.config and its source files
(BreakTimer.cpp/.h, ZoomItBreakScr.cpp) include no wil headers, so the
import was dead code copy-pasted from ZoomIt.vcxproj when the
screensaver project was introduced in #46506.

Until PR #41280 (.NET 10 upgrade), the sibling ZoomIt project restored
WIL 1.0.231216.1 via its own packages.config, so the folder
coincidentally existed and the stale Import silently succeeded. PR
#41280 bumped that dependency to 1.0.260126.7, leaving nothing in the
repo that requests the old version. NuGet no longer creates the
1.0.231216.1 folder, the EnsureNuGetPackage target fires, and the
official build fails with:

  ZoomItBreak.vcxproj(227,5): Error : This project references
  NuGet package(s) that are missing on this computer ...
  Microsoft.Windows.ImplementationLibrary.1.0.231216.1\...targets

Fix: drop the unused import and guard target. Verified by clean rebuild
of x64 Release and ARM64 Release; ZoomItBreak64.scr / ZoomItBreak64a.scr
produced with empty error logs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-06 12:03:09 +08:00
Alex Mihaiuc
b93fd97e80 Add ZoomIt webcam and append clip functionality (#47529)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
This adds the capability to include a webcam in the ZoomIt recording.
Also, the trim editor now supports appending multiple clips with
selectable transitions.

<img width="451" height="570" alt="image"
src="https://github.com/user-attachments/assets/025a7840-2e40-424c-af57-5ed523af8646"
/>

Also fixed some minor bugs in the ZoomIt settings within PowerToys and
added the options there, too.

<img width="1556" height="962" alt="image"
src="https://github.com/user-attachments/assets/dfe4209c-1b59-47c3-9170-36832d37f880"
/>

There was a bug in the microphone selection, fixed it together with the
webcam selection dialog, too.

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

- [x] Closes: #47230 
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: markrussinovich <markrussinovich@users.noreply.github.com>
Co-authored-by: Copilot <copilot@github.com>
2026-05-05 23:52:43 +02:00
Jeremy Sinclair
b4820c01cb [Deps] Upgrade .NET Runtime package versions to 10.0.7 (#47517)
Updated package versions for multiple dependencies to 10.0.7 to
remediate security vulnerabilities
2026-05-01 17:07:32 -05:00
Niels Laute
87b6ca0ab6 Revise download instructions and release notes link (#47432)
Updated instructions for downloading the .exe file and release notes
link.

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-04-30 17:30:36 +02:00
Gordon Lam
1744bdecd8 build: discover VS 2026 Insiders and exclude BuildTools in vswhere lookup (#47462)
## Summary of the Pull Request

Fixes `tools\build\build-common.ps1` so a clean
`tools\build\build-essentials.cmd` (or `build.ps1`) run discovers and
uses **Visual Studio 2026 Insiders** without any manual
`Enter-VsDevShell` preamble. Today the script lands on the first VS 2022
BuildTools instance it finds (which lacks the C++ workload) and every
native `.vcxproj` errors with `MSB4086: $(PlatformToolsetVersion)
evaluates to ""` during NuGet restore.

Two scoped commits, **only `tools\build\build-common.ps1` is touched**
(+58 / −36 net).

## PR Checklist

- [ ] Closes: #xxx
- [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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places (n/a — build-script
change only)
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

### What''s broken

`build-common.ps1`''s `vswhere` lookup runs **without `-prerelease`**,
so VS 2026 Insiders / Preview installs are invisible to it. The explicit
fallback path list also only contains VS 2022 entries. On a machine that
has VS 2022 BuildTools (typical for CI hosts and many dev boxes) but
only has VS 2026 in *Insiders* form, the script:

1. Picks `C:\Program Files (x86)\Microsoft Visual
Studio\2022\BuildTools` because it''s a candidate `vswhere` returned and
it''s in the fallback list.
2. Enters its DevShell — but BuildTools has no C++ workload installed,
so `$(VCToolsInstallDir)` and `$(PlatformToolsetVersion)` are unset.
3. NuGet restore over `PowerToys.slnx` fans out to every `.vcxproj` and
they each hit `Microsoft.CodeAnalysis.targets(401,15): error MSB4086: A
numeric comparison was attempted on "$(PlatformToolsetVersion)" that
evaluates to "" instead of a number, in condition
"''$(PlatformToolsetVersion)''<''120''".` The build dies before any
project compiles.

This was reproduced today against `origin/main` — confirming this is a
pre-existing breakage independent of any in-flight feature work.

### What this PR changes

Commit **`30acf72c` — Fix build scripts to discover VS 2026 / Insiders
installations**
- Adds `-prerelease` to `vswhere` calls, tried **before** the stable
lookup so prerelease VS is preferred when it''s the only one with a
working C++ workload.
- Adds VS 2026 year-name and internal-version (`18\Insiders`) paths to
the explicit fallback list.
- Keeps VS 2022 paths as the final fallback so existing setups keep
working.
- Priority order: `prerelease+VC tools` → `prerelease` → `stable+VC
tools` → `stable`.

Commit **`18b27209` — build: simplify VS environment initialization with
VS2022/VS2026 support**
- Adds `-prerelease` to `vswhere` (consolidates with the above; the
prerelease query subsumes the stable one now).
- Restricts the SKU query to `Community` / `Professional` / `Enterprise`
(explicitly excludes `BuildTools`) so the script can no longer
accidentally pick a SKU without the C++ workload.
- Reduces vswhere from **4 calls to 2**.
- Removes the destructive BuildTools env-var cleanup block (no longer
needed once vswhere refuses to return BuildTools in the first place).
- Adds `VsDevCmd.bat` exit-code validation so a partial DevShell init
fails loudly instead of silently producing a half-initialized
environment.
- Adds VS 2022 / VS 2026 Preview entries to the explicit fallback list.

### Why two commits instead of a squash

The first commit is the minimum-viable fix that addresses the reported
MSB4086 failure. The second commit is a follow-up cleanup that''s only
safe **once** prerelease is preferred and BuildTools is excluded.
Splitting them keeps each commit independently revert-able if a
regression shows up on a specific dev environment shape.

## Validation Steps Performed

| Step | Result |
|---|---|
| Reproduce on `main`: cold `tools\build\build-essentials.cmd` in a
non-DevShell PowerShell | **MSB4086** on
`Microsoft.CommandPalette.Extensions.vcxproj`,
`Microsoft.Terminal.UI.vcxproj`, `PowerToys.MeasureToolCore.vcxproj`,
`PowerRenameUI.vcxproj` — confirmed broken |
| With this branch checked out: same cold `build-essentials.cmd`
invocation | `[VS] vswhere found: ... C:\Program Files (x86)\Microsoft
Visual Studio\Installer\vswhere.exe` → `[VS] Checking candidate:
C:\Program Files\Microsoft Visual Studio\18\Insiders` → `[VS] Entered
Visual Studio DevShell at C:\Program Files\Microsoft Visual
Studio\18\Insiders` — VS 2026 Insiders selected directly, restore step
proceeds past the MSB4086 wall |
| Manual workaround pre-init via `Import-Module
Microsoft.VisualStudio.DevShell.dll` + `Enter-VsDevShell` | Now
**unnecessary** — the script self-initializes correctly |

After this fix, the next failure mode the build hits is unrelated NuGet
feed coverage for in-flight WinAppSDK upgrade work, which is the gated
dependency this PR was extracted from to keep this change atomic.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-30 14:55:43 +08:00
Jeremy Sinclair
05cd66c9bc [Dev][Build] .NET 10 Upgrade (#41280)
## Summary of the Pull Request
.NET 10 Upgrade. Requires Visual Studio 2026.


## PR Checklist

- [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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx


## Detailed Description of the Pull Request / Additional comments

- Upgraded target framework from `net9.0` to `net10.0` across all
projects
- Removed redundant package references now included by default in .NET
10
- Updated package versions to .NET 10 releases
- Modernized regex usage with source generators for better performance
- Added `vbcscompiler` to the spell-check allowlist
(`.github/actions/spell-check/expect.txt`)

## Validation Steps Performed

<!-- START COPILOT CODING AGENT TIPS -->
---

🔒 GitHub Advanced Security automatically protects Copilot coding agent
pull requests. You can protect all pull requests by enabling Advanced
Security for your repositories. [Learn more about Advanced
Security.](https://gh.io/cca-advanced-security)

---------

Co-authored-by: Jeroen van Warmerdam <jeronevw@hotmail.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-04-30 14:40:43 +08:00
Dustin L. Howett
cd15686416 ci: disable building of draft pull requests (#47442)
The influx of Copilot-originated pull requests has made it impossible
for our CI to keep up; this is in part because for some reason Copilot
is treated as a team member and therefore automatically scheduled for CI
on the build pool.
2026-04-29 13:27:41 -05:00
Boliang Zhang (from Dev Box)
184ccb75ec Merge origin/main into stable 2026-04-29 13:38:21 +08:00
moooyo
e6d346a59b [PowerDisplay] Default-off and confirm dialog for InputSource/ColorTemp/PowerState (#47303)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Three per-monitor PowerDisplay features have failure modes recoverable
only via physical buttons:

Input Source — switching to an input with no signal goes black;
PowerToys can no longer drive a panel that isn't displaying its own
signal
Color Temperature — some monitors apply changes that cannot be reset via
DDC/CI; OSD reset required
Power State — VCP 0xD6 standby may not respond to subsequent DDC/CI wake
commands
This PR:

Defaults all three features off for newly-discovered monitors. Supports*
derivation from VCP capabilities is unchanged — unsupported checkboxes
are still greyed out.
Pops a confirmation dialog when a user toggles any of them on in
Settings, mirroring the existing Color Temperature warning. Cancel
reverts the checkbox; Enable keeps it.
Refactors the existing Color Temperature click handler into a shared
HandleDangerousFeatureClickAsync(sender, resourceKeyPrefix, setter)
helper. All three feature handlers now reuse it.
Renames PowerDisplay_ColorTemperature_EnableButton →
PowerDisplay_Dialog_Enable so the three dialogs share one button-text
resource (paralleling the existing shared PowerDisplay_Dialog_Cancel)

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Yu Leng (from Dev Box) <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 13:35:12 +08:00
moooyo
2aece74831 [PowerDisplay] Use localized "Built-in Display" name for internal display (#47321)
Set all WMI monitor's name to "Built-in Display" to avoid confusing.

related discussion: #47255

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [ ] Closes: #
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Yu Leng (from Dev Box) <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Niels Laute <niels.laute@live.nl>
2026-04-29 13:34:34 +08:00
Alex Mihaiuc
7861bc408c Replay both key down and up for Win in GrabAndMove (#47326)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
The code for keyup on the `Win` key would replay the previously absorbed
keydown event and just leave this keyup to propagate normally, thus
leading to a race condition between `CallNextHookEx` and `SendInput`.
This resulted in almost guaranteed out-of-order event (`Win` up,
followed by `Win` down) in the case of `Win+G` (the Xbox Game bar
shortcut).

Fixed by also absorbing the keyup for `Win`, but calling `SendInput` for
both keydown and keyup.

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

- [x] Closes: #47293 
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-04-29 12:04:20 +08:00
Mike Griese
b835cde4d2 CmdPal: Fix a bug where dock label settings wouldn't save (#47317)
This setting is totally vestigial, from the 0.9 dev cycle. 

Unfortunately, the JSON parser would see that it wasn't in the
settings.json, then it would write `null` to it. But `ShowLabels` was
just a thin alias for `ShowTitles`, so we'd end up parsing totally sane
JSON settings into having `null` for `ShowTitle`.

This fixes that. You can hide your titles again folks.
2026-04-29 11:12:43 +08:00
Alex Mihaiuc
f79df0663c Skip desktop / explorer targets in GrabAndMove (#47302)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Added a few known Windows processes and window classes from desktop
elements to the implicit exclusion list, to avoid funny repositioning of
otherwise immovable content:

- The Windows Start menu.
- Tooltips from around the Notification Area (System Tray).
- The Alt-Tab and Win-Tab windows.
- Tooltips.

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Copilot <copilot@github.com>
2026-04-29 11:05:54 +08:00
Mike Griese
7211f7ed67 cmdpal: fix our settings load crash (#47296)
Fixes a category of crashes in CmdPal, related to our settings parsing. 

It would seem that I don't understand JSON parsing all that well in C#. 

Basically, we've got a bunch of places where we have
 
```c#
class Foo
{
  public Bar MySetting {get;init;} = new()
}
```

but when we JSON deserialize the settings, if there wasn't a
`"MySetting"` key, then the deserializer deserializes to `null`, not
`new()`. but since `Foo.MySetting` isn't a `Bar?`, then the compiler
can't check the fact that json _gets special rules to write a null to
it????_

Closes #47249

tested with the settings.json from that thread.
2026-04-28 12:24:27 -05:00
Alex Mihaiuc
215dfaf236 GrabAndMove release Alt key on other keypresses (#47261)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
When the Alt modifier is already pressed, "release" it on any other
interaction but the allowed mouse interactions.

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

- [x] Closes: #47257 
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
I ensured that pressing something like Shift, Ctrl, or even a character
key - besides Tab, of course, properly resets the internal state of Alt.
The win key was never affected by this behavior.

Co-authored-by: Copilot <copilot@github.com>
2026-04-28 17:40:00 +02:00
moooyo
f5a294bb66 [PowerDisplay] Add more log for PowerDisplay (#47270)
Users have reported missing monitors but the existing logs lack the
information needed to diagnose. Add discovery-phase logs that record the
raw MCCS capabilities string from the monitor, the parsed feature
support flags (brightness/contrast/color temperature/volume), the
specific reason a monitor is ignored, and DDC/CI API failures.

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Yu Leng (from Dev Box) <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 10:09:07 +00:00
Niels Laute
d10203b8ac Update README for PowerToys v0.99.0 release (#47227)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-04-28 14:01:18 +08:00
Boliang Zhang (from Dev Box)
455dc52430 Merge origin/main into stable 2026-04-26 21:05:06 +08:00
Niels Laute
fecd2e72a7 Handle DockSize enum changes (#47212)
### ⚠️ REVIEWERS TO DECIDE. MERGE THIS PR OR GO FOR: #47214⚠️

### Root cause

PR #46699 (compact mode) replaced the original `DockSize` enum
(`Small`/`Medium`/`Large`) with a new one (Default/Compact). Existing
users have `DockSize`: `Small` (or `Medium`/`Large`) in their
`settings.json`, which the source-generated EnumConverter can't parse →
the entire settings file fails to load.

### Fix

Added a custom `JsonConverter<DockSize>` in
_src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Settings/DockSettings.cs_
and applied it via `[JsonConverter]` on the enum.

The converter:

- Accepts current values (`Default`, `Compact`) — case-insensitive.
- Maps any unknown legacy string (e.g. `Small`/`Medium`/`Large`) to
`DockSize.Default`, preserving the user's existing visual experience.
- Tolerates numeric values too, falling back to `Default` if out of
range.
- Writes as a string so output stays consistent with the source-gen
`UseStringEnumConverter` setting.
2026-04-26 06:35:47 -05:00
Niels Laute
fde1599f7d [Grab And Move] Add touchpad compatibility InfoBar to settings page (#47213)
## Summary

Adds an informational InfoBar at the top of the Grab And Move settings
page noting that the utility may not work with some touchpads and is
intended to be used with a physical mouse device.

<img width="1180" height="460" alt="image"
src="https://github.com/user-attachments/assets/4999d2f5-c785-41ab-b5fc-9dd8b7e72c7d"
/>


## Changes

- `src/settings-ui/Settings.UI/SettingsXAML/Views/GrabAndMovePage.xaml`
— new `InfoBar` (Severity=Informational, IsClosable=False) placed at the
top of the page's `StackPanel`.
- `src/settings-ui/Settings.UI/Strings/en-us/Resources.resw` — added two
resource strings:
  - `GrabAndMove_TouchpadInfoBar.Title` — "Touchpad compatibility"
  - `GrabAndMove_TouchpadInfoBar.Message` — explanatory text.

Follows the existing InfoBar pattern (e.g., `MouseUtilsPage.xaml`).

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-25 21:25:10 +02:00
Alex Mihaiuc
c68003c678 Avoid MessageBox in ZoomIt in PowerToys (#47215)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
This stops the ZoomIt message boxes complaining about keyboard shortcut
conflicts - such conflicts are handled by the PowerToys settings window.

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

- [x] Closes: #47154
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Setting any ZoomIt shortcut to the same sequence as other shortcuts
won't produce the MessageBox anymore.

The easiest is to use the default shortcuts and to bind the last one,
**Panorama activation** to `Ctrl+7` (instead of the default `Ctrl+8`).
`Ctrl+7` clashes with the ZoomIt **DemoType activation** shortcut. To
make the MessageBox pop-out before the fix, takes pressing a few
`Ctrl+1`s (the default **Zoom activation**).

---------

Co-authored-by: Copilot <copilot@github.com>
2026-04-25 21:23:21 +02:00
Boliang Zhang
ed1d15f9a1 Fix: Install CommandPalette.Extensions.winmd to WinUI3Apps for COM marshalling (#47210)
## Summary

Follow-up fix for #47177. Installs `CommandPalette.Extensions.winmd` to
the `WinUI3Apps\` directory (ExternalLocation) instead of the root
install folder.

## Problem

PR #47177 moved the sparse package's `ExternalLocation` from root to
`WinUI3Apps\`, but the `CommandPalette.Extensions.winmd` was still
installed to root via `DirectoryRef=INSTALLFOLDER`. The WinRT runtime
needs this winmd in the ExternalLocation directory for COM proxy/stub
creation during cross-process CmdPal extension activation. Without it,
`CoCreateInstance` returns `E_NOINTERFACE` and the PowerToys extension
fails to load in Command Palette.

## Fix

Split the `BaseApplications.wxs` `DirectoryRef` into two blocks:
- **winmd component** -> `WinUI3AppsInstallFolder` (for WinRT COM
marshalling)
- **auto-generated components** -> `INSTALLFOLDER` (unchanged, avoids
ICE30 conflict with `WinUI3ApplicationsFiles`)

## Validation

- [x] Local WiX compilation: no ICE30 errors
- [x] ADO CI build 145429943 (v0.99.1): passed
- [x] Manual verification on 25H2: CmdPal loads 55 commands after winmd
placed in WinUI3Apps

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-25 23:48:22 +08:00
Boliang Zhang
e5b0667397 Fix: Install CommandPalette.Extensions.winmd to WinUI3Apps for COM marshalling (#47210)
## Summary

Follow-up fix for #47177. Installs `CommandPalette.Extensions.winmd` to
the `WinUI3Apps\` directory (ExternalLocation) instead of the root
install folder.

## Problem

PR #47177 moved the sparse package's `ExternalLocation` from root to
`WinUI3Apps\`, but the `CommandPalette.Extensions.winmd` was still
installed to root via `DirectoryRef=INSTALLFOLDER`. The WinRT runtime
needs this winmd in the ExternalLocation directory for COM proxy/stub
creation during cross-process CmdPal extension activation. Without it,
`CoCreateInstance` returns `E_NOINTERFACE` and the PowerToys extension
fails to load in Command Palette.

## Fix

Split the `BaseApplications.wxs` `DirectoryRef` into two blocks:
- **winmd component** -> `WinUI3AppsInstallFolder` (for WinRT COM
marshalling)
- **auto-generated components** -> `INSTALLFOLDER` (unchanged, avoids
ICE30 conflict with `WinUI3ApplicationsFiles`)

## Validation

- [x] Local WiX compilation: no ICE30 errors
- [x] ADO CI build 145429943 (v0.99.1): passed
- [x] Manual verification on 25H2: CmdPal loads 55 commands after winmd
placed in WinUI3Apps

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-25 15:22:49 +00:00
Boliang Zhang (from Dev Box)
31da4fa112 Merge origin/main into stable 2026-04-24 22:38:59 +08:00
Boliang Zhang
8536d7b1cd Fix MSIX sparse package DACL contamination breaking File Explorer preview handlers (#47177)
## Summary

Moves the MSIX sparse package's `ExternalLocation` from the PowerToys
root install folder to the `WinUI3Apps\` subfolder, isolating DACL
contamination from preview handler DLLs.

## Problem

On Windows 23H2/24H2/25H2, MSIX sparse package registration adds
AppContainer SIDs (`S-1-15-2-*` / `S-1-15-3-*`) to the DACL of the
`ExternalLocation` folder. Since `ExternalLocation` pointed to the
PowerToys root install folder, this broke File Explorer preview handlers
— `prevhost.exe` (running at LOW integrity) could no longer load preview
handler DLLs (`.txt`, `.md`, `.pdf`, `.svg`, etc.).

## Fix

- **`CustomAction.cpp`**: Changed `ExternalLocation` from
`installFolderPath` → `installFolderPath + L"WinUI3Apps\\"`
- **`AppxManifest.xml`**: Removed unused PowerOCR `<Application>` entry;
stripped `WinUI3Apps\` prefix from `Executable` paths (now relative to
new ExternalLocation)
- **`CmdPal.Ext.PowerToys.csproj`**: Moved `OutputPath` to `WinUI3Apps\`
so the AOT-compiled extension EXE resolves correctly under the new
ExternalLocation
- **WiX installer files**: Updated source/install paths for KBM assets,
CmdPal satellite assemblies, and `CommandPalette.Extensions.winmd` that
moved with the CmdPal output
- **ESRP signing**: Updated CmdPal dll/exe paths to include
`WinUI3Apps\` prefix

## Validation

| Test | 25H2 | 23H2 |
|------|------|------|
| DACL isolation (no S-1-15-* on root) |  |  |
| Preview handlers (.txt, .md, .pdf, .svg) |  |  |
| Peek |  |  |
| Context menus (PowerRename, FileLocksmith, ImageResizer, New+) |  | 
|
| Upgrade path (old → new) |  |  |

## Files changed (12)

- `installer/PowerToysSetupCustomActionsVNext/CustomAction.cpp` — core
fix
- `src/PackageIdentity/AppxManifest.xml` — manifest cleanup
-
`src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Microsoft.CmdPal.Ext.PowerToys.csproj`
— output path
-
`src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Helpers/PowerToysResourcesHelper.cs`
— icon path
- `installer/PowerToysSetupVNext/BaseApplications.wxs` — winmd source
path
- `installer/PowerToysSetupVNext/KeyboardManager.wxs` — KBM assets path
- `installer/PowerToysSetupVNext/Resources.wxs` — CmdPal satellite paths
- `installer/PowerToysSetupVNext/generateAllFileComponents.ps1` — scan
path
- `.pipelines/ESRPSigning_core.json` — signing paths
- `src/PackageIdentity/BuildSparsePackage.ps1` — dev script hint
- `src/PackageIdentity/readme.md` — docs
- `doc/devdocs/modules/cmdpal/powertoys-extension-local-development.md`
— docs

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-24 22:37:59 +08:00
Boliang Zhang (from Dev Box)
3ee7518850 Merge origin/main into stable 2026-04-24 22:34:19 +08:00
Niels Laute
7ac16118c8 Settings UX tweaks (#47197)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request


Before:
<img width="779" height="333" alt="image"
src="https://github.com/user-attachments/assets/92f7346f-11a3-4407-b26e-efc8196be59c"
/>

After:
<img width="766" height="268" alt="image"
src="https://github.com/user-attachments/assets/3d12676b-a245-4b53-8078-abcef4efbdab"
/>


Before:
<img width="766" height="310" alt="image"
src="https://github.com/user-attachments/assets/09e436da-317c-46e1-92c0-2c3200908b28"
/>


After:
<img width="772" height="175" alt="image"
src="https://github.com/user-attachments/assets/9f1024e5-0451-4577-b31f-366cde61d21c"
/>


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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-04-24 22:32:19 +08:00
Niels Laute
7508e6e794 Add CmdPal folder to installer (#47196)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-04-24 22:31:45 +08:00
Niels Laute
2d9dfff444 Fix for mouse jump crash (#47198)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-04-24 22:31:16 +08:00
Muyuan Li
9de2e5298a [GrabAndMove] excluded apps example text should use 'outlook' instead of 'outlook.exe' (#47194)
PR changes example text to outlook instead of outlook.exe, which can
match both old version and new version.

The placeholder text suggested 'outlook.exe', but new Outlook runs as
olk.exe so the .exe-based entry fails both path and title matching.
Using 'outlook' (without .exe) works correctly via window title
matching.

Fixes #47103

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [x] Closes: #47103
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-24 08:25:13 +00:00
Boliang Zhang (from Dev Box)
1bfa42b270 Merge origin/main into stable 2026-04-24 14:15:50 +08:00
Copilot
07beeca9b9 Add Grab And Move and Power Display to bug report area selector (#47168)
Adds missing module entries to the bug report issue template so
reporters can classify issues for Grab And Move and Power Display in the
existing **Area(s) with issue?** multi-select.

## Summary of the Pull Request

- **Issue template update**
- Extended `.github/ISSUE_TEMPLATE/bug_report.yml` dropdown options for
`Area(s) with issue?`.
  - Added:
    - `Grab And Move`
    - `Power Display`

```yaml
- type: dropdown
  attributes:
    label: Area(s) with issue?
    options:
      - FancyZones
      - FancyZones Editor
      - Grab And Move
      # ...
      - Peek
      - Power Display
      - PowerRename
```

## PR Checklist

- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

- **Scope**
  - Single-file, metadata-only change in the bug-report template.
- **Behavioral impact**
- Improves triage categorization for two modules that were not
previously selectable in the issue form.

## Validation Steps Performed

- Confirmed the issue template includes both new options under `Area(s)
with issue?`.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
2026-04-24 13:20:33 +08:00
Boliang Zhang
234933f6fa Add installer diagnostics guide for triaging update issues (#47105)
Step-by-step guide for diagnosing old update installer accumulation,
covering log files to check, UpdateState.json interpretation, and common
root causes.

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-04-24 06:56:41 +02:00
Boliang Zhang (from Dev Box)
e0979fce59 Merge origin/main into stable 2026-04-24 10:59:26 +08:00
Niels Laute
f8a10550f3 Update release notes skill (#47158)
Change the formatting from:

"PR description in #123. Thanks @user"

to

"PR description in #123 by @user"

----

this follows the GitHub release notes format and makes sure people are
correctly listed at the bottom of the release page
2026-04-24 10:56:32 +08:00
moooyo
ca1ffebc26 [Light Switch] Fix PowerDisplay profile integration (#47190)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

Fixes two bugs in the Light Switch ↔ PowerDisplay integration:

1. **Settings UI was hidden.** The "Apply monitor settings" expander
   (dark/light profile pickers) and the "PowerDisplay disabled"
   warning InfoBar were temporarily commented out in PR #46160. Users
   had no way to configure which profile to bind to each theme.

2. **Hotkey only applied one profile.** On every hotkey press
   ModuleInterface flips the Windows theme, but the service only
   notified PowerDisplay when `isManualOverride` toggled from `false`
   to `true`. Every even-numbered press was silently dropped, so the
   monitor profile stayed stuck on whichever direction the user
   pressed first.

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Yu Leng (from Dev Box) <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 10:55:45 +08:00
Boliang Zhang (from Dev Box)
b2684f74f5 Merge origin/main into stable 2026-04-24 10:55:14 +08:00
Josh Soref
2e5c7d2ee6 Refresh check-spelling 0.0.26 (#47119)
This is a refresh based on
976261d7b7

There are a couple of interesting new rules and I've extended one of the
patterns to all letters.

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2026-04-23 19:05:00 -05:00
Mike Griese
949e42c5c7 CmdPal: Fix crash when typing w/ indexer fallback on (#47186)
This isn't the same crash as #47148. It's another one.
Undoubtably regressed in #46907

The function signature was all wrong. Hence the
`System.ExecutionEngineException`

Tested manually.
2026-04-23 19:13:11 +00:00
Mike Griese
a65266fcad cmdpal: fix the dock window border being visible on startup (#47187)
This is worse after the compact mode change fixed our frame margins. We
hide our window frame with DWM. However, we only did that when we we
`Activated`. Turns out, when the window is first created? we're not
`Activated`. So until you focus another window, we'd look... objectively
bad.
2026-04-23 21:06:22 +02:00
Niels Laute
656ea91580 CmdPal: Enable dock pinning and per-profile icons for Windows Terminal (#46372)
## Summary of the Pull Request

Enables Windows Terminal profiles to be **pinned to the Command Palette
dock** and shows **per-profile icons** instead of the generic Terminal
app logo.

### Dock Pinning

**Root cause:** `LaunchProfileCommand.Id` was never set (defaulted to
`string.Empty`). The context menu factory checks
`!string.IsNullOrEmpty(itemId)` before showing "Pin to Dock", so the
option was silently hidden. Additionally, `GetCommandItem()` was not
overridden, so pinned commands could not be resolved on load.

**Fix:**
- Set stable `Id` on `LaunchProfileCommand` (format:
`terminal/{appUserModelId}/{profileName}`)
- Rename constructor parameter `id` → `appUserModelId` to avoid
ambiguity with the generated command `Id`
- Override `GetCommandItem(string id)` in
`WindowsTerminalCommandsProvider` to look up profile items by ID

<img
src="https://github.com/user-attachments/assets/81c7acfc-09b5-40ab-be1d-8f268b24219b">

### Per-Profile Icons

**Root cause:** All profiles showed the same Terminal application logo.
The per-profile `icon` field from Terminal settings.json was parsed into
`TerminalProfile.Icon` but never used.

**Fix:**
- Add `InstallPath` to `TerminalPackage` (from `Package.InstalledPath`)
- Add `ResolveProfileIcon()` helper to `TerminalHelper` that resolves
`ms-appx:///` URIs to the Terminal package install directory (with scale
variant probing), passes through file paths and glyphs, and falls back
to the Terminal logo
- Cache the resolved icon in a local variable to avoid duplicate
filesystem IO per profile
- Set resolved per-profile icon on both `ListItem.Icon` and
`LaunchProfileCommand`

<img
src="https://github.com/user-attachments/assets/a9a476e2-7932-4457-bf04-bc346f2ad971">

### Robustness

- Use `Guid.TryParse` instead of `Guid.Parse` when reading profile GUIDs
from settings.json, so a malformed or empty GUID value does not throw
and take down the entire profile list

## PR Checklist

- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

**Files changed:**
- `Commands/LaunchProfileCommand.cs` — Assigns stable `Id`, renames `id`
→ `appUserModelId` throughout, adds `static MakeId()` helper
- `Helpers/TerminalHelper.cs` — Adds `ResolveProfileIcon()`,
`TryResolveGuidIcon()`, and `ResolveAppxPath()` helpers; hardens GUID
parsing with `Guid.TryParse`
- `Helpers/TerminalQuery.cs` — Passes `p.InstalledPath` to the
`TerminalPackage` constructor
- `Pages/ProfilesListPage.cs` — Resolves and caches icon path per
profile; sets `ListItem.Icon`
- `TerminalPackage.cs` — Adds `InstallPath` property
- `WindowsTerminalCommandsProvider.cs` — Overrides
`GetCommandItem(string id)` for dock-pinned command rehydration; removes
unused `using` directive

## Validation Steps Performed

- [x] Build clean with exit code 0
- [x] Dock pinning tested and working — "Pin to Dock" option appears and
survives restart
- [x] Per-profile icons verified — each profile displays its own icon in
both the list and the dock

---------

Co-authored-by: Michael Jolley <mike@baldbeardedbuilder.com>
Co-authored-by: Mike Griese <migrie@microsoft.com>
2026-04-23 12:53:40 -05:00
Michael Jolley
d9bfc42229 CmdPal: Fix fallback command disable toggle using interface type check (#47127)
## Summary

One-line fix for
[#46928](https://github.com/microsoft/PowerToys/issues/46928) — unable
to disable built-in and third-party extension fallback commands in
Command Palette.

## Problem

In `TopLevelViewModel.cs`, the constructor checked:
```csharp
if (IsFallback && commandItem is FallbackCommandItem fallback)
```

This uses the **concrete toolkit class** `FallbackCommandItem`. However,
extensions loaded out-of-process via WinRT/COM only expose **interface
proxies** — they never match the concrete class. As a result,
`_fallbackId` was never set, and the settings toggle to disable a
fallback command had no effect.

## Fix

Changed the type check to use the `IFallbackCommandItem2` WinRT
interface (which defines the `Id` property):

```csharp
if (IsFallback && commandItem is IFallbackCommandItem2 fallback)
```

The `IFallbackCommandItem2` interface is already defined in the
Extensions IDL and implemented by `FallbackCommandItem` in the toolkit.
This correctly matches both in-process and out-of-process extension
objects.

## Validation

- [x] Build clean (`Microsoft.CmdPal.UI.ViewModels` — exit code 0)
- [x] No ABI or schema changes
- [x] Single file changed, single line modified

Fixes #46928

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-23 12:39:22 -05:00
Mike Griese
11bfb40ec6 bump cmdpal to 0.10 (#47181)
title
2026-04-23 12:37:35 -05:00
Niels Laute
1eecf46c51 Fix missing images in Settings (#47165)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

⚠️ I'm not sure if this is the actual fix..

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

- [x] Closes: #47150

<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-04-23 15:50:45 +02:00
Michael Jolley
eeaf89e481 Update .gitignore for squad-specific files (#47122)
Updating .gitignore to ignore all Squad related files
2026-04-23 06:40:55 -05:00
Muyuan Li
b67e11d000 Fix CmdPal crash when typing in search box (#47148)
Add reentrancy guard for FilteredItems ObservableCollection mutations.

WinUI3's native XAML renderer can pump the message loop while processing
a CollectionChanged notification from InPlaceUpdateList. This allows a
second DoOnUiThread task to begin mutating FilteredItems while the first
is still mid-update, causing heap corruption and an access violation
(0xc0000005) in ntdll.dll.

The fix introduces RunFilteredItemsUpdate() which uses a boolean flag to
detect same-thread reentrancy (C# lock is reentrant so _listLock cannot
prevent this). When reentrancy is detected, only the latest pending
update is stored and executed after the in-flight mutation completes,
ensuring the UI converges to the newest state without overlapping
mutations.

Fixes: 100% reproducible crash in CmdPal when typing any character in
the search box (build ID 145015494).

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [x] Closes: #47145
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-23 17:19:11 +08:00
Muyuan Li
bfc5fea11e Fix CmdPal crash when typing in search box (#47148)
Add reentrancy guard for FilteredItems ObservableCollection mutations.

WinUI3's native XAML renderer can pump the message loop while processing
a CollectionChanged notification from InPlaceUpdateList. This allows a
second DoOnUiThread task to begin mutating FilteredItems while the first
is still mid-update, causing heap corruption and an access violation
(0xc0000005) in ntdll.dll.

The fix introduces RunFilteredItemsUpdate() which uses a boolean flag to
detect same-thread reentrancy (C# lock is reentrant so _listLock cannot
prevent this). When reentrancy is detected, only the latest pending
update is stored and executed after the in-flight mutation completes,
ensuring the UI converges to the newest state without overlapping
mutations.

Fixes: 100% reproducible crash in CmdPal when typing any character in
the search box (build ID 145015494).

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [x] Closes: #47145
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-23 16:38:15 +08:00
Boliang Zhang (from Dev Box)
a5bc91028f Merge remote-tracking branch 'origin/main' into stable 2026-04-23 16:18:06 +08:00
Gordon Lam
98c5b45a30 [Settings] Make GrabAndMove strings modifier-agnostic (#47178)
## Summary of the Pull Request

[PR #47052](https://github.com/microsoft/PowerToys/pull/47052)
introduced a **Win** option alongside **Alt** for the GrabAndMove
activation modifier (`GrabAndMove_ModifierKey` dropdown, `Alt` / `Win`).
However several user-facing strings in Settings still hardcode `Alt`,
which now misrepresents the feature when a user has selected `Win` as
the modifier.

This PR updates the wording of those strings to be modifier-agnostic.

### Strings changed (en-us)

| Key | Before | After |
|---|---|---|
| `GrabAndMove.ModuleDescription` | Move and resize windows with
**Alt+Drag**. Left-click to move, right-click to resize. | Move and
resize windows by holding **a modifier key** and dragging. Left-click to
move, right-click to resize. |
| `Oobe_GrabAndMove_HowToUse.Text` | Hold **Alt** and left-click drag...
Hold **Alt** and right-click drag... | Hold the **activation modifier
key** and left-click drag... Hold the **activation modifier key** and
right-click drag... |
| `GrabAndMove_UseAltResize.Header` | Enable **Alt + Right-click** to
resize | Enable **modifier + right-click** to resize |
| `GrabAndMove_UseAltResize.Description` | Hold **Alt** and right-click
to resize... | Hold the **activation modifier key** and right-click to
resize... |
| `GrabAndMove_ExcludeApps.Description` | Excludes an application from
being moved or resized **with Alt+Drag** - add one application name per
line | Excludes an application from being moved or resized **by Grab And
Move** - add one application name per line |

`GrabAndMove_ShouldAbsorbAlt` strings are intentionally left unchanged
ΓÇö that toggle is genuinely Alt-specific (it suppresses the window-menu
activation triggered by Alt).

## PR Checklist

- [x] **Closes:** follow-up to #47052
- [x] **Communication:** no additional comms needed
- [x] **Tests:** N/A (en-us resource strings only)
- [x] **Manual Tests:** Launched Settings UI, verified the GrabAndMove
page renders the new strings correctly (module description, `Enable
modifier + right-click` toggle header/description, excluded-apps
description). Verified OOBE `How to use` text renders with the updated
phrasing.
- [x] **Localization:** Only `en-us/Resources.resw` updated; other
locales will pick up the new English strings via the standard
localization pipeline.
- [x] **No dev docs required**

## Detailed Description of the Pull Request / Additional comments

- Scope is deliberately kept to wording only ΓÇö no logic, IPC, or XAML
bindings touched. Resource keys are preserved, so nothing else needs to
change.
- CC @GordonLamMSFT as the GrabAndMove / #47052 author.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-23 06:54:14 +00:00
Niels Laute
5509628f51 Changing outline ico colors (#47166)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

Making sure it's using the right shade of black :)

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

- [x] Closes: #47152
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-04-23 06:48:20 +02:00
Niels Laute
a255493c68 Settings string updates (#47164)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

- Small tweaks to a few setting strings

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

- [x] Closes: #47151

<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-04-23 06:47:52 +02:00
Niels Laute
5c15a63846 Power Display tweaks (#47163)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

- Consistent naming: `Power Display`
- Making the flyout a bit smaller
- Removing dead code (titlebar button colors)

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

- [x] Closes: #47153

<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-04-23 09:19:17 +08:00
Michael Jolley
2c95a61bb3 fix(cmdpal): refresh dock settings on pin/unpin (#47155) (#47169)
## Summary of the Pull Request

Fixes the CmdPal Dock not refreshing when a command is pinned or
unpinned. The dock now immediately reflects pin/unpin changes without
requiring a CmdPal restart.

**Root cause:** `DockViewModel._settings` was cached at construction and
only refreshed via the `SettingsChanged` event. However, pin/unpin
operations in `CommandProviderWrapper.PinDockBand()` / `UnpinDockBand()`
intentionally save with `hotReload: false` (to avoid double-updates), so
`SettingsChanged` never fires. When `DockBands_CollectionChanged` called
`SetupBands()`, it iterated over the stale `_settings` which didn't
include the newly pinned band.

**Fix:** Re-read `DockSettings` from the settings service at the top of
`DockBands_CollectionChanged`, ensuring `SetupBands()` always sees the
latest persisted state.

## PR Checklist

- [x] Closes: #47155
- [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 —
N/A (no UI string changes)
- [ ] **Dev docs:** Added/updated — N/A (no public API or behavior doc
changes)

## Detailed Description of the Pull Request / Additional comments

Single-line change in
`src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Dock/DockViewModel.cs`:

```csharp
_settings = _settingsService.Settings.DockSettings;
```

Added before the existing `SetupBands()` call inside
`DockBands_CollectionChanged`. The edit-mode guard (`_isEditing`) is
already checked earlier in the method, so drag/drop operations are
unaffected.

This fix covers both pin and unpin flows since both use the same
`hotReload: false` → `CommandsChanged` → `DockBands_CollectionChanged`
code path.

## Validation Steps Performed

- Built `Microsoft.CmdPal.UI.ViewModels.csproj` — exit code 0, no
warnings related to change
- Verified unpin flow uses the same code path and benefits from the fix
- Manual verification: pin a command via CmdPal → dock updates
immediately without restart

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-22 15:05:44 -05:00
moooyo
dbc390ab0d fix: default 8 modules to disabled to match EnabledModules.cs (#47144)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Fixes a mismatch where 8 modules inherited the default
`is_enabled_by_default() = true` from `PowertoyModuleIface` while
`EnabledModules.cs` declared them `false`. On a clean install the Runner
would enable these modules on first launch, then Settings UI would flip
them back off once it persisted `settings.json` — a one-time visible
flicker and a DSC compliance gap.

Adds an explicit `is_enabled_by_default() const override { return false;
}` in the following module interfaces so both sides of the default
agree:

- `src/modules/launcher/Microsoft.Launcher/dllmain.cpp` (PowerToys Run)
- `src/modules/CropAndLock/CropAndLockModuleInterface/dllmain.cpp`
- `src/modules/AdvancedPaste/AdvancedPasteModuleInterface/dllmain.cpp`
- `src/modules/Hosts/HostsModuleInterface/dllmain.cpp`
- `src/modules/registrypreview/RegistryPreviewExt/dllmain.cpp`
-
`src/modules/EnvironmentVariables/EnvironmentVariablesModuleInterface/dllmain.cpp`
- `src/modules/Workspaces/WorkspacesModuleInterface/dllmain.cpp`
- `src/modules/powerdisplay/PowerDisplayModuleInterface/dllmain.cpp`

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Yu Leng (from Dev Box) <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 13:48:20 +00:00
Alex Mihaiuc
c6a79360f3 Unstick GrabAndMove keys, add Win modifier and improve coords (#47052)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
This brings some quality of life fixes:

- Alt won't stick when pressing Ctrl+Alt+Del or Alt+Tab into an admin
process.
- Add Win as an option for the move/resize modifier.
- The box window geometry box is opaque now.

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
- Tested that Ctrl+Alt+Del doesn't stick the Alt key.
- Tested that the Win key works as expected as a modifier.
- Compared the last commit for performance with the previous one (the
opaque geometry info box is drawn with an increased number of calls).
2026-04-22 15:02:37 +02:00
Boliang Zhang (from Dev Box)
1eebd47af0 Merge remote-tracking branch 'origin/main' into stable 2026-04-22 17:18:11 +08:00
Niels Laute
b0ccc2394a Add update-available badge to system tray icon (#47030)
When an update is available (readyToDownload or readyToInstall), the
tray icon switches to a badged variant with an orange dot. Works for
both default mode (color icon.ico) and theme-adaptive mode (light/dark
variants).

Closes: #19222
Closes: #25497

## Changes

### Tray icon update badge
- Add 3 badged icon variants
- Extend get_icon() to select badged variant based on update_available
state
- Add set_tray_icon_update_available() for runtime icon switching
- Hook into UpdateUtils.cpp state transitions via
dispatch_run_on_main_ui_thread
- Check UpdateState at startup to show badge immediately if update
pending
- Add 'Update available' context menu item at top of tray menu when
active

### Fix: update icons not deployed (bug fix)
- Add APPICON_UPDATE icon resource to runner.base.rc (iconUpdate.ico was
missing)
- Add CopyFileToFolders entries for iconUpdate.ico,
PowerToysDarkUpdate.ico, and PowerToysWhiteUpdate.ico in runner.vcxproj
- Add all update icon files to installer Core.wxs so they ship in
releases

### UX improvements
- 'Update available' tray menu item now navigates to General page
(Overview) instead of opening Settings to Dashboard
- Update InfoBar severity changed from Success/Informational to Warning
across GeneralPage, LaunchPage, and CheckUpdateControl
- Dashboard update badge gradient and icon refreshed (orange theme,
exclamation glyph)
- AccentButtonStyle applied to 'Install Now' button
- Fixed casing: 'Update Available' to 'Update available'
- Added UpdateAvailableInfoBar.Title resource string
- Add orange update dot to the General navview item

### Screenshots

Before:
<img width="146" height="78" alt="image"
src="https://github.com/user-attachments/assets/c80b8b5f-da94-4cba-92c9-3fcca685653c"
/>

After:

<img width="184" height="104" alt="image"
src="https://github.com/user-attachments/assets/13fc6b34-6e2a-4060-a2f7-f0b6b0d15363"
/>

<img width="150" height="84" alt="image"
src="https://github.com/user-attachments/assets/2673239c-8ce3-437b-947a-1d66803a87ec"
/>

<img width="150" height="100" alt="image"
src="https://github.com/user-attachments/assets/c321deda-770d-47ff-9600-c395f466d444"
/>

<img width="189" height="104" alt="image"
src="https://github.com/user-attachments/assets/2c56d1b7-6615-4d85-80b9-a1cee6413b75"
/>


<img width="473" height="218" alt="image"
src="https://github.com/user-attachments/assets/b0fb59ed-f8bd-40a0-aefd-816a71fc231f"
/>

<img width="1048" height="288" alt="image"
src="https://github.com/user-attachments/assets/29d34e01-f6a9-46c3-a56e-2c50a07718a1"
/>

<img width="206" height="155" alt="image"
src="https://github.com/user-attachments/assets/80e9f77e-aae5-429a-b6be-f0e9f296e929"
/>

<img width="434" height="163" alt="image"
src="https://github.com/user-attachments/assets/7c9d6cd5-fdaa-4b70-a2c0-cff87f5fcf1c"
/>

<img width="379" height="270" alt="image"
src="https://github.com/user-attachments/assets/03e0f60d-a901-45e7-a03a-18be28ec87ed"
/>


## How to test

Since local dev builds use version `0.0.1` which blocks update checks,
you need to temporarily fake an older version:

1. In `src/Version.props`, change `<Version>0.0.1</Version>` to
`<Version>0.87.0</Version>`
2. Optionally, in `src/runner/UpdateUtils.cpp`, change both interval
constants to `1` (minute) for faster testing:
   ```cpp
   constexpr int64_t UPDATE_CHECK_INTERVAL_MINUTES = 1;
   constexpr int64_t UPDATE_CHECK_AFTER_FAILED_INTERVAL_MINUTES = 1;
   ```
3. Build and run the runner
4. Within ~1 minute (with the interval change) or after clicking 'Check
for updates' in Settings > General, the runner will query GitHub and
find a newer version

### Verify
- [ ] Tray icon changes to the update variant (badged with orange dot)
- [ ] Right-clicking the tray icon shows 'Update available' at the top
of the context menu
- [ ] Clicking 'Update available' opens Settings directly to the General
page
- [ ] Settings General page shows the update InfoBar with Warning
severity
- [ ] Dashboard shows the update badge with orange gradient and
exclamation icon
- [ ] Quick Access flyout shows update InfoBar with Warning severity

**Remember to revert Version.props and UpdateUtils.cpp before
committing!**

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-22 16:48:03 +08:00
moooyo
c8ffcb73c3 [ImageResizer] Fix JPEG quality setting ignored after WinUI3 migration (#47134)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Restores honoring of the user-configured JPEG quality — via the Settings
UI slider, the CLI `--quality` flag, or the persisted
`imageresizer_jpegQualityLevel` — when resizing JPEG files. Since the
WinUI3 migration (#45288) any Q value from 1 to 100 produced
byte-identical output at WIC's internal default (~Q90) because the
transcode encoder silently ignored the setting. Only
`src/modules/imageresizer/ui/Models/ResizeOperation.cs` is changed.

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

- [x] Closes: #47135
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

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

Built `ImageResizerCLI.csproj` in `Release|x64` with
`/p:RuntimeIdentifier=win-x64`; no new warnings. Ran the resulting
`x64\Release\WinUI3Apps\PowerToys.ImageResizerCLI.exe` against a
synthetic test JPEG (`a.jpg` 2373×905, ~240 KB) and both in-tree EXIF
assets:

- `src/modules/imageresizer/tests/TestMetadataIssue1928.jpg` (42 EXIF
properties)
- `src/modules/imageresizer/tests/TestMetadataIssue2447.jpg` (44 EXIF
properties)

Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 14:46:41 +08:00
Niels Laute
fcfbf83b55 Settings design tweaks + fixes (#47132)
This PR:

- Fixed a UI regression on the ZoomIt page
- Updates the CmdPal settings page to make sure it has the latest links
and imagery
- Updates the New+ assets so they fit inline with all other screenshots
and assets
- Adds missing screenshots to the `docs` folder

Closes: #44521
2026-04-21 14:11:33 +02:00
Boliang Zhang (from Dev Box)
1f840000f5 Merge remote-tracking branch 'origin/main' into stable 2026-04-21 14:29:24 +08:00
Niels Laute
de6ba922fd Fixing OOBE and assets for Power Display and Grab And Move (#47033)
## Summary

Adds the out-of-box experience (OOBE) for the new **Grab And Move**
module and refreshes related assets across the repo.

## Changes

### Grab And Move OOBE
- New `OobeGrabAndMove.xaml` / `.xaml.cs` page following the standard
PowerToys OOBE pattern (hero image, How to use, Tips & tricks, Settings
button, Learn more link)
- Wired into `OobeWindow.xaml(.cs)` as a new `NavigationViewItem` so it
appears in the OOBE wizard
- Added localized resource strings (Title, Description, How to use, Tips
and tricks) in `Resources.resw`
- New OOBE animation: `Assets/Settings/Modules/OOBE/GrabAndMove.gif`

### Settings UI polish
- Moved the Grab And Move nav item under *Windowing & Layouts* into its
proper alphabetical position (after FancyZones, before Workspaces)
- Added a "NEW" `InfoBadge` to both the Grab And Move item and its
parent *Windowing & Layouts* group so users can discover the new utility

### Asset refresh
- High-res `GrabAndMove.ico` (replaces the placeholder)
- Updated Settings module icons
(`Assets/Settings/Icons/GrabAndMove.png`,
`Assets/Settings/Modules/GrabAndMove.png`)
- New overview/marketing PNGs under `doc/images/overview/` (large,
small, and original)

### README
- Added **Grab And Move** and **PowerDisplay** to the utilities table in
`README.md`, reflowed alphabetically into a clean 10x3 grid
- New `doc/images/icons/GrabAndMove.png` and
`doc/images/icons/PowerDisplay.png` for the table

## Validation
- Settings UI builds cleanly
- Grab And Move appears in the OOBE wizard navigation and renders
correctly
- "NEW" badges visible on first launch
- README table renders with all 30 utilities, no empty trailing cells

<img width="1307" height="807" alt="image"
src="https://github.com/user-attachments/assets/f8d2ef96-a9f3-4307-9714-c308e216c044"
/>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 06:23:54 +02:00
Dave Rayment
71cb9bc54e [Quick Accent] Fix issue where default "All available" setting is not parsed correctly (#47117)
## Summary of the Pull Request
When first enabled in the Settings application, Quick Accent defaults to
**All available** character sets, but the persisted "ALL" option in the
settings.json file is not understood by the application itself. This
leads to the fallback SPECIAL character set being selected - unbeknownst
to the user - which only contains a small subset of the available
mappings.

This PR also adds two new characters to the Hungarian language, as
requested under #47085.

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

- [x] Closes: #47113
- [x] Closes: #47085
- [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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

The cause of the issue is:

1. The default `SelectedLang` value for a new Quick Accent settings file
is "ALL", set in `PowerAccentProperties.cs`:
 

5520ae4cfa/src/settings-ui/Settings.UI.Library/PowerAccentProperties.cs (L46)

2. The Settings application understands the "ALL" setting, _but Quick
Accent itself does not_.
3. There is an existing fallback in Quick Accent for when the language
cannot be parsed, which is to select the "SPECIAL" language instead.
This is a grab-bag of mappings for non-language-specific entries such as
cross-cultural punctuation, IPA, currency etc.

The effect is that new users will see that All available character sets
have been selected in the Settings application by default, but that only
a small number of the available mappings will be shown when they trigger
Quick Accent. De-selecting and re-selecting All available will fix the
issue, but a new user is unlikely to do this. This leads to issues being
logged such as #47085, where missing characters are reported, but they
actually are present in the underlying mappings for the language(s).

There is also another issue with `SelectedLang` parsing, in that entries
are compared against the in-built language codes in a case-sensitive
non-trimmed manner. This means that entries such as "FR", "fr" and " FR"
are all distinct. Although this isn't an issue at the moment, it means
that adding new languages or editing the settings file manually is prone
to triggering fall-throughs and the selection of the SPECIAL language
without the user knowing.

The fix here is to:

1. Pre-parse the SelectedLang entries to trim them and remove any empty
values.
2. Do an explicit (case-insensitive) check for "ALL"; if present, all
languages are immediately selected.
3. If "ALL" is not present in the list, do a case-insensitive check for
each entry against the in-built language codes.
4. Reject any non-matches and log a warning. Do not fall through to
auto-select the SPECIAL character set. This respects the principle of
least surprise, and means that the user is never given character options
that they did not explicitly select.

Changes to the Quick Accent application are in `ReadSettings()` in
SettingsService.cs. I have also made the Settings application parsing
more robust, so both it and Quick Accent should be able to correctly
parse entries like "SP, INVALID, EST".

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

Follow the manual steps below:

1. Close the Quick Accent process if it is currently running
6. Edit the settings.json file for Quick Accent, and set the
"selected_lang" value to "all" (this setting is no longer
case-sensitive).
7. (Re)start Quick Accent by starting `PowerToys.PowerAccent.exe`.
8. Trigger Quick Accent for the E key and observe the selection dialog
that opens. It should contain E mappings for every language:

<img width="3371" height="155" alt="image"
src="https://github.com/user-attachments/assets/84d709ea-fdcc-4430-8d22-f9732969a20a"
/>

9. Trigger Quick Accent for the Y key and observe the selection dialog
that opens. It should contain Y mappings for every language, including
the Y-With-Diaresis character originally reported as missing:

<img width="1264" height="149" alt="image"
src="https://github.com/user-attachments/assets/ecea3734-e58c-4da6-896b-2e58a9fd05e8"
/>

10. Back in the settings file, change "selected_lang" value to "HR" for
Croatian. Save the file.
11. Trigger Quick Accent for the C key and observe that only the
following mappings are shown:

<img width="1055" height="146" alt="image"
src="https://github.com/user-attachments/assets/69764145-0836-4dfb-8655-3a8a3be7f561"
/>

12. Again, in settings, change the "selected_lang" value to "". Save the
file.
13. Confirm that triggering Quick Accent does not result in an error and
simply does not show the dialog.
14. In settings again, change the "selected_lang" value to "FR, INVALID,
DE" and save.
15. Trigger Quick Accent and confirm that entries for French and German
are available in the dialog.
16. Check the logs and confirm that a warning is present about "INVALID"
not being a valid language and being skipped.

Separately, for the Settings application:

1. Close the PowerToys Runner and ensure Quick Accent and Settings are
not present in the Processes list.
2. Edit the settings.json file for Quick Accent, changing the
"selected_lang" value to "FR, INVALID, DE" and save.
3. Run PowerToys and open the Settings application.
4. On the Quick Accent settings page, ensure that French and German
languages are selected. (Previously, parsing would fail after FR.)
2026-04-21 11:41:25 +08:00
Gordon Lam
8ad571dcde Fix Common.Interop.UnitTests.TestSend infinite hang on CI (#47123)
## Summary

Fixes an infinite hang in Common.Interop.UnitTests.TestSend that caused
the x64 CI job to time out at 80 minutes on retried runs (originally
observed on #47106, but the race is latent in any run that shares a CI
agent with a previous run).

## Root cause

The test used two machine-global named pipes (\\.\pipe\serverside and
\\.\pipe\clientside) as fixed constants, and waited for the pipe
callback with an **unbounded** eset.WaitOne().

If a prior test run on the same CI agent left a pipe handle alive (e.g.
after a job cancellation or a flaky cleanup), the next run's
TwoWayPipeMessageIPCManaged handshake would silently never complete, and
`WaitOne()` would block until the pipeline's job-level timeout (~80
minutes) killed the agent.

## Fix

Two small, orthogonal changes in `InteropTests.cs`:

1. **Unique pipe names per run** — suffix the pipe paths with
`Environment.ProcessId` + a fresh `Guid`, so runs on the same agent can
never collide.
2. **Bounded wait** — `reset.WaitOne(TimeSpan.FromSeconds(30))` wrapped
in `Assert.IsTrue` with a diagnostic message identifying the pipes. A
broken handshake now fails the test in 30 s with a clear error, instead
of hanging the CI job.

The inner `Assert.AreEqual(testString, msg)` — the actual correctness
check — is unchanged. On the happy path the callback fires in
milliseconds and the test behaves identically to before.

## Verification

Built and ran locally with VS2026 MSBuild (x64 Release): `TestSend`
passes in ~139 ms.

## Follow-up (not in this PR)

`TwoWayPipeMessageIPC.cpp` still relies on a `Thread.Sleep(100)` race
workaround (comment in the test) for server-ready timing. A proper
handshake there would let us drop the sleep; out of scope here.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 11:08:08 +08:00
Niels Laute
bf00c1b94f [Common][PowerDisplay][QuickAccess] Shared flyout positioning helper (#47097)
## Summary

Introduces a shared FlyoutWindowHelper in Common.UI.Controls and
migrates both **PowerDisplay** and **QuickAccess** to it, eliminating
two pre-existing flyout positioning bugs and removing duplicated math.

## Bugs fixed

### 1. PowerDisplay flyout overlapped the taskbar at 100% scaling
The previous PowerDisplay-only positioning math anchored to the screen
bounds rather than `DisplayArea.WorkArea` on certain monitor
configurations, so the bottom edge of the flyout could land on top of
the taskbar.

### 2. QuickAccess flyout rendered too large / partially off-screen
after switching DPI between 150% and 100%
The previous code passed `WindowEx.Width`/`Height` into `MoveAndResize`
on every summon. Those properties are **not** the XAML literals — they
are computed live as `AppWindow.Size / GetDpiForWindow() * 96`. After a
system-scaling switch, the runtime size has drifted, that wrong "DIP"
value got fed into `MoveAndResize`, and the destination DPI multiplier
scaled it again → wrong size, and the wrong size shifted the
bottom-right anchor off-screen.

QuickAccess now caches the XAML design size once at construction (when
the values are still trustworthy) and uses the cache as the source of
truth.

## How the helper works

- Uses **absolute screen coordinates** against `DisplayArea.WorkArea`,
so it handles non-primary and negatively-positioned monitors correctly.
- Performs a **1×1 `MoveAndResize` "teleport"** onto the target display
before the final visible-size call. The 1×1 jump may cross a DPI
boundary, but it's invisible; the second call sets the real size while
the window is already on the destination monitor, so no DPI boundary is
crossed for the rendered size and `WM_DPICHANGED` never fires on a
visible window.
- Exposes overloads for bottom-right anchoring (both flyouts) and
centered placement (PowerDisplay's `IdentifyWindow`).

This teleport-then-size approach matches the technique the original
Settings.UI flyout used for years before it was removed.

## Cleanup

- Deletes the PowerDisplay-only `DpiSuppressor` — its
WM_DPICHANGED-suppression code path is now dead because the helper
sidesteps the message entirely.
- The `DpiSuppressor` class also doubled as a generic WndProc subclass
to route `WM_HOTKEY` into `HotkeyService`. That piece is preserved as
`WindowMessageHook` in `Common.UI.Controls/Window/` since PowerDisplay
still needs in-process hotkey handling.

## Validation

- `Common.UI.Controls`, `PowerDisplay`, and `QuickAccess` build clean
(x64/Debug).
- Manual repro:
- PowerDisplay flyout no longer overlaps taskbar at 100% scaling, on
multiple invocations.
- QuickAccess renders at the correct size and position when switching
system scaling between 150% and 100%.
- PowerDisplay hotkey toggle still works after the `DpiSuppressor` →
`WindowMessageHook` rename.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-21 10:20:34 +08:00
Niels Laute
7a89220a91 [QuickAccent] Add en-dash to VK_MINUS for SPECIAL language (#47106)
## Summary of the Pull Request
Add en-dash to the existing dash characters available under the minus
key for the Special Characters set.

This PR re-creates #45965 by @daverayment because that PR's pipeline
appears to have been corrupted. All credit for the change belongs to
@daverayment — the commit on this branch preserves their original
authorship.

## PR Checklist

- [x] Closes: #44030
- [x] Closes: #36805

## Detailed Description of the Pull Request / Additional comments

This PR adds the en-dash '–' character to the VK_MINUS key under the
Special Characters character set, positioned before the em-dash
character.

Although the character is available under VK_COMMA, it should be present
under VK_MINUS, along with the other dash characters.

Previously, en-dash was available for VK_MINUS under the Hebrew
language, so users who selected **All available** character sets (or who
specifically selected Hebrew as a workaround) had access to en-dash via
the minus key. However, this was seen as a duplication of the VK_COMMA
functionality and the character was removed for the Hebrew character set
in #43504. Although this is technically correct, this has understandably
caused confusion for users who relied on the prior behaviour.

The comment on the VK_COMMA for the Special Characters declaration
previously read:

`csharp
// – is in VK_MINUS for other languages, but not VK_COMMA, so we add it
here.
`

That ""for other languages"" is telling. The Hebrew en-dash entry was
removed, and the en-dash mapping for the minus key is not present for
any other language, orphaning the functionality.

## Validation Steps Performed

Original author @daverayment built and ran the updated Quick Accent code
and confirmed that the character was available when only the Special
character set was selected, and that it was absent when that set was
deselected. Confirmed that the character was available under both comma
and minus keys.

Co-authored-by: Dave Rayment <dave.rayment@gmail.com>
2026-04-21 00:59:35 +00:00
Michael Jolley
3a541bb3eb CmdPal: Adding prop to cmdpal.ui.csproj to enable telem in AOT builds (#47121)
This pull request makes a configuration change to the
`Microsoft.CmdPal.UI.csproj` project file to improve telemetry support
for AOT (Ahead-Of-Time) builds.

Project configuration:

* Added the `EventSourceSupport` property and set it to `true` to ensure
telemetry events are triggered correctly when building with AOT.
2026-04-20 19:49:39 -05:00
Niels Laute
f4d23c85a6 [CmdPal Dock] Compact mode (#46699)
## Summary of the Pull Request

This PR introduces the following changes:
- Shaving off a few pixels of the default height in `Top` or `Bottom`
mode.
- A new `Compact` mode that automatically hides the `Subtitle` and is
28px in height.
- Compact mode is only available for Top/Bottom dock positions.
Left/Right always use the Default size.
- The Dock Size settings card is hidden in the settings UI when Left or
Right is selected.
- At runtime, Left/Right positions force `DockSize.Default` regardless
of the persisted setting, ensuring default item styles and appbar sizing
are always used. The user's Compact preference is preserved so switching
back to Top/Bottom restores it.

Stable vs. Compact mode:

<img width="392" height="131" alt="image"
src="https://github.com/user-attachments/assets/f0ac3126-a773-46c6-87da-001fd66c5899"
/>

<img width="929" height="272" alt="image"
src="https://github.com/user-attachments/assets/684c2ea7-449d-4ed2-989d-5066c7f28200"
/>

## PR Checklist

- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx


## Detailed Description of the Pull Request / Additional comments

### Compact mode restricted to Top/Bottom
Compact mode is only supported when the dock is positioned at the Top or
Bottom of the screen. When Left or Right is selected:
- The **Dock Size** settings card is hidden in the dock settings UI.
- The runtime forces \\DockSize.Default\\ so the default band template,
default item styles, and default appbar dimensions are always used.
- The persisted \\DockSize\\ value is **not** cleared — switching back
to Top/Bottom restores the user's previous Compact choice.

### Files changed
- \\DockSettingsPage.xaml\\ / \\.xaml.cs\\ — Conditional visibility for
the Dock Size settings card
- \\DockControl.xaml.cs\\ — Effective size override in
\\UpdateSettings()\\
- \\DockWindow.xaml.cs\\ — \\EffectiveDockSize()\\ helper used for
appbar sizing and change detection

## Validation Steps Performed

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
2026-04-20 16:07:41 +00:00
Jiří Polášek
5e302bed79 CmdPal: Improve indexer plain query search (#46907)
## Summary of the Pull Request

This PR improves File Search:
- Improves simple free-text Windows Search queries with implicit
filename broadening while preserving structured AQS input.
- Adds resilient fallback behavior for noisy or punctuation-heavy
searches by retrying with literal filename matching (fixes failed
searches with `&` or other symbols).
- Surfaces Windows Search availability and indexing-status notices in
the indexer page and fallback item -- if the Windows Search service is
down or unreachable, we show this to the user.
- Extends production time logging.
- Adds documentation of query transformation for maintainers.
- Adds some unit tests to pretend that we care.
 
## Pictures? Pictures!

Error notices:

<img width="890" height="148" alt="image"
src="https://github.com/user-attachments/assets/2370af01-04de-48a5-aa8e-06b95b54571e"
/>

<img width="880" height="369" alt="image"
src="https://github.com/user-attachments/assets/b2afa52b-02f8-4031-a61a-fa1031f86542"
/>



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

- [x] Closes: #46574
- [X] Closes: #44689
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-04-20 10:41:27 -05:00
Jiří Polášek
520037e128 CmdPal: Add persistent calculator history (#45307)
## Summary of the Pull Request

This PR adds a persistent memory to Calculator extension and updates
result commands.

<img width="815" height="515" alt="image"
src="https://github.com/user-attachments/assets/e3b84ec4-a399-4c63-a773-76bcdf05f94a"
/>


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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-04-20 10:40:49 -05:00
Jiří Polášek
d80d216bef CmdPal: Fix first-open top-level context menus for slow providers (#46626)
## Summary of the Pull Request

This PR fixes opening of the list item context menu through right-click,
which affected mainly 3rd party out-of-process extensions.

- Keeps the first context-menu request alive when a top-level item is
selected but its out-of-proc MoreCommands are still hydrating.
- Short-circuits CanOpenContextMenu when a valid synthetic primary
command is already available, so items with a usable primary action can
open immediately without waiting for late menu hydration.


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

- [x] Closes: #46625
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-04-20 10:13:24 -05:00
Michael Jolley
b310c55835 fix(cmdpal): handle unavailable extension packages during loading (#47032)
## Summary of the Pull Request

Fixes a Watson crash where \AppExtension.Package\ throws a COM/HRESULT
exception when the underlying package is in a bad state (being updated,
partially installed, recently uninstalled, or corrupted). Previously,
one bad extension killed the entire extension-loading loop, preventing
**all** extensions from loading.

This adds try-catch guards in \ExtensionService\ at two levels so a
single failing extension is logged and skipped rather than aborting the
enumeration.

## PR Checklist

- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** This is a defensive resilience fix with no behavior
change for the happy path; existing tests still pass
- [ ] **Localization:** N/A — no end-user-facing strings changed (log
messages are developer-facing)
- [ ] **Dev docs:** N/A — no new APIs or features
- [ ] **New binaries:** N/A — no new binaries

## Detailed Description of the Pull Request / Additional comments

**File changed:**
\src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Models/ExtensionService.cs\

Two try-catch blocks added:

1. **\GetInstalledExtensionsAsync\** — wraps the per-extension loop body
(lines 200–211) so that if \CreateWrappersForExtension\ or any property
access on \AppExtension\ throws, the loop continues to the next
extension.

2. **\CreateWrappersForExtension\** — wraps the per-classId wrapper
creation (lines 252–264) so that if the \ExtensionWrapper\ constructor
throws (e.g. \ppExtension.Package\ is unavailable), remaining class IDs
in the same extension still get processed.

Both catch blocks log via \Logger.LogError\ with the extension display
name and error message.

The \InstallPackageUnderLock\ code path also calls
\CreateWrappersForExtension\ and inherits the inner protection
automatically.

## Validation Steps Performed

- Built \Microsoft.CmdPal.UI.ViewModels\ with \ ools/build/build.cmd\ —
exit code 0, no warnings or errors
- Verified no existing tests are broken by the change

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-20 10:12:46 -05:00
Boliang Zhang (from Dev Box)
04fe688e7a Merge remote-tracking branch 'origin/main' into stable 2026-04-20 16:34:06 +08:00
moooyo
5520ae4cfa [PowerDisplay] Fix startup restore, volume init, and identify window lifecycle (#47051)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
- **Volume initialization**: Read VCP 0x62 on monitor discovery so
`CurrentVolume` reflects actual hardware state instead of staying at the
50% default.
- **Brightness capability check**: Guard brightness init behind
`SupportsBrightness` flag, consistent with contrast/volume handling.
- **IdentifyWindow lifecycle**: Replace fire-and-forget `Task.Delay`
with `DispatcherQueueTimer` (UI-thread-safe, stoppable on dispose). Swap
`Activate`/`PositionOnDisplay` order to eliminate first-show flicker.
- **Startup restore fix**: Change `MonitorStateEntry` fields to `int?`
so unset values (`null`) aren't confused with zero — prevents writing
default 0% brightness/volume to hardware on startup.
- **Restore/profile apply refactor**: Push value validation down to
`Set*Async` (continuous → `Math.Clamp`, discrete → capabilities check),
extract unified `TryRestore` helper, remove redundant `IsValueInRange`
and `> 0` checks.
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [x] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Yu Leng (from Dev Box) <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 08:41:14 +00:00
moooyo
beddc3b065 [ImageResizer] Fix JsonPropertyName forwarding in ObservableProperty generator (#47056)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
This issue introduced by our recent WinUI 3 migration

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

- [x] Closes: #47055
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Yu Leng <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4 <noreply@anthropic.com>
2026-04-17 15:20:45 +08:00
Boliang Zhang (from Dev Box)
8fc31de489 Merge main into stable for 0.99 release 2026-04-16 15:36:07 +08:00
Niels Laute
088da21a70 Update default module states (#47027)
## Summary

- **Disable 7 modules by default** for new users: PowerToys Run, Crop
and Lock, Advanced Paste, Hosts File Editor, Registry Preview,
Environment Variables, Workspaces
- **Swap default hotkeys**: Command Palette now defaults to \Alt+Space\,
PowerToys Run now defaults to \Win+Alt+Space\
- Update unit test to reflect PowerLauncher default-off state

## Changes

| File | Change |
|------|--------|
| \EnabledModules.cs\ | Set 7 module defaults to off |
| \PowerLauncherProperties.cs\ | Default hotkey → \Win+Alt+Space\ |
| \SettingsModel.cs\ (CmdPal) | Default hotkey → \Alt+Space\ |
| \General.cs\ (test) | Assert PowerLauncher is false |

## Validation

- Existing unit test updated to match new defaults
- No ABI or IPC contract changes

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-16 08:44:25 +02:00
Gordon Lam
befb5c672e Fix AdvancedPaste auto-copy failing on Electron/Chromium apps (#46486)
## Summary

Fixes #46485

AdvancedPaste's auto-copy feature fails on Electron/Chromium-based apps
(e.g. Microsoft Teams, VS Code, browsers) because `WM_COPY` is delivered
successfully but silently ignored by these apps.

## Problem

The auto-copy code sends `WM_COPY` via `SendMessageTimeout`. For
standard Win32 controls this works, but Electron apps accept the message
delivery without actually copying to clipboard. The code treated
successful delivery as success and **never fell back to `SendInput`
Ctrl+C**.

## Changes


**`src/modules/AdvancedPaste/AdvancedPasteModuleInterface/dllmain.cpp`**:

- **Changed retry logic**: Each attempt now tries both `WM_COPY` and
`SendInput` Ctrl+C. If `WM_COPY` is delivered but clipboard is
unchanged, it falls through to Ctrl+C instead of giving up.
- **Extracted `poll_clipboard_sequence()` helper**: Reusable clipboard
polling logic (checks `GetClipboardSequenceNumber` over N polls with
configurable delay).
- **Extracted `send_ctrl_c_input()` helper**: Sends Ctrl+C via
`SendInput` with `CENTRALIZED_KEYBOARD_HOOK_DONT_TRIGGER_FLAG`.
- **Improved logging**: Each strategy logs clearly whether it succeeded
or fell through, making future debugging easier.

## Validation

- [x] Manual testing with Microsoft Teams (Electron): auto-copy now
works for selected text
- [x] Standard Win32 apps (Notepad, etc.): `WM_COPY` still works on
first try, no regression
- [x] No new warnings or errors in build

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-16 10:49:40 +08:00
Niels Laute
578554d157 [Settings] Format last update check date with friendly relative dates (#46923)
## Summary

Formats the Last checked date on the General and Dashboard pages with
friendly relative strings instead of raw date/time output.

**Before:** Last checked: 4/12/2026 1:22:00 PM
**After:** Last checked: Today at 1:22 PM / Yesterday at 3:45 PM

### Changes

- Add LastCheckedDateTime property to UpdatingSettings exposing the
parsed DateTime
- Create FriendlyDateHelper in Settings.UI that formats Today/Yesterday
with localized resource strings, falling back to the full
culture-specific format for older dates
- Update GeneralViewModel and CheckUpdateControl to use the friendly
format
- Add localized resource strings General_LastCheckedDate_TodayAt and
General_LastCheckedDate_YesterdayAt

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-15 10:06:10 +02:00
Gordon Lam
e4f98897ce Add window positioning and sizing with Alt+mouse button (#47024)
Re-creation of #46817 from an internal branch to work around stale
code-scanning merge protection.

## Original PR
See #46817 for full context, discussion, and review history.

## Summary
This adds a new toy, GrabAndMove (previously WinPos), that allows
dragging (left click) or resizing (right click) of windows while the Alt
key is pressed.

Closes: #269

## PR Checklist
- [x] Communication: discussed with core contributors
- [ ] Tests: Added/updated and all pass
- [ ] Localization: All end-user-facing strings can be localized
- [ ] Dev docs: Added/updated

---------

Co-authored-by: foxmsft <foxmsft@hotmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Muyuan Li (from Dev Box) <muyuanli@microsoft.com>
Co-authored-by: Niels Laute <niels.laute@live.nl>
Co-authored-by: Alex Mihaiuc <amihaiuc@microsoft.com>
2026-04-15 09:13:56 +02:00
Muyuan Li
be1e749574 Add telemetry support for CLI modules (#46872)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
This PR adds comprehensive localization and telemetry support to the
modules with CLI (FileLocksmith, Awake, ImageResizer), improving user
experience for international users and enabling usage tracking for
product insights.
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-04-15 14:14:12 +08:00
Niels Laute
dc57d22754 [Settings] Fix Dashboard layout and 1px alignment offset (#46922)
## Summary

Fixes layout issues on the Settings Dashboard page:

- **Scroll area fix**: The scroll area on the Home page extended far
beyond the content, leaving a large empty space below the modules list.
(By wrapping the quick launch / shortcuts cards into a `StackPanel` vs
separate `Grid.Rows`
- **Resizing fix**: On main, resizing states are not applied when making
the window smaller. This is now fixed.
- **1px alignment fix**: Fixed a 1-pixel vertical alignment mismatch on
the Dashboard shortcut conflict control.

Closes #45925
Closes #41523
2026-04-14 15:30:29 +02:00
moooyo
99ef5948b0 [PD] Fix thread safety, color temperature guard, and log accuracy (#47008)
Mark _disposed and _isDirty as volatile for correct cross-thread
visibility. Guard color temperature apply/restore behind
ShowColorTemperature to avoid writing unsupported VCP codes. Fix
misleading log message in Settings UI profile apply path.

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Yu Leng (from Dev Box) <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 08:49:54 +00:00
Niels Laute
218a01c1a9 Fix for back up folder path being clipped (#46920)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

Before:
<img width="661" height="530" alt="image"
src="https://github.com/user-attachments/assets/b77c12b2-481f-4f77-8f74-fa679331a604"
/>

After:
<img width="678" height="365" alt="image"
src="https://github.com/user-attachments/assets/ea997ab6-f1f5-4191-ac24-15885b2e19d3"
/>

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

- [x] Closes: #27366
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-14 10:23:58 +02:00
Niels Laute
1c7f3d832c [Text Extractor] Remove WPF-UI in favor of Fluent theming in WPF (#46218)
Replaces the `WPF-UI` dependency in Text Extractor with native WPF
Fluent theming (`ThemeMode="System"`), custom
`SubtleButtonStyle`/`SubtleToggleButtonStyle` control templates, and
Segoe Fluent Icons font — eliminating the third-party library while
retaining light/dark theme support.

## Summary of the Pull Request

- Drops `xmlns:ui` (WPF-UI) from `App.xaml` and `OCROverlay.xaml`
- Removes `Wpf.Ui.Appearance.SystemThemeWatcher.Watch()` call; replaced
by `ThemeMode="System"` on `<Application>`
- Defines inline `SubtleButtonStyle` and `SubtleToggleButtonStyle` using
WinUI-aligned resource brush names (`SubtleFillColorSecondaryBrush`,
`AccentFillColorDefaultBrush`, etc.)
- Replaces `<ui:SymbolIcon>` with `<TextBlock
FontFamily="{DynamicResource SymbolThemeFontFamily}">` using Unicode
glyph codes
- Background uses `SolidBackgroundFillColorBaseBrush` instead of
`ApplicationBackgroundBrush`

| Light | Dark |
|-------|------|
|
![light](https://github.com/user-attachments/assets/dc03fdb3-3ef4-4f18-8352-c58fbdd19dd5)
|
![dark](https://github.com/user-attachments/assets/38fdbd6a-53cb-410d-8486-92927019be2a)
|

## PR Checklist

- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

Related: #46220

## Validation Steps Performed

Verified light and dark themes render correctly with proper accent
highlight on the active toggle button.

---------

Co-authored-by: Joe Finney <josephfinney@LIVE.COM>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
2026-04-14 14:37:27 +08:00
Boliang Zhang (from Dev Box)
0a510119c8 Remove duplicate PowerDisplay model classes after merge from main
The merge from main added a PowerDisplay.Models project reference to
Settings.UI.Library, but the old duplicate model classes (CustomVcpValueMapping
and ColorPresetItem) in Settings.UI.Library/Models/ were not removed, causing
CS0104 ambiguous reference errors. Additionally, two files had stale using
aliases and a XAML DataTemplate referenced the old namespace.

Changes:
- Delete Settings.UI.Library/Models/CustomVcpValueMapping.cs (duplicate)
- Delete Settings.UI.Library/Models/ColorPresetItem.cs (duplicate)
- Update PowerDisplayPage.xaml.cs and PowerDisplayViewModel.cs using directives
- Update PowerDisplayPage.xaml x:DataType to use pdmodels namespace

Verified with local build of both Settings.UI and PowerDisplay projects.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-14 11:08:53 +08:00
moooyo
ff87dce4a4 [PD] Clean up PowerDisplay: fix resource leaks, remove dead code, and fix some bugs (#46979)
- Replace custom GetLastError P/Invoke with Marshal.GetLastWin32Error
and add SetLastError=true
- Fix resource leaks: dispose DpiSuppressor on window close, dispose
MonitorViewModels on refresh, destroy unused small icon handle, wrap WMI
outParams in using block
- Remove unused code: IProfileService, ColorTemperatureHelper,
ProfileHelper (Lib), CustomVcpValueMappingExtensions, IPCMessageAction,
UpdatePropertySilently, LocalizedCodeNameProvider, bring_to_front,
Constants.h
- Convert recursive MccsCapabilitiesParser.TryParseEntry to iterative
loop
- Simplify ProfileService to static class
- Use std::atomic for m_enabled flag in module interface
- Change default activation shortcut to Win+Ctrl+Shift+P
- Add null-coalescing fallback for ActivationShortcut property
- Add PowerDisplay to ModuleHelper name mapping
- Update GPO policy to target PowerToys 0.99.0
- Fix NamedPipeProcessor to break on pipe close and reduce log verbosity
- Add ShortcutControl workaround in Settings UI

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Yu Leng <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4 <noreply@anthropic.com>
2026-04-13 18:00:04 +00:00
Jiří Polášek
758a60103c CmdPal: Include new transitive dependencies in SLNF (#46896)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

This PR adds new transitive dependencies to Command Palette’s SLNF (UI
tests -> UITestAutomation -> ...), and introduces a new SLNF that
excludes UI tests entirely, making it leaner.

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-04-13 11:47:25 -05:00
Copilot
f8cadbf7f0 Fix AlwaysOnTop sound playing when pin/unpin fails (#46910)
## Summary of the Pull Request

`ProcessCommand` played the pin/unpin sound unconditionally, regardless
of whether `SetWindowPos` succeeded. This caused spurious audio feedback
when targeting desktop, taskbar, task view, start menu, or elevated
windows from a non-elevated process.

Gate sound playback on actual state change:

```cpp
bool stateChanged = false;
// ...
if (UnpinTopmostWindow(window)) { stateChanged = true; /* ... */ }
// ...
if (PinTopmostWindow(window))   { stateChanged = true; /* ... */ }
// ...
if (stateChanged && AlwaysOnTopSettings::settings()->enableSound)
    m_sound.Play(soundType);
```

## PR Checklist

- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

`PinTopmostWindow` and `UnpinTopmostWindow` already return `bool`
indicating success, and the existing code already branches on those
return values for bookkeeping and telemetry — but the sound playback at
the end of `ProcessCommand` ignored the result. Added a `stateChanged`
flag set only inside the success branches, then checked before calling
`m_sound.Play()`.

## Validation Steps Performed

- Verified that the `soundType` / `stateChanged` logic covers all four
paths: pin success, pin failure, unpin success, unpin failure.
- Code review passed with no comments.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
2026-04-13 12:53:06 +02:00
Boliang Zhang (from Dev Box)
38dfc55a2d Merge branch 'main' into stable
# Conflicts:
#	src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandItemViewModel.cs
#	src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/MainListPage.cs
#	src/modules/cmdpal/Microsoft.CmdPal.UI/Dock/DockControl.xaml.cs
#	src/modules/cmdpal/Microsoft.CmdPal.UI/Dock/DockWindow.xaml.cs
#	src/modules/keyboardmanager/common/Helpers.cpp
#	src/settings-ui/Settings.UI.Library/MonitorInfo.cs
#	src/settings-ui/Settings.UI.Library/PowerDisplayProperties.cs
#	src/settings-ui/Settings.UI.Library/Settings.UI.Library.csproj
#	src/settings-ui/Settings.UI.Library/SettingsSerializationContext.cs
#	src/settings-ui/Settings.UI/SettingsXAML/Views/CustomVcpMappingEditorDialog.xaml.cs
2026-04-13 16:33:34 +08:00
Niels Laute
0819a6268b [CmdPal] Move dev docs to doc/devdocs/modules/cmdpal (#46926)
## Summary

Move Command Palette developer documentation from
\src/modules/cmdpal/doc\ to \doc/devdocs/modules/cmdpal\, consistent
with the location of other module dev docs.

Also updates the spell-check exclude path for the moved \.pdn\ file.

Points 2 and 3 from the issue (extension settings how-to and details
pane markdown documentation) are addressed in the windows-dev-docs-pr
repo.

Closes #38107

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-12 12:33:30 -05:00
Niels Laute
a31f82fcbd [CmdPal] Fix Window Walker 'Not Responding' tag illegible in dark mode (#46924)
## Summary

The 'Not Responding' tag in Window Walker used a hardcoded crimson
foreground color (rgb 220,20,60) that was illegible against the dark tag
background in dark mode.

**Fix:** Remove the hardcoded color override so the tag uses the default
theme-aware TagForeground brush, which is legible in both light and dark
modes.

Closes #40219

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-12 12:32:49 -05:00
Copilot
daeb2e1ef4 Fix CmdPal Calc extension unit test failure in non-English cultures (#46911)
## Summary of the Pull Request

`TrigModeSettingsTest` fails under cultures using `,` as decimal
separator (e.g., `de-DE`, `fr-FR`). Two root causes: the C++ calculator
engine's `ToWStringFullPrecision` doesn't pin the stream locale, and the
test classes don't set a deterministic thread culture.

## PR Checklist

- [x] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated

## Detailed Description of the Pull Request / Additional comments

**C++ locale fix** — `ExprtkEvaluator.cpp`: `std::wostringstream`
defaults to the global C++ locale, which can be changed to the system
locale by the runtime. Pin it to `std::locale::classic()` so the decimal
separator is always `.` across the WinRT boundary:

```cpp
std::wostringstream oss;
oss.imbue(std::locale::classic());
oss << std::fixed << std::setprecision(15) << value;
```

**Test culture setup** — `QueryTests.cs`, `QueryHelperTests.cs`: Added
`TestInitialize`/`TestCleanup` to set thread culture to `en-US`,
matching the existing pattern across all TimeDate test classes.

**Non-English culture test cases** — New
`TrigModeSettingsTest_NonEnglishCulture` parameterized over `de-DE` and
`fr-FR` verifies `outputUseEnglishFormat: true` produces `.`-separated
output regardless of `CurrentCulture`.

## Validation Steps Performed

- Code review passed with no actionable findings (naming convention
matches existing TimeDate test pattern across 7+ files)
- New `TrigModeSettingsTest_NonEnglishCulture` test exercises the exact
failure scenario from the issue

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
2026-04-12 14:12:34 +02:00
Niels Laute
89b2dfe9ac [KBM] Manual key selection — code review fixes (#46377)
Addresses code review feedback on the KBM manual key selection feature.
No new user-facing behavior; all changes are correctness, robustness,
and maintainability fixes.

## Summary of the Pull Request

- **Localization:** All hard-coded `RemappingDialog.Title` assignments
replaced with `ResourceHelper.GetString()`; added
`RemappingDialog_TitleEdit` resource key
- **VK_DISABLED centralization:** Replaced scattered `0x100`/`"256"`
literals and local `const string vkDisabledCode` with `private const int
VkDisabled = 0x100` / `private const string VkDisabledString = "256"` on
`MainPage`
- **Disable action validation:** Added
`ValidationHelper.ValidateDisableMapping()` — same trigger-key rules as
other action types (empty keys, modifier-only, illegal shortcuts,
duplicates, conflicting modifier variants); wired into
`ValidateMapping()` switch
- **Binding-safe dropdown revert:** `TriggerKeyDropDown_KeyChanged` /
`ActionKeyDropDown_KeyChanged` no longer set `dropDown.KeyName =
e.OldKeyName` on failure (breaks `{Binding}` expression); now use
`RevertKeySelection(keys, index)` which does
`ObservableCollection.RemoveAt` + `Insert` to force a binding-tracked
refresh without touching the DP directly. `NewKeyCode == 0` ("None") is
rejected via the same path
- **Dropdown validation:** `ValidateDropDownSelection` skips
`string.IsNullOrEmpty` placeholder slots (added by
`HandleAutoGrowShrink`) when checking repeated-modifier and max-size
rules
- **`SetActionType`:** Replaced hard-coded `SelectedIndex` with
tag-matching iteration over `ActionTypeComboBox.Items`; immune to XAML
item reorder
- **`ServiceStatusHelper`:** Dispose all `Process` objects returned by
`GetProcessesByName` before returning; prevents handle accumulation on
the 3-second polling timer
- **`KeyDropDownButton.GetKeyList()`:** Filter out `KeyCode == 0`
entries (native "None" sentinel for shortcut lists) before caching
- **`SettingsManager`:** `_mappingService!` used consistently in
`CreateSettingsFromKeyboardManagerService`
- **`KeyboardHookHelper`:** Constructor catch broadened from
`DllNotFoundException or InvalidOperationException` to `Exception`

## PR Checklist

- [ ] **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
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments

The `RevertKeySelection` pattern: in WinUI, assigning directly to a
bound `DependencyProperty` overwrites the binding expression. Using
`ObservableCollection.RemoveAt` + `Insert` instead raises
`CollectionChanged(Replace)`, causing the binding to re-read from the
source without clearing the expression.

```csharp
private static void RevertKeySelection(ObservableCollection<string> keys, int index)
{
    string current = keys[index];
    keys.RemoveAt(index);
    keys.Insert(index, current);
}
```

## Validation Steps Performed

Manually verified: dropdown key selection and revert on invalid
selection, Disable mapping save/load with the new validation, "None"
absent from key picker flyout, `SetActionType` correctly selects items
with preserved XAML order.

---------

Co-authored-by: Zach Teutsch <88554871+zateutsch@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-04-09 13:10:05 -04:00
Jaylyn Barbee
2ef65e7d63 [KBM] Fixes to text replacement issues (#46794)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
This PR attempts to fix some of the issues that were introduced in
0.98.0 with text replacement

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

- [x] Closes: #46498
- [x] Closes: #46440
- [x] Closes: #46366

<!-- 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
In 0.98.0 I made a change to support multiline text replacement using
Ctrl + V. This was very inconsistent so I have reverted back to
_basically_ the same approach we were using before except now when we
encounter a newline indicator we send "Shift + Enter" so that this works
in chat boxes and plan editors.

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Manual testing with single line and multiline replacements in Teams,
Terminal, Git bash, Edge, etc
2026-04-09 13:10:05 -04:00
Zach Teutsch
3dc5b3a3ed [Keyboard Manager] Remove service enable/disable separate from module, fix editor clear shortcut (#46530)
Two changes to shortcuts here:
1) Remove toggling the KBM service with a shortcut or via command
palette
2) Ensure that shortcut is disabled for editor when shortcut is cleared
2026-03-26 13:35:11 -04:00
Zach Teutsch
fc5b65c5c3 [Keyboard Manager] Allow whitespace-only TextRemappings (#46510)
Title.

Closes #46453
2026-03-26 13:35:11 -04:00
Zach Teutsch
da5448b169 fix merge mixup for hotfix 0.98.1 2026-03-24 22:17:10 -04:00
Zach Teutsch
1ab685ee07 Merge 0.98.1 hotfixes into stable
Cherry-picked commits:
- Make KBM Editor pinnable (#46482)
- CmdPal: Fix missing primary context command for late-bound items (#46131)
- CmdPal: Ensure DockWindow property cleans up after itself (#46303)
- CmdPal: Hotfix commonCallbacks array initial count to prevent negative number (#46215)
- CmdPal: Fix missing app context menu actions on the main page (#46293)
- CmdPal: Fix dock popup XamlRoot handling on DockControl (#46305)
- CmdPal: Reduce DockWindow backdrop switching and visual artifacts (#46309)
- Always On Top: The opacity should be able to configure the hotkey individually (#46410)
- [OOBE] Ensure the Settings button on the SCOOBE page opens Home, not a blank page (#46203)
- CmdPal: Fix scroller scrolling and down glyph (#46447)
- [Settings] Decouple Settings.UI.Library from PowerDisplay.Lib to fix (#46325)
2026-03-24 21:25:13 -04:00
Zach Teutsch
cf137ccbbc Merge branch 'main' into stable 2026-03-16 21:39:04 -04:00
Zach Teutsch
2cc051ee33 Merge branch 'main' into stable 2026-03-12 14:29:12 -04:00
Zach Teutsch
efc89b01ff Merge branch 'main' into stable 2026-03-10 22:42:57 -04:00
Zach Teutsch
9717eaac4c Merge branch 'main' into stable 2026-03-09 22:19:50 -04:00
Zach Teutsch
b5716d0499 add kbm ui dll to esrp signing json 2026-03-04 21:58:03 -05:00
Zach Teutsch
a4d23b7607 fix ESRP path for kbm winui 2026-03-04 20:24:20 -05:00
Zach Teutsch
5409b1b907 fix AppListItem.cs dupe function from merge 2026-03-04 18:12:01 -05:00
Zach Teutsch
fbe952715c Merge branch 'main' into stable 2026-03-04 17:05:50 -05:00
Shawn Yuan
034759f949 Fix WinuiEx crash issue (#45443)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Fixes a crash related to `IsShownInSwitchers` when explorer.exe is not
running. The property has been removed from XAML and is now set in the
C# backend with added exception handling to improve stability. No
changes were made for projects where the property is set to true, as
they are not affected.

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: vanzue <vanzue@outlook.com>
2026-02-06 17:31:07 +08:00
Thanh Nguyen
934c3bbce9 Fix CursorWrap "Automatically activate on utility startup" setting not persisting (#45210)
## Summary of the Pull Request

Fixes #45185 - CursorWrap "Automatically activate on utility startup"
setting cannot be disabled, and prevents spurious activation on startup.

## PR Checklist

- [x] Closes: #45185
- [x] **Communication:** Issue was reported by community; fix follows
established patterns from MousePointerCrosshairs
- [x] **Tests:** Manual validation performed by contributor (video
available)
- [x] **Localization:** No new user-facing strings added
- [ ] **Dev docs:** N/A - bug fix only
- [ ] **New binaries:** N/A - no new binaries
- [ ] **Documentation updated:** N/A - bug fix only

## Detailed Description of the Pull Request / Additional comments

### Problem

Users reported that disabling the "Automatically activate on utility
startup" setting for CursorWrap does not work - the mouse hook always
starts automatically regardless of the setting value.

### Root Causes

1. **`dllmain.cpp` `enable()` method**: `StartMouseHook()` was always
called unconditionally, ignoring `m_autoActivate`.
2. **`MouseUtilsViewModel.cs` `IsCursorWrapEnabled` setter**: enabling
CursorWrap forced `AutoActivate = true`, overriding the user's
preference.
3. **Startup edge case**: the trigger event could remain signaled from a
previous session, immediately toggling CursorWrap on startup even when
AutoActivate is off.

### Solution

1. **`src/modules/MouseUtils/CursorWrap/dllmain.cpp`**: only start the
mouse hook if `m_autoActivate` is true.
2. **`src/settings-ui/Settings.UI/ViewModels/MouseUtilsViewModel.cs`**:
remove the line that forced `AutoActivate = true` when enabling
CursorWrap.
3. **`src/modules/MouseUtils/CursorWrap/dllmain.cpp`**: reset the
trigger event on enable to avoid immediate activation on startup.

### Pattern Reference

This fix follows the same pattern used by **MousePointerCrosshairs**
module which has a similar `AutoActivate` setting that works correctly.

## Validation Steps Performed

### Build

- `tools\build\build.ps1 -Platform x64 -Configuration Debug`

### Manual validation (contributor)

#### Test Case 1: AutoActivate = false (should NOT auto-start mouse
hook)

1. Open PowerToys Settings → Mouse Utilities → Cursor Wrap
2. Enable Cursor Wrap
3. **Disable** "Automatically activate on utility startup"
4. Close PowerToys completely (right-click tray icon → Exit)
5. Restart PowerToys
6. **Expected Result**: CursorWrap module is loaded but mouse hook is
NOT active - cursor does NOT wrap at screen edges
7. Press activation hotkey (default: `Win+Alt+U`)
8. **Expected Result**: Mouse hook activates, cursor now wraps at screen
edges
9. **Actual Result**:  Works as expected

#### Test Case 2: AutoActivate = true (should auto-start mouse hook)

1. Open PowerToys Settings → Mouse Utilities → Cursor Wrap
2. Enable Cursor Wrap
3. **Enable** "Automatically activate on utility startup"
4. Close PowerToys completely
5. Restart PowerToys
6. **Expected Result**: Mouse hook is immediately active, cursor wraps
at screen edges without pressing hotkey
7. **Actual Result**:  Works as expected

#### Test Case 3: Setting persistence after restart

1. Set AutoActivate = false, restart PowerToys
2. Open Settings and verify AutoActivate is still false
3. Set AutoActivate = true, restart PowerToys
4. Open Settings and verify AutoActivate is still true
5. **Actual Result**:  Setting persists correctly

#### Test Case 4: Hotkey toggle works correctly

1. With AutoActivate = false, restart PowerToys
2. Press hotkey → cursor should start wrapping
3. Press hotkey again → cursor should stop wrapping
4. **Actual Result**:  Hotkey toggle works correctly

---

**Note**: Video demonstration available from contributor.
2026-02-05 20:34:15 +08:00
Mike Hall
ac548297c9 Add option to disable CursorWrap when on a single monitor. (#45303)
## Summary of the Pull Request
CursorWrap wraps on the outer edge of monitors, if a user is swapping
between a laptop and docked laptop with external monitors the user might
want to only enable wrapping when connected to external monitors, and
disable when only on the laptop.

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

- [ ] Closes: #45198
- [ ] Closes: #45154
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments
Currently CursorWrap will wrap around the horizontal/vertical edges of
monitors, if the user has more than one monitor the outer edges are used
as wrap targets, if the user only has one monitor (perhaps a laptop)
wrapping might be temporarily disabled until additional external
monitors are added (such as being plugged into a dock or using a USB-C
monitor).

The new option will disable wrapping if only a single monitor is
detected, monitor detection is dynamic.

## Validation Steps Performed
Validated on a Surface Laptop 7 Pro (Intel) with a USB-C External
Monitor.

---------

Co-authored-by: Niels Laute <niels.laute@live.nl>
2026-02-05 20:33:49 +08:00
Shawn Yuan
17a215d321 Fix Advanced Paste settings page crash issue (#45207)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
This pull request refactors the `AdvancedPasteAdditionalActions` class
to use private backing fields and custom property accessors for its
action properties. This change allows for better control over property
initialization and ensures that the properties always have valid,
non-null default values.

**Refactoring for property initialization and null safety:**

* Introduced private backing fields (`_imageToText`, `_pasteAsFile`,
`_transcode`) for the `ImageToText`, `PasteAsFile`, and `Transcode`
properties in `AdvancedPasteAdditionalActions`, replacing
auto-properties.
* Updated the property accessors for `ImageToText`, `PasteAsFile`, and
`Transcode` to use the new backing fields and ensure that a new default
instance is assigned if a null value is provided during initialization.
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [x] Closes: #45189
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-02-05 10:37:31 +08:00
Jaylyn Barbee
1b6a8c54ff [Light Switch] Fix Light Switch start up logic (#45304)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Title

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

- [x] Closes: https://github.com/microsoft/PowerToys/issues/45291
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected

<!-- 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
Before, there was a function that initialized some variables about the
current system state that were later used to check against if that state
needed to change in a different function. That caused from some issues
because I was reusing the function for a double purpose. Now the
`SyncInitialThemeState()` function in the State Manager will sync those
initial variables and apply the correct theme if needed.

I also removed an unnecessary parameter from `onTick`

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Manual testing
2026-02-05 10:29:42 +08:00
Kai Tao
67518dd754 Workspace: Fix an overlay issue for workspace snapshot draw (#45183)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Root cause: Workspaces uses DPI-unaware coordinates (via
GetDpiUnawareScreens()
which runs in a temporary DPI-unaware thread) to store/match window
positions
across different DPI settings. However, WorkspacesEditor itself uses
PerMonitorV2
DPI awareness for UI clarity. When assigning these DPI-unaware
coordinates directly
to WPF window properties, WPF automatically scaled them again based on
current DPI,
causing incorrect overlay positioning.

Fix: Use SetWindowPositionDpiUnaware() to bypass WPF's automatic DPI
scaling
by temporarily switching to DPI-unaware context when calling Win32
SetWindowPos.

Fix #45174

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

- [ ] Closes: #45174
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Verified in local build vs production build, and the problem fixed in
local build.
2026-02-05 10:29:36 +08:00
Kai Tao
18d1fd568c PowerToys extension: Bundle localization files into installer (#45194)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [ ] Closes: #45171
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
<img width="925" height="612" alt="image"
src="https://github.com/user-attachments/assets/214ead95-504a-4e48-bc25-138323d973f9"
/>
2026-02-05 10:29:31 +08:00
leileizhang
3eae35f356 [ImageResizer] Fix Image Resizer not working after upgrade on Windows 10 (#45184)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
- Fixes an issue where Image Resizer stops working after upgrading
PowerToys on Windows 10
- Root cause: the PackageIdentityMSIX (sparse app) was not being
properly cleaned up during upgrade

## Problem
Previous versions of PowerToys installed the sparse app on Windows 10.
The current version only installs it on Windows 11+ (build >= 22000).
During upgrade on Windows 10:
1. The `NOT UPGRADINGPRODUCTCODE` condition prevented the uninstall
action from running
2. The Windows 11 version check prevented the new sparse app from being
installed
3. Result: the old sparse app remained on the system, causing Image
Resizer to malfunction

## Fix
Changed the `UninstallPackageIdentityMSIX` condition from:
Installed AND (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
to:
Installed AND (REMOVE="ALL")

This ensures the old sparse app is properly cleaned up during upgrades,
which is also consistent with other similar cleanup

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

- [x] Closes: #45178 #45280
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
1. Install PowerToys version 0.96.1 on Windows 10.
2. Upgrade to version 0.97.1.
3. Run Get-AppxPackage -Name "*Sparse*" in PowerShell to check whether a
Sparse App package is present.
2026-02-05 10:29:25 +08:00
Niels Laute
e349779766 Fix contrast issue (#45367)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [X] Closes: #42261
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-02-05 10:29:19 +08:00
Mike Hall
5466ab6cf8 CursorWrap improvements (#44936)
## Summary of the Pull Request
- Updated engine for better multi-monitor support.
- Closing the laptop lid will now update the monitor topology
- New settings/dropdown to support wrapping on horizontal, vertical, or
both

<img width="1103" height="643" alt="image"
src="https://github.com/user-attachments/assets/ff4f0835-a8ca-4603-9441-123b71747d5c"
/>

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

- [x] Closes: #44820
- [x] Closes: #44864
- [x] Closes: #44952

- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

## Detailed Description of the Pull Request / Additional comments
Feedback for CursorWrap shows that users want the ability to constrain
wrapping for horizontal only, vertical only, or both (default behavior).
This PR adds a new dropdown to CursorWrap settings to enable a user to
select the appropriate wrapping model.

## Validation Steps Performed
Local build and running on Surface Laptop 7 Pro - will also validate on
a multi-monitor setup.

---------

Co-authored-by: vanzue <vanzue@outlook.com>
2026-01-27 13:28:31 +08:00
Heiko
bf19bdc1ee [Enterprise; Policy] Add policy for CursorWrap to ADMX (#45028)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

Added missing policy definition.

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

- [x] Closes: #44897
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [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
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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:** See PR for issue #44484 

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-01-27 11:42:06 +08:00
Jiří Polášek
2441621b80 CmdPal: Remove deadlock bait from AppListItem (#45076)
## Summary of the Pull Request

This PR removes a Task.Wait() call from lazy-loading AppListItem details
that could be invoked on the UI thread and lead to a deadlock.

It now follows the same pattern previously used for loading icons in the
same class, which has proven to work well.

Prevents #44938 from stepping on this landmine.

Cherry-picked from #44973.

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

- [x] Closes: #45074 
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-01-27 10:36:42 +08:00
Shawn Yuan
1ca9d10ff5 [Settings] [Advanced Paste] Upgrade advanced paste settings safely to fix settings ui crash (#44862)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
This pull request makes a minor fix in the `AdvancedPasteViewModel`
constructor to ensure the correct settings repository is used for null
checking. The change improves code correctness by verifying
`advancedPasteSettingsRepository` instead of the generic
`settingsRepository`.

- Fixed null check to use `advancedPasteSettingsRepository` instead of
`settingsRepository` in the `AdvancedPasteViewModel` constructor for
more accurate validation.
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [x] Closes: #44835
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-01-26 16:06:19 +08:00
Gordon Lam
b438f15f6e [Peek] Fix Space key triggering during file rename (#44845) (#44995)
Don't show error window when CurrentItem is null - just return silently.
This restores the original behavior where CaretVisible() detection in
GetSelectedItems() would suppress Peek by returning null, and no window
would be shown.

PR #44703 added an error window for virtual folders (Home/Recent), but
this also triggered when user was typing (rename, search, address bar),
stealing focus and cancelling the operation.

Fixes #44845

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
2026-01-26 16:06:12 +08:00
Shawn Yuan
48de981f50 Add telemetry for tray icon (#44985)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
This pull request adds telemetry tracking for user interactions with the
application's tray icon. Specifically, it introduces new methods for
logging `left-click`, `right-click`, and `double-click` events, and
integrates these telemetry calls into the tray icon event handling
logic.

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-01-26 16:06:06 +08:00
Shawn Yuan
9ab6559fac [Settings] Fix right click menu display issue (#44982)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
This pull request updates the tray icon context menu logic to better
reflect the state of the "Quick Access" feature. The menu now
dynamically updates its items and labels based on whether Quick Access
is enabled or disabled, improving clarity for users.

**Menu behavior improvements:**

* The tray icon menu now reloads itself when the Quick Access setting
changes, ensuring the menu always matches the current state.
* The "Settings" menu item label changes to "Settings\tLeft-click" when
Quick Access is disabled, providing clearer instructions to users.
[[1]](diffhunk://#diff-e5efbda4c356e159a6ca82a425db84438ab4014d1d90377b98a2eb6d9632d32dR176-R179)
[[2]](diffhunk://#diff-7139ecb2cf76e472c574a155268c19e919e2cce05d9d345c50c1f1bffc939e1aR198-R248)
* The Quick Access menu item is removed from the context menu when the
feature is disabled, preventing confusion.

**Internal state tracking:**

* Added a new variable `last_quick_access_state` to track the previous
Quick Access state and trigger menu reloads only when necessary.
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [x] Closes: #44810
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

<!-- 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
- When Quick Access is disabled

<img width="1537" height="312" alt="image"
src="https://github.com/user-attachments/assets/5d51f24e-ccb4-4973-afaa-8b64cc35db87"
/>

- When Quick Access is enabled
<img width="1601" height="201" alt="image"
src="https://github.com/user-attachments/assets/56366d10-bcec-4892-b2d2-f8213ad726aa"
/>

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-01-26 16:05:58 +08:00
moooyo
8cc32d3098 fix: Improve Unicode normalization and add regex metachar tests (#44944)
Enhanced SanitizeAndNormalize to handle Unicode normalization more
robustly, ensuring correct buffer sizing and error handling. Added unit
tests for regex metacharacters `$` and `^` to verify correct replacement
behavior at string boundaries. Improves Unicode support and test
coverage for regex edge cases.

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [x] Closes: #44942 #44892
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Yu Leng <yuleng@microsoft.com>
2026-01-26 16:05:54 +08:00
Jiří Polášek
3b7eedfb67 CmdPal: Improve loading of application icons - part 1 (#44938)
## Summary of the Pull Request

This PR improves loading of application icons:

- Fixes loading of icons from internet shortcuts

## Pictures? Pictures!

<img width="683" height="399" alt="image"
src="https://github.com/user-attachments/assets/5e566648-7b1a-4254-8afd-557a321b19d6"
/>


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

- [x] Closes: #44819
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-01-26 16:05:49 +08:00
Kai Tao
d7e1b18ba4 Runner TrayIcon: Monochrome icon should adapt to windows theme instead of the app theme (#44931)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
As title
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [X] Closes: #44891
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
============ System light + App Light
<img width="903" height="239" alt="image"
src="https://github.com/user-attachments/assets/581606fb-99b5-4df9-a520-545a0c04676c"
/>
============ System Light + App Dark
<img width="991" height="239" alt="image"
src="https://github.com/user-attachments/assets/822009e9-57cf-452b-b3aa-f1cbc25883f8"
/>
============ System Dark + App Light
<img width="932" height="236" alt="image"
src="https://github.com/user-attachments/assets/98a56d48-31f0-4f75-95a4-8c7dc83c3866"
/>
============ System Dark + App Dark
<img width="903" height="236" alt="image"
src="https://github.com/user-attachments/assets/2500a0d5-6b27-403e-89b4-69b7d3b91e79"
/>
============
2026-01-26 16:05:43 +08:00
Kai Tao
0206fdbec1 Cmdpal: use latest msix to install (#44886)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
We should install latest cmdpal msix
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ ] Closes: #44860
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-01-26 16:05:36 +08:00
Leilei Zhang
bdaf644f02 test sign 2026-01-19 14:29:46 +08:00
moooyo
329c8c2616 refactor(imageresizer): disable AI feature and cache functionality (#44759)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- 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: Yu Leng <yuleng@microsoft.com>
2026-01-19 10:51:10 +08:00
Niels Laute
b081e413b1 Upgrade MarkdownTextBlock (#44793)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

This PR:

- upgrades `CommunityToolkit.WinUI.Labs.MarkdownTextBlock` to version
`0.1.260116-build.2514`. This update includes a bunch of improvements
for markdown rendering in its default config, and fixes a couple of bug
with regards to rendering large images getting clipped when resizing the
window.
- replaces an incorrect image in the `Command Palette Sample Page`
extension for the markdown + images sample.

Before vs after:

<img width="910" height="234" alt="image"
src="https://github.com/user-attachments/assets/b3dad76c-a89e-4b47-90f8-d3c64f00615f"
/>


<img width="1245" height="827" alt="image"
src="https://github.com/user-attachments/assets/00037fb5-453e-4d85-83c9-92c265b9f968"
/>



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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-01-19 09:56:30 +08:00
leileizhang
290fa01adf [ImageResizer] Temporarily disable AI Super Resolution feature (#44768)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Temporarily disables the AI Super Resolution feature in Image Resizer
while keeping all code intact for re-enabling in a future release.

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

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **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
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [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)
- [ ] **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: #xxx

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-01-17 11:28:47 +08:00
1170 changed files with 85031 additions and 16563 deletions

View File

@@ -57,6 +57,7 @@ body:
- Environment Variables
- FancyZones
- FancyZones Editor
- Grab And Move
- File Locksmith
- "File Explorer: Preview Pane"
- "File Explorer: Thumbnail preview"
@@ -69,6 +70,7 @@ body:
- Mouse Without Borders
- New+
- Peek
- Power Display
- PowerRename
- PowerToys Run
- Quick Accent

View File

@@ -51,6 +51,7 @@ resw
resx
srt
Stereolithography
taskmgr
terabyte
UYVY
xbf
@@ -127,6 +128,7 @@ HOLDSPACE
HOLDBACKSPACE
IDIGNORE
KBDLLHOOKSTRUCT
keydowns
keyevent
LAlt
LBUTTON
@@ -185,6 +187,12 @@ xmlutil
# Prefix
pcs
# EXPRTK / C++ MATH
ifunction
isinf
isnan
# User32.SYSTEM_METRICS_INDEX.cs
CLEANBOOT
@@ -309,6 +317,7 @@ onefuzz
# NameInCode
leilzh
mengyuanchen
contoso
# DllName
testhost
@@ -328,19 +337,38 @@ MRUCMPPROC
MRUINFO
REGSTR
#Xaml
NVI
Storyboards
# Misc Win32 APIs and PInvokes
DEFAULTTONEAREST
INVOKEIDLIST
LCMAP
MEMORYSTATUSEX
ABE
Mdt
HTCAPTION
POSCHANGED
QPC
QUERYPOS
SETAUTOHIDEBAR
ULW
WINDOWPOS
WINEVENTPROC
WORKERW
FULLSCREENAPP
ACLO
CACLI
DOENVSUBST
FILESYSONLY
URLIS
WAITTIMEOUT
DEFAULTTONEAREST
DWRITE
LWIN
VCENTER
VREDRAW
# COM/WinRT interface prefixes and type fragments
BAlt
@@ -375,6 +403,12 @@ YYY
# Unicode
precomposed
# names of characters
zwsp
# mermaid
autonumber
# GitHub issue/PR commands
azp
feedbackhub
@@ -391,3 +425,10 @@ Nonpaged
# XAML
Untargeted
# Program names
SEARCHHOST
SHELLEXPERIENCEHOST
SHELLHOST
STARTMENUEXPERIENCEHOST
WIDGETBOARD

View File

@@ -209,6 +209,7 @@ Bilibili
BVID
capturevideosample
cmdow
contoso
Contoso
Controlz
cortana

View File

@@ -7,7 +7,9 @@ AUDCLNT
axisdefer
axisflip
axisstart
BGRX
bitmaps
blits
BREAKSCR
BUFFERFLAGS
Cands
@@ -17,6 +19,7 @@ CLASSW
coeffs
coprime
CREATEDIBSECTION
CREATESTRUCTW
crossfades
Ctl
CTLCOLOR
@@ -25,7 +28,10 @@ CTLCOLORDLG
CTLCOLOREDIT
CTLCOLORLISTBOX
CTrim
DBuffer
ddx
ddy
DEVSOURCE
DFCS
dlg
dlu
@@ -41,11 +47,14 @@ dupsegments
DWLP
EDITCONTROL
ENABLEHOOK
ENDOFSTREAM
expectedlock
fabsf
fastscroll
FDE
GETCHANNELRECT
GETCHECK
GETCOUNT
GETSCREENSAVEACTIVE
GETSCREENSAVETIMEOUT
GETTHUMBRECT
@@ -57,6 +66,7 @@ HTHEME
htol
ICONINFORMATION
ICONWARNING
igc
Inj
jumprecover
KSDATAFORMAT
@@ -78,9 +88,11 @@ manualdrop
maskcache
maxstep
MENUINFO
MFSTARTUP
mfxhw
mic
middledrop
middledrop
MJPEG
MMRESULT
momentumreversal
mrate
@@ -92,6 +104,7 @@ nduplicates
niterations
nmonitor
NONCLIENTMETRICS
NONOTIFY
nonvle
nredraw
nstop
@@ -102,16 +115,22 @@ osc
OWNERDRAW
PBGRA
periodictrap
pillarbox
pfdc
playhead
pointerreuse
PSWA
pwfx
qpc
Qpc
quantums
RCZOOMITSCR
readback
READERF
realcapture
REFKNOWNFOLDERID
reposted
RETURNCMD
SCREENSAVE
SCRNSAVE
SCRNSAVECONFIGURE
@@ -131,6 +150,7 @@ shortlist
slowthenfast
smallstart
SNIPOCR
sqrtf
ssi
startuprecovery
stf
@@ -139,6 +159,7 @@ STREAMFLAGS
submix
sxx
sxy
synthesising
syy
tallportal
tci
@@ -154,6 +175,7 @@ vaddvq
vandq
vcgeq
vdup
VIDCAP
vld
vle
Vle
@@ -169,6 +191,9 @@ vsync
WASAPI
WAVEFORMATEX
WAVEFORMATEXTENSIBLE
webcam
Webcam
webcams
wfopen
wideportal
wil

View File

@@ -1,6 +1,3 @@
# D2D
#D?2D
# Repeated letters
\b([a-z])\g{-1}{2,}\b
@@ -14,7 +11,7 @@
^.*\b[Cc][Ss][Pp][Ee][Ll]{2}:\s*[Dd][Ii][Ss][Aa][Bb][Ll][Ee]-[Ll][Ii][Nn][Ee]\b
# copyright
Copyright (?:\([Cc]\)|)(?:[-\d, ]|and)+(?: [A-Z][a-z]+ [A-Z][a-z]+,?)+
Copyright (?:\([Cc]\)|©|)(?:[-\d, ]|and)+(?: [A-Z][a-z]+ [A-Z][a-z]+,?)+
# patch hunk comments
^@@ -\d+(?:,\d+|) \+\d+(?:,\d+|) @@ .*
@@ -22,10 +19,10 @@ Copyright (?:\([Cc]\)|)(?:[-\d, ]|and)+(?: [A-Z][a-z]+ [A-Z][a-z]+,?)+
index (?:[0-9a-z]{7,40},|)[0-9a-z]{7,40}\.\.[0-9a-z]{7,40}
# file permissions
['"`\s][-bcdLlpsw](?:[-r][-w][-Ssx]){2}[-r][-w][-SsTtx]\+?['"`\s]
(?:^|['"`\s])(?!-+\s)[-bcdLlpsw](?:[-r][-w][-Ssx]){2}[-r][-w][-SsTtx]\+?['"`\s]
# css fonts
\bfont(?:-family|):[^;}]+
\bfont(?:-family(?:[-\w+]*)|):[^;}]+
# css url wrappings
\burl\([^)]+\)
@@ -90,6 +87,9 @@ arn:aws:[-/:\w]+
# AWS VPC
vpc-\w+
# Azure AD
\baad\.\w{48}\b
# While you could try to match `http://` and `https://` by using `s?` in `https?://`, sometimes there
# YouTube url
\b(?:(?:www\.|)youtube\.com|youtu.be)/(?:channel/|embed/|user/|playlist\?list=|watch\?v=|v/|)[-a-zA-Z0-9?&=_%]*
@@ -171,7 +171,7 @@ themes\.googleusercontent\.com/static/fonts/[^/\s"]+/v\d+/[^.]+.
GHSA(?:-[0-9a-z]{4}){3}
# GitHub actions
\buses:\s+[-\w.]+/[-\w./]+@[-\w.]+
\buses:\s+(['"]?)[-\w.]+/[-\w./]+@[-\w.]+\g{-1}
# GitLab commit
\bgitlab\.[^/\s"]*/\S+/\S+/commit/[0-9a-f]{7,16}#[0-9a-f]{40}\b
@@ -240,7 +240,7 @@ accounts\.binance\.com/[a-z/]*oauth/authorize\?[-0-9a-zA-Z&%]*
\bmedium\.com/@?[^/\s"]+/[-\w]+
# microsoft
\b(?:https?://|)(?:(?:(?:blogs|download\.visualstudio|docs|msdn2?|research)\.|)microsoft|blogs\.msdn)\.co(?:m|\.\w\w)/[-_a-zA-Z0-9()=./%]*
\b(?:https?://|)(?:(?:(?:blogs|download\.visualstudio|docs|msdn2?|research)\.|)microsoft|blogs\.msdn)\.co(?:m|\.\w\w)/[-_a-zA-Z0-9()=./%?#]*
# powerbi
\bapp\.powerbi\.com/reportEmbed/[^"' ]*
# vs devops
@@ -414,7 +414,7 @@ ipfs://[0-9a-zA-Z]{3,}
\bgetopts\s+(?:"[^"]+"|'[^']+')
# ANSI color codes
(?:\\(?:u00|x)1[Bb]|\\03[1-7]|\x1b|\\u\{1[Bb]\})\[\d+(?:;\d+)*m
(?:\\(?:u00|x)1[Bb]|\\03[1-7]|\x1b|\\u\{1[Bb]\})\[(?:\d+(?:;\d+)*|)m
# URL escaped characters
%[0-9A-F][A-F](?=[A-Za-z])
@@ -431,7 +431,7 @@ sha\d+:[0-9a-f]*?[a-f]{3,}[0-9a-f]*
# sha-... -- uses a fancy capture
(\\?['"]|&quot;)[0-9a-f]{40,}\g{-1}
# hex runs
\b[0-9a-fA-F]{16,}\b
\b(?=(?:[a-fA-F]{0,2}\d)*[a-fA-F]{3})[0-9a-fA-F]{16,}\b
# hex in url queries
=[0-9a-fA-F]*?(?:[A-F]{3,}|[a-f]{3,})[0-9a-fA-F]*?&
# ssh
@@ -455,7 +455,11 @@ LS0tLS1CRUdJT.*
# uuid:
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
# hex digits including css/html color classes:
# unicode escaped characters (4)
\\u[0-9a-fA-F]{4}
# hex digits including css/html color classes
(?:[\\0][xX]|\\u\{?|[uU]\+|#x?|%23|&H)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|[iu]\d+)\b
# integrity
@@ -478,7 +482,7 @@ Name\[[^\]]+\]=.*
(?:(?:\b|_|(?<=[a-z]))I|(?:\b|_)(?:nsI|isA))(?=(?:[A-Z][a-z]{2,})+(?:[A-Z\d]|\b))
# python
#\b(?i)py(?!gments|gmy|lon|ramid|ro|th)(?=[a-z]{2,})
#\b(?i)py(?!gment|gmy|lon|ramid|ro|th)(?=[a-z]{2,})
# crypt
(['"])\$2[ayb]\$.{56}\g{-1}
@@ -498,12 +502,21 @@ Name\[[^\]]+\]=.*
# go.sum
\bh1:\S+
# golang print-f-style functions
#(?i)(?<=append|comma|debug|equal|err|error|exit|fatal|format|info|log|name|panic|print|skip|scan|string|trace|true|warn|warning|wrap|write)(?:f|ln)(?:[ (]|$)
# golang regular expression
(?<!")\br".+?"
# imports
^import\s+(?:(?:static|type)\s+|)(?:[\w.]|\{\s*\w*?(?:,\s*(?:\w*|\*))+\s*\})+
^import\s+(?:(?:static|type)\s+|)(?:[\w.]|\{\s*\w*?(?:,\s*(?:\w*|\*))+\s*\})+(?:\s+from (['"]).*?\g{-1}|)
# scala modules
#("[^"]+"\s*%%?\s*){2,3}"[^"]+"
# Dataframes / NumPy
#\b(?:df|np)\.\w{3,}
# container images
image: [-\w./:@]+
@@ -533,12 +546,18 @@ content: (['"])[-a-zA-Z=;:/0-9+]*=\g{-1}
# Note that there's a high false positive rate, remove the `?=` and search for the regex to see if the matches seem like reasonable strings
(?<!['"])\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)['"](?=[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})
# Regular expression for word breaks
#\\b(?=[a-z]{2})
# Regular expressions for (P|p)assword
\([A-Z]\|[a-z]\)[a-z]+
# Java regular expressions
Pattern\.(?:compile|matches)\(".*"
# JavaScript regular expressions
# javascript test regex
/.{3,}/[gim]*\.test\(
# javascript exec/test regex
/.{3,}?/[gim]*\.(?:exec|test)\(
# javascript match regex
\.match\(/[^/\s"]{3,}/[gim]*\s*
# javascript match regex
@@ -565,7 +584,7 @@ perl(?:\s+-[a-zA-Z]\w*)+
regexp?\.MustCompile\((?:`[^`]*`|".*"|'.*')\)
# regex choice
# \(\?:[^)]+\|[^)]+\)
#\((?:\?:|)[^)|]+(?<! )\|(?!(?:jq|xargs)\b)[^)| ][^)]*\)
# proto
^\s*(\w+)\s\g{-1} =
@@ -588,6 +607,9 @@ urn:shemas-jetbrains-com
# Debian changelog severity
[-\w]+ \(.*\) (?:\w+|baseline|unstable|experimental); urgency=(?:low|medium|high|emergency|critical)\b
# Red Hat Package management spec file dependencies
^(?:Build|)Requires: [-.\w]+
# kubernetes pod status lists
# https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
\w+(?:-\w+)+\s+\d+/\d+\s+(?:Running|Pending|Succeeded|Failed|Unknown)\s+
@@ -642,6 +664,8 @@ PrependWithABINamepsace
>[-a-zA-Z=;:/0-9+]{3,}=</
# base64 encoded content, possibly wrapped in mime
#(?:^|[\s=;:?])[-a-zA-Z=;:/0-9+]{50,}(?:[\s=;:?]|$)
# jwt
(?:\be[wy][-a-zA-Z=;:/0-9+]+\.){2}[-_\w]+
# base64 encoded json
\beyJ[-a-zA-Z=;:/0-9+]+
# base64 encoded pkcs
@@ -679,9 +703,9 @@ systemd.*?running in system mode \([-+].*\)$
# Non-English
# Even repositories expecting pure English content can unintentionally have Non-English content... People will occasionally mistakenly enter [homoglyphs](https://en.wikipedia.org/wiki/Homoglyph) which are essentially typos, and using this pattern will mean check-spelling will not complain about them.
#
# .
# If the content to be checked should be written in English and the only Non-English items will be people's names, then you can consider adding this.
#
# .
# Alternatively, if you're using check-spelling v0.0.25+, and you would like to _check_ the Non-English content for spelling errors, you can. For information on how to do so, see:
# https://docs.check-spelling.dev/Feature:-Configurable-word-characters.html#unicode
[a-zA-Z]*[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*|[a-zA-Z]{3,}[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]|[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3,}
@@ -693,7 +717,7 @@ systemd.*?running in system mode \([-+].*\)$
# This corpus only had capital letters, but you probably want lowercase ones as well.
\b[LN]'+[a-z]{2,}\b
# latex (check-spelling >= 0.0.22)
# LaTeX
\\\w{2,}\{
# American Mathematical Society (AMS) / Doxygen
@@ -720,7 +744,6 @@ nolint:\s*[\w,]+
# cygwin paths
/cygdrive/[a-zA-Z]/(?:Program Files(?: \(.*?\)| ?)(?:/[-+.~\\/()\w ]+)*|[-+.~\\/()\w])+
# in check-spelling@v0.0.22+, printf markers aren't automatically consumed
# printf markers
#(?<!\\)\\[nrt](?=[a-z]{2,})
# alternate printf markers if you run into latex and friends
@@ -749,12 +772,12 @@ W/"[^"]+"
# Compiler flags (Unix, Java/Scala)
# Use if you have things like `-Pdocker` and want to treat them as `docker`
#(?:^|[\t ,>"'`=(#])-(?:(?:J-|)[DPWXY]|[Llf])(?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
#(?:^|[\t ,>"'`=\[(#])-(?:(?:J-|)[DPWXY]|[Llf])(?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
# Compiler flags (Windows / PowerShell)
# This is a subset of the more general compiler flags pattern.
# It avoids matching `-Path` to prevent it from being treated as `ath`
#(?:^|[\t ,"'`=(#])-(?:[DPL](?=[A-Z]{2,})|[WXYlf](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,}))
#(?:^|[\t ,"'`=\[(#])-(?:[DPL](?=[A-Z]{2,})|[WXYlf](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,}))
# Compiler flags (linker)
,-B
@@ -762,7 +785,7 @@ W/"[^"]+"
# Library prefix
# e.g., `lib`+`archive`, `lib`+`raw`, `lib`+`unwind`
# (ignores some words that happen to start with `lib`)
(?:\b|_)[Ll]ib(?:re(?=office)|)(?!era[lt]|ero|erty|rar(?:i(?:an|es)|y))(?=[a-z])
(?:\b|_)[Ll]ib(?!era[lt])(?:re(?=office)|era|)(?!ero|erty|rar(?:i(?:an|es)|y))(?=[a-z])
# iSCSI iqn (approximate regex)
\biqn\.[0-9]{4}-[0-9]{2}(?:[\.-][a-z][a-z0-9]*)*\b
@@ -773,9 +796,9 @@ W/"[^"]+"
# curl arguments
\b(?:\\n|)curl(?:\.exe|)(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)*
# set arguments
\b(?:bash|sh|set)(?:\s+[-+][abefimouxE]{1,2})*\s+[-+][abefimouxE]{3,}(?:\s+[-+][abefimouxE]+)*
\b(?:bash|(?<!\.)sh|set)(?:\s+[-+][abefimouxE]{1,2})*\s+[-+][abefimouxE]{3,}(?:\s+[-+][abefimouxE]+)*
# tar arguments
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
\b(?:\\n|)g?tar(?:\.exe|)(?:\s-C \S+|(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
# tput arguments -- https://man7.org/linux/man-pages/man5/terminfo.5.html -- technically they can be more than 5 chars long...
\btput\s+(?:(?:-[SV]|-T\s*\w+)\s+)*\w{3,5}\b
# macOS temp folders

View File

@@ -112,6 +112,8 @@
^src/modules/cmdpal/Microsoft\.CmdPal\.UI/Settings/InternalPage\.SampleData\.cs$
^src/modules/cmdpal/Tests/Microsoft\.CmdPal\.Common\.UnitTests/.*\.TestData\.cs$
^src/modules/cmdpal/Tests/Microsoft\.CmdPal\.Common\.UnitTests/Text/.*\.cs$
^src/modules/cmdpal/Tests/Microsoft\.CommandPalette\.Extensions\.Toolkit\.UnitTests/FuzzyMatcherComparisonTests.cs$
^src/modules/cmdpal/Tests/Microsoft\.CommandPalette\.Extensions\.Toolkit\.UnitTests/FuzzyMatcherDiacriticsTests.cs$
^src/modules/colorPicker/ColorPickerUI/Shaders/GridShader\.cso$
^src/modules/launcher/Plugins/Microsoft\.PowerToys\.Run\.Plugin\.TimeDate/Properties/
^src/modules/MouseUtils/MouseJumpUI/MainForm\.resx$
@@ -143,3 +145,4 @@ ignore$
src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleMarkdownImagesPage.cs
^src/modules/powerrename/unittests/testdata/avif_test\.avif$
^src/modules/powerrename/unittests/testdata/heif_test\.heic$
^deps/spdlog-msvc-fix/

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,10 +1,30 @@
# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns
Inno Setup
FFmpeg
# https://github.com/MicrosoftEdge/edge-launcher
MIcrosoftEdgeLauncherCsharp
# x64
(?:(?<=[a-df-z])x|(?<=[A-Z]X))64
# reversed irreversible binomials
\b(?:mouse down and up|low and high)\b
# marker to ignore all code on line
^.*/\* #no-spell-check-line \*/.*$
# marker for ignoring a comment to the end of the line
// #no-spell-check.*$
# JavaScript regex literals that start with \b can be reported as "b..." words.
# Example: /\bclass\s+.../
^\s*/\\[b].{3,}?/[gim]*\s*(?:\)(?:;|$)|,$)
# GitHub API header token used in code (not natural language).
\bx-ratelimit-reset\b
# Gaelic
Gàidhlig
@@ -71,11 +91,14 @@ StringComparer.OrdinalIgnoreCase\) \{.*\}
# the last line of mimetype="application/x-microsoft.net.object.bytearray.base64" things in .resx files
^\s*[-a-zA-Z=;:/0-9+]*[-a-zA-Z;:/0-9+][-a-zA-Z=;:/0-9+]*=$
# DateTime Formats
Get-Date -Format \w+|DateTime\.Now(?::|\.ToString\(")\w+
# Automatically suggested patterns
# hit-count: 5402 file-count: 1339
# IServiceProvider / isAThing
(?:(?:\b|_|(?<=[a-z]))[IT]|(?:\b|_)(?:nsI|isA))(?=(?:[A-Z][a-z]{2,})+(?:[A-Z\d]|\b))
(?:(?:\b|_|(?<=[a-z]))[A-Z]|(?:\b|_)(?:nsI|isA))(?=(?:[A-Z][a-z]{2,})+(?:[A-Z\d]|\b))
# hit-count: 2073 file-count: 842
# #includes
@@ -159,6 +182,10 @@ aka\.ms/[a-zA-Z0-9]+
# kubernetes crd patterns
^\s*pattern: .*$
# hit-count: 7 file-count: 3
# unicode escaped characters (4)
\\u[0-9a-fA-F]{4}
# hit-count: 5 file-count: 3
# URL escaped characters
%[0-9A-F][A-F](?=[A-Za-z])
@@ -171,6 +198,10 @@ aka\.ms/[a-zA-Z0-9]+
# medium
\bmedium\.com/@?[^/\s"]+/[-\w:/*.]+
# hit-count: 2 file-count: 2
# tar arguments
\b(?:\\n|)g?tar(?:\.exe|)(?:\s-C \S+|(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
# hit-count: 2 file-count: 1
# While you could try to match `http://` and `https://` by using `s?` in `https?://`, sometimes there
# YouTube url
@@ -184,10 +215,6 @@ aka\.ms/[a-zA-Z0-9]+
# curl arguments
\b(?:\\n|)curl(?:\.exe|)(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)*
# hit-count: 1 file-count: 1
# tar arguments
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
# #pragma lib
^\s*#pragma comment\(lib, ".*?"\)
@@ -210,13 +237,15 @@ RegExp\(@?([`'"]).*?\g{-1}\)|(?:escapes|regEx):\s*(?:/.*/|([`'"]).*?\g{-1})|retu
# mount
\bmount\s+-t\s+(\w+)\s+\g{-1}\b
# C types and repeated CSS values
\s(auto|buffalo|center|div|inherit|long|LONG|none|normal|solid|thin|transparent|very)(?:\s\g{-1})+\s
\s(auto|await|buffalo|center|div|inherit|long|LONG|none|normal|solid|thin|transparent|very)(?:\s\g{-1})+\s
# C enum and struct
\b(?:enum|struct)\s+(\w+)\s+\g{-1}\b
# go templates
\s(\w+)\s+\g{-1}\s+\`(?:graphql|inject|json|yaml):
# doxygen / javadoc / .net
(?:[\\@](?:brief|defgroup|groupname|link|t?param|return|retval)|(?:public|private|\[Parameter(?:\(.+\)|)\])(?:\s+(?:static|override|readonly|required|virtual))*)(?:\s+\{\w+\}|)\s+(\w+)\s+\g{-1}\s
# C# getter/setter
\s(\w+)\s+\g{-1}\s*\{\s*[gs]et;
# macOS file path
(?:Contents\W+|(?!iOS)/)MacOS\b

View File

@@ -1,23 +1,30 @@
^attache$
^bellows?$
attache
aroynt.*
bellows?
benefitting
occurences?
^dependan.*
^develope$
^developement$
^developpe
^Devers?$
^devex
^devide
^Devinn?[ae]
^devisal
^devisor
^diables?$
^oer$
.*dnt
dependan.*
developement
developp?e
Devers?
devex.*
devide
Devinn?[ae]
devisals?
devisors?
diables?
hasta?
hastat.*
immediatly
inisle
inital
linge
oer
Sorce
^[Ss]pae.*
^Teh$
^untill$
^untilling$
^venders?$
^wether.*
[Ss]pae.*
Teh
untill
untilling
venders?
wether.*

View File

@@ -163,7 +163,7 @@ configuration:
association: Collaborator
then:
- addReply:
reply: Hi! We've identified this issue as a duplicate of another one that already exists on this Issue Tracker. This specific instance is being closed in favor of tracking the concern over on the referenced thread. Thanks for your report!
reply: We've identified this issue as a duplicate of an existing one and are closing this thread so discussion stays in one place.<br/><br/>Please see the comment above for the link to the original tracking issue, and feel free to subscribe there for updates.
- closeIssue
- removeLabel:
label: Needs-Triage
@@ -266,16 +266,5 @@ configuration:
- addReply:
reply: Hi! Your last comment indicates to our system, that you might want to contribute to this feature/fix this bug. Thank you! Please make us aware on our ["Would you like to contribute to PowerToys?" thread](https://github.com/microsoft/PowerToys/issues/28769), as we don't see all the comments. <br /><br />_I'm a bot (beep!) so please excuse any mistakes I may make_
description:
- if:
- payloadType: Issues
- isAction:
action: Opened
- bodyContains:
pattern: 'Area\(s\) with issue\?\s*\nWorkspaces'
isRegex: True
then:
- addLabel:
label: Product-Workspaces
description:
onFailure:
onSuccess:

377
.github/scripts/telemetry-pr-check.js vendored Normal file
View File

@@ -0,0 +1,377 @@
#!/usr/bin/env node
/**
* Detects telemetry-event additions/modifications in a pull request and
* posts (or updates) a PR comment when telemetry-related changes are found.
*
* This script is executed by .github/workflows/telemetry-pr-check.yml.
* Keep both files aligned when changing trigger behavior, env usage, or messaging.
*/
const fs = require('node:fs');
const REVIEWER_LOGIN = 'chatasweetie';
const REVIEWER_MENTION = `@${REVIEWER_LOGIN}`;
const COMMENT_MARKER = '<!-- telemetry-event-check -->';
const COMMENT_BODY_WITH_PRIVACY_UPDATE = `${COMMENT_MARKER}
Thank you for contributing to PowerToys. We've detected that this PR might include a new or modified telemetry event. After this PR is merged, please follow these next steps:
- [ ] Reach out to Jessica (${REVIEWER_MENTION}) to follow up on the next steps: https://aka.ms/pt-telemetry-process
`;
const COMMENT_BODY_WITHOUT_PRIVACY_UPDATE = `${COMMENT_MARKER}
Thank you for contributing to PowerToys. We've detected that this PR might include a new or modified telemetry event. Please ensure the following before merging:
- [ ] Add your telemetry events to [DATA_AND_PRIVACY](https://github.com/microsoft/PowerToys/blob/main/DATA_AND_PRIVACY.md).md within this PR.
- [ ] Reach out to Jessica (${REVIEWER_MENTION}) to follow up on the next steps: https://aka.ms/pt-telemetry-process`;
const TELEMETRY_PATH_PATTERNS = [
/(^|\/)trace\.(h|hpp|cpp|cs)$/i,
/(^|\/)telemetry\//i,
/(^|\/)events\/.+event\.cs$/i,
/^src\/common\/Telemetry\//i,
/^src\/common\/ManagedTelemetry\//i,
/^src\/runner\/trace\.(h|cpp)$/i,
/^src\/settings-ui\/.+\/Telemetry\//i,
];
const TELEMETRY_LINE_PATTERNS = [
/TraceLoggingWriteWrapper\s*\(/,
/\bTraceLoggingWrite\s*\(/,
/\bTRACELOGGING_DEFINE_PROVIDER\b/,
/\bTraceLoggingOptionProjectTelemetry\b/,
/\bProjectTelemetryPrivacyDataTag\b/,
/\bPROJECT_KEYWORD_MEASURE\b/,
/\bRegisterProvider\s*\(/,
/\bUnregisterProvider\s*\(/,
/\bPowerToysTelemetry\.Log\.WriteEvent\s*\(/,
/\bclass\s+\w+\s*:\s*EventBase\s*,\s*IEvent\b/,
/\bclass\s+\w+\s*:\s*TelemetryBase\b/,
/\bPartA_PrivTags\b/,
/\[EventData\]/,
/\bEventName\b/,
];
function requireEnv(name) {
const value = process.env[name];
if (!value) {
throw new Error(`Missing required environment variable: ${name}`);
}
return value;
}
function validateRepository(repository) {
if (!/^[^/]+\/[^/]+$/.test(repository)) {
throw new Error(
`GITHUB_REPOSITORY must be in owner/repo format, received: ${JSON.stringify(repository)}`
);
}
}
function readEventPayload(eventPath) {
let raw;
try {
raw = fs.readFileSync(eventPath, 'utf8');
} catch (error) {
throw new Error(`Failed to read event payload at ${eventPath}: ${error.message}`);
}
try {
return JSON.parse(raw);
} catch (error) {
throw new Error(`Failed to parse JSON from ${eventPath}: ${error.message}`);
}
}
function resolvePullNumber(event) {
const fromPullRequest = event?.pull_request?.number;
const fromWorkflowDispatch = event?.inputs?.pr_number;
const rawPullNumber = fromPullRequest ?? fromWorkflowDispatch;
if (rawPullNumber === undefined || rawPullNumber === null || rawPullNumber === '') {
throw new Error(
'Unable to determine pull request number from event payload. Expected pull_request.number or inputs.pr_number.'
);
}
const pullNumber = Number.parseInt(String(rawPullNumber), 10);
if (!Number.isInteger(pullNumber) || pullNumber <= 0) {
throw new Error(`Invalid pull request number: ${JSON.stringify(rawPullNumber)}`);
}
return pullNumber;
}
function isTelemetryPath(filePath) {
return TELEMETRY_PATH_PATTERNS.some((pattern) => pattern.test(filePath));
}
function changedLinesFromPatch(patch) {
if (!patch) {
return [];
}
return patch
.split('\n')
.filter((line) => {
if (line.startsWith('+++') || line.startsWith('---')) {
return false;
}
return line.startsWith('+') || line.startsWith('-');
})
.map((line) => line.slice(1));
}
function hasTelemetryLineSignal(lines) {
return lines.some((line) => TELEMETRY_LINE_PATTERNS.some((pattern) => pattern.test(line)));
}
async function apiRequest(url, method = 'GET', body) {
const token = requireEnv('GITHUB_TOKEN');
let response;
try {
response = await fetch(url, {
method,
headers: {
Authorization: `Bearer ${token}`,
Accept: 'application/vnd.github+json',
'Content-Type': 'application/json',
},
body: body ? JSON.stringify(body) : undefined,
});
} catch (error) {
throw new Error(`Network error during ${method} ${url}: ${error.message}`);
}
if (!response.ok) {
const text = await response.text();
const rateLimitReset = response.headers.get('x-ratelimit-reset');
const rateLimitHint =
response.status === 403 && rateLimitReset
? ` (rate limit reset at epoch ${rateLimitReset})`
: '';
throw new Error(`${method} ${url} failed (${response.status})${rateLimitHint}: ${text}`);
}
if (response.status === 204) {
return null;
}
try {
return await response.json();
} catch (error) {
throw new Error(`Failed to parse JSON response for ${method} ${url}: ${error.message}`);
}
}
async function getAllPullFiles(apiBaseUrl, repository, pullNumber) {
const files = [];
let page = 1;
while (true) {
const url = `${apiBaseUrl}/repos/${repository}/pulls/${pullNumber}/files?per_page=100&page=${page}`;
const batch = await apiRequest(url);
if (!Array.isArray(batch)) {
throw new Error(`Unexpected response while listing PR files on page ${page}.`);
}
if (batch.length === 0) {
break;
}
files.push(...batch);
if (batch.length < 100) {
break;
}
page += 1;
}
return files;
}
async function getPullRequest(apiBaseUrl, repository, pullNumber) {
const url = `${apiBaseUrl}/repos/${repository}/pulls/${pullNumber}`;
const pullRequest = await apiRequest(url);
if (!pullRequest || typeof pullRequest !== 'object') {
throw new Error('Unexpected response while fetching pull request details.');
}
return pullRequest;
}
async function ensureReviewerRequested(apiBaseUrl, repository, pullNumber, pullRequest) {
const authorLogin = String(pullRequest?.user?.login || '').toLowerCase();
const targetReviewer = REVIEWER_LOGIN.toLowerCase();
if (authorLogin === targetReviewer) {
console.log(`Skipping reviewer request: ${REVIEWER_LOGIN} is the PR author.`);
return;
}
const requestedReviewers = Array.isArray(pullRequest?.requested_reviewers)
? pullRequest.requested_reviewers
: [];
const alreadyRequested = requestedReviewers.some(
(reviewer) => String(reviewer?.login || '').toLowerCase() === targetReviewer
);
if (alreadyRequested) {
console.log(`Reviewer ${REVIEWER_LOGIN} is already requested.`);
return;
}
const url = `${apiBaseUrl}/repos/${repository}/pulls/${pullNumber}/requested_reviewers`;
try {
await apiRequest(url, 'POST', { reviewers: [REVIEWER_LOGIN] });
console.log(`Requested reviewer ${REVIEWER_LOGIN}.`);
} catch (error) {
// Reviewer request should not fail the telemetry guidance workflow.
console.warn(
`Unable to request reviewer ${REVIEWER_LOGIN}: ${error instanceof Error ? error.message : String(error)}`
);
}
}
async function findExistingTelemetryComment(apiBaseUrl, repository, pullNumber) {
let page = 1;
while (true) {
const commentsUrl = `${apiBaseUrl}/repos/${repository}/issues/${pullNumber}/comments?per_page=100&page=${page}`;
const comments = await apiRequest(commentsUrl);
if (!Array.isArray(comments)) {
throw new Error(`Unexpected response while listing issue comments on page ${page}.`);
}
const existing = comments.find(
(comment) => typeof comment.body === 'string' && comment.body.includes(COMMENT_MARKER)
);
if (existing) {
return existing;
}
if (comments.length < 100) {
return null;
}
page += 1;
}
}
function detectTelemetryChanges(files) {
const matches = [];
for (const file of files) {
const filename = file.filename || '';
const telemetryPath = isTelemetryPath(filename);
const changedLines = changedLinesFromPatch(file.patch);
const telemetryLineSignal = hasTelemetryLineSignal(changedLines);
// Some large diffs omit patch content. If the file path is telemetry-centric,
// treat it as a telemetry modification to avoid false negatives.
const patchUnavailable = !file.patch && telemetryPath;
if (telemetryPath || telemetryLineSignal || patchUnavailable) {
matches.push({
filename,
telemetryPath,
telemetryLineSignal,
patchUnavailable,
});
}
}
return matches;
}
function hasDataAndPrivacyChange(files) {
return files.some((file) => {
const filename = (file.filename || '').toLowerCase();
return filename === 'data_and_privacy.md';
});
}
async function upsertPrComment(apiBaseUrl, repository, pullNumber, body) {
const existing = await findExistingTelemetryComment(apiBaseUrl, repository, pullNumber);
if (existing) {
const updateUrl = `${apiBaseUrl}/repos/${repository}/issues/comments/${existing.id}`;
await apiRequest(updateUrl, 'PATCH', { body });
console.log(`Updated existing telemetry comment (id: ${existing.id}).`);
return;
}
const createUrl = `${apiBaseUrl}/repos/${repository}/issues/${pullNumber}/comments`;
await apiRequest(createUrl, 'POST', { body });
console.log('Created telemetry comment on PR.');
}
async function main() {
const eventPath = requireEnv('GITHUB_EVENT_PATH');
const repository = requireEnv('GITHUB_REPOSITORY');
const apiBaseUrl = process.env.GITHUB_API_URL || 'https://api.github.com';
validateRepository(repository);
let parsedApiBaseUrl;
try {
parsedApiBaseUrl = new URL(apiBaseUrl);
} catch {
throw new Error(`Invalid GITHUB_API_URL: ${JSON.stringify(apiBaseUrl)}`);
}
const event = readEventPayload(eventPath);
const pullNumber = resolvePullNumber(event);
console.log(`Event name: ${process.env.GITHUB_EVENT_NAME || 'unknown'}`);
console.log(`Repository: ${repository}`);
console.log(`PR number: ${pullNumber}`);
const files = await getAllPullFiles(parsedApiBaseUrl.origin, repository, pullNumber);
if (files.length === 0) {
console.log('No changed files found for PR; skipping telemetry comment update.');
return;
}
const matches = detectTelemetryChanges(files);
const dataAndPrivacyChanged = hasDataAndPrivacyChange(files);
console.log(`Scanned ${files.length} changed files.`);
console.log(`Telemetry matches found: ${matches.length}.`);
console.log(`DATA_AND_PRIVACY.md changed: ${dataAndPrivacyChanged}.`);
if (matches.length === 0) {
console.log('No telemetry-related additions/modifications detected.');
return;
}
for (const match of matches) {
console.log(
`- ${match.filename} (telemetryPath=${match.telemetryPath}, telemetryLineSignal=${match.telemetryLineSignal}, patchUnavailable=${match.patchUnavailable})`
);
}
try {
const pullRequest = await getPullRequest(parsedApiBaseUrl.origin, repository, pullNumber);
await ensureReviewerRequested(parsedApiBaseUrl.origin, repository, pullNumber, pullRequest);
} catch (error) {
console.warn(
'Failed to fetch PR details or request reviewer; continuing to post telemetry guidance comment.'
);
console.warn(error instanceof Error ? error.stack || error.message : error);
}
const commentBody = dataAndPrivacyChanged
? COMMENT_BODY_WITH_PRIVACY_UPDATE
: COMMENT_BODY_WITHOUT_PRIVACY_UPDATE;
await upsertPrComment(apiBaseUrl, repository, pullNumber, commentBody);
}
main().catch((error) => {
console.error('Telemetry PR check failed.');
console.error(error instanceof Error ? error.stack || error.message : error);
process.exit(1);
});

View File

@@ -1,12 +1,12 @@
---
name: release-note-generation
description: Toolkit for generating PowerToys release notes from GitHub milestone PRs or commit ranges. Use when asked to create release notes, summarize milestone PRs, generate changelog, prepare release documentation, request Copilot reviews for PRs, update README for a new release, manage PR milestones, or collect PRs between commits/tags. Supports PR collection by milestone or commit range, milestone assignment, grouping by label, summarization with external contributor attribution, and README version bumping.
description: Toolkit for generating PowerToys release notes from GitHub milestone PRs or commit ranges. Use when asked to create release notes, summarize milestone PRs, generate changelog, prepare release documentation, generate PR review summaries locally for release notes, update README for a new release, manage PR milestones, collect PRs between commits/tags, or prepare release assets (download installers and compute installer hashes).
license: Complete terms in LICENSE.txt
---
# Release Note Generation Skill
Generate professional release notes for PowerToys milestones by collecting merged PRs, requesting Copilot code reviews, grouping by label, and producing user-facing summaries.
Generate professional release notes for PowerToys milestones by collecting merged PRs, summarizing each PR with the local CLI agent, grouping by label, and producing user-facing summaries.
## Output Directory
@@ -26,16 +26,17 @@ Generated Files/ReleaseNotes/
- Generate release notes for a milestone
- Summarize PRs merged in a release
- Request Copilot reviews for milestone PRs
- Generate per-PR review summaries locally for release-notes copy
- Assign milestones to PRs missing them
- Collect PRs between two commits/tags
- Update README.md for a new version
- Prepare GitHub release assets (download installers/symbols + compute hashes)
## Prerequisites
- **GitHub CLI (`gh`) installed and authenticated** — The collection script uses `gh pr view` and `gh api graphql` to fetch PR metadata and co-author information. Run `gh auth status` to verify; if not logged in, run `gh auth login` first. See [Step 1.0.0](./references/step1-collection.md) for details.
- MCP Server: github-mcp-server installed
- GitHub Copilot code review enabled for the org/repo
- MCP Server: github-mcp-server installed (used to fetch PR diffs/files for the local-agent review step)
- For [prepare-release-assets.ps1](./scripts/prepare-release-assets.ps1) only: **Azure CLI** authenticated against the Microsoft tenant (`az login`) with the `azure-devops` extension; access to the `microsoft/Dart` ADO project
## Required Variables
@@ -65,12 +66,12 @@ Generated Files/ReleaseNotes/
└────────────────────────────────┘
┌────────────────────────────────┐
│ 3.1 Request Reviews (Copilot)
│ 3.1 Local-agent PR summaries
│ (writes CopilotSummary) │
└────────────────────────────────┘
┌────────────────────────────────┐
│ 3.2 Refresh PR data
│ (CopilotSummary) │
│ 3.2 (Optional) Refresh PR data │
└────────────────────────────────┘
┌────────────────────────────────┐
@@ -93,7 +94,7 @@ Generated Files/ReleaseNotes/
| 1.1 | Collect PRs | From previous release tag on `stable` branch → `sorted_prs.csv` |
| 1.2 | Assign Milestones | Ensure all PRs have correct milestone |
| 2.12.4 | Label PRs | Auto-suggest + human label low-confidence |
| 3.13.3 | Reviews & Grouping | Request Copilot reviews → refresh → group by label |
| 3.13.3 | Reviews & Grouping | Local agent summarizes each PR diff into `CopilotSummary` → (optional refresh) → group by label |
| 4.14.2 | Summaries & Final | Generate grouped summaries, then consolidate |
## Detailed workflow docs
@@ -114,6 +115,7 @@ Do not read all steps at once—only read the step you are executing.
| [group-prs-by-label.ps1](./scripts/group-prs-by-label.ps1) | Group PRs into CSVs |
| [collect-or-apply-milestones.ps1](./scripts/collect-or-apply-milestones.ps1) | Assign milestones |
| [diff_prs.ps1](./scripts/diff_prs.ps1) | Incremental PR diff |
| [prepare-release-assets.ps1](./scripts/prepare-release-assets.ps1) | Download installers + symbols from an ADO build, compute SHA256, emit the "Installer Hashes" markdown table for the GitHub release page |
## References
@@ -133,5 +135,6 @@ Do not read all steps at once—only read the step you are executing.
|-------|----------|
| `gh` command not found | Install GitHub CLI and add to PATH |
| No PRs returned | Verify milestone title matches exactly |
| Empty CopilotSummary | Request Copilot reviews first, then re-run dump |
| Empty `CopilotSummary` for many PRs | Run Step 3.1 (local-agent summaries). Do **not** use `mcp_github_request_copilot_review` from a CLI/coding agent — the GitHub API rejects bot-initiated review requests, so the column will stay empty. |
| Many unlabeled PRs | Return to labeling step before grouping |
| `prepare-release-assets.ps1` fails with "Failed to acquire ADO access token" | Run `az login` and ensure you have access to the `microsoft/Dart` ADO project |

View File

@@ -1,22 +1,40 @@
# Step 3: Copilot Reviews and Grouping
# Step 3: Local Agent Reviews and Grouping
## 3.0 To-do
- 3.1 Request Copilot Reviews (Agent Mode)
- 3.2 Refresh PR Data
- 3.1 Generate PR Summaries with the Local Agent
- 3.2 (Optional) Refresh PR Data
- 3.3 Group PRs by Label
## 3.1 Request Copilot Reviews (Agent Mode)
## 3.1 Generate PR Summaries with the Local Agent
Use MCP tools to request Copilot reviews for all PRs in `Generated Files/ReleaseNotes/sorted_prs.csv`:
> ⚠️ **Do not use `mcp_github_request_copilot_review` (or any "request Copilot review" tool that calls the GitHub API).**
> When this skill is driven from a CLI / coding agent, the request is made from a bot identity and the GitHub API rejects it ("Bot reviewers cannot be requested"). The PR ends up with no Copilot review and `CopilotSummary` stays empty.
>
> Instead, **the local agent that is running this skill performs the review itself** and writes the summary directly into `sorted_prs.csv`.
- Use `mcp_github_request_copilot_review` for each PR ID
- Do NOT generate or run scripts for this step
For every PR listed in `Generated Files/ReleaseNotes/sorted_prs.csv` whose `CopilotSummary` is empty:
1. Fetch the PR diff using a tool that does **not** post anything back to GitHub. Any of these works:
- `mcp_github_pull_request_read` with `method: get_diff`
- `mcp_github_pull_request_read` with `method: get_files` (when the diff is large)
- `gh pr diff <PR_NUMBER> --repo microsoft/PowerToys`
2. Read the PR title, body, and diff. Produce a 13 sentence, user-facing summary in the same style as a Copilot PR review (focus on observable behavior change, not implementation details).
3. Write the summary into the `CopilotSummary` column for that PR row in `Generated Files/ReleaseNotes/sorted_prs.csv`. Preserve all other columns and the existing row order.
**Batching guidance**
- Process PRs in the order they appear in `sorted_prs.csv`.
- Generate summaries for **all** PRs in one pass before continuing to Step 3.3, so the human reviewer can validate them together.
- For very large diffs, summarize from `get_files` (filenames + per-file patches) rather than the full diff.
- Skip PRs that already have a non-empty `CopilotSummary` (e.g. PRs where a human reviewer already pasted one). Do not overwrite existing summaries.
**Why not post the summary back to the PR?** Posting a comment from the agent's identity would not be picked up by `dump-prs-since-commit.ps1` (which only matches Copilot bot authors), and it adds noise to the PR. Writing straight into the CSV keeps the artifact self-contained.
---
## 3.2 Refresh PR Data
## 3.2 (Optional) Refresh PR Data
Re-run the collection script to capture Copilot review summaries into the `CopilotSummary` column:
Only re-run the collection script if PR metadata on GitHub has changed (new labels, retitled PRs, etc.) since Step 1.1. **Skip this step if you only want to preserve the locally generated `CopilotSummary` values from Step 3.1**, because re-running the dump will overwrite the CSV.
```powershell
pwsh ./.github/skills/release-note-generation/scripts/dump-prs-since-commit.ps1 `
@@ -24,6 +42,8 @@ pwsh ./.github/skills/release-note-generation/scripts/dump-prs-since-commit.ps1
-OutputDir 'Generated Files/ReleaseNotes'
```
If you do refresh, redo Step 3.1 afterwards to repopulate `CopilotSummary`.
---
## 3.3 Group PRs by Label
@@ -35,3 +55,4 @@ pwsh ./.github/skills/release-note-generation/scripts/group-prs-by-label.ps1 -Cs
Creates `Generated Files/ReleaseNotes/grouped_csv/` with one CSV per label combination.
**Validation:** The `Unlabeled.csv` file should be minimal (ideally empty). If many PRs remain unlabeled, return to Step 2 (see [step2-labeling.md](./step2-labeling.md)).

View File

@@ -16,7 +16,7 @@ For each CSV in `Generated Files/ReleaseNotes/grouped_csv/`, create a markdown f
- Use the “Verb-ed + Scenario + Impact” sentence structure—make readers think, “Thats exactly what I need” or “Yes, thats an awesome fix.”; The "impact" can be end-user focused (written to convey user excitement) or technical (performance/stability) when user-facing impact is minimal.
- If nothing special on impact or unclear impact, mark as needing human summary
- Source from Title, Body, and CopilotSummary (prefer CopilotSummary when available)
- The `NeedThanks` column contains a comma-separated list of external contributor usernames who should be thanked (empty = no thanks needed, all authors are core team). For each non-empty `NeedThanks` value, append thanks for **every** listed contributor: `Thanks [@user1](https://github.com/user1)!` for a single contributor, or `Thanks [@user1](https://github.com/user1) and [@user2](https://github.com/user2)!` for two, or `Thanks [@user1](https://github.com/user1), [@user2](https://github.com/user2), and [@user3](https://github.com/user3)!` for three or more.
- The `NeedThanks` column contains a comma-separated list of external contributor usernames who should be credited (empty = no attribution needed, all authors are core team). For each non-empty `NeedThanks` value, append a `by` attribution that lists **every** contributor, matching GitHub's standard contributor-attribution style: `by [@user1](https://github.com/user1)` for a single contributor, `by [@user1](https://github.com/user1) and [@user2](https://github.com/user2)` for two, or `by [@user1](https://github.com/user1), [@user2](https://github.com/user2), and [@user3](https://github.com/user3)` for three or more. In the final consolidated release notes (Step 4.2), the attribution follows the PR link, e.g. `…in [#1234](url) by [@user](url)`. Do not use "Thanks @user!" phrasing.
- Do NOT include PR numbers in bullet lines
- Do NOT mention “security” or “privacy” issues, since these are not known and could be leveraged by attackers in earlier versions. Instead, describe the user-facing scenario, usage, or impact.
- If confidence < 70%, write: `Human Summary Needed: <PR full link>`

View File

@@ -0,0 +1,334 @@
<#
.SYNOPSIS
Prepares the binary assets for a PowerToys GitHub release: downloads the
four installers (per-user/per-machine x x64/arm64) and the symbol archives
from an ADO pipeline build, computes SHA256 hashes, and emits the
"Installer Hashes" markdown table.
.DESCRIPTION
Given an ADO Dart pipeline build id (e.g. from
https://microsoft.visualstudio.com/Dart/_build/results?buildId=NNN),
downloads the four installer EXEs and the per-arch symbol zips into a
single per-version folder, then writes a hashes.md alongside them with a
markdown table ready to paste into the GitHub release notes.
Requires: az login (Azure CLI authenticated), az devops extension.
.EXAMPLE
.\prepare-release-assets.ps1 -BuildId 145505247
.\prepare-release-assets.ps1 -BuildId 145505247 -OutputFolder D:\Releases
#>
param(
[Parameter(Mandatory = $true)]
[int]$BuildId,
[string]$OutputFolder = "$env:USERPROFILE\Downloads",
[string]$Organization = "https://dev.azure.com/microsoft",
[string]$Project = "Dart",
[string]$GitHubRepo = "microsoft/PowerToys"
)
$ErrorActionPreference = "Stop"
$env:AZURE_CORE_NO_PROMPT = "true"
# --- Helpers -----------------------------------------------------------------
# Invoke an `az` CLI command and capture stderr in $script:LastAzError so
# callers can surface the underlying message (expired login, blocked extension,
# tenant policy, ...) instead of swallowing it with `2>$null`.
function Invoke-Az {
$tmpErr = [System.IO.Path]::GetTempFileName()
try {
$output = & az @args 2>$tmpErr
# Get-Content -Raw returns $null for an empty file, and calling .Trim()
# on $null throws under $ErrorActionPreference = 'Stop' -- which would
# turn every successful (no-stderr) az call into a fatal error. Guard
# explicitly so $script:LastAzError is always a (possibly empty) string.
$rawErr = Get-Content $tmpErr -Raw -ErrorAction SilentlyContinue
$script:LastAzError = if ($null -eq $rawErr) { '' } else { $rawErr.Trim() }
return $output
}
finally {
Remove-Item $tmpErr -Force -ErrorAction SilentlyContinue
}
}
# Build an ADO artifact download URL from scratch instead of regex-replacing
# the URL returned by `az pipelines runs artifact list`. Preserves any other
# query parameters and only swaps `format` and `subPath`, so we don't break if
# the upstream URL shape ever changes.
function Get-ArtifactDownloadUrl {
param(
[Parameter(Mandatory)][string]$BaseUrl,
[Parameter(Mandatory)][string]$SubPath,
[Parameter(Mandatory)][ValidateSet('file', 'zip')][string]$Format
)
$encodedSubPath = [Uri]::EscapeDataString($SubPath)
$idx = $BaseUrl.IndexOf('?')
if ($idx -lt 0) {
return "${BaseUrl}?format=${Format}&subPath=${encodedSubPath}"
}
$base = $BaseUrl.Substring(0, $idx)
$kept = $BaseUrl.Substring($idx + 1) -split '&' | Where-Object {
$_ -and -not ($_ -match '^(format|subPath)=')
}
$kept = @($kept) + @("format=$Format", "subPath=$encodedSubPath")
return "${base}?$($kept -join '&')"
}
# Download a single ADO artifact file with bearer auth and a small retry/backoff
# loop. A transient network blip on a ~200 MB installer or symbol zip otherwise
# aborts the entire release-prep run.
function Invoke-AdoDownload {
param(
[Parameter(Mandatory)][string]$Url,
[Parameter(Mandatory)][string]$DestPath,
[Parameter(Mandatory)][string]$Token,
[int]$MaxAttempts = 3
)
$lastError = $null
for ($attempt = 1; $attempt -le $MaxAttempts; $attempt++) {
$webClient = New-Object System.Net.WebClient
$webClient.Headers.Add("Authorization", "Bearer $Token")
try {
$webClient.DownloadFile($Url, $DestPath)
return
}
catch {
$lastError = $_
if (Test-Path $DestPath) {
Remove-Item $DestPath -Force -ErrorAction SilentlyContinue
}
if ($attempt -lt $MaxAttempts) {
$backoffSec = [int][Math]::Pow(2, $attempt) # 2, 4, 8 ...
Write-Host " Attempt $attempt failed: $($_.Exception.Message). Retrying in ${backoffSec}s..." -ForegroundColor Yellow
Start-Sleep -Seconds $backoffSec
}
}
finally {
$webClient.Dispose()
}
}
throw "Download failed after $MaxAttempts attempts. Last error: $($lastError.Exception.Message)`nURL: $Url"
}
# -----------------------------------------------------------------------------
# Work around broken az extensions: if the default extension dir has
# inaccessible files, redirect to a clean directory.
$defaultExtDir = "$env:USERPROFILE\.azure\cliextensions"
if (-not $env:AZURE_EXTENSION_DIR -and (Test-Path $defaultExtDir)) {
$broken = Get-ChildItem "$defaultExtDir\*\*.dist-info" -Directory -ErrorAction SilentlyContinue | Where-Object {
try { [System.IO.Directory]::GetFiles($_.FullName) | Out-Null; $false } catch { $true }
}
if ($broken) {
$cleanDir = "$env:USERPROFILE\.azure\cliextensions_clean"
Write-Host " Detected broken az extension, redirecting to $cleanDir" -ForegroundColor Yellow
$env:AZURE_EXTENSION_DIR = $cleanDir
if (-not (Test-Path $cleanDir)) { New-Item -ItemType Directory -Path $cleanDir -Force | Out-Null }
}
}
# Ensure azure-devops extension is installed
$ext = Invoke-Az extension list --query "[?name=='azure-devops']" -o tsv
if (-not $ext) {
Write-Host "Installing azure-devops extension..." -ForegroundColor Yellow
Invoke-Az extension add --name azure-devops --yes | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-Error "Failed to install azure-devops extension. (az: $script:LastAzError)"
exit 1
}
}
# Configure az devops defaults
Invoke-Az devops configure --defaults organization=$Organization project=$Project | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-Error "Failed to configure az devops defaults. (az: $script:LastAzError)"
exit 1
}
# --- Step 1: Get build info to determine version ---
Write-Host "Fetching build $BuildId info..." -ForegroundColor Cyan
$buildJson = Invoke-Az pipelines build show --id $BuildId --output json
if (-not $buildJson) {
Write-Error "Could not fetch build $BuildId. Are you logged in (az login)? (az: $script:LastAzError)"
exit 1
}
$build = $buildJson | ConvertFrom-Json
$versionParam = $build.templateParameters.VersionNumber
if (-not $versionParam) {
Write-Error "Could not determine version from build $BuildId"
exit 1
}
Write-Host " Version: $versionParam" -ForegroundColor DarkGray
# --- Step 2: Get artifact metadata once ---
Write-Host "Fetching artifact metadata..." -ForegroundColor Cyan
$artifactsJson = Invoke-Az pipelines runs artifact list --run-id $BuildId --output json
if (-not $artifactsJson) {
Write-Error "Could not list artifacts for build $BuildId. (az: $script:LastAzError)"
exit 1
}
$artifacts = $artifactsJson | ConvertFrom-Json
# --- Step 3: Prepare destination folder ---
$destFolder = Join-Path $OutputFolder "PowerToys-v$versionParam"
if (-not (Test-Path $destFolder)) {
New-Item -ItemType Directory -Path $destFolder -Force | Out-Null
}
Write-Host " Destination: $destFolder" -ForegroundColor DarkGray
# --- Step 4: Get an ADO access token once ---
$token = Invoke-Az account get-access-token --resource "499b84ac-1321-427f-aa17-267ca6975798" --query accessToken -o tsv
if (-not $token) {
Write-Error "Failed to acquire ADO access token. Run 'az login' first. (az: $script:LastAzError)"
exit 1
}
# --- Step 5: Define the four installers to download ---
$targets = @(
[pscustomobject]@{ Description = "Per user - x64"; Scope = "perUser"; Arch = "x64"; Artifact = "build-x64-Release"; FileName = "PowerToysUserSetup-$versionParam-x64.exe" }
[pscustomobject]@{ Description = "Per user - ARM64"; Scope = "perUser"; Arch = "arm64"; Artifact = "build-arm64-Release"; FileName = "PowerToysUserSetup-$versionParam-arm64.exe" }
[pscustomobject]@{ Description = "Machine wide - x64"; Scope = "perMachine"; Arch = "x64"; Artifact = "build-x64-Release"; FileName = "PowerToysSetup-$versionParam-x64.exe" }
[pscustomobject]@{ Description = "Machine wide - ARM64"; Scope = "perMachine"; Arch = "arm64"; Artifact = "build-arm64-Release"; FileName = "PowerToysSetup-$versionParam-arm64.exe" }
)
# --- Step 6: Download each installer (skip if already present) ---
foreach ($t in $targets) {
$destPath = Join-Path $destFolder $t.FileName
if (Test-Path $destPath) {
$sizeMB = [math]::Round((Get-Item $destPath).Length / 1MB, 1)
Write-Host "[skip] $($t.FileName) already exists ($sizeMB MB)" -ForegroundColor DarkGray
continue
}
$artifact = $artifacts | Where-Object { $_.name -eq $t.Artifact }
if (-not $artifact) {
Write-Error "Artifact '$($t.Artifact)' not found in build $BuildId. Available: $(($artifacts | ForEach-Object name) -join ', ')"
exit 1
}
$fileUrl = Get-ArtifactDownloadUrl -BaseUrl $artifact.resource.downloadUrl -SubPath "/$($t.FileName)" -Format file
Write-Host "Downloading $($t.FileName) ..." -ForegroundColor Cyan
try {
Invoke-AdoDownload -Url $fileUrl -DestPath $destPath -Token $token
}
catch {
Write-Error "Download failed for $($t.FileName): $_"
exit 1
}
$sizeMB = [math]::Round((Get-Item $destPath).Length / 1MB, 1)
Write-Host " Saved ($sizeMB MB)" -ForegroundColor Green
}
# --- Step 6b: Download symbols (one zip per arch) ---
$symbolTargets = @(
[pscustomobject]@{ Arch = "x64"; Artifact = "build-x64-Release"; SubPath = "/symbols-x64" }
[pscustomobject]@{ Arch = "arm64"; Artifact = "build-arm64-Release"; SubPath = "/symbols-arm64" }
)
foreach ($s in $symbolTargets) {
$finalZip = Join-Path $destFolder "symbols-$($s.Arch).zip"
if (Test-Path $finalZip) {
$sizeMB = [math]::Round((Get-Item $finalZip).Length / 1MB, 1)
Write-Host "[skip] symbols-$($s.Arch).zip already exists ($sizeMB MB)" -ForegroundColor DarkGray
continue
}
$artifact = $artifacts | Where-Object { $_.name -eq $s.Artifact }
if (-not $artifact) {
Write-Error "Artifact '$($s.Artifact)' not found in build $BuildId."
exit 1
}
# Symbols are downloaded as a folder => keep format=zip and append subPath
$symbolsUrl = Get-ArtifactDownloadUrl -BaseUrl $artifact.resource.downloadUrl -SubPath $s.SubPath -Format zip
$tmpZip = Join-Path ([System.IO.Path]::GetTempPath()) ("ptsym-$($s.Arch)-$([Guid]::NewGuid().ToString('N')).zip")
$tmpExtract = Join-Path ([System.IO.Path]::GetTempPath()) ("ptsym-$($s.Arch)-$([Guid]::NewGuid().ToString('N'))")
$stageRoot = Join-Path ([System.IO.Path]::GetTempPath()) ("ptsym-stage-$([Guid]::NewGuid().ToString('N'))")
try {
Write-Host "Downloading symbols-$($s.Arch).zip ..." -ForegroundColor Cyan
try {
Invoke-AdoDownload -Url $symbolsUrl -DestPath $tmpZip -Token $token
}
catch {
Write-Error "Symbols download failed for $($s.Arch): $_"
exit 1
}
Write-Host " Extracting..." -ForegroundColor DarkGray
Expand-Archive -Path $tmpZip -DestinationPath $tmpExtract -Force
# Walk down while the current dir holds exactly one subfolder and no files.
$current = Get-Item $tmpExtract
while ($true) {
$children = Get-ChildItem -LiteralPath $current.FullName -Force
$subDirs = @($children | Where-Object { $_.PSIsContainer })
$files = @($children | Where-Object { -not $_.PSIsContainer })
if ($subDirs.Count -eq 1 -and $files.Count -eq 0) {
$current = $subDirs[0]
}
else {
break
}
}
# Stage to a folder named symbols-<arch> so the zip extracts to that name.
$stageInner = Join-Path $stageRoot "symbols-$($s.Arch)"
New-Item -ItemType Directory -Path $stageInner -Force | Out-Null
Get-ChildItem -LiteralPath $current.FullName -Force | ForEach-Object {
Copy-Item -LiteralPath $_.FullName -Destination $stageInner -Recurse -Force
}
Write-Host " Repacking to $finalZip ..." -ForegroundColor DarkGray
if (Test-Path $finalZip) { Remove-Item $finalZip -Force }
Compress-Archive -Path "$stageInner\*" -DestinationPath $finalZip -CompressionLevel Optimal
$sizeMB = [math]::Round((Get-Item $finalZip).Length / 1MB, 1)
Write-Host " Saved symbols-$($s.Arch).zip ($sizeMB MB)" -ForegroundColor Green
}
catch {
# Don't leave a half-built zip behind if anything in the pipeline blew up.
if (Test-Path $finalZip) { Remove-Item $finalZip -Force -ErrorAction SilentlyContinue }
throw
}
finally {
Remove-Item $tmpZip -Force -ErrorAction SilentlyContinue
Remove-Item $tmpExtract -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item $stageRoot -Recurse -Force -ErrorAction SilentlyContinue
}
}
# --- Step 7: Compute SHA256 and build markdown ---
Write-Host "`nComputing SHA256 hashes..." -ForegroundColor Cyan
$sb = [System.Text.StringBuilder]::new()
[void]$sb.AppendLine("## Installer Hashes")
[void]$sb.AppendLine("")
[void]$sb.AppendLine("| Description | Filename | sha256 hash |")
[void]$sb.AppendLine("| --- | --- | --- |")
foreach ($t in $targets) {
$destPath = Join-Path $destFolder $t.FileName
$hash = (Get-FileHash -Path $destPath -Algorithm SHA256).Hash.ToUpper()
[void]$sb.AppendLine("| $($t.Description) | $($t.FileName) | $hash |")
Write-Host " $($t.FileName) $hash" -ForegroundColor DarkGray
}
$markdown = $sb.ToString()
$mdPath = Join-Path $destFolder "hashes.md"
Set-Content -Path $mdPath -Value $markdown -Encoding UTF8
Write-Host "`nMarkdown written to: $mdPath" -ForegroundColor Green
Write-Host "`n----- Installer Hashes -----`n" -ForegroundColor Yellow
Write-Host $markdown
Write-Host "Draft a new GitHub release at: https://github.com/$GitHubRepo/releases/new?tag=v$versionParam" -ForegroundColor Green

213
.github/workflows/auto-label-issues.yml vendored Normal file
View File

@@ -0,0 +1,213 @@
name: Automatic Triaging on Issue Creation
on:
issues:
types: [opened, reopened]
# Manual trigger: go to Actions → "Automatic Triaging on Issue Creation" → Run workflow.
# Enter one or more comma-separated issue numbers (e.g. "1234" or "1234,1235,1236")
# to apply AI-generated area labels to existing untriaged issues.
workflow_dispatch:
inputs:
issue_numbers:
description: 'Comma-separated issue number(s) to label (e.g. 1234 or 1234,1235)'
required: true
permissions:
models: read
issues: write
concurrency:
# Each workflow run gets its own concurrency group.
# For issue events, group by issue number so a rapid close+reopen only runs once.
# For manual dispatch (which may cover multiple issues), use the unique run ID.
group: ${{ github.event_name == 'issues' && format('{0}-issue-{1}', github.workflow, github.event.issue.number) || github.run_id }}
cancel-in-progress: true
jobs:
label:
runs-on: ubuntu-latest
steps:
- name: Apply area labels with AI
uses: actions/github-script@v7
env:
# actions/github-script does not propagate `github-token` to
# process.env. Expose it explicitly so the inline script can
# authenticate against the GitHub Models inference endpoint.
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
// When triggered manually, process each supplied issue number in turn.
// When triggered by an issue event, use the event's issue number.
let issueNumbers;
if (context.eventName === 'workflow_dispatch') {
issueNumbers = String(context.payload.inputs.issue_numbers)
.split(',')
.map(s => parseInt(s.trim(), 10))
.filter(n => Number.isFinite(n) && n > 0);
} else {
issueNumbers = [context.issue.number];
}
if (issueNumbers.length === 0) {
console.log('No valid issue numbers to process; skipping.');
return;
}
for (const issueNumber of issueNumbers) {
console.log(`\n--- Processing issue #${issueNumber} ---`);
await labelIssue(issueNumber);
}
async function labelIssue(issueNumber) {
// Fetch the issue so both the automatic and manual paths have the same data.
const { data: issue } = await github.rest.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
});
const title = issue.title ?? '';
const body = issue.body ?? '';
if (!title && !body) {
console.log(`Issue #${issueNumber} has no title or body; skipping.`);
return;
}
// Truncation limit for issue body sent to the model. Keeps the
// prompt within the model's context window and avoids high token usage.
const MAX_BODY_LENGTH = 4000;
// Upper bound on model response tokens. A JSON array of label strings
// is compact; 200 tokens is more than enough for any realistic response.
const MAX_TOKENS = 200;
// All valid Product-* and Area-* labels the agent may choose from.
const VALID_LABELS = [
'Product-Advanced Paste',
'Product-Always On Top',
'Product-Awake',
'Product-Color Picker',
'Product-CommandNotFound',
'Product-Command Palette',
'Product-CropAndLock',
'Product-Environment Variables',
'Product-FancyZones',
'Product-File Explorer',
'Product-File Locksmith',
'Product-Find My Mouse',
'Product-Grab And Move',
'Product-Hosts File Editor',
'Product-Image Resizer',
'Product-Keyboard Manager',
'Product-LightSwitch',
'Product-Mouse Highlighter',
'Product-Mouse Jump',
'Product-Mouse Pointer Crosshairs',
'Product-Mouse Utilities',
'Product-Mouse Without Borders',
'Product-New+',
'Product-Peek',
'Product-PowerDisplay',
'Product-PowerRename',
'Product-PowerToys Run',
'Product-Quick Accent',
'Product-Registry Preview',
'Product-Screen Ruler',
'Product-Settings',
'Product-Shortcut Guide',
'Product-Text Extractor',
'Product-Workspaces',
'Product-ZoomIt',
'Area-Setup/Install',
'Area-Localization',
];
const systemPrompt = `You are a GitHub issue triage assistant for the microsoft/PowerToys repository.
Your job is to classify issues by assigning the correct area label(s).
Rules:
- Only return labels from the following list, exactly as written:
${VALID_LABELS.map(l => ` • ${l}`).join('\n')}
- Choose only the labels that clearly match the issue content.
- If the issue mentions multiple areas, include a label for each one.
- If no label fits, return an empty array.
- Respond with ONLY a JSON array of label strings, no explanation.
Example: ["Product-FancyZones","Product-Settings"]`;
const userPrompt = `Issue title: ${title}
Issue body:
${body.slice(0, MAX_BODY_LENGTH)}`;
// Validate that the token is available before making the API call.
const token = process.env.GITHUB_TOKEN;
if (!token) {
console.log('GITHUB_TOKEN is not set; skipping.');
return;
}
// Call the GitHub Models inference endpoint (OpenAI-compatible).
const response = await fetch(
'https://models.inference.ai.azure.com/chat/completions',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'gpt-4o-mini',
messages: [
{ role: 'system', content: systemPrompt },
{ role: 'user', content: userPrompt },
],
max_tokens: MAX_TOKENS,
// temperature: 0 ensures deterministic, consistent label
// classification across similar issues.
temperature: 0,
}),
}
);
if (!response.ok) {
const errorBody = await response.text();
console.log(`GitHub Models API error: ${response.status} ${response.statusText} — ${errorBody}`);
return;
}
const data = await response.json();
const text = data.choices?.[0]?.message?.content?.trim() ?? '';
console.log(`Model response: ${text}`);
let suggested;
try {
suggested = JSON.parse(text);
} catch {
console.log('Could not parse model response as JSON; skipping.');
return;
}
if (!Array.isArray(suggested) || suggested.length === 0) {
console.log('No labels suggested by the model.');
return;
}
// Only apply labels that are in the allow-list.
const validSet = new Set(VALID_LABELS);
const toApply = [...new Set(suggested.filter(l => validSet.has(l)))];
if (toApply.length === 0) {
console.log('Model returned no valid labels.');
return;
}
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
labels: toApply,
});
console.log(`Issue #${issueNumber}: added labels: ${toApply.join(', ')}`);
}

View File

@@ -55,7 +55,7 @@ name: Spell checking
# spelling:
# # remove `security-events: write` and `use_sarif: 1`
# # remove `experimental_apply_changes_via_bot: 1`
# ... otherwise adjust the `with:` as you wish
# ... otherwise, adjust the `with:` as you wish
on:
push:
@@ -74,6 +74,8 @@ on:
types:
- "created"
permissions: {}
jobs:
spelling:
name: Check Spelling
@@ -85,7 +87,7 @@ jobs:
outputs:
followup: ${{ steps.spelling.outputs.followup }}
runs-on: ubuntu-latest
if: ${{ contains(github.event_name, 'pull_request') || github.event_name == 'push' }}
if: ${{ (contains(github.event_name, 'pull_request') && github.event.pull_request.state == 'open') || github.event_name == 'push' }}
concurrency:
group: spelling-${{ github.event.pull_request.number || github.ref }}
# note: If you use only_check_changed_files, you do not want cancel-in-progress
@@ -140,7 +142,7 @@ jobs:
comment-push:
name: Report (Push)
# If your workflow isn't running on push, you can remove this job
runs-on: ubuntu-latest
runs-on: ubuntu-slim
needs: spelling
permissions:
actions: read
@@ -150,24 +152,21 @@ jobs:
- name: comment
uses: check-spelling/check-spelling@cfb6f7e75bbfc89c71eaa30366d0c166f1bd9c8c # v0.0.26
with:
spell_check_this: microsoft/PowerToys@main
task: ${{ needs.spelling.outputs.followup }}
comment-pr:
name: Report (PR)
# If you workflow isn't running on pull_request*, you can remove this job
runs-on: ubuntu-latest
runs-on: ubuntu-slim
needs: spelling
permissions:
actions: read
contents: read
pull-requests: write
if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request')
steps:
- name: comment
uses: check-spelling/check-spelling@cfb6f7e75bbfc89c71eaa30366d0c166f1bd9c8c # v0.0.26
with:
spell_check_this: check-spelling/spell-check-this@prerelease
task: ${{ needs.spelling.outputs.followup }}
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }}
@@ -177,12 +176,13 @@ jobs:
contents: write
pull-requests: write
actions: read
runs-on: ubuntu-latest
runs-on: ubuntu-slim
if: ${{
github.repository_owner != 'microsoft' &&
github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
contains(github.event.comment.body, '@check-spelling-bot apply') &&
contains(github.event.comment.body, '@check-spelling-bot') &&
contains(github.event.comment.body, 'apply') &&
contains(github.event.comment.body, 'https://')
}}
concurrency:

View File

@@ -0,0 +1,35 @@
# NOTE: This workflow depends on .github/scripts/telemetry-pr-check.js for telemetry detection and PR comments.
# Keep this workflow and script behavior in sync when making changes.
name: Telemetry PR Check
on:
pull_request_target:
types: [opened, reopened, synchronize, ready_for_review]
workflow_dispatch:
inputs:
pr_number:
description: "Pull Request Number to test against"
required: true
type: string
permissions:
contents: read
pull-requests: write
concurrency:
group: telemetry-pr-check-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
detect-telemetry-events:
if: ${{ github.event.pull_request.draft == false }}
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Detect telemetry event changes and comment PR
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: node .github/scripts/telemetry-pr-check.js

11
.gitignore vendored
View File

@@ -365,6 +365,13 @@ installer/*/*.wxs.bk
**/.claude/settings.local.json
# Squad / Copilot agents — local-only, not committed
.squad/
.copilot
.squad
.squad-workstream
.github/agents/
.github/agents/**squad**.md
.github/workflows/**squad**.yml
# vcpkg manifest mode installed packages
vcpkg_installed/
deps/vcpkg/

6
.gitmodules vendored
View File

@@ -1,6 +0,0 @@
[submodule "deps/spdlog"]
path = deps/spdlog
url = https://github.com/gabime/spdlog.git
[submodule "deps/expected-lite"]
path = deps/expected-lite
url = https://github.com/martinmoene/expected-lite.git

View File

@@ -212,6 +212,7 @@
"WinUI3Apps\\PowerToys.NewPlus.ShellExtension.win10.dll",
"PowerAccent.Core.dll",
"PowerAccent.Common.dll",
"PowerToys.PowerAccent.dll",
"PowerToys.PowerAccent.exe",
"PowerToys.PowerAccentModuleInterface.dll",
@@ -243,13 +244,20 @@
"WinUI3Apps\\PowerToys.RegistryPreview.dll",
"WinUI3Apps\\PowerToys.RegistryPreview.exe",
"PowerToys.ShortcutGuide.exe",
"PowerToys.ShortcutGuideModuleInterface.dll",
"WinUI3Apps\\PowerToys.ShortcutGuide.exe",
"WinUI3Apps\\PowerToys.ShortcutGuide.dll",
"WinUI3Apps\\PowerToys.ShortcutGuideModuleInterface.dll",
"WinUI3Apps\\PowerToys.ShortcutGuide.IndexYmlGenerator.dll",
"WinUI3Apps\\PowerToys.ShortcutGuide.IndexYmlGenerator.exe",
"WinUI3Apps\\ShortcutGuide.CPPProject.dll",
"PowerToys.ZoomIt.exe",
"PowerToys.ZoomItModuleInterface.dll",
"PowerToys.ZoomItSettingsInterop.dll",
"PowerToys.GrabAndMove.exe",
"PowerToys.GrabAndMoveModuleInterface.dll",
"WinUI3Apps\\PowerToys.Settings.dll",
"WinUI3Apps\\PowerToys.Settings.exe",
@@ -261,8 +269,8 @@
"Workspaces.ModuleServices.dll",
"Microsoft.CommandPalette.Extensions.dll",
"Microsoft.CommandPalette.Extensions.Toolkit.dll",
"Microsoft.CmdPal.Ext.PowerToys.dll",
"Microsoft.CmdPal.Ext.PowerToys.exe",
"WinUI3Apps\\Microsoft.CmdPal.Ext.PowerToys.dll",
"WinUI3Apps\\Microsoft.CmdPal.Ext.PowerToys.exe",
"*Microsoft.CmdPal.UI_*.msix",
"PowerToys.DSC.dll",
@@ -380,6 +388,11 @@
"ColorCode.Core.dll",
"Microsoft.SemanticKernel.Connectors.Ollama.dll",
"OllamaSharp.dll",
"WinUI3Apps\\Google.Apis.dll",
"WinUI3Apps\\Google.Apis.Auth.dll",
"WinUI3Apps\\Google.Apis.Core.dll",
"WinUI3Apps\\Google.GenAI.dll",
"WinUI3Apps\\YamlDotNet.dll",
"boost_regex-vc143-mt-gd-x32-1_87.dll",
"boost_regex-vc143-mt-gd-x64-1_87.dll",

View File

@@ -16,6 +16,7 @@ pr:
include:
- main
- stable
drafts: false
# paths:
# exclude:
# - '**.md'

View File

@@ -104,6 +104,10 @@ extends:
# Have msbuild use the release nuget config profile
additionalBuildOptions: /p:RestoreConfigFile="$(Build.SourcesDirectory)\.pipelines\release-nuget.config" /p:EnableCmdPalAOT=true
beforeBuildSteps:
# Install the Terrapin retrieval tool, which replaces vcpkg's download handler
# to redirect it to a safe Microsoft-controlled location
- template: .pipelines/v2/templates/steps-install-terrapin.yml@self
# Sets versions for all PowerToy created DLLs
- pwsh: |-
.pipelines/versionSetting.ps1 -versionNumber '${{ parameters.versionNumber }}' -DevEnvironment ''
@@ -140,6 +144,10 @@ extends:
signCertName: $(SigningSignCertName)
useManagedIdentity: $(SigningUseManagedIdentity)
clientId: $(SigningOriginalClientId)
beforeBuildSteps:
# Install the Terrapin retrieval tool, which replaces vcpkg's download handler
# to redirect it to a safe Microsoft-controlled location
- template: .pipelines/v2/templates/steps-install-terrapin.yml@self
- stage: Publish
displayName: Publish

View File

@@ -70,7 +70,7 @@ parameters:
default: false
- name: winAppSDKVersionNumber
type: string
default: 1.6
default: '2.0'
- name: useExperimentalVersion
type: boolean
default: false
@@ -200,7 +200,7 @@ jobs:
- template: steps-ensure-dotnet-version.yml
parameters:
sdk: true
version: '9.0'
version: '10.0'
- ${{ if eq(parameters.runTests, true) }}:
- task: VisualStudioTestPlatformInstaller@1
@@ -270,6 +270,34 @@ jobs:
parameters:
directory: $(build.sourcesdirectory)\src\modules\cmdpal
# --- vcpkg detection + binary cache --------------------------------------
# PowerToys consumes spdlog (and, over time, other native deps) via vcpkg in
# manifest mode. steps-install-vcpkg.yml prefers the vcpkg shipped with
# Visual Studio (Microsoft.VisualStudio.Component.Vcpkg) and falls back to a
# fresh clone of microsoft/vcpkg into deps/vcpkg if VS doesn't have it.
# Either way it sets the VCPKG_ROOT pipeline variable; MSBuild integration
# is wired globally from Cpp.Build.props (with vcpkg.targets in
# Cpp.Build.targets) using the three-tier VcpkgRoot fallback
# (env var > VS-shipped > deps/vcpkg runtime clone).
#
# Vcpkg's MSBuild integration runs `vcpkg install` once per project, so the
# binary cache below saves ~3-5 minutes per triplet on cache hits.
- template: .\steps-install-vcpkg.yml
parameters:
useVSPreview: ${{ parameters.useVSPreview }}
- ${{ if eq(parameters.enablePackageCaching, true) }}:
- task: Cache@2
displayName: 'Cache vcpkg binary archives'
inputs:
# Key on the inputs vcpkg uses to compute its package ABI: the manifest,
# configuration, every overlay-port file, and the agent OS.
key: '"vcpkg" | "$(Agent.OS)" | vcpkg.json | vcpkg-configuration.json | deps/vcpkg-overlays/**'
restoreKeys: |
"vcpkg" | "$(Agent.OS)"
"vcpkg"
path: $(LOCALAPPDATA)\vcpkg\archives
- ${{ parameters.beforeBuildSteps }}
@@ -418,7 +446,7 @@ jobs:
/p:VCRTForwarders-IncludeDebugCRT=false
/p:PowerToysRoot=$(Build.SourcesDirectory)
/p:PublishProfile=InstallationPublishProfile.pubxml
/p:TargetFramework=net9.0-windows10.0.26100.0
/p:TargetFramework=net10.0-windows10.0.26100.0
/bl:$(LogOutputDirectory)\publish-${{ join('_',split(project, '/')) }}.binlog
$(RestoreAdditionalProjectSourcesArg)
platform: $(BuildPlatform)

View File

@@ -15,6 +15,9 @@ parameters:
- name: signingIdentity
type: object
default: {}
- name: beforeBuildSteps
type: stepList
default: []
jobs:
- job: "BuildSDK"
@@ -45,6 +48,8 @@ jobs:
parameters:
directory: $(build.sourcesdirectory)\src\modules\cmdpal
- ${{ parameters.beforeBuildSteps }}
- pwsh: |-
& "$(build.sourcesdirectory)\src\modules\cmdpal\extensionsdk\nuget\BuildSDKHelper.ps1" -Configuration "Release" -BuildStep "build" -IsAzurePipelineBuild
displayName: Build SDK

View File

@@ -64,7 +64,7 @@ jobs:
- template: steps-ensure-dotnet-version.yml
parameters:
sdk: true
version: '9.0'
version: '10.0'
- template: .\steps-restore-nuget.yml

View File

@@ -30,7 +30,7 @@ parameters:
default: false
- name: winAppSDKVersionNumber
type: string
default: 1.6
default: '2.0'
- name: useExperimentalVersion
type: boolean
default: false

View File

@@ -27,6 +27,7 @@ stages:
name: SHINE-INT-L
${{ else }}:
name: SHINE-OSS-L
demands: ImageOverride -equals SHINE-VS18-Latest
buildPlatforms:
- ${{ parameters.platform }}
uiTestModules: ${{ parameters.uiTestModules }}

View File

@@ -1,7 +1,7 @@
parameters:
- name: version
type: string
default: "9.0"
default: "10.0"
- name: sdk
type: boolean
default: false

View File

@@ -0,0 +1,6 @@
steps:
- pwsh: |-
nuget install -source "https://microsoft.pkgs.visualstudio.com/Dart/_packaging/PowerToysDependencies/nuget/v3/index.json" TerrapinRetrievalTool -Prerelease -OutputDirectory _trt -Config "$(Build.SourcesDirectory)\.pipelines\release-nuget.config"
$TerrapinRetrievalToolPath = (Get-Item _trt\TerrapinRetrievalTool.*\win-x64\TerrapinRetrievalTool.exe).FullName
Write-Host "##vso[task.setvariable variable=X_VCPKG_ASSET_SOURCES]x-script,${TerrapinRetrievalToolPath} -b https://vcpkg.storage.devpackages.microsoft.io/artifacts/ -a true -u None -p {url} -s {sha512} -d {dst};x-block-origin"
displayName: Set up the Terrapin Retrieval Tool (vcpkg cache)

View File

@@ -0,0 +1,41 @@
# Adapted from microsoft/terminal build/pipelines/templates-v2/steps-install-vcpkg.yml.
#
# Detects vcpkg from (in order):
# 1. The Visual Studio installation (Microsoft.VisualStudio.Component.Vcpkg,
# declared in the repo-root .vsconfig).
# 2. A local clone at deps/vcpkg, cloned and bootstrapped on demand.
#
# Sets the pipeline-scoped VCPKG_ROOT variable; the rest of the build
# resolves vcpkg through it (see the three-tier VcpkgRoot fallback in
# Cpp.Build.props). No repo-level vcpkg submodule required.
parameters:
- name: useVSPreview
type: boolean
default: false
steps:
- pwsh: |-
# vswhere -prerelease is opt-in via the useVSPreview parameter so CI on
# stable VS doesn't accidentally pick up a Preview install when both
# are present. Matches the existing useVSPreview plumbing for
# verifyAndSetLatestVCToolsVersion.ps1.
$vswhereArgs = @('-latest', '-requires', 'Microsoft.VisualStudio.Component.Vcpkg', '-property', 'installationPath')
$useVSPreview = '${{ parameters.useVSPreview }}' -eq 'True'
if ($useVSPreview) { $vswhereArgs = @('-prerelease') + $vswhereArgs }
$VsInstallRoot = & 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' @vswhereArgs
If ([String]::IsNullOrEmpty($VsInstallRoot)) {
Remove-Item -Recurse -Force deps/vcpkg -ErrorAction:Ignore
git clone https://github.com/microsoft/vcpkg deps/vcpkg
if ($LASTEXITCODE -ne 0) { throw "git clone vcpkg failed (exit $LASTEXITCODE)" }
Push-Location deps/vcpkg
& ./bootstrap-vcpkg.bat -disableMetrics
if ($LASTEXITCODE -ne 0) { Pop-Location; throw "bootstrap-vcpkg failed (exit $LASTEXITCODE)" }
$VcpkgRoot = $PWD
Pop-Location
Write-Host "Using vcpkg from local checkout ($VcpkgRoot)"
} Else {
$VcpkgRoot = Join-Path $VsInstallRoot 'VC\vcpkg'
Write-Host "Using vcpkg from Visual Studio installation ($VcpkgRoot)"
}
Write-Host "##vso[task.setvariable variable=VCPKG_ROOT]$VcpkgRoot"
displayName: Detect VS vcpkg or bootstrap locally

View File

@@ -1,7 +1,7 @@
parameters:
- name: versionNumber
type: string
default: 1.6
default: '2.0'
- name: useExperimentalVersion
type: boolean
default: false

View File

@@ -48,6 +48,11 @@ foreach ($csprojFile in $csprojFilesArray) {
continue
}
# The PowerAccent.Common project does not target WinRT, so skip it
if ($csprojFile -like '*PowerAccent.Common.csproj') {
continue
}
$importExists = Test-ImportSharedCsWinRTProps -filePath $csprojFile
if (!$importExists) {
Write-Output "$csprojFile need to import 'Common.Dotnet.CsWinRT.props'."

View File

@@ -22,7 +22,7 @@ $totalList = $projFiles | ForEach-Object -Parallel {
#Workaround for preventing exit code from dotnet process from reflecting exit code in PowerShell
$procInfo = New-Object System.Diagnostics.ProcessStartInfo -Property @{
FileName = "dotnet.exe";
Arguments = "list $csproj package";
Arguments = "list $csproj package --no-restore";
RedirectStandardOutput = $true;
RedirectStandardError = $true;
}

View File

@@ -13,5 +13,6 @@
{
"file": ".github/prompts/create-pr-summary.prompt.md"
}
]
],
"sarif-viewer.connectToGithubCodeScanning": "on"
}

View File

@@ -18,6 +18,7 @@
"Microsoft.VisualStudio.Component.VC.ATL.ARM64.Spectre",
"Microsoft.VisualStudio.Component.VC.ATL",
"Microsoft.VisualStudio.Component.VC.ATL.Spectre",
"Microsoft.VisualStudio.Component.Vcpkg",
"Microsoft.VisualStudio.ComponentGroup.WindowsAppSDK.Cs"
]
}

View File

@@ -39,7 +39,8 @@
<PropertyGroup>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
<PreferredToolArchitecture Condition="'$(PROCESSOR_ARCHITECTURE)' == 'ARM64' or '$(PROCESSOR_ARCHITEW6432)' == 'ARM64'">arm64</PreferredToolArchitecture>
<VcpkgEnabled>false</VcpkgEnabled>
<!-- vcpkg.targets is imported via Cpp.Build.targets after Microsoft.Cpp.targets. -->
<ForceImportAfterCppTargets>$(MSBuildThisFileDirectory)Cpp.Build.targets</ForceImportAfterCppTargets>
<ReplaceWildcardsInProjectItems>true</ReplaceWildcardsInProjectItems>
<ExternalIncludePath>$(MSBuildThisFileDirectory)deps;$(MSBuildThisFileDirectory)packages;$(ExternalIncludePath)</ExternalIncludePath>
<!-- Enable control flow guard for C++ projects that don't consume any C++ files -->
@@ -121,6 +122,48 @@
<SpectreMitigation>Spectre</SpectreMitigation>
</PropertyGroup>
<!--
vcpkg integration. Set globally and loaded before Microsoft.Cpp.props (via
ForceImportBeforeCppProps) so that vcpkg.props' ClCompile hook is in place
before the C++ targets run. VcpkgRoot is resolved via the same three-tier
fallback used by microsoft/terminal (env var → VS-shipped → deps/vcpkg).
-->
<PropertyGroup Label="vcpkg">
<VcpkgEnabled>true</VcpkgEnabled>
<VcpkgEnableManifest>true</VcpkgEnableManifest>
<VcpkgManifestEnabled>true</VcpkgManifestEnabled>
<VcpkgManifestRoot>$(MSBuildThisFileDirectory)</VcpkgManifestRoot>
<VcpkgOSTarget>windows</VcpkgOSTarget>
<VcpkgUseStatic>true</VcpkgUseStatic>
<!--
Force VcpkgConfiguration to follow $(Configuration). Without this,
vcpkg.props infers VcpkgConfiguration from $(UseDebugLibraries), which
Microsoft.Cpp.Default.props has already defaulted to 'false' by the
time vcpkg.props is imported here (the PowerToys-wide Debug override
below runs LATER). That would silently link the Release-built spdlog
into Debug consumers and trigger LNK2038 (MT/MTd, _ITERATOR_DEBUG_LEVEL).
-->
<VcpkgConfiguration>$(Configuration)</VcpkgConfiguration>
<!-- vcpkg validates triplets case-sensitively; PowerToys uses ARM64 capital-case. -->
<VcpkgPlatformTarget Condition="'$(Platform)' == 'ARM64'">arm64</VcpkgPlatformTarget>
<VcpkgApplocalDeps>false</VcpkgApplocalDeps>
<VcpkgInstalledDir>$(MSBuildThisFileDirectory)vcpkg_installed\$(Platform)\</VcpkgInstalledDir>
<VcpkgRoot Condition="'$(VcpkgRoot)' == ''">$(VCPKG_ROOT)</VcpkgRoot>
<VcpkgRoot Condition="'$(VcpkgRoot)' == '' and '$(VsInstallRoot)' != ''">$(VsInstallRoot)\VC\vcpkg</VcpkgRoot>
<VcpkgRoot Condition="'$(VcpkgRoot)' == '' or !Exists('$(VcpkgRoot)\vcpkg.exe')">$(MSBuildThisFileDirectory)deps\vcpkg</VcpkgRoot>
<CAExcludePath>$(CAExcludePath);$(VcpkgInstalledDir)</CAExcludePath>
<VCPkgLocalAppDataDisabled>true</VCPkgLocalAppDataDisabled>
</PropertyGroup>
<!-- Fail fast with an actionable message instead of opaque C1083 spdlog/spdlog.h errors. -->
<Target Name="PowerToysEnsureVcpkgAvailable"
BeforeTargets="PrepareForBuild"
Condition="'$(MSBuildProjectExtension)' == '.vcxproj' and '$(VcpkgEnabled)' == 'true' and !Exists('$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.props')">
<Error Text="PowerToys requires the 'vcpkg' Visual Studio component, but it was not found.%0A%0AOpen the Visual Studio Installer, click Modify on your VS install, search for 'vcpkg', enable 'C++ vcpkg package manager', and click Modify. (Visual Studio will also prompt you to install missing .vsconfig components when you open PowerToys.slnx.)%0A%0AIf you have vcpkg installed elsewhere, set the VCPKG_ROOT environment variable to its root before building.%0A%0ASearched: '$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.props'" />
</Target>
<Import Project="$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.props"
Condition="'$(MSBuildProjectExtension)' == '.vcxproj' and Exists('$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.props')" />
<!-- Debug/Release props -->
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>

16
Cpp.Build.targets Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<!--
PowerToys global C++ post-targets. Wired in via
<ForceImportAfterCppTargets> in Cpp.Build.props so MSBuild loads this
file AFTER Microsoft.Cpp.targets for every .vcxproj.
Conditionally imports vcpkg.targets to hook ClCompile into vcpkg's
VcpkgInstallManifestDependencies target so spdlog headers are
auto-discovered on the include path and spdlog.lib is auto-linked.
vcpkg.props is imported in Cpp.Build.props (before Microsoft.Cpp.props);
vcpkg.targets needs the matching "after" hook here.
-->
<Import Project="$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.targets"
Condition="'$(MSBuildProjectExtension)' == '.vcxproj' and '$(VcpkgEnabled)' == 'true' and Exists('$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.targets')" />
</Project>

View File

@@ -108,6 +108,7 @@ Thank you for using PowerToys!
| Microsoft.PowerToys.AwakeIndefinitelyKeepAwakeEvent | Triggered when the system is set to stay awake indefinitely. |
| Microsoft.PowerToys.AwakeNoKeepAwakeEvent | Occurs when Awake is turned off, allowing the computer to enter sleep mode. |
| Microsoft.PowerToys.AwakeTimedKeepAwakeEvent | Triggered when the system is kept awake for a specified time duration. |
| Microsoft.PowerToys.Awake_CLICommand | Triggered when an Awake CLI command is executed, logging the command name and success status. |
### Color Picker
@@ -204,6 +205,7 @@ Thank you for using PowerToys!
| Microsoft.PowerToys.FileLocksmith_Invoked | Occurs when File Locksmith is invoked. |
| Microsoft.PowerToys.FileLocksmith_InvokedRet | Triggered when File Locksmith invocation returns a result. |
| Microsoft.PowerToys.FileLocksmith_QueryContextMenuError | Occurs when there is an error querying the context menu for File Locksmith. |
| Microsoft.PowerToys.FileLocksmith_CLICommand | Triggered when a File Locksmith CLI command is executed, logging the operation mode (query, kill, query-wait, query-json, or help) and success status. |
### FileExplorerAddOns
@@ -240,6 +242,13 @@ Thank you for using PowerToys!
| Microsoft.PowerToys.FindMyMouse_EnableFindMyMouse | Triggered when Find My Mouse is enabled. |
| Microsoft.PowerToys.FindMyMouse_MousePointerFocused | Occurs when the mouse pointer is focused using Find My Mouse, including the activation method (double-tap left/right Ctrl, shake mouse, or shortcut). |
### Grab And Move
| Event Name | Description |
| --- | --- |
| Microsoft.PowerToys.GrabAndMove_EnableGrabAndMove | Triggered when Grab And Move is enabled or disabled. |
| Microsoft.PowerToys.GrabAndMove_ShortcutUse | Logs an attempt to move or resize a window via the Alt+Drag shortcut, including whether it succeeded, the action type (move or resize), and the reason (e.g., started, blocked by game mode). |
### Hosts File Editor
| Event Name | Description |
@@ -258,6 +267,7 @@ Thank you for using PowerToys!
| Microsoft.PowerToys.ImageResizer_Invoked | Occurs when Image Resizer is invoked by the user. |
| Microsoft.PowerToys.ImageResizer_InvokedRet | Fires when the Image Resizer operation is completed and returns a result. |
| Microsoft.PowerToys.ImageResizer_QueryContextMenuError | Triggered when there is an error querying the context menu for Image Resizer. |
| Microsoft.PowerToys.ImageResizer_CLICommand | Triggered when an Image Resizer CLI command is executed, logging the command name and success status. |
### Keyboard Manager
@@ -359,6 +369,15 @@ Thank you for using PowerToys!
| Microsoft.PowerToys.Peek_Settings | Triggered when the settings for Peek are modified. |
| Microsoft.PowerToys.Peek_SpaceModeEnabled | Triggered when the Space key activation mode is enabled or disabled in Peek. |
### Power Display
| Event Name | Description |
| --- | --- |
| Microsoft.PowerToys.PowerDisplay_EnablePowerDisplay | Triggered when Power Display is enabled or disabled. |
| Microsoft.PowerToys.PowerDisplay_Activate | Triggered when Power Display is activated via hotkey or tray toggle. |
| Microsoft.PowerToys.PowerDisplay_Start | Triggered when the Power Display application process starts. |
| Microsoft.PowerToys.PowerDisplay_Settings | Periodic snapshot of Power Display settings, including whether the hotkey and tray icon are enabled, the number of detected monitors, and the number of saved profiles. |
### PowerRename
| Event Name | Description |

View File

@@ -171,6 +171,12 @@
$(USERPROFILE)\AppData\LocalLow\Microsoft\PowerToys\**;
</MSBuildCacheAllowFileAccessAfterProjectFinishFilePatterns>
<!-- dotnet.exe seems to access files after builds. Temporarily putting in this entry for testing if we get further. This looks to be related to a .NET Roslyn Analyzer in .NET 10-->
<MSBuildCacheAllowFileAccessAfterProjectFinishProcessPatterns>
$(MSBuildCacheAllowFileAccessAfterProjectFinishProcessPatterns);
\**\dotnet\dotnet.exe;
\**\vbcscompiler.exe;
</MSBuildCacheAllowFileAccessAfterProjectFinishProcessPatterns>
<!--
This repo uses a common output directory with many projects writing duplicate outputs. Allow everything, but note this costs some performance in the form of requiring
the cache to use copies instead of hardlinks when pulling from cache.

View File

@@ -65,4 +65,20 @@
<!-- Note: For C++ skipped test projects, build is effectively skipped by removing all compile items above.
We don't define empty Build/Rebuild/Clean targets here because MSBuild Target definitions with Condition
on the Target element still override the default targets even when condition is false. -->
<!-- Clean up unused VC++ runtime DLLs that CopyCppRuntimeToOutputDir copies from the full
VCRedist tree (MFC, C++ AMP, OpenMP). No PowerToys binary links against these — verified
with dumpbin /dependents across all installed binaries. -->
<Target Name="RemoveUnusedVCRuntimeDlls"
AfterTargets="Build"
Condition="'$(CopyCppRuntimeToOutputDir)' == 'true' and '$(MSBuildProjectExtension)' == '.vcxproj'">
<ItemGroup>
<_UnusedVCRuntimeDlls Include="$(OutDir)mfc140*.dll" />
<_UnusedVCRuntimeDlls Include="$(OutDir)mfcm140*.dll" />
<_UnusedVCRuntimeDlls Include="$(OutDir)vcamp140*.dll" />
<_UnusedVCRuntimeDlls Include="$(OutDir)vcomp140*.dll" />
</ItemGroup>
<Delete Files="@(_UnusedVCRuntimeDlls)" Condition="'@(_UnusedVCRuntimeDlls)' != ''" />
<Message Importance="normal" Text="Cleaned up unused VC runtime DLLs: @(_UnusedVCRuntimeDlls)" Condition="'@(_UnusedVCRuntimeDlls)' != ''" />
</Target>
</Project>

View File

@@ -1,4 +1,4 @@
<Project>
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
@@ -39,36 +39,37 @@
<PackageVersion Include="Markdig.Signed" Version="0.34.0" />
<!-- Including MessagePack to force version, since it's used by StreamJsonRpc but contains vulnerabilities. After StreamJsonRpc updates the version of MessagePack, we can upgrade StreamJsonRpc instead. -->
<PackageVersion Include="MessagePack" Version="3.1.3" />
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="9.0.0" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.10" />
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.102" />
<PackageVersion Include="Microsoft.CommandPalette.Extensions" Version="0.9.260303001" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.8" />
<!-- Including Microsoft.Bcl.AsyncInterfaces to force version, since it's used by Microsoft.SemanticKernel. -->
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.10" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.8" />
<PackageVersion Include="Microsoft.Graphics.Win2D" Version="1.3.2" />
<PackageVersion Include="Microsoft.Windows.CppWinRT" Version="2.0.250303.1" />
<PackageVersion Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.16" />
<PackageVersion Include="Microsoft.Extensions.AI" Version="9.9.1" />
<PackageVersion Include="Microsoft.Extensions.AI.OpenAI" Version="9.9.1-preview.1.25474.6" />
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.10" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.10" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.10" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.10" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.10" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.10" />
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.10" />
<PackageVersion Include="Microsoft.Extensions.AI" Version="10.2.0" />
<PackageVersion Include="Microsoft.Extensions.AI.OpenAI" Version="10.0.1-preview.1.25571.5" />
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="10.0.8" />
<PackageVersion Include="Microsoft.AI.Foundry.Local" Version="0.3.0" />
<PackageVersion Include="Microsoft.SemanticKernel" Version="1.66.0" />
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.OpenAI" Version="1.66.0" />
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.AzureAIInference" Version="1.66.0-beta" />
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Google" Version="1.66.0-alpha" />
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.MistralAI" Version="1.66.0-alpha" />
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Ollama" Version="1.66.0-alpha" />
<PackageVersion Include="Microsoft.SemanticKernel" Version="1.71.0" />
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.OpenAI" Version="1.71.0" />
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.AzureAIInference" Version="1.71.0-beta" />
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Google" Version="1.71.0-alpha" />
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.MistralAI" Version="1.71.0-alpha" />
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Ollama" Version="1.71.0-alpha" />
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.3179.45" />
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.3719.77" />
<!-- Package Microsoft.Win32.SystemEvents added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Drawing.Common but the 8.0.1 version wasn't published to nuget. -->
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="9.0.10" />
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="10.0.8" />
<PackageVersion Include="Microsoft.WindowsPackageManager.ComInterop" Version="1.10.340" />
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="9.0.10" />
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.3.183" />
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="10.0.8" />
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.3.269" />
<!-- CsWinRT version needs to be set to have a WinRT.Runtime.dll at the same version contained inside the NET SDK we're currently building on CI. -->
<!--
TODO: in Common.Dotnet.CsWinRT.props, on upgrade, verify RemoveCsWinRTPackageAnalyzer is no longer needed.
@@ -77,10 +78,10 @@
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
<PackageVersion Include="Microsoft.Windows.ImplementationLibrary" Version="1.0.250325.1"/>
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.6901" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.8.260209005" />
<PackageVersion Include="Microsoft.WindowsAppSDK.Foundation" Version="1.8.260203002" />
<PackageVersion Include="Microsoft.WindowsAppSDK.AI" Version="1.8.47" />
<PackageVersion Include="Microsoft.WindowsAppSDK.Runtime" Version="1.8.260209005" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="2.0.1" />
<PackageVersion Include="Microsoft.WindowsAppSDK.Foundation" Version="2.0.20" />
<PackageVersion Include="Microsoft.WindowsAppSDK.AI" Version="2.0.185" />
<PackageVersion Include="Microsoft.WindowsAppSDK.Runtime" Version="2.0.1" />
<PackageVersion Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
<PackageVersion Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
<PackageVersion Include="ModernWpfUI" Version="0.9.4" />
@@ -89,11 +90,11 @@
<PackageVersion Include="MSTest" Version="$(MSTestVersion)" />
<PackageVersion Include="MSTest.TestFramework" Version="$(MSTestVersion)" />
<PackageVersion Include="NJsonSchema" Version="11.4.0" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
<PackageVersion Include="NLog" Version="5.2.8" />
<PackageVersion Include="NLog.Extensions.Logging" Version="5.3.8" />
<PackageVersion Include="NLog.Schema" Version="5.2.8" />
<PackageVersion Include="OpenAI" Version="2.5.0" />
<PackageVersion Include="OpenAI" Version="2.7.0" />
<PackageVersion Include="Polly.Core" Version="8.6.5" />
<PackageVersion Include="ReverseMarkdown" Version="4.1.0" />
<PackageVersion Include="RtfPipe" Version="2.0.7677.4303" />
@@ -105,31 +106,28 @@
<PackageVersion Include="StreamJsonRpc" Version="2.21.69" />
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
<!-- Package System.CodeDom added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Management but the 8.0.1 version wasn't published to nuget. -->
<PackageVersion Include="System.CodeDom" Version="9.0.10" />
<PackageVersion Include="System.Collections.Immutable" Version="9.0.0" />
<PackageVersion Include="System.CodeDom" Version="10.0.8" />
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageVersion Include="System.ComponentModel.Composition" Version="9.0.10" />
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="9.0.10" />
<PackageVersion Include="System.Data.OleDb" Version="9.0.10" />
<!-- Package System.Data.SqlClient added to force it as a dependency of Microsoft.Windows.Compatibility to the latest version available at this time. -->
<PackageVersion Include="System.Data.SqlClient" Version="4.9.0" />
<PackageVersion Include="System.ComponentModel.Composition" Version="10.0.8" />
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="10.0.8" />
<PackageVersion Include="System.Data.OleDb" Version="10.0.8" />
<!-- Package System.Diagnostics.EventLog added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Data.OleDb but the 8.0.1 version wasn't published to nuget. -->
<PackageVersion Include="System.Diagnostics.EventLog" Version="9.0.10" />
<PackageVersion Include="System.Diagnostics.EventLog" Version="10.0.8" />
<!-- Package System.Diagnostics.PerformanceCounter added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.11. -->
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="9.0.10" />
<PackageVersion Include="System.ClientModel" Version="1.7.0" />
<PackageVersion Include="System.Drawing.Common" Version="9.0.10" />
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="10.0.8" />
<PackageVersion Include="System.ClientModel" Version="1.8.1" />
<PackageVersion Include="System.Drawing.Common" Version="10.0.8" />
<PackageVersion Include="System.IO.Abstractions" Version="22.0.13" />
<PackageVersion Include="System.IO.Abstractions.TestingHelpers" Version="22.0.13" />
<PackageVersion Include="System.Management" Version="9.0.10" />
<PackageVersion Include="System.Management" Version="10.0.8" />
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
<PackageVersion Include="System.Numerics.Tensors" Version="9.0.11" />
<PackageVersion Include="System.Numerics.Tensors" Version="10.0.2" />
<PackageVersion Include="System.Private.Uri" Version="4.3.2" />
<PackageVersion Include="System.Reactive" Version="6.0.1" />
<PackageVersion Include="System.Runtime.Caching" Version="9.0.10" />
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="9.0.10" />
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.10" />
<PackageVersion Include="System.Text.Json" Version="9.0.10" />
<PackageVersion Include="System.Runtime.Caching" Version="10.0.8" />
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="10.0.8" />
<PackageVersion Include="System.Text.Encoding.CodePages" Version="10.0.8" />
<PackageVersion Include="System.Text.Json" Version="10.0.8" />
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
<PackageVersion Include="ToolGood.Words.Pinyin" Version="3.1.0.3" />
<PackageVersion Include="UnicodeInformation" Version="2.6.0" />
@@ -137,8 +135,8 @@
<PackageVersion Include="UTF.Unknown" Version="2.6.0" />
<PackageVersion Include="WinUIEx" Version="2.8.0" />
<PackageVersion Include="WmiLight" Version="6.14.0" />
<PackageVersion Include="WPF-UI" Version="3.0.5" />
<PackageVersion Include="WyHash" Version="1.0.5" />
<PackageVersion Include="YamlDotNet" Version="16.3.0" />
<PackageVersion Include="WixToolset.Heat" Version="5.0.2" />
<PackageVersion Include="WixToolset.Firewall.wixext" Version="5.0.2" />
<PackageVersion Include="WixToolset.Util.wixext" Version="5.0.2" />

View File

@@ -1587,7 +1587,6 @@ SOFTWARE.
- NLog.Extensions.Logging
- NLog.Schema
- OpenAI
- Polly.Core
- ReverseMarkdown
- ScipBe.Common.Office.OneNote
- SharpCompress
@@ -1601,5 +1600,5 @@ SOFTWARE.
- UTF.Unknown
- WinUIEx
- WmiLight
- WPF-UI
- WyHash
- YamlDotNet

View File

@@ -68,10 +68,7 @@
<Project Path="src/common/interop/PowerToys.Interop.vcxproj" Id="f055103b-f80b-4d0c-bf48-057c55620033" />
</Folder>
<Folder Name="/common/log/">
<Project Path="src/common/logger/logger.vcxproj" Id="d9b8fc84-322a-4f9f-bbb9-20915c47ddfd">
<BuildDependency Project="src/logging/logging.vcxproj" />
</Project>
<Project Path="src/logging/logging.vcxproj" Id="7e1e3f13-2bd6-3f75-a6a7-873a2b55c60f" />
<Project Path="src/common/logger/logger.vcxproj" Id="d9b8fc84-322a-4f9f-bbb9-20915c47ddfd" />
</Folder>
<Folder Name="/common/notifications/">
<Project Path="src/common/notifications/BackgroundActivator/BackgroundActivator.vcxproj" Id="0b593a6c-4143-4337-860e-db5710fb87db" />
@@ -207,6 +204,10 @@
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
</Project>
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Actions/Microsoft.CmdPal.Ext.Actions.csproj">
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
</Project>
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Microsoft.CmdPal.Ext.Bookmarks.csproj">
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
@@ -320,6 +321,10 @@
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
</Project>
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.Indexer.UnitTests/Microsoft.CmdPal.Ext.Indexer.UnitTests.csproj">
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
</Project>
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.Registry.UnitTests/Microsoft.CmdPal.Ext.Registry.UnitTests.csproj">
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
@@ -794,6 +799,14 @@
<Project Path="src/modules/peek/peek/peek.vcxproj" Id="a1425b53-3d61-4679-8623-e64a0d3d0a48" />
</Folder>
<Folder Name="/modules/PowerAccent/">
<Project Path="src/modules/poweraccent/PowerAccent.Common.UnitTests/PowerAccent.Common.UnitTests.csproj">
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
</Project>
<Project Path="src/modules/poweraccent/PowerAccent.Common/PowerAccent.Common.csproj">
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
</Project>
<Project Path="src/modules/poweraccent/PowerAccent.Core/PowerAccent.Core.csproj">
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
@@ -982,9 +995,20 @@
<Platform Solution="*|x64" Project="x64" />
</Project>
</Folder>
<Folder Name="/modules/shortcutguide/">
<Project Path="src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj" Id="2edb3eb4-fa92-4bff-b2d8-566584837231" />
<Project Path="src/modules/ShortcutGuide/ShortcutGuideModuleInterface/ShortcutGuideModuleInterface.vcxproj" Id="2d604c07-51fc-46bb-9eb7-75aecc7f5e81" />
<Folder Name="/modules/ShortcutGuide/">
<Project Path="src/modules/ShortcutGuide/ShortcutGuide.IndexYmlGenerator/ShortcutGuide.IndexYmlGenerator.csproj">
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
</Project>
<Project Path="src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj">
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
</Project>
<Project Path="src/modules/ShortcutGuide/ShortcutGuide.UnitTests/ShortcutGuide.UnitTests.csproj">
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
</Project>
<Project Path="src/modules/ShortcutGuide/ShortcutGuideModuleInterface/ShortcutGuideModuleInterface.vcxproj" Id="e487304a-b1fb-4e6b-8e70-014051af5b99" />
</Folder>
<Folder Name="/modules/Workspaces/">
<Project Path="src/modules/Workspaces/Workspaces.ModuleServices/Workspaces.ModuleServices.csproj">
@@ -1037,6 +1061,10 @@
<Project Path="src/modules/ZoomIt/ZoomItModuleInterface/ZoomItModuleInterface.vcxproj" Id="e4585179-2ac1-4d5f-a3ff-cfc5392f694c" />
<Project Path="src/modules/ZoomIt/ZoomItSettingsInterop/ZoomItSettingsInterop.vcxproj" Id="ca7d8106-30b9-4aec-9d05-b69b31b8c461" />
</Folder>
<Folder Name="/modules/GrabAndMove/">
<Project Path="src/modules/GrabAndMove/GrabAndMove/GrabAndMove.vcxproj" Id="568c4c30-2e3c-4c2c-a691-007362073765" />
<Project Path="src/modules/GrabAndMove/GrabAndMoveModuleInterface/GrabAndMoveModuleInterface.vcxproj" Id="2c3f7770-4e57-46b7-8dc1-7428a383d0db" />
</Folder>
<Folder Name="/settings-ui/">
<Project Path="src/settings-ui/QuickAccess.UI/PowerToys.QuickAccess.csproj">
<Platform Solution="*|ARM64" Project="ARM64" />
@@ -1101,6 +1129,8 @@
<BuildDependency Project="src/modules/launcher/Microsoft.Launcher/Microsoft.Launcher.vcxproj" />
<BuildDependency Project="src/modules/LightSwitch/LightSwitchModuleInterface/LightSwitchModuleInterface.vcxproj" />
<BuildDependency Project="src/modules/LightSwitch/LightSwitchService/LightSwitchService.vcxproj" />
<BuildDependency Project="src/modules/GrabAndMove/GrabAndMoveModuleInterface/GrabAndMoveModuleInterface.vcxproj" />
<BuildDependency Project="src/modules/GrabAndMove/GrabAndMove/GrabAndMove.vcxproj" />
<BuildDependency Project="src/modules/powerrename/dll/PowerRenameExt.vcxproj" />
<BuildDependency Project="src/modules/powerrename/lib/PowerRenameLib.vcxproj" />
<BuildDependency Project="src/modules/previewpane/Common/PreviewHandlerCommon.csproj" />
@@ -1113,3 +1143,5 @@
<Project Path="src/Update/PowerToys.Update.vcxproj" Id="44ce9ae1-4390-42c5-bacc-0fd6b40aa203" />
<Project Path="tools/project_template/ModuleTemplate/ModuleTemplateCompileTest.vcxproj" Id="64a80062-4d8b-4229-8a38-dfa1d7497749" />
</Solution>

View File

@@ -29,13 +29,13 @@ PowerToys includes over 30 utilities to help you customize and optimize your Win
| [<img src="doc/images/icons/AdvancedPaste.png" alt="Advanced Paste icon" height="16"> Advanced Paste](https://aka.ms/PowerToysOverview_AdvancedPaste) | [<img src="doc/images/icons/Always%20On%20Top.png" alt="Always on Top icon" height="16"> Always on Top](https://aka.ms/PowerToysOverview_AoT) | [<img src="doc/images/icons/Awake.png" alt="Awake icon" height="16"> Awake](https://aka.ms/PowerToysOverview_Awake) |
| [<img src="doc/images/icons/Color%20Picker.png" alt="Color Picker icon" height="16"> Color Picker](https://aka.ms/PowerToysOverview_ColorPicker) | [<img src="doc/images/icons/Command%20Not%20Found.png" alt="Command Not Found icon" height="16"> Command Not Found](https://aka.ms/PowerToysOverview_CmdNotFound) | [<img src="doc/images/icons/Command Palette.png" alt="Command Palette icon" height="16"> Command Palette](https://aka.ms/PowerToysOverview_CmdPal) |
| [<img src="doc/images/icons/Crop%20And%20Lock.png" alt="Crop and Lock icon" height="16"> Crop And Lock](https://aka.ms/PowerToysOverview_CropAndLock) | [<img src="doc/images/icons/Environment%20Manager.png" alt="Environment Variables icon" height="16"> Environment Variables](https://aka.ms/PowerToysOverview_EnvironmentVariables) | [<img src="doc/images/icons/FancyZones.png" alt="FancyZones icon" height="16"> FancyZones](https://aka.ms/PowerToysOverview_FancyZones) |
| [<img src="doc/images/icons/File%20Explorer%20Preview.png" alt="File Explorer Add-ons icon" height="16"> File Explorer Add-ons](https://aka.ms/PowerToysOverview_FileExplorerAddOns) | [<img src="doc/images/icons/File%20Locksmith.png" alt="File Locksmith icon" height="16"> File Locksmith](https://aka.ms/PowerToysOverview_FileLocksmith) | [<img src="doc/images/icons/Host%20File%20Editor.png" alt="Hosts File Editor icon" height="16"> Hosts File Editor](https://aka.ms/PowerToysOverview_HostsFileEditor) |
| [<img src="doc/images/icons/Image%20Resizer.png" alt="Image Resizer icon" height="16"> Image Resizer](https://aka.ms/PowerToysOverview_ImageResizer) | [<img src="doc/images/icons/Keyboard%20Manager.png" alt="Keyboard Manager icon" height="16"> Keyboard Manager](https://aka.ms/PowerToysOverview_KeyboardManager) | [<img src="doc/images/icons/Light Switch.png" alt="Light Switch icon" height="16"> Light Switch](https://aka.ms/PowerToysOverview_LightSwitch) |
| [<img src="doc/images/icons/Find My Mouse.png" alt="Mouse Utilities icon" height="16"> Mouse Utilities](https://aka.ms/PowerToysOverview_MouseUtilities) | [<img src="doc/images/icons/MouseWithoutBorders.png" alt="Mouse Without Borders icon" height="16"> Mouse Without Borders](https://aka.ms/PowerToysOverview_MouseWithoutBorders) | [<img src="doc/images/icons/NewPlus.png" alt="New+ icon" height="16"> New+](https://aka.ms/PowerToysOverview_NewPlus) |
| [<img src="doc/images/icons/Peek.png" alt="Peek icon" height="16"> Peek](https://aka.ms/PowerToysOverview_Peek) | [<img src="doc/images/icons/PowerRename.png" alt="PowerRename icon" height="16"> PowerRename](https://aka.ms/PowerToysOverview_PowerRename) | [<img src="doc/images/icons/PowerToys%20Run.png" alt="PowerToys Run icon" height="16"> PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) |
| [<img src="doc/images/icons/PowerAccent.png" alt="Quick Accent icon" height="16"> Quick Accent](https://aka.ms/PowerToysOverview_QuickAccent) | [<img src="doc/images/icons/Registry%20Preview.png" alt="Registry Preview icon" height="16"> Registry Preview](https://aka.ms/PowerToysOverview_RegistryPreview) | [<img src="doc/images/icons/MeasureTool.png" alt="Screen Ruler icon" height="16"> Screen Ruler](https://aka.ms/PowerToysOverview_ScreenRuler) |
| [<img src="doc/images/icons/Shortcut%20Guide.png" alt="Shortcut Guide icon" height="16"> Shortcut Guide](https://aka.ms/PowerToysOverview_ShortcutGuide) | [<img src="doc/images/icons/PowerOCR.png" alt="Text Extractor icon" height="16"> Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) | [<img src="doc/images/icons/Workspaces.png" alt="Workspaces icon" height="16"> Workspaces](https://aka.ms/PowerToysOverview_Workspaces) |
| [<img src="doc/images/icons/ZoomIt.png" alt="ZoomIt icon" height="16"> ZoomIt](https://aka.ms/PowerToysOverview_ZoomIt) | | |
| [<img src="doc/images/icons/File%20Explorer%20Preview.png" alt="File Explorer Add-ons icon" height="16"> File Explorer Add-ons](https://aka.ms/PowerToysOverview_FileExplorerAddOns) | [<img src="doc/images/icons/File%20Locksmith.png" alt="File Locksmith icon" height="16"> File Locksmith](https://aka.ms/PowerToysOverview_FileLocksmith) | [<img src="doc/images/icons/GrabAndMove.png" alt="Grab And Move icon" height="16"> Grab And Move](https://aka.ms/PowerToysOverview_GrabAndMove) |
| [<img src="doc/images/icons/Host%20File%20Editor.png" alt="Hosts File Editor icon" height="16"> Hosts File Editor](https://aka.ms/PowerToysOverview_HostsFileEditor) | [<img src="doc/images/icons/Image%20Resizer.png" alt="Image Resizer icon" height="16"> Image Resizer](https://aka.ms/PowerToysOverview_ImageResizer) | [<img src="doc/images/icons/Keyboard%20Manager.png" alt="Keyboard Manager icon" height="16"> Keyboard Manager](https://aka.ms/PowerToysOverview_KeyboardManager) |
| [<img src="doc/images/icons/Light Switch.png" alt="Light Switch icon" height="16"> Light Switch](https://aka.ms/PowerToysOverview_LightSwitch) | [<img src="doc/images/icons/Find My Mouse.png" alt="Mouse Utilities icon" height="16"> Mouse Utilities](https://aka.ms/PowerToysOverview_MouseUtilities) | [<img src="doc/images/icons/MouseWithoutBorders.png" alt="Mouse Without Borders icon" height="16"> Mouse Without Borders](https://aka.ms/PowerToysOverview_MouseWithoutBorders) |
| [<img src="doc/images/icons/NewPlus.png" alt="New+ icon" height="16"> New+](https://aka.ms/PowerToysOverview_NewPlus) | [<img src="doc/images/icons/Peek.png" alt="Peek icon" height="16"> Peek](https://aka.ms/PowerToysOverview_Peek) | [<img src="doc/images/icons/PowerDisplay.png" alt="PowerDisplay icon" height="16"> PowerDisplay](https://aka.ms/PowerToysOverview_PowerDisplay) |
| [<img src="doc/images/icons/PowerRename.png" alt="PowerRename icon" height="16"> PowerRename](https://aka.ms/PowerToysOverview_PowerRename) | [<img src="doc/images/icons/PowerToys%20Run.png" alt="PowerToys Run icon" height="16"> PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) | [<img src="doc/images/icons/PowerAccent.png" alt="Quick Accent icon" height="16"> Quick Accent](https://aka.ms/PowerToysOverview_QuickAccent) |
| [<img src="doc/images/icons/Registry%20Preview.png" alt="Registry Preview icon" height="16"> Registry Preview](https://aka.ms/PowerToysOverview_RegistryPreview) | [<img src="doc/images/icons/MeasureTool.png" alt="Screen Ruler icon" height="16"> Screen Ruler](https://aka.ms/PowerToysOverview_ScreenRuler) | [<img src="doc/images/icons/Shortcut%20Guide.png" alt="Shortcut Guide icon" height="16"> Shortcut Guide](https://aka.ms/PowerToysOverview_ShortcutGuide) |
| [<img src="doc/images/icons/PowerOCR.png" alt="Text Extractor icon" height="16"> Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) | [<img src="doc/images/icons/Workspaces.png" alt="Workspaces icon" height="16"> Workspaces](https://aka.ms/PowerToysOverview_Workspaces) | [<img src="doc/images/icons/ZoomIt.png" alt="ZoomIt icon" height="16"> ZoomIt](https://aka.ms/PowerToysOverview_ZoomIt) |
## 📦 Installation
@@ -47,21 +47,7 @@ But to get started quickly, choose one of the installation methods below:
<summary><strong>Download the .exe file from GitHub</strong></summary>
<br/>
Go to the [PowerToys GitHub releases](https://aka.ms/installPowerToys), select **Assets** to reveal the installation files, and choose the one that matches your architecture and install scope. For most devices, that would be _x64 per-user_.
<!-- items that need to be updated release to release -->
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.99%22
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.98.1/PowerToysUserSetup-0.98.1-x64.exe
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.98.1/PowerToysUserSetup-0.98.1-arm64.exe
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.98.1/PowerToysSetup-0.98.1-x64.exe
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.98.1/PowerToysSetup-0.98.1-arm64.exe
| Description | Filename |
| --- | --- |
| Per user - x64 | [PowerToysUserSetup-0.98.1-x64.exe][ptUserX64] |
| Per user - ARM64 | [PowerToysUserSetup-0.98.1-arm64.exe][ptUserArm64] |
| Machine wide - x64 | [PowerToysSetup-0.98.1-x64.exe][ptMachineX64] |
| Machine wide - ARM64 | [PowerToysSetup-0.98.1-arm64.exe][ptMachineArm64] |
Go to the [PowerToys GitHub releases](https://aka.ms/installPowerToys), scroll down and select **Assets** to reveal the installation files, and choose the one that matches your architecture and install scope. For most devices, that would be _x64 per-user_.
</details>
@@ -106,11 +92,11 @@ There are [community driven install methods](https://learn.microsoft.com/windows
[![What's new image](doc/images/readme/Release-Banner.png)](https://github.com/microsoft/PowerToys/releases)
To see what's new, check out the [release notes](https://github.com/microsoft/PowerToys/releases/tag/v0.98.1).
To see what's new, check out the [release notes](https://github.com/microsoft/PowerToys/releases/).
## 🛣️ Roadmap
We are planning some nice new features and improvements for the next releases PowerDisplay, Command Palette improvements and a brand-new Shortcut Guide experience! Stay tuned for [v0.99][github-next-release-work]!
We are planning some nice new features and improvements for the next releases a brand-new Shortcut Guide experience, ensuring it's easier to find and install Command Palette extensions and so much more! Stay tuned for [v0.100][github-next-release-work]!
## ❤️ PowerToys Community
@@ -131,3 +117,4 @@ The application logs basic diagnostic data (telemetry). For more privacy informa
[oss-CLA]: https://cla.opensource.microsoft.com
[oss-conduct-code]: CODE_OF_CONDUCT.md
[community-link]: COMMUNITY.md
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.100%22

54
auto-cherry-pick.ps1 Normal file
View File

@@ -0,0 +1,54 @@
# Auto-resolve cherry-pick conflicts
param([int]$MaxAttempts = 100)
$attempts = 0
while ($attempts -lt $MaxAttempts) {
$attempts++
# Check if cherry-pick is in progress
$status = git status --porcelain
if (-not $status) {
Write-Host "Cherry-pick complete!" -ForegroundColor Green
break
}
# Get conflicted files
$conflicts = git diff --name-only --diff-filter=U
if ($conflicts) {
Write-Host "Attempt $attempts`: Resolving conflicts..." -ForegroundColor Yellow
foreach ($file in $conflicts) {
Write-Host " Resolving: $file"
git checkout --ours $file 2>$null
}
# Handle deleted files
git status --short | Where-Object { $_ -match '^DU' } | ForEach-Object {
$file = ($_ -split '\s+', 2)[1]
Write-Host " Removing deleted: $file"
git rm $file 2>$null
}
git add . 2>$null
}
# Try to continue
$result = git cherry-pick --continue 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host " Continued successfully" -ForegroundColor Green
}
elseif ($result -match 'empty') {
Write-Host " Skipping empty commit" -ForegroundColor Cyan
git cherry-pick --skip 2>&1 | Out-Null
}
else {
Write-Host " Error: $result" -ForegroundColor Red
Start-Sleep -Seconds 1
}
}
if ($attempts -ge $MaxAttempts) {
Write-Host "Max attempts reached. Check status manually." -ForegroundColor Red
}

1
deps/expected-lite vendored

Submodule deps/expected-lite deleted from 95b9cb015f

7
deps/expected.props vendored
View File

@@ -1,7 +0,0 @@
<Project>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)expected-lite\include\nonstd\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
</Project>

1
deps/spdlog vendored

Submodule deps/spdlog deleted from 616866fcf4

18
deps/spdlog.props vendored
View File

@@ -1,8 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)spdlog\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>SPDLOG_WCHAR_TO_UTF8_SUPPORT;SPDLOG_COMPILED_LIB;SPDLOG_WCHAR_FILENAMES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<!--
SPDLOG_* preprocessor defines for spdlog consumers. The actual vcpkg
integration (VcpkgEnabled, VcpkgRoot, triplet, manifest install) lives
in Cpp.Build.props; this file just carries the defines that match how
the pre-vcpkg in-tree build was configured.
-->
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>SPDLOG_WCHAR_TO_UTF8_SUPPORT;SPDLOG_COMPILED_LIB;SPDLOG_WCHAR_FILENAMES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
</Project>

View File

@@ -0,0 +1,16 @@
--- a/include/spdlog/fmt/bundled/format.h
+++ b/include/spdlog/fmt/bundled/format.h
@@ -354,7 +354,12 @@ inline typename Container::value_type* get_data(Container& c) {
return c.data();
}
-#if defined(_SECURE_SCL) && _SECURE_SCL
+// PowerToys: stdext::checked_array_iterator was deprecated in VS 2019 16.10
+// and removed entirely in MSVC 14.51 (compiler 19.51, _MSC_VER >= 1951;
+// see microsoft/STL STL4043). Skip the broken branch on those toolsets so the
+// pointer-based fallback below is used instead. Drop this guard once
+// deps/spdlog is bumped past v1.14 (which ships fmt 10.2 and removes this code).
+#if defined(_SECURE_SCL) && _SECURE_SCL && (!defined(_MSC_VER) || _MSC_VER < 1951)
// Make a checked iterator to avoid MSVC warnings.
template <typename T> using checked_ptr = stdext::checked_array_iterator<T*>;
template <typename T> checked_ptr<T> make_checked(T* p, size_t size) {

View File

@@ -0,0 +1,43 @@
# PowerToys overlay port for spdlog.
#
# Pinned to the same git commit that the deleted deps/spdlog submodule pointed
# at, so this is a 1:1 submodule->vcpkg migration with no version change
# (per the maintainer guidance: convert one submodule at a time, atomic
# commit, don't also bump the version).
#
# A single hunk patch works around MSVC 14.51 STL4043 (removal of
# stdext::checked_array_iterator) in spdlog's bundled fmt 7. Drop this overlay
# (and switch to upstream vcpkg's spdlog port) once PowerToys bumps spdlog
# past v1.14, which ships fmt 10.2 and removes the affected code path.
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO gabime/spdlog
REF 616866fcf40340ea25a8f218369bad810ef58e72
SHA512 2076c527c7768627e6856b2f7ef663b185fd6251894cffd9299203d00f3d2de5696461060442dd72b96c9d3f0fd27f7f63ad2edfdf295e9b06c5fac6d6212faf
HEAD_REF v1.x
PATCHES
msvc-14.51-stdext-checked-array-iterator.patch
)
vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
OPTIONS
-DSPDLOG_BUILD_EXAMPLE=OFF
-DSPDLOG_BUILD_TESTS=OFF
-DSPDLOG_BUILD_BENCH=OFF
-DSPDLOG_FMT_EXTERNAL=OFF
-DSPDLOG_WCHAR_SUPPORT=ON
-DSPDLOG_WCHAR_FILENAMES=ON
-DSPDLOG_NO_EXCEPTIONS=OFF
-DSPDLOG_BUILD_SHARED=OFF
)
vcpkg_cmake_install()
vcpkg_cmake_config_fixup(PACKAGE_NAME spdlog CONFIG_PATH lib/cmake/spdlog)
vcpkg_fixup_pkgconfig()
vcpkg_copy_pdbs()
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include")
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE")

18
deps/vcpkg-overlays/spdlog/vcpkg.json vendored Normal file
View File

@@ -0,0 +1,18 @@
{
"name": "spdlog",
"version-string": "1.8.5-pt-616866fc",
"port-version": 0,
"description": "Very fast, header-only/compiled, C++ logging library. PowerToys overlay pinned to gabime/spdlog@616866fc (the exact submodule commit before this migration), with a single-hunk patch that works around MSVC 14.51 removing stdext::checked_array_iterator (STL4043).",
"homepage": "https://github.com/gabime/spdlog",
"license": "MIT",
"dependencies": [
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
]
}

View File

@@ -97,6 +97,10 @@ The Shell Process Debugging Tool is a Visual Studio extension that helps debug m
- Check Event Viewer for application crashes related to `PowerToys.Settings.exe`
- Crash dumps can be obtained from Event Viewer
### Debugging Command Palette
Command Palette can be easily debugged using the solution filter in `src/modules/cmdpal/Command Palette.slnf`. This will open Command Palette as its own Visual Studio solution that can be run and debugged directly in Visual Studio without the need for the Shell Process Debugging Tool.
## Troubleshooting Build Errors
### Missing Image Files or Corrupted Build State

View File

@@ -56,7 +56,7 @@ After generating the resx file, rename the existing rc and h files to ProjName.b
</Target>
```
This event runs a script which generates a resource.h and ProjName.rc in the `Generated Files` folder using the strings in all the resx files along with the existing information in resource.base.h and ProjName.base.rc. The script is [convert-resx-to-rc.ps1](https://github.com/microsoft/PowerToys/blob/main/tools/build/convert-resx-to-rc.ps1). The script uses [`resgen`](https://learn.microsoft.com/dotnet/framework/tools/resgen-exe-resource-file-generator#Convert) to convert the resx file to a string table expected in the .rc file format. When the resources are added to the rc file the `IDS_` prefix is added and resource names are in upper case (as it was originally). Any occurrences of `"` in the string resource is escaped as `""` to prevent build errors. The string tables are added to the rc file in the following format:
This event runs a script which generates a resource.h and ProjName.rc in the `Generated Files` folder using the strings in all the resx files along with the existing information in resource.base.h and ProjName.base.rc. The script is [convert-resx-to-rc.ps1](https://github.com/microsoft/PowerToys/blob/main/tools/build/convert-resx-to-rc.ps1). The script uses [`resgen`](https://learn.microsoft.com/dotnet/framework/tools/resgen-exe-resource-file-generator#Convert) to convert the resx file to a string table expected in the .rc file format. When the resources are added to the rc file the `IDS_` prefix is added and resource names are in uppercase (as it was originally). Any occurrences of `"` in the string resource is escaped as `""` to prevent build errors. The string tables are added to the rc file in the following format:
```
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -461,7 +461,7 @@ Editor read/write config data handler is in FancyZonesEditorCommon project.
FancyZones cpp project read/write config data handler is in FancyZonesLib project.
![Debug Step Image](../images/fancyzones/19.png)
However, the files write and read those are C:\Users\“xxxxxx”\AppData\Local\Microsoft\PowerToys\FancyZones
However, the files read from and written to are those in `C:\Users\“xxxxxx”\AppData\Local\Microsoft\PowerToys\FancyZones`
You can think of the editor as a visual config editor, which is most of its functionality. Another feature is used to set the layout for the monitor displays.

View File

@@ -3,9 +3,9 @@
- [ ] The plugin is a project under `modules\launcher\Plugins`
- [ ] Microsoft plugin project name pattern: `Microsoft.PowerToys.Run.Plugin.{PluginName}`
- [ ] Community plugin project name pattern: `Community.PowerToys.Run.Plugin.{PluginName}`
- [ ] The plugin target framework should be `net9.0-windows10.0.22621.0`
- [ ] The plugin target framework should be `net10.0-windows10.0.22621.0`
- [ ] If the plugin uses any 3rd party dependencies the project file should import `DynamicPlugin.props`
- [ ] 3rd party dependencies must be compatible with .NET 9
- [ ] 3rd party dependencies must be compatible with .NET 10
- [ ] The plugin has to contain a `plugin.json` file of the following format in its root folder:
```json

View File

@@ -75,7 +75,7 @@ There are three different score types with different start values.
| Medium score | 5000 |
| Low score | 1000 |
Each score will decreased by one when a condition match.
Each score will be decreased by one when a condition match.
| Priority | Condition | Score type |
| -------- | ----------------------------------------------------------------- | ------------ |
@@ -134,7 +134,7 @@ The plugin use only these interfaces (all inside the `Main.cs`):
| `plugin.json` | All meta-data for this plugin |
1. We need this extra wrapper class to make it possible that the JSON file can have and use a JSON schema file.
Because the JSON file must have a object as root type, instead of a array.
Because the JSON file must have an object as root type, instead of an array.
### Important project values (*.csproj)

View File

@@ -9,12 +9,14 @@
[Pull Requests](https://github.com/microsoft/PowerToys/pulls?q=is%3Apr+is%3Aopen+label%3A%22Product-Shortcut+Guide%22+)
## Overview
Shortcut Guide is a PowerToy that displays an overlay of available keyboard shortcuts when the Windows key is pressed and held. It provides a visual reference for Windows key combinations, helping users discover and utilize built-in Windows shortcuts.
Shortcut Guide is a PowerToy that displays an overlay of available keyboard shortcuts when a user-set keyboard shortcut is pressed. It helps users discover and remember keyboard shortcuts for Windows and apps.
> [!NOTE]
> The spec for the manifest files is in development and will be linked here once available.
## Usage
- Press and hold the Windows key to display the overlay of available shortcuts
- Press the hotkey again to dismiss the overlay
- The overlay displays Windows shortcuts with their corresponding actions
- Press the user-defined hotkey to display the overlay
- Press the hotkey again or press ESC to dismiss the overlay
## Build and Debug Instructions
@@ -25,67 +27,89 @@ Shortcut Guide is a PowerToy that displays an overlay of available keyboard shor
4. The executable is named PowerToys.ShortcutGuide.exe
### Debug
1. Right-click the ShortcutGuide project and select 'Set as Startup Project'
1. Right-click the ShortcutGuide.Ui project and select 'Set as Startup Project'
2. Right-click the project again and select 'Debug'
## Code Structure
> [!NOTE]
> When run in debug mode, the window behaves differently than in release mode. It will not automatically close when loosing focus, it will be displayed on top of all other windows, and it is not hidden from the taskbar.
![Diagram](../images/shortcutguide/diagram.png)
## Project Structure
### Core Files
The Shortcut Guide module consists of the following 4 projects:
#### [`dllmain.cpp`](/src/modules/shortcut_guide/dllmain.cpp)
Contains DLL boilerplate code. Implements the PowertoyModuleIface, including enable/disable functionality and GPO policy handling. Captures hotkey events and starts the PowerToys.ShortcutGuide.exe process to display the shortcut guide window.
### [`ShortcutGuide.Ui`](/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj
#### [`shortcut_guide.cpp`](/src/modules/shortcut_guide/shortcut_guide.cpp)
Contains the module interface code. It initializes the settings values and the keyboard event listener. Defines the OverlayWindow class, which manages the overall logic and event handling for the PowerToys Shortcut Guide.
This is the main UI project for the Shortcut Guide module. Upon startup it does the following tasks:
#### [`overlay_window.cpp`](/src/modules/shortcut_guide/overlay_window.cpp)
Contains the code for loading the SVGs, creating and rendering of the overlay window. Manages and displays overlay windows with SVG graphics through two main classes:
- D2DOverlaySVG: Handles loading, resizing, and manipulation of SVG graphics
- D2DOverlayWindow: Manages the display and behavior of the overlay window
1. Copies the built-in manifest files to the users manifest directory (overwriting existing files).
2. Generate the `index.yml` manifest file.
3. Populate the PowerToys shortcut manifest with the user-defined shortcuts.
4. Starts the UI.
#### [`keyboard_state.cpp`](/src/modules/shortcut_guide/keyboard_state.cpp)
Contains helper methods for checking the current state of the keyboard.
### Related files in PowerToys.Interop
#### [`target_state.cpp`](/src/modules/shortcut_guide/target_state.cpp)
State machine that handles the keyboard events. It's responsible for deciding when to show the overlay, when to suppress the Start menu (if the overlay is displayed long enough), etc. Handles state transitions and synchronization to ensure the overlay is shown or hidden appropriately based on user interactions.
#### [`excluded_app.cpp`](/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/excluded_app.cpp)
#### [`trace.cpp`](/src/modules/shortcut_guide/trace.cpp)
Contains code for telemetry.
This file contains one function with the following signature:
### Supporting Files
```cpp
__declspec(dllexport) bool IsCurrentWindowExcludedFromShortcutGuide()
```
#### [`animation.cpp`](/src/modules/shortcut_guide/animation.cpp)
Handles the timing and interpolation of animations. Calculates the current value of an animation based on elapsed time and a specified easing function.
This function checks if the current window is excluded from the Shortcut Guide overlay. It returns `true` if the current window is excluded otherwise it returns `false`.
#### [`d2d_svg.cpp`](/src/modules/shortcut_guide/d2d_svg.cpp)
Provides functionality for loading, resizing, recoloring, rendering, and manipulating SVG images using Direct2D.
#### [`tasklist_positions.cpp`](/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/tasklist_positions.cpp)
#### [`d2d_text.cpp`](/src/modules/shortcut_guide/d2d_text.cpp)
Handles creation, resizing, alignment, and rendering of text using Direct2D and DirectWrite.
This file contains helper functions to retrieve the positions of the taskbar buttons. It exports the following function:
#### [`d2d_window.cpp`](/src/modules/shortcut_guide/d2d_window.cpp)
Manages a window using Direct2D and Direct3D for rendering. Handles window creation, resizing, rendering, and destruction.
```cpp
__declspec(dllexport) TasklistButton* get_buttons(HMONITOR monitor, int* size)
```
#### [`native_event_waiter.cpp`](/src/modules/shortcut_guide/native_event_waiter.cpp)
Waits for a named event and executes a specified action when the event is triggered. Uses a separate thread to handle event waiting and action execution.
This function retrieves the positions of the taskbar buttons for a given monitor. It returns an array of `TasklistButton` structures (max 10), which contain the position and size of each button.
#### [`tasklist_positions.cpp`](/src/modules/shortcut_guide/tasklist_positions.cpp)
Handles retrieving and updating the positions and information of taskbar buttons in Windows.
`monitor` must be the monitor handle of the monitor containing the taskbar instance of which the buttons should be retrieved.
#### [`main.cpp`](/src/modules/shortcut_guide/main.cpp)
The entry point for the PowerToys Shortcut Guide application. Handles initialization, ensures single instance execution, manages parent process termination, creates and displays the overlay window, and runs the main event loop.
`size` will contain the resulting array size.
It determines the positions through Windows `FindWindowEx` function.
For the primary taskbar it searches for:
* A window called "Shell_TrayWnd"
* that contains a window called "ReBarWindow32"
* that contains a window called "MSTaskSwWClass"
* that contains a window called "MSTaskListWClass"
For any secondary taskbar it searches for:
* A window called "Shell_SecondaryTrayWnd"
* that contains a window called "WorkerW"
* that contains a window called "MSTaskListWClass"
It then enumerates all the button elements inside "MSTaskListWClass" while skipping such with a same name (which implies the user does not use combining taskbar buttons)
If this method fails, which it will for newer versions of Windows, it falls back to searching for:
* A window called "Shell_TrayWnd" or "Shell_SecondaryTrayWnd"
* that contains a window called "Windows.UI.Composition.DesktopWindowContentBridge"
* that contains a window called "Windows.UI.Input.InputSite.WindowClass"
* the first child element
It then enumerates all the button elements inside the selected while skipping such with a same name (which implies the user does not use combining taskbar buttons) and such that do not start with "Appid:" (which are not actual taskbar buttons related to apps, but others like the widgets or the search button).
### [`ShortcutGuide.IndexYmlGenerator`](/src/modules/ShortcutGuide/ShortcutGuide.IndexYmlGenerator/)
This application generates the `index.yml` manifest file.
It is a separate project so that its code can be easier ported to WinGet in the future.
### [`ShortcutGuideModuleInterface`](/src/modules/ShortcutGuide/ShortcutGuideModuleInterface/ShortcutGuideModuleInterface.vcxproj)
The module interface that handles opening and closing the user interface.
## Features and Limitations
- The overlay displays Windows shortcuts (Windows key combinations)
- The module supports localization, but only for the Windows controls on the left side of the overlay
- Currently the displayed shortcuts (Except the ones from PowerToys) are not localized.
- It's currently rated as a P3 (lower priority) module
## Future Development
A community-contributed version 2 is in development that will support:
- Application-specific shortcuts based on the active application
- Additional shortcuts beyond Windows key combinations
- PowerToys shortcuts
- Implementing with WinGet to get new shortcut manifest files
- Adding localization support for the built-in manifest files

View File

@@ -0,0 +1,93 @@
# PowerToys Installer & Update Diagnostics
A step-by-step guide for diagnosing installer and update issues reported by users.
## Quick Reference: Key Files
| File/Folder | Path | Contains |
|---|---|---|
| UpdateState.json | `%LOCALAPPDATA%\Microsoft\PowerToys\UpdateState.json` | Persisted update state machine |
| Runner logs | `%LOCALAPPDATA%\Microsoft\PowerToys\RunnerLogs\runner-log_*.log` | Startup, update checks, cleanup |
| Update logs | `%LOCALAPPDATA%\Microsoft\PowerToys\UpdateLogs\update-log_*.log` | PowerToys.Update.exe activity |
| Updates folder | `%LOCALAPPDATA%\Microsoft\PowerToys\Updates\` | Downloaded installer files |
> **Note:** These paths use `%LOCALAPPDATA%` (per-user AppData) regardless of whether PowerToys was installed per-user or per-machine. The data/settings location is always per-user.
## Update State Values
From `src/common/updating/updateState.h` (`UpdateState::State` enum):
| Value | Name | Meaning |
|---|---|---|
| 0 | upToDate | No update needed |
| 1 | errorDownloading | Download or install failed, will retry |
| 2 | readyToDownload | New version found, not yet downloaded |
| 3 | readyToInstall | Installer downloaded, waiting for user action |
| 4 | networkError | GitHub API call failed |
---
## Symptom: Old update installers accumulating on disk
### What to ask the user for
1. Contents of `UpdateState.json`
2. Runner logs (last few days from `RunnerLogs\`)
3. Update logs (from `UpdateLogs\`, if they exist)
4. List of files in `Updates\` folder (names + sizes)
### Step 1: Check the running version
In runner logs, look for the startup line:
```
[info] Scoobe: product_version=v0.XX.X last_version_run=v0.XX.X
```
- **If version < v0.73.0**: The pre-download cleanup (PR #27908) is missing. Each downloaded installer accumulates because cleanup only runs at startup when state is `upToDate`. Ask the user to manually upgrade to the latest version.
- **If version >= v0.73.0**: The pre-download cleanup exists. Accumulation should not happen under normal conditions. Continue to Step 2.
### Step 2: Check UpdateState.json
```jsonc
{"state": 3, "downloadedInstallerFilename": "powertoyssetup-0.98.1-x64.exe" /* additional fields may be present */}
```
- **state = 0 (upToDate)**: Cleanup should run at startup. If files are accumulating, check runner logs for "Failed to delete" warnings (Step 4).
- **state = 3 (readyToInstall)**: An installer is downloaded but never installed. Cleanup at startup is skipped (by design, to preserve the pending installer). On v0.73+, cleanup can still occur when a future update check triggers a new download (pre-download cleanup path).
- **state = 1 (errorDownloading)**: A previous download or install failed. Startup cleanup is skipped (state is not `upToDate`). On v0.73+, cleanup runs before the next installer download is attempted.
- **state = 2 or 4**: Startup cleanup is skipped. On v0.73+, cleanup runs before the next installer download is attempted.
### Step 3: Check if PowerToys.Update.exe has ever run
- **UpdateLogs directory missing**: This suggests `PowerToys.Update.exe` may never have been launched, or it did not progress far enough to create logs. The user may never have triggered an install, or Stage 1 may have failed before Stage 2 could run.
- **UpdateLogs exist but show only "logger is initialized"**: The exe launched but the command-line argument didn't match any action (possible argument parsing issue).
- **UpdateLogs show install activity**: The update process ran. Check for success/failure.
### Step 4: Check runner logs for cleanup evidence
Search for these patterns:
| Log pattern | Meaning |
|---|---|
| `Failed to delete installer file ... Access is denied` | File locked by AV, another process, or permissions issue |
| `Failed to delete log file ...` | Same, for old log files |
| `Discovered new version` | Periodic update check ran |
| `New version is already downloaded` | State is `readyToInstall` and filename matches — no re-download, no cleanup |
| No cleanup-related entries at all | Inconclusive by itself — `cleanup_updates()` is silent on success. Corroborate with the Updates folder contents (Step 5) and the running version (Step 1). |
### Step 5: Check the Updates folder contents
- **All different versions**: Cleanup likely did not run across multiple update cycles. Confirm with the running version (Step 1) and update state before concluding a state gate issue.
- **Duplicate filenames**: Unusual — would suggest repeated download without cleanup.
- **Single file matching `downloadedInstallerFilename`**: Normal for `readyToInstall` state.
### Common root causes
| Root cause | Evidence | Fix |
|---|---|---|
| Running pre-v0.73.0 binary | `product_version` < v0.73.0 in runner log | Manually upgrade to latest |
| State stuck at `readyToInstall` (pre-v0.73) | `"state": 3` in UpdateState.json, no UpdateLogs | Manually upgrade to latest |
| File lock preventing deletion | "Failed to delete ... Access is denied" in runner logs | Check AV software, reboot and retry |
| Update installer never launched | No UpdateLogs directory | Check if update notifications are disabled by GPO or setting |
| Install fails silently | UpdateLogs show init but no install activity | Check related issues: #46966, #46967, #46969 |

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 275 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 KiB

After

Width:  |  Height:  |  Size: 258 KiB

View File

@@ -0,0 +1,326 @@
# WinGet Manifest Keyboard Shortcuts schema
## 1 What this spec is about
This spec provides an extension to the existing [WinGet manifest schema](https://github.com/microsoft/winget-pkgs/blob/master/doc/manifest/README.md) in form of an additional yaml file, that describes keyboard shortcuts the application provides.
These yaml files are saved on a per-user base and so called manifest interpreters can then display these manifests in a human-friendly version.
### 1.1 What this spec is not about
This spec does not provide a way to back up or save user-defined keyboard shortcuts.
## 2 Save location of manifests
### 2.1 WinGet
These files are saved online along with the other manifest files in the [WinGet Package repository](https://github.com/microsoft/winget-pkgs).
### 2.2 Locally
All manifests and one index file are saved locally under `%LocalAppData%/Microsoft/WinGet/KeyboardShortcuts`. All apps are allowed to add their manifest files there. In addition Package Managers (like WinGet) and manifest interpreters (like PowerToys Shortcut Guide) can control and add other manifests themselves.
#### 2.2.1 Downloading manifests
When WinGet or other package managers download a package, they should also download the corresponding keyboard shortcuts manifest file and save it in the local directory, given such a file exists in the WinGet repository.
The downloader is also responsible for updating the local `index.yaml` file, which contains all the information about the different manifest files that are saved in the same directory.
#### 2.2.2 Updating manifests
When a manifest interpreter starts, it should download the latest version of the manifests from the WinGet repository and save them in the local directory. If a manifest interpreter is not able to download the manifests or they do not exist, it should use the locally saved manifests.
The updater is also responsible for updating the local `index.yaml` file, which contains all the information about the different manifest files that are saved in the same directory.
> Note: WinGet must provide a way to update the keyboard shortcuts manifests given a package id.
### 2.3 File names
The file name of a keyboard shortcuts file is the WinGet package identifier, plus the locale of the strings of the file and at last the `.KBSC.yaml` file extension.
For example the package "test.bar" saves its manifest with `en-US` strings in `test.bar.en-US.KBSC.yaml`.
#### 2.3.1 No winget package available
If an application has no corresponding WinGet package its name starts with a plus (`+`) symbol.
### 2.4 Reserved namespaces
Every name starting with `+WindowsNT` is reserved for the Windows OS and its components.
## 3 File syntax
All relevant files are written in [YAML](https://yaml.org/spec).
> Note: A JSON schema will be provided as soon as the spec reaches a further step
### 3.1 Manifest Schema vNext Keyboard Shortcuts File
```
PackageName: # The package unique identifier
WindowFilter: # The filter of window processes to which the shortcuts apply to
BackgroundProcess: # Optionally allows applying WindowFilter to background processes
Shortcuts: # List of sections with keyboard shortcuts
- SectionName: # Name of the category of shortcuts
Properties: # List of shortcuts in the category
- Name: # Name of the shortcut
Description: # Optional description of the shortcut
AdditionalInfo: # Optional additional information about the shortcut
Recommended: # Optionally determines if the shortcut is displayed in a designated recommended area
Shortcut: # An array of shortcuts that need to be pressed
- Win: # Determines if the Windows Key is part of the shortcut
Ctrl: # Determines if the Ctrl Key is part of the shortcut
Shift: # Determines if the Shift Key is part of the shortcut
Alt: # Determines if the Alt Key is part of the shortcut
Keys: # Array of keys that need to be pressed
```
Per Application/Package one or more Keyboard manifests can be declared. Every manifest must have a different locale and the same `PackageName`, `WindowFilter` and `BackgroundProcess` fields.
<details>
<summary><b>PackageName</b> - The package unique identifier</summary>
Package identifier (see 2.1 for more information on the package identifier).
</details>
<details>
<summary><b>WindowFilter</b> - The filter of window processes to which the shortcuts apply to</summary>
This field declares for which process name the shortcuts should be shown (To rephrase: For which processes the shortcut will have an effect if pressed). The value can be either an exact process executable name, for example `explorer.exe` or `chrome.exe`, or a single asterisk (`*`) to apply to any process. No other wildcard patterns are supported by this specification.
</details>
<details>
<summary><b>BackgroundProcess</b> - Optionally allows applying WindowFilter to background processes.</summary>
**Optional field**
Defaults to `False`. Determines if WindowFilter should apply to background processes as well (Rephrased: When the process is running, the shortcuts will apply).
</details>
<details>
<summary><b>Shortcuts</b> - List of sections with keyboard shortcuts</summary>
List of different section (also called categories) of shortcuts.
</details>
<details>
<summary><b>SectionName</b> - Name of the category of shortcuts</summary>
Name of the section of shortcuts.
**Special sections**:
Special sections start with an identifier enclosed between `<` and `>`. This declares the category as a special display. If the interpreter of the manifest file can't understand the content this section should be left out.
</details>
<details>
<summary><b>Properties</b> - List of shortcuts in the category</summary>
</details>
<details>
<summary><b>Name</b> - Name of the shortcut</summary>
Name of the shortcut. This is the name that will be displayed in the interpreter.
</details>
<details>
<summary><b>Description</b> - Optional description of the shortcut</summary>
Optional description of the shortcut. This is the description that will be displayed by the interpreter.
</details>
<details>
<summary><b>AdditionalInfo</b> - Optional additional information about the shortcut</summary>
Array of additional information about the shortcut. This is the additional information that will be displayed by the interpreter and are not part of this manifest.
**Example**:
For example, if the shortcut is only available on a certain Windows version, this information could be added here.
```yaml
AdditionalInfo:
- MinWindowsVersion: "10.0.19041.0"
```
</details>
<details>
<summary><b>Shortcut</b> - An array of shortcuts that need to be pressed</summary>
An array of shortcuts that need to be pressed. This allows defining sequential shortcuts that need to be pressed in order to trigger the action.
</details>
<details>
<summary><b>Win</b> - Determines if the Windows Key is part of the shortcut</summary>
Refers to the left Windows Key on the keyboard.
</details>
<details>
<summary><b>Ctrl</b> - Determines if the Ctrl Key is part of the shortcut</summary>
Refers to the left Ctrl Key on the keyboard.
</details>
<details>
<summary><b>Shift</b> - Determines if the Shift Key is part of the shortcut</summary>
Refers to the left Shift Key on the keyboard.
</details>
<details>
<summary><b>Alt</b> - Determines if the Alt Key is part of the shortcut</summary>
Refers to the left Alt Key on the keyboard.
</details>
<details>
<summary><b>Recommended</b> - Optionally determines if the shortcut is displayed in a designated recommended area</summary>
**Optional field**
Defaults to `False`. Determines if the shortcut should be displayed in a designated recommended area. This is a visual hint for the user that this shortcut is important.
</details>
<details>
<summary><b>Keys</b> - Array of keys that need to be pressed</summary>
A string array of all the keys that need to be pressed. If a number is supplied, it should be read as a [KeyCode](https://learn.microsoft.com/windows/win32/inputdev/virtual-key-codes) and displayed accordingly (based on the Keyboard Layout of the user).
**Literal digit keys**:
Because a bare number is interpreted as a virtual-key code, a literal digit key must be authored using the `<N>` notation (the digit enclosed between `<` and `>`), where `N` is `0``9`. For example, `<9>` represents the literal `9` key (as in the "switch to the last tab" shortcut), not the virtual-key code `9` (which is `Tab`). The interpreter strips the brackets and displays just the digit.
This applies only to a single literal digit. A range such as `1 - 8` is a free-form label, not a key, and is supplied verbatim (the brackets would only be trimmed from the ends, so `<1> - <8>` would not render as intended).
**Special keys**:
Special keys are enclosed between `<` and `>` and correspond to a key that should be displayed in a certain way. If the interpreter of the manifest file can't understand the content, the brackets should be left out.
By convention these tokens are written as double-quoted strings in the YAML (for example `"<Enter>"` and `"<9>"`), matching the quoting used for punctuation key values. YAML treats the quoted and unquoted forms identically, so quoting is for consistency rather than a strict requirement for bracketed tokens.
|Name|Description|
|----|-----------|
|`<Office>`| Corresponds to the Office key on some Windows keyboards |
|`<Copilot>`| Corresponds to the Copilot key on some Windows keyboards |
|`<Left>`| Corresponds to the left arrow key |
|`<Right>`| Corresponds to the right arrow key |
|`<Up>`| Corresponds to the up arrow key |
|`<Down>`| Corresponds to the down arrow key |
|`<Enter>`| Corresponds to the Enter key |
|`<Space>`| Corresponds to the Space key |
|`<Tab>`| Corresponds to the Tab key |
|`<Backspace>`| Corresponds to the Backspace key |
|`<Delete>`| Corresponds to the Delete key |
|`<Insert>`| Corresponds to the Insert key |
|`<Home>`| Corresponds to the Home key |
|`<End>`| Corresponds to the End key |
|`<PrtScr>`| Corresponds to the Print Screen key |
|`<Pause>`| Corresponds to the pause key |
|`<PageUp>`| Corresponds to the Page Up key |
|`<PageDown>`| Corresponds to the Page Down key |
|`<Escape>`| Corresponds to the Escape key |
|`<Arrow>`| Corresponds to either the left, right, up or down arrow key |
|`<ArrowLR>`| Corresponds to either the left or right arrow key |
|`<ArrowUD>`| Corresponds to either the up or down arrow key |
|`<Underlined letter>`| Corresponds to any letter that is _underlined_ in the UI |
</details>
#### 3.2.2 Example
```yaml
PackageName: Microsoft.PowerToys
WindowFilter: "*"
BackgroundProcess: True
Shortcuts:
- SectionName: General
Properties:
- Name: Advanced Paste
Shortcut:
- Win: True
Ctrl: False
Alt: False
Shift: False
Keys:
- 86
Description: Open Advanced Paste window
- Name: Advanced Paste
Shortcut:
- Win: True
Ctrl: True
Alt: True
Shift: False
Keys:
- 86
Description: Paste as plain text directly
```
### 3.2 `index.yaml` file
The `index.yaml` file is a file that contains all the information about the different manifest files that are saved in the same directory. This file is only available locally and is not saved in the WinGet repository as it is specific to the user.
```yaml
DefaultShellName: # The package identifier of the default shell used in Windows
Index: # List of all manifest files
- WindowFilter: # The filter of window processes to which the shortcuts apply to
BackgroundProcess: # Optionally allows applying WindowFilter to background processes
Apps: # List of all manifest files for the filter
```
<details>
<summary><b>DefaultShellName</b> - The package identifier of the default shell used in Windows</summary>
This declares the package identifier of the default shell used in Windows. Most commonly it is `+WindowsNT.Shell`. Although not enforced, only the shell declared in the registry key `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell` should be used here.
</details>
<details>
<summary><b>Index</b> - List of all manifest files</summary>
</details>
<details>
<summary><b>WindowFilter</b> - The filter of window processes to which the shortcuts apply to</summary>
See the `WindowFilter` field in the manifest file for more information.
</details>
<details>
<summary><b>BackgroundProcess</b> - Optionally allows applying WindowFilter to background processes</summary>
**Optional field**
See the `BackgroundProcess` field in the manifest file for more information.
</details>
<details>
<summary><b>Apps</b> - List of all the package identifiers applying for the filter</summary>
</details>
#### 3.2.1 Example
```yaml
DefaultShellName: "+WindowsNT.Shell"
Index:
- Filter: "*"
BackgroundProcess: True
Apps: ["+WindowsNT.Shell", "Microsoft.PowerToys"]
- Filter: "explorer.exe"
Apps: ["+WindowsNT.WindowsExplorer"]
- Filter: "taskmgr.exe"
Apps: ["+WindowsNT.TaskManager"]
- Filter: "msedge.exe"
Apps: ["+WindowsNT.Edge"]
```

View File

@@ -79,3 +79,4 @@ Below are community created plugins that target a website or software. They are
| [Linear](https://github.com/vednig/powertoys-linear) | [vednig](https://github.com/vednig) | Create Linear Issues directly from Powertoys Run |
| [PerplexitySearchShortcut](https://github.com/0x6f677548/PowerToys-Run-PerplexitySearchShortcut) | [0x6f677548](https://github.com/0x6f677548) | Search Perplexity |
| [SpeedTest](https://github.com/ruslanlap/PowerToysRun-SpeedTest) | [ruslanlap](https://github.com/ruslanlap) | One-command internet speed tests with real-time results, modern UI, and shareable links. |
| [DiskAnalyzer](https://github.com/thetsaw/PowerToys.Plugin) | [thetsaw](https://github.com/thetsaw) | Scan folders, find the largest files, and view drive space usage with visual progress bars. |

View File

@@ -8,9 +8,6 @@
</Project>
<Project Path="../src/common/Telemetry/EtwTrace/EtwTrace.vcxproj" Id="8f021b46-362b-485c-bfba-ccf83e820cbd" />
<Project Path="../src/common/version/version.vcxproj" Id="cc6e41ac-8174-4e8a-8d22-85dd7f4851df" />
<Project Path="../src/logging/logging.vcxproj" Id="7e1e3f13-2bd6-3f75-a6a7-873a2b55c60f">
<Build Solution="Debug|ARM64" Project="false" />
</Project>
<Project Path="PowerToysSetupCustomActionsVNext/PowerToysSetupCustomActionsVNext.vcxproj" Id="b3a354b0-1e54-4b55-a962-fb5af9330c19">
<Build Solution="Debug|ARM64" Project="false" />
</Project>

View File

@@ -4,6 +4,7 @@
#include <ProjectTelemetry.h>
#include <spdlog/sinks/base_sink.h>
#include <filesystem>
#include <fstream>
#include <string_view>
#include "../../src/common/logger/logger.h"
@@ -639,7 +640,7 @@ UINT __stdcall InstallPackageIdentityMSIXCA(MSIHANDLE hInstall)
try
{
std::wstring externalLocation = installFolderPath; // External content location (PowerToys install folder)
std::wstring externalLocation = installFolderPath + L"WinUI3Apps\\"; // External content location (WinUI3Apps subfolder to isolate DACL changes from preview handler DLLs)
Uri externalUri{ externalLocation }; // External location URI for sparse package content
Uri packageUri{ msixPath }; // The MSIX file URI
@@ -1807,6 +1808,223 @@ void initSystemLogger()
} });
}
// Naming note: the *Hardlinks* names in this CA, the matching WiX CustomAction Ids
// in Product.wxs, and the manifest filename "hardlinks.txt" are kept for continuity
// with the original PR design. The implementation uses fs::copy_file -- not
// CreateHardLinkW -- because hard-links share an inode (and DACL) between root and
// WinUI3Apps, which lets MSIX sparse-package registration propagate a rich DACL onto
// the root copy of files like hostfxr.dll and break LOW-IL prevhost.exe loads,
// turning the Monaco preview pane blank. Copies create a fresh inode in WinUI3Apps so the root
// copy keeps its simple DACL. See the in-body comment for the full RCA reference.
UINT __stdcall CreateWinAppSDKHardlinksCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
std::wstring installationFolder;
hr = WcaInitialize(hInstall, "CreateWinAppSDKHardlinks");
ExitOnFailure(hr, "Failed to initialize");
hr = getInstallFolder(hInstall, installationFolder);
ExitOnFailure(hr, "Failed to get installFolder.");
{
namespace fs = std::filesystem;
const fs::path installDir(installationFolder);
const fs::path winui3Dir = installDir / L"WinUI3Apps";
const fs::path manifestPath = winui3Dir / L"hardlinks.txt";
if (!fs::exists(manifestPath))
{
WcaLog(LOGMSG_STANDARD, "CreateWinAppSDKHardlinks: No hardlinks.txt manifest found, skipping.");
goto LExit;
}
std::ifstream manifestFile(manifestPath); // Read as bytes, then convert UTF-8 -> wide explicitly.
std::string narrowLine;
int created = 0;
int failed = 0;
// INSTALLFOLDER from MSI typically arrives with a trailing backslash. lexically_normal
// preserves that as an empty trailing path component, which would later make the
// per-component std::mismatch containment check below reject every legitimate entry.
// Strip any trailing separators before normalizing.
auto stripTrailingSep = [](fs::path p) {
auto s = p.native();
while (s.size() > 1 && (s.back() == L'\\' || s.back() == L'/')) s.pop_back();
return fs::path(s);
};
// Normalize once so the per-line containment check below is cheap.
const fs::path installDirNorm = stripTrailingSep(installDir).lexically_normal();
const fs::path winui3DirNorm = stripTrailingSep(winui3Dir).lexically_normal();
while (std::getline(manifestFile, narrowLine))
{
if (narrowLine.empty())
{
continue;
}
// Strip CR if the manifest uses CRLF line endings.
if (narrowLine.back() == '\r')
{
narrowLine.pop_back();
if (narrowLine.empty()) continue;
}
// Manifest is written as UTF-8 (no BOM) -- convert to wide string explicitly
// rather than relying on the locale-default codecvt of std::wifstream, which is
// the ANSI code page on Windows and would silently mangle any non-ASCII path.
const int wideLen = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, narrowLine.c_str(), -1, nullptr, 0);
if (wideLen <= 0)
{
WcaLog(LOGMSG_STANDARD, "CreateWinAppSDKHardlinks: Skipping non-UTF-8 entry: %hs", narrowLine.c_str());
failed++;
continue;
}
std::wstring fileName(static_cast<size_t>(wideLen) - 1, L'\0');
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, narrowLine.c_str(), -1, fileName.data(), wideLen);
// Defense-in-depth: reject manifest entries that would escape the install root
// via "..", absolute paths, or alternate stream syntax. lexically_normal collapses
// any "." / ".." / repeated separators, then std::mismatch verifies the resolved
// path is still rooted at installDir / winui3Dir respectively.
const fs::path source = (installDir / fileName).lexically_normal();
const fs::path target = (winui3Dir / fileName).lexically_normal();
const auto sourceIn = std::mismatch(installDirNorm.begin(), installDirNorm.end(), source.begin(), source.end());
const auto targetIn = std::mismatch(winui3DirNorm.begin(), winui3DirNorm.end(), target.begin(), target.end());
if (sourceIn.first != installDirNorm.end() || targetIn.first != winui3DirNorm.end())
{
WcaLog(LOGMSG_STANDARD, "CreateWinAppSDKHardlinks: Rejecting entry outside install root: %ls", fileName.c_str());
failed++;
continue;
}
if (!fs::exists(source))
{
WcaLog(LOGMSG_STANDARD, "CreateWinAppSDKHardlinks: Source not found: %ls", source.c_str());
failed++;
continue;
}
// Remove existing file if present (leftover from previous install)
std::error_code ec;
fs::remove(target, ec);
// Use a regular file copy (not a hard-link). Hard-links share an
// NTFS inode -- and therefore one DACL -- between root and
// WinUI3Apps, which lets MSIX sparse-package registration
// propagate the WinUI3Apps parent's rich (Capability/Package SID)
// DACL onto the root path. That trips a kernel "stricter access
// evaluation" path that blocks LOW-IL prevhost.exe from loading
// hostfxr.dll, so File Explorer Monaco preview goes blank on
// Windows 11 23H2. Copying creates a fresh inode in WinUI3Apps,
// so the root copy keeps its simple DACL while the WinUI3Apps
// copy inherits the rich DACL from its parent (matches 0.99.1
// behaviour). See Documents\PR-47233-Handoff.md for full RCA.
fs::copy_file(source, target, fs::copy_options::overwrite_existing, ec);
if (ec)
{
WcaLog(LOGMSG_STANDARD, "CreateWinAppSDKHardlinks: Failed to copy: %ls (%hs)", fileName.c_str(), ec.message().c_str());
failed++;
}
else
{
created++;
}
}
WcaLog(LOGMSG_STANDARD, "CreateWinAppSDKHardlinks: Copied %d files, %d failures", created, failed);
// Catastrophic-case escalation: if every copy failed, the WinUI3Apps tree is
// unusable (Monaco preview / context-menu shells will break). Surface this rather
// than reporting install success. Per-file failures remain tolerated.
if (created == 0 && failed > 0)
{
hr = E_FAIL;
ExitOnFailure(hr, "All WinAppSDK file copies failed; aborting install.");
}
}
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall DeleteWinAppSDKHardlinksCA(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
std::wstring installationFolder;
hr = WcaInitialize(hInstall, "DeleteWinAppSDKHardlinks");
ExitOnFailure(hr, "Failed to initialize");
hr = getInstallFolder(hInstall, installationFolder);
ExitOnFailure(hr, "Failed to get installFolder.");
{
namespace fs = std::filesystem;
const fs::path winui3Dir = fs::path(installationFolder) / L"WinUI3Apps";
const fs::path manifestPath = winui3Dir / L"hardlinks.txt";
if (!fs::exists(manifestPath))
{
goto LExit;
}
std::ifstream manifestFile(manifestPath); // Read as bytes; convert UTF-8 -> wide explicitly.
std::string narrowLine;
// INSTALLFOLDER from MSI typically arrives with a trailing backslash; strip it before
// normalizing so the per-line containment check doesn't false-reject every entry.
auto stripTrailingSep = [](fs::path p) {
auto s = p.native();
while (s.size() > 1 && (s.back() == L'\\' || s.back() == L'/')) s.pop_back();
return fs::path(s);
};
const fs::path winui3DirNorm = stripTrailingSep(winui3Dir).lexically_normal();
while (std::getline(manifestFile, narrowLine))
{
if (narrowLine.empty())
{
continue;
}
if (narrowLine.back() == '\r')
{
narrowLine.pop_back();
if (narrowLine.empty()) continue;
}
const int wideLen = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, narrowLine.c_str(), -1, nullptr, 0);
if (wideLen <= 0)
{
WcaLog(LOGMSG_STANDARD, "DeleteWinAppSDKHardlinks: Skipping non-UTF-8 entry: %hs", narrowLine.c_str());
continue;
}
std::wstring fileName(static_cast<size_t>(wideLen) - 1, L'\0');
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, narrowLine.c_str(), -1, fileName.data(), wideLen);
// Defense-in-depth: reject entries whose resolved target escapes WinUI3Apps.
const fs::path target = (winui3Dir / fileName).lexically_normal();
const auto inWinui3 = std::mismatch(winui3DirNorm.begin(), winui3DirNorm.end(), target.begin(), target.end());
if (inWinui3.first != winui3DirNorm.end())
{
WcaLog(LOGMSG_STANDARD, "DeleteWinAppSDKHardlinks: Rejecting entry outside WinUI3Apps: %ls", fileName.c_str());
continue;
}
std::error_code ec;
fs::remove(target, ec);
}
WcaLog(LOGMSG_STANDARD, "DeleteWinAppSDKHardlinks: Cleaned up deduplicated copy files");
}
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
// DllMain - Initialize and cleanup WiX custom action utils.
extern "C" BOOL WINAPI DllMain(__in HINSTANCE hInst, __in ULONG ulReason, __in LPVOID)
{

View File

@@ -36,3 +36,5 @@ EXPORTS
SetBundleInstallLocationCA
InstallPackageIdentityMSIXCA
UninstallPackageIdentityMSIXCA
CreateWinAppSDKHardlinksCA
DeleteWinAppSDKHardlinksCA

View File

@@ -6,13 +6,16 @@
<?define BaseApplicationsFilesPath=$(var.BinDir)\?>
<Fragment>
<DirectoryRef Id="INSTALLFOLDER">
<!-- winmd must be in WinUI3Apps (ExternalLocation) for WinRT COM proxy/stub resolution -->
<DirectoryRef Id="WinUI3AppsInstallFolder">
<Component Id="Microsoft_CommandPalette_Extensions_winmd" Guid="304AD25A-A986-4058-940E-61DB79EBD78C" Bitness="always64">
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
<RegistryValue Type="string" Name="Microsoft_CommandPalette_Extensions_winmd" Value="" KeyPath="yes" />
</RegistryKey>
<File Id="Microsoft.CommandPalette.Extensions.winmd" Source="$(var.BinDir)Microsoft.CommandPalette.Extensions.winmd" />
<File Id="Microsoft.CommandPalette.Extensions.winmd" Source="$(var.BinDir)WinUI3Apps\Microsoft.CommandPalette.Extensions.winmd" />
</Component>
</DirectoryRef>
<DirectoryRef Id="INSTALLFOLDER">
<!-- Generated by generateFileComponents.ps1 -->
<!--BaseApplicationsFiles_Component_Def-->
</DirectoryRef>

View File

@@ -67,8 +67,11 @@
<RegistryValue Type="string" Name="svgs_icons" Value="" KeyPath="yes" />
</RegistryKey>
<File Id="icon.ico" Source="$(var.BinDir)svgs\icon.ico" />
<File Id="iconUpdate.ico" Source="$(var.BinDir)svgs\iconUpdate.ico" />
<File Id="PowerToysWhite.ico" Source="$(var.BinDir)svgs\PowerToysWhite.ico" />
<File Id="PowerToysWhiteUpdate.ico" Source="$(var.BinDir)svgs\PowerToysWhiteUpdate.ico" />
<File Id="PowerToysDark.ico" Source="$(var.BinDir)svgs\PowerToysDark.ico" />
<File Id="PowerToysDarkUpdate.ico" Source="$(var.BinDir)svgs\PowerToysDarkUpdate.ico" />
</Component>
</Directory>
</DirectoryRef>

View File

@@ -4,11 +4,11 @@
<?define KeyboardManagerAssetsFiles=?>
<?define KeyboardManagerAssetsWinUI3Files=?>
<?define KeyboardManagerAssetsFilesPath=$(var.BinDir)\Assets\KeyboardManager\?>
<?define KeyboardManagerAssetsFilesPath=$(var.BinDir)\WinUI3Apps\Assets\KeyboardManager\?>
<?define KeyboardManagerAssetsWinUI3FilesPath=$(var.BinDir)\WinUI3Apps\Assets\KeyboardManagerEditor\?>
<Fragment>
<DirectoryRef Id="BaseApplicationsAssetsFolder">
<DirectoryRef Id="WinUI3AppsAssetsFolder">
<Directory Id="KeyboardManagerAssetsInstallFolder" Name="KeyboardManager" />
</DirectoryRef>
<DirectoryRef Id="WinUI3AppsAssetsFolder">

View File

@@ -112,6 +112,8 @@
<Custom Action="SetInstallCmdPalPackageParam" Before="InstallCmdPalPackage" />
<Custom Action="SetUninstallCommandNotFoundParam" Before="UninstallCommandNotFound" />
<Custom Action="SetUpgradeCommandNotFoundParam" Before="UpgradeCommandNotFound" />
<Custom Action="SetCreateWinAppSDKHardlinksParam" Before="CreateWinAppSDKHardlinks" />
<Custom Action="SetDeleteWinAppSDKHardlinksParam" Before="DeleteWinAppSDKHardlinks" />
<Custom Action="SetApplyModulesRegistryChangeSetsParam" Before="ApplyModulesRegistryChangeSets" />
<Custom Action="SetInstallPackageIdentityMSIXParam" Before="InstallPackageIdentityMSIX" />
@@ -124,6 +126,7 @@
<Custom Action="SetBundleInstallLocationData" Before="SetBundleInstallLocation" Condition="NOT Installed OR WIX_UPGRADE_DETECTED" />
<Custom Action="SetBundleInstallLocation" After="InstallFiles" Condition="NOT Installed OR WIX_UPGRADE_DETECTED" />
<Custom Action="ApplyModulesRegistryChangeSets" After="InstallFiles" Condition="NOT Installed" />
<Custom Action="CreateWinAppSDKHardlinks" After="InstallFiles" Condition="NOT Installed OR WIX_UPGRADE_DETECTED OR REINSTALL" />
<Custom Action="InstallCmdPalPackage" After="InstallFiles" Condition="NOT Installed" />
<Custom Action="InstallPackageIdentityMSIX" After="InstallFiles" Condition="NOT Installed AND WINDOWSBUILDNUMBER &gt;= 22000" />
<Custom Action="override Wix4CloseApplications_$(sys.BUILDARCHSHORT)" Before="RemoveFiles" />
@@ -137,6 +140,7 @@
<?endif?>
<Custom Action="TelemetryLogInstallSuccess" After="InstallFinalize" Condition="NOT Installed" />
<Custom Action="TelemetryLogUninstallSuccess" After="InstallFinalize" Condition="Installed and (NOT UPGRADINGPRODUCTCODE) AND (REMOVE=&quot;ALL&quot;)" />
<Custom Action="DeleteWinAppSDKHardlinks" Before="RemoveFiles" Condition="Installed AND (REMOVE=&quot;ALL&quot;)" />
<Custom Action="UnApplyModulesRegistryChangeSets" Before="RemoveFiles" Condition="Installed AND (REMOVE=&quot;ALL&quot;)" />
<Custom Action="UnRegisterContextMenuPackages" Before="RemoveFiles" Condition="Installed AND (REMOVE=&quot;ALL&quot;)" />
<Custom Action="CleanImageResizerRuntimeRegistry" Before="RemoveFiles" Condition="Installed AND (REMOVE=&quot;ALL&quot;)" />
@@ -189,8 +193,10 @@
<CustomAction Id="SetUpgradeCommandNotFoundParam" Property="UpgradeCommandNotFound" Value="[INSTALLFOLDER]" />
<CustomAction Id="SetCreateWinAppSDKHardlinksParam" Property="CreateWinAppSDKHardlinks" Value="[INSTALLFOLDER]" />
<CustomAction Id="CreateWinAppSDKHardlinks" Return="check" Impersonate="yes" Execute="deferred" DllEntry="CreateWinAppSDKHardlinksCA" BinaryRef="PTCustomActions" />
<CustomAction Id="SetDeleteWinAppSDKHardlinksParam" Property="DeleteWinAppSDKHardlinks" Value="[INSTALLFOLDER]" />
<CustomAction Id="DeleteWinAppSDKHardlinks" Return="ignore" Impersonate="yes" Execute="deferred" DllEntry="DeleteWinAppSDKHardlinksCA" BinaryRef="PTCustomActions" />
<CustomAction Id="SetCreatePTInteropHardlinksParam" Property="CreatePTInteropHardlinks" Value="[INSTALLFOLDER]" />

View File

@@ -9,7 +9,7 @@
<Fragment>
<!-- Resource directories should be added only if the installer is built on the build farm -->
<?ifdef env.IsPipeline?>
<?foreach ParentDirectory in INSTALLFOLDER;HistoryPluginFolder;CalculatorPluginFolder;FolderPluginFolder;ProgramPluginFolder;ShellPluginFolder;IndexerPluginFolder;UnitConverterPluginFolder;ValueGeneratorPluginFolder;UriPluginFolder;WindowWalkerPluginFolder;OneNotePluginFolder;RegistryPluginFolder;VSCodeWorkspacesPluginFolder;ServicePluginFolder;SystemPluginFolder;TimeDatePluginFolder;WindowsSettingsPluginFolder;WindowsTerminalPluginFolder;WebSearchPluginFolder;PowerToysPluginFolder?>
<?foreach ParentDirectory in INSTALLFOLDER;WinUI3AppsInstallFolder;HistoryPluginFolder;CalculatorPluginFolder;FolderPluginFolder;ProgramPluginFolder;ShellPluginFolder;IndexerPluginFolder;UnitConverterPluginFolder;ValueGeneratorPluginFolder;UriPluginFolder;WindowWalkerPluginFolder;OneNotePluginFolder;RegistryPluginFolder;VSCodeWorkspacesPluginFolder;ServicePluginFolder;SystemPluginFolder;TimeDatePluginFolder;WindowsSettingsPluginFolder;WindowsTerminalPluginFolder;WebSearchPluginFolder;PowerToysPluginFolder?>
<DirectoryRef Id="$(var.ParentDirectory)">
<!-- Resource file directories -->
<?foreach Language in $(var.LocLanguageList)?>
@@ -361,11 +361,11 @@
</RegistryKey>
<File Id="BgcodePreviewHandler_$(var.IdSafeLanguage)_File" Source="$(var.BinDir)\$(var.Language)\PowerToys.BgcodePreviewHandler.resources.dll" />
</Component>
<Component Id="CmdPalExtPowerToys_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)INSTALLFOLDER" Guid="$(var.CompGUIDPrefix)23">
<Component Id="CmdPalExtPowerToys_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)WinUI3AppsInstallFolder" Guid="$(var.CompGUIDPrefix)23">
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
<RegistryValue Type="string" Name="CmdPalExtPowerToys_$(var.IdSafeLanguage)_Component" Value="" KeyPath="yes" />
</RegistryKey>
<File Id="CmdPalExtPowerToys_$(var.IdSafeLanguage)_File" Source="$(var.BinDir)\$(var.Language)\Microsoft.CmdPal.Ext.PowerToys.resources.dll" />
<File Id="CmdPalExtPowerToys_$(var.IdSafeLanguage)_File" Source="$(var.BinDir)\WinUI3Apps\$(var.Language)\Microsoft.CmdPal.Ext.PowerToys.resources.dll" />
</Component>
<?undef IdSafeLanguage?>
<?undef CompGUIDPrefix?>
@@ -433,6 +433,7 @@
<?define IdSafeLanguage = $(var.Language)?>
<?endif?>
<RemoveFolder Id="RemoveFolderResourcesResource$(var.IdSafeLanguage)INSTALLFOLDER" Directory="Resource$(var.IdSafeLanguage)INSTALLFOLDER" On="uninstall" />
<RemoveFolder Id="RemoveFolderResourcesResource$(var.IdSafeLanguage)WinUI3AppsInstallFolder" Directory="Resource$(var.IdSafeLanguage)WinUI3AppsInstallFolder" On="uninstall" />
<RemoveFolder Id="RemoveFolderResourcesResource$(var.IdSafeLanguage)CalculatorPluginFolder" Directory="Resource$(var.IdSafeLanguage)CalculatorPluginFolder" On="uninstall" />
<RemoveFolder Id="RemoveFolderResourcesResource$(var.IdSafeLanguage)FolderPluginFolder" Directory="Resource$(var.IdSafeLanguage)FolderPluginFolder" On="uninstall" />
<RemoveFolder Id="RemoveFolderResourcesResource$(var.IdSafeLanguage)ProgramPluginFolder" Directory="Resource$(var.IdSafeLanguage)ProgramPluginFolder" On="uninstall" />

View File

@@ -17,6 +17,9 @@
<?define SettingsV2IconsModelsFiles=?>
<?define SettingsV2IconsModelsFilesPath=$(var.BinDir)WinUI3Apps\Assets\Settings\Icons\Models\?>
<?define SettingsV2AssetsCmdPalFiles=?>
<?define SettingsV2AssetsCmdPalFilesPath=$(var.BinDir)WinUI3Apps\Assets\Settings\CmdPal\?>
<Fragment>
<DirectoryRef Id="WinUI3AppsAssetsFolder">
<Directory Id="SettingsV2AssetsInstallFolder" Name="Settings">
@@ -27,6 +30,7 @@
<Directory Id="SettingsV2AssetsModulesInstallFolder" Name="Modules">
<Directory Id="SettingsV2OOBEAssetsModulesInstallFolder" Name="OOBE" />
</Directory>
<Directory Id="SettingsV2AssetsCmdPalInstallFolder" Name="CmdPal" />
</Directory>
</DirectoryRef>
@@ -55,6 +59,11 @@
<!--SettingsV2IconsModelsFiles_Component_Def-->
</DirectoryRef>
<DirectoryRef Id="SettingsV2AssetsCmdPalInstallFolder" FileSource="$(var.SettingsV2AssetsCmdPalFilesPath)">
<!-- Generated by generateFileComponents.ps1 -->
<!--SettingsV2AssetsCmdPalFiles_Component_Def-->
</DirectoryRef>
<DirectoryRef Id="SettingsAppAssetsScriptsFolder" FileSource="$(var.SettingsV2AssetsFilesPath)\Scripts\">
<Component Id="CommandNotFound_Scripts" Guid="898EFA1E-EDD3-4F4B-8C7F-4A14B0D05B02" Bitness="always64">
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
@@ -80,6 +89,7 @@
<RemoveFolder Id="RemoveFolderSettingsV2IconsModelsInstallFolder" Directory="SettingsV2IconsModelsInstallFolder" On="uninstall" />
<RemoveFolder Id="RemoveFolderSettingsV2AssetsModulesInstallFolder" Directory="SettingsV2AssetsModulesInstallFolder" On="uninstall" />
<RemoveFolder Id="RemoveFolderSettingsV2OOBEAssetsModulesInstallFolder" Directory="SettingsV2OOBEAssetsModulesInstallFolder" On="uninstall" />
<RemoveFolder Id="RemoveFolderSettingsV2AssetsCmdPalInstallFolder" Directory="SettingsV2AssetsCmdPalInstallFolder" On="uninstall" />
<RemoveFolder Id="RemoveFolderSettingsAppAssetsScriptsFolder" Directory="SettingsAppAssetsScriptsFolder" On="uninstall" />
</Component>
<ComponentRef Id="CommandNotFound_Scripts" />

View File

@@ -2,26 +2,39 @@
<?include $(sys.CURRENTDIR)\Common.wxi?>
<?define ShortcutGuideSvgFiles=?>
<?define ShortcutGuideSvgFilesPath=$(var.BinDir)\Assets\ShortcutGuide\?>
<?define ShortcutGuideAssetsFiles=?>
<?define ShortcutGuideAssetsFilesPath=$(var.BinDir)WinUI3Apps\Assets\ShortcutGuide\?>
<?define ShortcutGuideManifestsFiles=?>
<?define ShortcutGuideManifestsFilesPath=$(var.BinDir)WinUI3Apps\Assets\ShortcutGuide\Manifests\?>
<Fragment>
<!-- Shortcut guide files -->
<DirectoryRef Id="BaseApplicationsAssetsFolder">
<Directory Id="ShortcutGuideSvgsInstallFolder" Name="ShortcutGuide" />
<DirectoryRef Id="WinUI3AppsAssetsFolder">
<Directory Id="ShortcutGuideAssetsFolder" Name="ShortcutGuide">
<Directory Id="ShortcutGuideManifestsFolder" Name="Manifests" />
</Directory>
</DirectoryRef>
<DirectoryRef Id="ShortcutGuideSvgsInstallFolder" FileSource="$(var.ShortcutGuideSvgFilesPath)">
<DirectoryRef Id="ShortcutGuideAssetsFolder" FileSource="$(var.ShortcutGuideAssetsFilesPath)">
<!-- Generated by generateFileComponents.ps1 -->
<!--ShortcutGuideSvgFiles_Component_Def-->
<!--ShortcutGuideAssetsFiles_Component_Def-->
</DirectoryRef>
<DirectoryRef Id="ShortcutGuideManifestsFolder" FileSource="$(var.ShortcutGuideManifestsFilesPath)">
<!-- Generated by generateFileComponents.ps1 -->
<!--ShortcutGuideManifestsFiles_Component_Def-->
</DirectoryRef>
<!-- Shortcut guide -->
<ComponentGroup Id="ShortcutGuideComponentGroup">
<Component Id="RemoveShortcutGuideFolder" Guid="AD1ABC55-B593-4A60-A86A-BA8C0ED493A5" Directory="ShortcutGuideSvgsInstallFolder">
<ComponentGroup Id="ShortcutGuideComponentGroup" >
<Component Id="RemoveShortcutGuideFolder" Guid="AD1ABC55-B593-4A60-A86A-BA8C0ED493A5" Directory="ShortcutGuideAssetsFolder" >
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
<RegistryValue Type="string" Name="RemoveShortcutGuideFolder" Value="" KeyPath="yes" />
<RegistryValue Type="string" Name="RemoveShortcutGuideFolder" Value="" KeyPath="yes"/>
</RegistryKey>
<RemoveFolder Id="RemoveFolderShortcutGuideSvgsInstallFolder" Directory="ShortcutGuideSvgsInstallFolder" On="uninstall" />
<RemoveFolder Id="RemoveFolderShortcutGuideAssetsInstallFolder" Directory="ShortcutGuideAssetsFolder" On="uninstall"/>
</Component>
<Component Id="RemoveShortcutGuideManifestsFolder" Guid="F47E2C3A-8D91-4B6F-A2E5-9C8D7F6A1B3E" Directory="ShortcutGuideManifestsFolder" >
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
<RegistryValue Type="string" Name="RemoveShortcutGuideManifestsFolder" Value="" KeyPath="yes"/>
</RegistryKey>
<RemoveFolder Id="RemoveFolderShortcutGuideManifestsInstallFolder" Directory="ShortcutGuideManifestsFolder" On="uninstall"/>
</Component>
</ComponentGroup>

View File

@@ -7,11 +7,18 @@
<Fragment>
<DirectoryRef Id="WinUI3AppsInstallFolder">
<Component Id="WinUI3Apps_Hardlinks_Manifest" Guid="F7A2C3D1-8E4B-4F6A-9D2E-1B3C5A7F8E90" Bitness="always64">
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
<RegistryValue Type="string" Name="WinUI3Apps_Hardlinks_Manifest" Value="" KeyPath="yes" />
</RegistryKey>
<File Id="WinUI3Apps_hardlinks_txt" Source="$(var.BinDir)\WinUI3Apps\hardlinks.txt" />
</Component>
<!-- Generated by generateFileComponents.ps1 -->
<!--WinUI3ApplicationsFiles_Component_Def-->
</DirectoryRef>
<ComponentGroup Id="WinUI3ApplicationsComponentGroup">
<ComponentRef Id="WinUI3Apps_Hardlinks_Manifest" />
</ComponentGroup>
</Fragment>

View File

@@ -28,7 +28,11 @@ Function Generate-FileList() {
$fileExclusionList = @("*.pdb", "*.lastcodeanalysissucceeded", "createdump.exe", "powertoys.exe")
$fileInclusionList = @("*.dll", "*.exe", "*.json", "*.msix", "*.png", "*.gif", "*.ico", "*.cur", "*.svg", "index.html", "reg.js", "gitignore.js", "srt.js", "monacoSpecialLanguages.js", "customTokenThemeRules.js", "*.pri")
$fileInclusionList = @("*.dll", "*.exe", "*.json", "*.msix", "*.png", "*.gif", "*.ico", "*.cur", "*.svg", "index.html", "reg.js", "gitignore.js", "srt.js", "monacoSpecialLanguages.js", "customTokenThemeRules.js", "*.pri", "*.yml")
# MFC DLLs leak into the output via WindowsAppSDKSelfContained but no PowerToys binary imports them.
# Verified with dumpbin /dependents across all 2176 binaries — zero consumers.
$fileExclusionList += @("mfc140.dll", "mfc140u.dll", "mfcm140.dll", "mfcm140u.dll")
$dllsToIgnore = @("System.CodeDom.dll", "WindowsBase.dll")
@@ -85,11 +89,16 @@ Function Generate-FileComponents() {
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'fileList',
Justification = 'variable is used in another scope')]
$fileList = $matches[2] -split ';'
$fileList = $matches[2] -split ';' | Where-Object { $_ -ne '' }
return
}
}
if ($null -eq $fileList -or $fileList.Count -eq 0) {
# No files to generate components for — leave placeholder intact
return
}
$componentId = "$($fileListName)_Component"
$componentDefs = "`r`n"
@@ -103,6 +112,8 @@ Function Generate-FileComponents() {
foreach ($file in $fileList) {
$fileTmp = $file -replace "-", "_"
$fileTmp = $fileTmp -replace "[^A-Za-z0-9_.]", "_"
if ($fileTmp -match "^[^A-Za-z_]") { $fileTmp = "_$fileTmp" }
$componentDefs +=
@"
<File Id="$($fileListName)_File_$($fileTmp)" Source="`$(var.$($fileListName)Path)\$($file)" />`r`n
@@ -154,6 +165,67 @@ Generate-FileComponents -fileListName "BaseApplicationsFiles" -wxsFilePath $PSSc
#WinUI3Applications
Generate-FileList -fileDepsJson "" -fileListName WinUI3ApplicationsFiles -wxsFilePath $PSScriptRoot\WinUI3Applications.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps"
# Deduplicate: Remove files from WinUI3Apps that are identical to root (same name + same hash).
# These will be re-created as plain file copies at install time by CreateWinAppSDKHardlinksCA.
# (The CA's name is historical: it now uses fs::copy_file rather than CreateHardLinkW to avoid
# DACL contamination across the shared inode -- see CustomAction.cpp for details.)
$rootPath = "$PSScriptRoot..\..\..\$platform\Release"
$winui3Path = "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps"
$winui3WxsPath = "$PSScriptRoot\WinUI3Applications.wxs"
$winui3Wxs = Get-Content $winui3WxsPath -Raw
$manifestPath = Join-Path $winui3Path "hardlinks.txt"
if ($winui3Wxs -match "\<\?define WinUI3ApplicationsFiles=([^?]*)\?\>") {
$winui3FileList = $matches[1] -split ';' | Where-Object { $_ -ne '' }
$hardlinkFiles = @()
# Read the BaseApplications WXS file list so we only deduplicate files that the MSI
# is actually deploying to the install root. If a file was stripped from BaseApplications
# by an earlier step (e.g., the ImageResizer leaked-apphost workaround above), the
# install-time CA's source would be missing and both copies would disappear.
$baseAppsWxs = Get-Content $baseAppWxsPath -Raw
$baseAppsFileList = @()
if ($baseAppsWxs -match "\<\?define BaseApplicationsFiles=([^?]*)\?\>") {
$baseAppsFileList = $matches[1] -split ';' | Where-Object { $_ -ne '' }
}
foreach ($file in $winui3FileList) {
# Skip files that were intentionally not deployed to root by the build
if ($baseAppsFileList -notcontains $file) { continue }
$rootFile = Join-Path $rootPath $file
$winui3File = Join-Path $winui3Path $file
if ((Test-Path $rootFile) -and (Test-Path $winui3File)) {
$rootHash = (Get-FileHash $rootFile -Algorithm SHA256).Hash
$winui3Hash = (Get-FileHash $winui3File -Algorithm SHA256).Hash
if ($rootHash -eq $winui3Hash) {
$hardlinkFiles += $file
}
}
}
if ($hardlinkFiles.Count -gt 0) {
# Remove deduplicated files from WinUI3Apps file list
$remainingFiles = $winui3FileList | Where-Object { $_ -notin $hardlinkFiles }
if ($remainingFiles.Count -eq 0) {
# All files are duplicates — keep at least a dummy entry won't be emitted
# Generate-FileComponents handles empty defines by producing no <File> entries
$winui3Wxs = $winui3Wxs -replace "\<\?define WinUI3ApplicationsFiles=[^?]*\?\>", "<?define WinUI3ApplicationsFiles=?>"
} else {
$winui3Wxs = $winui3Wxs -replace "\<\?define WinUI3ApplicationsFiles=[^?]*\?\>", "<?define WinUI3ApplicationsFiles=$($remainingFiles -join ';')?>"
}
Set-Content -Path $winui3WxsPath -Value $winui3Wxs
Write-Host "Deduplicated $($hardlinkFiles.Count) files from WinUI3Apps (will be copied at install time)"
}
# Always write hardlinks.txt (may be empty — CA handles that gracefully)
# Write as UTF-8 without BOM so the install-time CA can read it via std::ifstream
# + MultiByteToWideChar(CP_UTF8) without dealing with PS-version-dependent default
# encodings or a leading BOM.
[System.IO.File]::WriteAllLines($manifestPath, [string[]]$hardlinkFiles, (New-Object System.Text.UTF8Encoding($false)))
}
Generate-FileComponents -fileListName "WinUI3ApplicationsFiles" -wxsFilePath $PSScriptRoot\WinUI3Applications.wxs
#AdvancedPaste
@@ -191,7 +263,7 @@ Generate-FileList -fileDepsJson "" -fileListName ImageResizerAssetsFiles -wxsFil
Generate-FileComponents -fileListName "ImageResizerAssetsFiles" -wxsFilePath $PSScriptRoot\ImageResizer.wxs
#KeyboardManager
Generate-FileList -fileDepsJson "" -fileListName KeyboardManagerAssetsFiles -wxsFilePath $PSScriptRoot\KeyboardManager.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\KeyboardManager"
Generate-FileList -fileDepsJson "" -fileListName KeyboardManagerAssetsFiles -wxsFilePath $PSScriptRoot\KeyboardManager.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\KeyboardManager"
Generate-FileList -fileDepsJson "" -fileListName KeyboardManagerAssetsWinUI3Files -wxsFilePath $PSScriptRoot\KeyboardManager.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\KeyboardManagerEditor"
Generate-FileComponents -fileListName "KeyboardManagerAssetsFiles" -wxsFilePath $PSScriptRoot\KeyboardManager.wxs
Generate-FileComponents -fileListName "KeyboardManagerAssetsWinUI3Files" -wxsFilePath $PSScriptRoot\KeyboardManager.wxs
@@ -327,8 +399,24 @@ Generate-FileComponents -fileListName "ValueGeneratorImagesCmpFiles" -wxsFilePat
## Plugins
#ShortcutGuide
Generate-FileList -fileDepsJson "" -fileListName ShortcutGuideSvgFiles -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\ShortcutGuide\"
Generate-FileComponents -fileListName "ShortcutGuideSvgFiles" -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs
# Ensure manifest yml files are in the build output (the Build target's CopyToOutputDirectory
# may not run reliably under -graph mode in solution builds).
$sgManifestsSrc = "$PSScriptRoot..\..\..\src\modules\ShortcutGuide\ShortcutGuide.Ui\Assets\ShortcutGuide\Manifests"
$sgManifestsDst = "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\ShortcutGuide\Manifests"
Write-Host "ShortcutGuide manifests: src=$sgManifestsSrc exists=$(Test-Path $sgManifestsSrc)"
Write-Host "ShortcutGuide manifests: dst=$sgManifestsDst exists=$(Test-Path $sgManifestsDst)"
if (Test-Path $sgManifestsSrc) {
New-Item -Path $sgManifestsDst -ItemType Directory -Force | Out-Null
Copy-Item "$sgManifestsSrc\*.yml" -Destination $sgManifestsDst -Force
$copied = (Get-ChildItem "$sgManifestsDst\*.yml" -ErrorAction SilentlyContinue).Count
Write-Host "ShortcutGuide manifests: copied $copied yml files to build output"
} else {
Write-Host "WARNING: ShortcutGuide manifest source not found at $sgManifestsSrc"
}
Generate-FileList -fileDepsJson "" -fileListName ShortcutGuideAssetsFiles -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\ShortcutGuide\"
Generate-FileComponents -fileListName "ShortcutGuideAssetsFiles" -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs
Generate-FileList -fileDepsJson "" -fileListName ShortcutGuideManifestsFiles -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\ShortcutGuide\Manifests\"
Generate-FileComponents -fileListName "ShortcutGuideManifestsFiles" -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs
#Settings
Generate-FileList -fileDepsJson "" -fileListName SettingsV2AssetsFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\"
@@ -336,11 +424,13 @@ Generate-FileList -fileDepsJson "" -fileListName SettingsV2AssetsModulesFiles -w
Generate-FileList -fileDepsJson "" -fileListName SettingsV2OOBEAssetsModulesFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\Modules\OOBE\"
Generate-FileList -fileDepsJson "" -fileListName SettingsV2OOBEAssetsFluentIconsFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\Icons\"
Generate-FileList -fileDepsJson "" -fileListName SettingsV2IconsModelsFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\Icons\Models\"
Generate-FileList -fileDepsJson "" -fileListName SettingsV2AssetsCmdPalFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\CmdPal\"
Generate-FileComponents -fileListName "SettingsV2AssetsFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
Generate-FileComponents -fileListName "SettingsV2AssetsModulesFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
Generate-FileComponents -fileListName "SettingsV2OOBEAssetsModulesFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
Generate-FileComponents -fileListName "SettingsV2OOBEAssetsFluentIconsFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
Generate-FileComponents -fileListName "SettingsV2IconsModelsFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
Generate-FileComponents -fileListName "SettingsV2AssetsCmdPalFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
#Workspaces
Generate-FileList -fileDepsJson "" -fileListName WorkspacesImagesComponentFiles -wxsFilePath $PSScriptRoot\Workspaces.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\Workspaces\"

View File

@@ -8,10 +8,10 @@ SET VCToolsVersion=!VCToolsVersion!
SET ClearDevCommandPromptEnvVars=false
rem In case of Release we should not use Debug CRT in VCRT forwarders
msbuild !PTRoot!\src\modules\previewpane\MonacoPreviewHandler\MonacoPreviewHandler.csproj -t:Publish -p:Configuration="Release" -p:Platform="!PlatformArg!" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml -p:TargetFramework=net9.0-windows10.0.26100.0
msbuild !PTRoot!\src\modules\previewpane\MonacoPreviewHandler\MonacoPreviewHandler.csproj -t:Publish -p:Configuration="Release" -p:Platform="!PlatformArg!" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml -p:TargetFramework=net10.0-windows10.0.26100.0
msbuild !PTRoot!\src\modules\previewpane\MarkdownPreviewHandler\MarkdownPreviewHandler.csproj -t:Publish -p:Configuration="Release" -p:Platform="!PlatformArg!" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml -p:TargetFramework=net9.0-windows10.0.26100.0
msbuild !PTRoot!\src\modules\previewpane\MarkdownPreviewHandler\MarkdownPreviewHandler.csproj -t:Publish -p:Configuration="Release" -p:Platform="!PlatformArg!" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml -p:TargetFramework=net10.0-windows10.0.26100.0
msbuild !PTRoot!\src\modules\previewpane\SvgPreviewHandler\SvgPreviewHandler.csproj -t:Publish -p:Configuration="Release" -p:Platform="!PlatformArg!" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml -p:TargetFramework=net9.0-windows10.0.26100.0
msbuild !PTRoot!\src\modules\previewpane\SvgPreviewHandler\SvgPreviewHandler.csproj -t:Publish -p:Configuration="Release" -p:Platform="!PlatformArg!" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml -p:TargetFramework=net10.0-windows10.0.26100.0
msbuild !PTRoot!\src\modules\previewpane\SvgThumbnailProvider\SvgThumbnailProvider.csproj -t:Publish -p:Configuration="Release" -p:Platform="!PlatformArg!" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml -p:TargetFramework=net9.0-windows10.0.26100.0
msbuild !PTRoot!\src\modules\previewpane\SvgThumbnailProvider\SvgThumbnailProvider.csproj -t:Publish -p:Configuration="Release" -p:Platform="!PlatformArg!" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml -p:TargetFramework=net10.0-windows10.0.26100.0

View File

@@ -14,7 +14,6 @@
<PropertyGroup Label="Configuration">
</PropertyGroup>
<Import Project="$(RepoRoot)deps\expected.props" />
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
</PropertyGroup>
@@ -62,7 +61,7 @@
<Import Project="$(RepoRoot)deps\spdlog.props" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(RepoRoot)packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('$(RepoRoot)packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="$(RepoRoot)packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('$(RepoRoot)packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
<Import Project="$(RepoRoot)packages\Microsoft.Windows.ImplementationLibrary.1.0.260126.7\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('$(RepoRoot)packages\Microsoft.Windows.ImplementationLibrary.1.0.260126.7\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
@@ -70,6 +69,6 @@
</PropertyGroup>
<Error Condition="!Exists('$(RepoRoot)packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '$(RepoRoot)packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('$(RepoRoot)packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(RepoRoot)packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('$(RepoRoot)packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(RepoRoot)packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
<Error Condition="!Exists('$(RepoRoot)packages\Microsoft.Windows.ImplementationLibrary.1.0.260126.7\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(RepoRoot)packages\Microsoft.Windows.ImplementationLibrary.1.0.260126.7\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
</Target>
</Project>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.250303.1" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.260126.7" targetFramework="native" />
</packages>

View File

@@ -4,7 +4,7 @@
<Import Project=".\Common.Dotnet.PrepareGeneratedFolder.targets" />
<PropertyGroup>
<CoreTargetFramework>net9.0</CoreTargetFramework>
<CoreTargetFramework>net10.0</CoreTargetFramework>
<WindowsSdkPackageVersion>10.0.26100.68-preview</WindowsSdkPackageVersion>
<TargetFramework>$(CoreTargetFramework)-windows10.0.26100.0</TargetFramework>
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>

View File

@@ -38,17 +38,7 @@
</Capabilities>
<Applications>
<Application Id="PowerToys.OCR" Executable="PowerToys.PowerOCR.exe" EntryPoint="Windows.FullTrustApplication">
<uap:VisualElements
DisplayName="PowerToys.OCR"
Description="PowerToys OCR Module"
BackgroundColor="transparent"
Square150x150Logo="Images\Square150x150Logo.png"
Square44x44Logo="Images\Square44x44Logo.png"
AppListEntry="none">
</uap:VisualElements>
</Application>
<Application Id="PowerToys.SettingsUI" Executable="WinUI3Apps\PowerToys.Settings.exe" EntryPoint="Windows.FullTrustApplication">
<Application Id="PowerToys.SettingsUI" Executable="PowerToys.Settings.exe" EntryPoint="Windows.FullTrustApplication">
<uap:VisualElements
DisplayName="PowerToys.SettingsUI"
Description="PowerToys Settings UI"
@@ -58,7 +48,7 @@
AppListEntry="none">
</uap:VisualElements>
</Application>
<Application Id="PowerToys.ImageResizerUI" Executable="WinUI3Apps\PowerToys.ImageResizer.exe" EntryPoint="Windows.FullTrustApplication">
<Application Id="PowerToys.ImageResizerUI" Executable="PowerToys.ImageResizer.exe" EntryPoint="Windows.FullTrustApplication">
<uap:VisualElements
DisplayName="PowerToys.ImageResizer"
Description="PowerToys Image Resizer UI"

View File

@@ -417,6 +417,7 @@ if ($NoSign) {
Write-BuildLog "Identity Name: $($script:Config.IdentityName)" -Level Info
}
$winUI3AppsDir = Join-Path $outDir "WinUI3Apps"
Write-BuildLog "Register sparse package:" -Level Info
Write-BuildLog " Add-AppxPackage -Path `"$msixPath`" -ExternalLocation `"$outDir`"" -Level Warning
Write-BuildLog "(If already installed and you changed manifest only): Add-AppxPackage -Register `"$manifestPath`" -ExternalLocation `"$outDir`" -ForceApplicationShutdown" -Level Warning
Write-BuildLog " Add-AppxPackage -Path `"$msixPath`" -ExternalLocation `"$winUI3AppsDir`"" -Level Warning
Write-BuildLog "(If already installed and you changed manifest only): Add-AppxPackage -Register `"$manifestPath`" -ExternalLocation `"$winUI3AppsDir`" -ForceApplicationShutdown" -Level Warning

Some files were not shown because too many files have changed in this diff Show More