## 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>
<!-- 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
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.
## 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).
## 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>
## 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>
## 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>
## 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>
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>
`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>
<!-- 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>
<!-- 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
## 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"
/>
## 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"
/>
## 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
## 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
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.
(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>
## 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>
## 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>
## 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>
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).
## 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 -->
- Fixesmicrosoft/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>
## 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>
## 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>
## 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>
## 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.
## 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>
## 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>
<!-- 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>
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>
## 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.
## 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>
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>
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>
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>
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"
/>
## 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 -->
- Fixesmicrosoft/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>
## 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>
## 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>
<!-- 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>
<!-- 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
## 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>
## 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>
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'
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
<!-- 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>
<!-- 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>
<!-- 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.
## 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>
## 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>
<!-- 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>
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
## 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>
## 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>
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
533 changed files with 37962 additions and 6312 deletions
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: 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
- **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 |
| [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` 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 |
Use MCP tools to request Copilotreviews 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)
2. Read the PR title, body, and diff. Produce a 1–3 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.
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)).
Write-Error"Failed to acquire ADO access token. Run 'az login' first. (az: $script:LastAzError)"
exit1
}
# --- 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"}
@@ -242,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 |
@@ -362,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. |
<!-- 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-->
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.
<!-- 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. -->
<!-- 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. -->
<!-- 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. -->
<!-- Package System.Data.SqlClient added to force it as a dependency of Microsoft.Windows.Compatibility to the latest version available at this time. -->
<!-- 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. -->
<!-- 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. -->
@@ -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 -->
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,7 +92,7 @@ There are [community driven install methods](https://learn.microsoft.com/windows
[](https://github.com/microsoft/PowerToys/releases)
To see what's new, check out the [release notes](https://github.com/microsoft/PowerToys/releases/tag/v0.99.0).
To see what's new, check out the [release notes](https://github.com/microsoft/PowerToys/releases/).
## 🛣️ Roadmap
@@ -131,3 +117,4 @@ The application logs basic diagnostic data (telemetry). For more privacy informa
In my head, I am still leaning towards a more full-featured version of draft C,
but with full CommandItem's in the `ISearchUpdateArgs` instead of just strings.
We'd almost need a new page type to support that, where the extension can add
`ICommandItem`s to the search box directly.
## Addenda IV: Dock bands
The "dock" is another way to surface commands to the user. This is a
@@ -2158,7 +2342,6 @@ because that method is was designed for two main purposes:
In neither of those scenarios was the full "display" of the item needed. In
pinning scenarios, however, we need everything that the user would see in the UI
for that item, which is all in the `ICommandItem`.
## Class diagram
This is a diagram attempting to show the relationships between the various types we've defined for the SDK. Some elements are omitted for clarity. (Notably, `IconData` and `IPropChanged`, which are used in many places.)
<Custom Action="TelemetryLogUninstallSuccess" After="InstallFinalize" Condition="Installed and (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")" />
<Custom Action="DeleteWinAppSDKHardlinks" Before="RemoveFiles" Condition="Installed AND (REMOVE="ALL")" />
<Custom Action="UnApplyModulesRegistryChangeSets" Before="RemoveFiles" Condition="Installed AND (REMOVE="ALL")" />
<Custom Action="UnRegisterContextMenuPackages" Before="RemoveFiles" Condition="Installed AND (REMOVE="ALL")" />
<Custom Action="CleanImageResizerRuntimeRegistry" Before="RemoveFiles" Condition="Installed AND (REMOVE="ALL")" />
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
<PackageReferenceInclude="System.Data.SqlClient"/><!-- It's a dependency of Microsoft.Windows.Compatibility. We're adding it here to force it to the version specified in Directory.Packages.props -->
<PackageReferenceInclude="System.Data.SqlClient"/><!-- It's a dependency of Microsoft.Windows.Compatibility. We're adding it here to force it to the version specified in Directory.Packages.props -->
<PackageReferenceInclude="System.Data.SqlClient"/><!-- It's a dependency of Microsoft.Windows.Compatibility. We're adding it here to force it to the version specified in Directory.Packages.props -->
<!-- HACK: To make sure the version pulled in by Microsoft.Extensions.Hosting is current. -->
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.