mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-07-09 20:09:28 +02:00
powerscripts_prototype
9343 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
514d593dd9 |
[PowerScripts] Move parameter prompt to a WinUI 3 helper process
The parameter prompt was an in-process WinForms dialog in PowerScripts.Host. Keyboard Manager launches the Host hidden and actively hides every window the Host process owns (ChordKeyboardHandler HideProgram), so the dialog was spawned then immediately hidden -- pressing a KBM hotkey bound to a prompt-enabled script appeared to do nothing. Fix + native UI in one change: render the prompt in a separate WinUI 3 helper, PowerScripts.PromptUI (self-contained, unpackaged Windows App SDK). A child process's window is outside KBM's reach, so the prompt shows reliably while the Host stays silent -- and it now matches PowerToys' WinUI 3 / Fluent design (ComboBox / ToggleSwitch / NumberBox / TextBox, accent Run button, themed). - PowerScripts.PromptUI: new WinUI 3 app. Reads a PromptSpec from --spec (temp JSON), builds a control per parameter, writes chosen values to --out; exit 0 = confirmed, 2 = cancelled/closed. Brings itself to the foreground and centers. - Host: PromptLauncher serializes the spec, launches the helper, waits, reads back values. Resolves the helper next to the Host, via POWERSCRIPTS_PROMPTUI, or by discovering the prompt project's bin for in-repo runs; degrades to defaults if it can't be found. Program.cs calls PromptLauncher instead of the old dialog; WinForms dependency and ParameterPromptDialog removed. - README: document the WinUI 3 prompt helper and control mapping. Core tests 32/32. Verified end-to-end: Host launched hidden spawns the visible WinUI 3 prompt; confirming passes values through to the script. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
6bf15961a0 |
[PowerScripts] Add optional prompted script parameters
Adds an opt-in parameter-prompt feature: a script may declare typed parameters in its manifest and set promptForParameters=true. When set, the Host shows a small dialog before running so the user picks/enters values, which are passed to the script (PowerShell -Name value, Python kwargs). When omitted, no UI shows and behavior is unchanged (parameters only via --set). - Manifest: ScriptParameter gains a 'choice' type (with options), Label, Description; add manifest-level promptForParameters. Validated in ManifestValidator (known types, choice needs options, default within options, int min/max, unique names). - Host: ParameterPromptDialog (WinForms) builds a control per parameter (choice->dropdown, bool->checkbox, int->numeric, string->textbox); wired into the run path with a --no-prompt bypass. list --json now exposes promptForParameters. Main is [STAThread]; Host enables WinForms. - Samples: greet (PowerShell) and py_greet (Python) demonstrating choice+string+bool prompted parameters. Core tests 32/32; parameter values verified reaching PowerShell via --set, and the prompt dialog verified rendering for the run path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
fe13577c8d |
[PowerScripts] Fix context menu not rendering (use ExtendedSubCommandsKey)
The Explorer cascading submenu registered an empty 'SubCommands' value with an inline \shell subkey. On Windows 11 an empty SubCommands frequently renders nothing, so the PowerScripts submenu never appeared even though the keys were present. Switch to the documented per-user cascade pattern: the verb points at an 'ExtendedSubCommandsKey' (HKCU\\Software\\Classes\\PowerScripts.Cascade.<ext>) whose \shell subtree holds the child commands. Uninstall now also removes the cascade key. Fixed the remaining 'PowerScript' -> 'PowerScripts' doc reference. Verified: after shell-install the .txt/.md verbs carry ExtendedSubCommandsKey (no SubCommands) and the cascade command trees resolve to the Host run command. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
aa9b94d0cf |
[PowerScripts] Fix stale id/folder-name doc comment
The manifest Id doc comment still claimed the id must match the containing folder name, contradicting the implemented decoupling (ManifestValidator ignores folderName; ScriptRegistry enforces id uniqueness). Correct it to describe id as a portable identity independent of the folder, so scripts can be renamed or relocated for sharing without changing identity. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
85228635fc |
[PowerScripts] Fix enabled gate, menu label, add Python samples
Fixes three issues reported during e2e testing of the PowerScripts prototype: 1. Enabled gate was inert after any PowerToys launch. The C++ runner rewrites settings.json's enabled block from its registered-module list on launch, dropping the PowerScripts key (PowerScripts is not yet a registered runner module). The gate treated the absent key as OFF, so the context menu, KBM hotkeys and Advanced Paste all went dead. The module's own config.json enabled flag (owned solely by this module, never touched by the runner) is now authoritative; an absent settings.json key falls back to enabled. The Settings toggle writes both settings.json (for the UI) and config.json (authoritative + restart-durable). Explicit false still disables all surfaces persistently. 2. Explorer right-click menu label was "PowerScript" (singular) in the registry-based ShellRegistration; corrected to "PowerScripts". 3. Added dedicated Python samples: py_uppercase_files (file / context menu, powerscript_from_files_to_files) and py_beep (system / Keyboard Manager, powerscript_from_none_to_none). Core tests 27/27; Host, Core, Settings.UI and AdvancedPaste build clean; enabled gate, both Python samples, and the context-menu registration verified end-to-end. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
12769727ca |
[PowerScripts] Add Python runtime + Advanced Paste surface
Extend PowerScripts so a script authored once runs from every surface, now including Python and Advanced Paste. Core/Host: - Add Python runtime (Windows + WSL) driven by the convention powerscript_from_<input>_to_<output>; a bundled _runner.py bridges a JSON stdin/stdout transform protocol. - Add PythonSettings (mode/windows/wsl/timeout) persisted in the module config.json python section (merge-preserving with scriptsRoot). - ScriptExecutor delegates Python scripts to PythonRuntime. - Host gains a `transform` command (JSON in/out) shared by all surfaces and enriches `list --json` with each script's transform contract. - Sample Python PowerScript: samples/uppercase (text -> text). Settings UI: - PowerScripts page exposes a Python runtime section: mode combo (Disabled/Windows/WSL), interpreter path (with browse), and a WSL distribution combo populated from `wsl -l -q`. Config writes now preserve all sections. Advanced Paste: - New PowerScriptsService enumerates advancedPaste-surface scripts via the host and runs one as a clipboard text transform. - PasteFormats.PowerScript + per-script PasteFormat factory; formats are populated in the options list and dispatched in PasteFormatExecutor. - Scripts only appear when PowerScripts is enabled (host also gates), so disabling the module makes them inert everywhere. Tests: add PythonConventionTests (parser); Core suite 27/27. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
944ae41cf7 |
[PowerScripts] Rename context menu to "PowerScripts" + central enabled gate
- Explorer context-menu title now reads "PowerScripts" (was "PowerScript"). - Add ModuleState, a single runtime enabled gate read from PowerToys settings.json (enabled.PowerScripts). PowerScripts.Host.exe `run` and `shell-menu` consult it, so when the module is disabled every binding (Keyboard Manager hotkeys, the context menu, and any future module that shells out to the host) becomes inert without being deleted or rewritten; re-enabling restores them. Missing settings file (standalone/dev/test) or a corrupt file fails open; an absent key means off (module default). POWERSCRIPTS_IGNORE_ENABLED=1 bypasses the gate for tests/dev. - Add ModuleStateTests (5) covering enabled/disabled/absent/missing/corrupt. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
97ba9b8ec5 |
[PowerScripts] KBM: dedicated PowerScript action in new editor
Present PowerScript hotkeys as a first-class action in the Keyboard Manager editor instead of raw run-program cards: - Add PowerScriptShortcut model + dedicated "PowerScripts" section in MainPage that lists "runs PowerScript: <name>" with its own edit/toggle/delete flow. - LoadPowerScriptShortcuts filters RunProgram mappings whose program is PowerScripts.Host.exe; LoadProgramShortcuts now skips them. - On save, record trust for the script (Host trust approve <id>) and run non-interactively (run <id> --no-consent) so the engine-launched hidden Host never blocks on a consent dialog and the hotkey actually fires. - Add catalog helpers ApproveTrust/IsPowerScriptProgramPath/ParseScriptId/ GetScriptName. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
1cbc5d6fdb |
[PowerScripts] Fix greyed-out Save for PowerScript hotkey mappings
The new Keyboard Manager editor's UnifiedMappingControl.IsInputComplete() had no case for ActionType.PowerScript, so it fell through to `false` and the Save button was permanently disabled when mapping a shortcut to a PowerScript. Add the PowerScript completion rule (a script must be selected) and the missing PowerScript case in SetActionType so a saved PowerScript mapping round-trips to the correct action type when edited. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
24ce23fa12 |
[PowerScripts] Decouple script id from folder + add trust-on-first-use gate
Two prototype improvements toward a shareable, safe script catalogue: Catalogue-readiness (id decoupled from folder): - Script `id` is now the portable identity; the id-must-equal-folder-name rule is removed so a shared/downloaded script keeps its id in any folder. - Registry enforces id uniqueness across the catalogue (duplicate id is reported and skipped rather than silently shadowed). - Manifest gains optional provenance fields: publisher, version, source. Capability safety (trust-on-first-use): - New ScriptIntegrity content hash (SHA-256 over entry body + kind + declared capabilities) and a persisted TrustStore (trust.json). - Host `run` now gates every execution (the single choke point for context menu, KBM and agents): untrusted scripts prompt a native consent dialog showing name/publisher/source/capabilities/path; editing the body or escalating capabilities invalidates trust and re-prompts. - `--no-consent` / POWERSCRIPTS_NO_CONSENT refuses instead of prompting (for non-interactive/agent callers); new `trust list|approve|revoke` subcommands; `list --json` exposes a `trusted` flag. - Settings page shows a read-only Trust status row per script. Tests: id decoupling, duplicate-id rejection, integrity stability/ invalidation, and trust-store round-trip (16/16 Core tests pass). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
6d4a1dee6e |
[PowerScripts] Make the new KBM editor's PowerScript action e2e-ready
The new Keyboard Manager editor (KeyboardManagerEditorUI) already exposes a
PowerScript action, but on a Debug build it couldn't locate PowerScripts.Host.exe
(it isn't copied next to the editor), so the picker came up empty.
- PowerScriptsCatalog.ResolveHostPath: add the same dev-bin fallback the Settings
view-model uses (walk up from the editor's base dir and probe
src\modules\PowerScripts\PowerScripts.Host\bin\{Debug,Release}). The editor can
now enumerate system scripts and resolve the host path for the saved RunProgram
mapping in a dev build.
- Add kbm-e2e.ps1: a self-contained end-to-end helper that forces the new editor
(useNewEditor=true), opens it to assign a hotkey to a system PowerScript, then
runs KeyboardManagerEngine standalone so the hotkey actually fires
Host.exe run <id> — no full runner required.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
||
|
|
cd327dda07 |
[PowerScripts] Make Settings page a read-only script catalogue
The manifest.json is the single source of truth for a script's trigger extensions, surfaces and capabilities. Drop the in-Settings extensions editor (which only rewrote the manifest via the host) and instead show that information read-only, so the UI reflects the manifest rather than duplicating authoring of it. - PowerScriptListItem: replace the editable ExtensionsText with read-only display projections (ExtensionsDisplay/SurfacesDisplay/CapabilitiesDisplay/ RuntimeDisplay); surface Runtime/Surfaces/Capabilities from list --json. - PowerScriptsPage.xaml: each script expander now lists Trigger file types (file scripts), Runtime, Surfaces and Capabilities as read-only rows. - Remove SetScriptExtensions / ApplyExtensionsButton_Click. The host set-extensions command remains as a CLI/agent capability. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
54bd07c08d |
[PowerScripts] Add Win11 modern context-menu handler (IExplorerCommand)
Legacy registry verbs only appear under "Show more options" on Windows 11. This adds a self-contained IExplorerCommand COM server (sparse MSIX package) that surfaces a top-level "PowerScript" entry with a dynamic submenu of the file scripts matching the current selection. - PowerScripts.Host: new `shell-menu --files` command emitting tab-separated id/name lines for matching file scripts (no JSON parser needed in native code). - PowerScriptsContextMenu: WRL ClassicCom DLL (dllmain.cpp, dll.def) with a top-level command (GetState runs Host shell-menu, caches matches, hides when none), an IEnumExplorerCommand enumerator, and per-script items whose Invoke runs `Host run <id> --files <path>`. Host located next to the DLL. - AppxManifest.xml registers the verb (ItemType Type="*", runtime visibility), build.cmd compiles via cl.exe, register.ps1 builds+publishes Host+deploys+ registers the unsigned package (Add-AppxPackage -Register, Developer Mode). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
35ccc7658d |
PowerScripts: let users edit a file script's trigger extensions in Settings
Add a per-script "Trigger on file types" editor (a SettingsExpander with an editable extensions box + Apply) on the PowerScripts page for file scripts. Applying calls a new host command, set-extensions <id> --ext <.md .txt ...>, which rewrites the manifest's input.extensions via the shared serializer, then re-registers the Explorer right-click submenu (uninstall old verbs first so a changed extension leaves nothing stale). list --json now surfaces input.extensions so the box shows current values. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
b58b2f1a4c |
PowerScripts: locate the Host exe from in-repo dev builds
The Settings page lists scripts by shelling out to PowerScripts.Host.exe, but a dev build never copies the Host next to Settings, so the list was always empty even when the default scripts folder had scripts. Walk up from the Settings base directory and probe the Host project's bin output (Debug/Release) as a fallback, in addition to the existing next-to-exe and %LOCALAPPDATA% locations. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
0188c1ac69 |
PowerScripts: let users choose the scripts folder from Settings
Add a "Scripts folder" card to the PowerScripts page with Browse/Reset. The chosen path is persisted to the shared config.json, and Core's ResolveScriptsRoot now reads it (explicit > env > config > default) so every surface (Settings list, Explorer context menu, KBM run) honors the same folder. Selecting a folder reloads the list and re-registers the context-menu entries. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
11bda2709b |
PowerScripts: add ModuleTitle/Description strings to fix blank Dashboard
The Dashboard builds every module tile via resourceLoader.GetString of the module's ModuleTitle key, which throws COMException "NamedResource Not Found" for a missing key and aborts BuildModuleList, blanking the Home page. Add the PowerScripts.ModuleTitle/ModuleDescription resources. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
a618b2f2f9 |
PowerScripts: update README with implemented-surface table and e2e demo
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
3cdbca3fa6 |
PowerScripts: add Settings module page listing scripts + enable toggle
- Add ModuleType.PowerScripts and Enabled.PowerScripts plumbing (EnabledModules, ModuleHelper, ModuleGpoHelper, App.GetPage) - Add PowerScripts Settings nav item + page (NavigablePage) that lists installed scripts via 'PowerScripts.Host.exe list --json' and shows an enable toggle - Enable toggle wires the Explorer context menu directly (Host shell-install/ shell-uninstall), so the prototype is functional without a runner module DLL Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
be711d12bf |
PowerScripts: add 'PowerScript' action to Keyboard Manager editor
Adds a new 'PowerScript' action type in the KBM editor's mapping control. The picker lists system PowerScripts (via PowerScripts.Host.exe list --json) and saves an ordinary RunProgram mapping invoking 'Host.exe run <id>', so a hotkey can launch a PowerScript. Editor stays decoupled from PowerScripts assemblies by shelling out to the Host CLI. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
29ca6328f9 |
PowerScripts: add convert_md_to_txt + volume_up samples and context-menu registration
- Add two e2e sample scripts: convert_md_to_txt (file/.md) and volume_up (system) - Add Host shell-install/shell-uninstall: registry-driven 'PowerScript' cascading submenu under SystemFileAssociations\\<ext>\\shell, one sub-verb per matching script - Switch PowerScripts.Host TFM to net10.0-windows for registry access Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
af2c3c61cd |
[PowerScripts] Add prototype module: core, host CLI, samples, tests
Introduces a prototype of the PowerScripts module (write a script once, surface it across PowerToys). Includes: - PowerScripts.Core: manifest schema, validation, registry, executor - PowerScripts.Host: list/run/kbm CLI (shared invocation + KBM RunProgram mapping) - PowerScripts.Core.Tests: MSTest unit tests (9 passing) - Two sample scripts (system-snapshot, sha256-checksum) and README Surfaces prioritized: Explorer right-click + Keyboard Manager. Build is isolated from the repo (local Directory.Build.props/Packages/nuget.config) while prototyping; remove to adopt standard PowerToys build rules. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
a864d421fc |
[Keyboard Manager] Fix stuck modifiers and dropped key-to-text remaps (#48571)
## Summary Fixes stuck modifier keys and silently-dropped remaps on Keyboard Manager's **single key → text** path, and adds unit coverage (including a mockable injection-failure seam). ## What this changes 1. **Insert a dummy key event before releasing held modifiers.** Releasing a lone Win or Alt key-up otherwise triggers the Start Menu / menu bar. The dummy key absorbs it so the release is inert. The dummy + releases are only injected when a modifier is actually held. 2. **Accept `WM_SYSKEYDOWN` as well as `WM_KEYDOWN`.** While Alt is held the system delivers `WM_SYSKEYDOWN`, so the previous `WM_KEYDOWN`-only guard silently dropped the remap whenever Alt was down. 3. **Route `Helpers::SendTextInput` through `InputInterface`** instead of calling Win32 `SendInput` directly. Besides making the path mockable, this stops the existing unit tests from injecting real keystrokes into the OS during a test run. Text is still flushed per character to preserve the existing batching workaround. 4. **Never re-press released modifiers.** Once a modifier key-up is injected, `GetAsyncKeyState` reports it as up, so re-pressing risks leaving it stuck if the user let go during injection. Leaving it released is always safe. ## Testing - New `MockedInput` failure seam (`SetSendVirtualInputShouldFail`). - `RemappedKey_ShouldPassOriginalKeyThrough_WhenInjectionFails` — verifies the original key is passed through when injection fails (the core stuck-key behavior, previously untestable because the mock always succeeded). - `HandleSingleKeyToTextRemapEvent_ShouldFireAndReleaseAlt_WhenAltIsHeld` — covers fix #2 by asserting the remap still fires (and releases the held Alt) when the key arrives as `WM_SYSKEYDOWN`. - Full Keyboard Manager engine suite: **98/98 passing**, Release x64, against current `main`. This is one of a small set of related "stuck key" hardening fixes; each stands alone. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
3331bdf02a |
CmdPal: add support for compact mode (#48801)
This is a bear of a PR. Watch out. This PR adds support for compact mode to the command palette. In compact mode, the results of the command palette window are collapsed by default. And the only thing that is visible is the search bar. When the user types, the window is expanded only just enough to show the available results[^1] https://github.com/user-attachments/assets/fd11bbc9-1173-426f-8f44-b513baf2ac5f This is made possible by a fairly annoyingly substantial refactoring to how our windowing is done. Animating the size or bounds of an HWND on Windows is not fun. With pretty much any XAML application, you're going to get at least one frame of blackness when you resize your window. The trick then is to create an experience where it looks like your application is resizing, but the HWND never actually resizes. So the main bulk of this PR is actually just refactoring our window handling. Our `MainWindow` class now becomes a dummy holder of _some content_, and most of the main content is moved into the `CmdPalMainControl` class. `MainWindow`'s job then is to handle a transparent window that hosts some XAML content inside of it, and pretend that content is the real bounds of the window. We need to fake our NCHITTEST results, so that the edges of the XAML content act like they're the edge of the actual HWND. We need to hide our actual window frame and shadow, but then also re-create them in XAML around our content. Previously we've done work like this using a single full screen transparent window with XAML content inside of it. However that has the downside of not allowing the XAML content to be movable across different monitors. By faking out the NCHITTEST results, we allow users to resize and move the window using the normal user32 move size loop. Our HWND is also cropped (with SetWindowRgn to the bounds of the shadow around our XAML content. We need to include the shadow in the hit testable region, because if we don't, then the shadow will be visibly cropped on the edges. In compact mode, instead of centering our window in the middle of the monitor, the user can set a relative height where the search box opens on that monitor. This defaults to about 60% up from the bottom of the monitor, so that there's room for the results to expand downwards and feel centered within the screen. This position is a setting, so users can customize it to whatever they like. I've also added a developer only debug build only internal setting, which allows you to see the actual frame of our HWND. This makes it easier to visually debug where the bounds of the window are and understand a little bit more about the layout of our application. This setting and functionality is disabled in release builds. <img width="1334" height="1164" alt="cmdpal-compact-diagram" src="https://github.com/user-attachments/assets/cb1c273d-37cc-4cb7-8680-e1878aa20c9c" /> Closes #38423 [^1]: with some caveats: pages with details expand fully always. |
||
|
|
9ee0c7259b |
CmdPal: Dock Auto-hide (#48565)
This pull request introduces a new "Auto-hide" feature for the dock, allowing users to collapse the dock until they hover over its screen edge. The changes include updates to the settings model, UI, localization resources, and automated tests to support and verify this new functionality. **Show me:** https://github.com/user-attachments/assets/689625e8-9050-4a54-9c4b-9e303a3da63a **Conflicted?** "What if I have Taskbar and Dock on the same side and both with auto-hide turned on?" <img width="1437" height="264" alt="Screenshot 2026-06-14 144814" src="https://github.com/user-attachments/assets/bd037a11-0653-4b9a-bd21-625aca03b901" /> Closes #46239 --------- Co-authored-by: root <root@io.bbq> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
7e877558b9 |
Add powertoys-module-verification agent skill (#48717)
## Summary of the Pull Request
Adds a new **GitHub Copilot Agent Skill**,
`powertoys-module-verification`, under `.github/skills/`. It packages
the workflow, drive techniques, helper scripts, and per-module reference
data an AI agent uses to verify a single PowerToys module's
release-checklist items end-to-end (each checkbox → a structured PASS /
FAIL / BLOCKED verdict with evidence).
This is **docs/automation tooling only** — no product code, binaries, or
end-user strings are touched.
## PR Checklist
- [ ] Closes: #xxx
- [x] **Communication:** Internal tooling for release sign-off; happy to
adjust scope/placement based on review.
- [x] **Tests:** N/A — documentation/skill bundle only (no product code
paths). The 12 bundled `.ps1` helpers are agent utilities, not part of
the product build/test.
- [x] **Localization:** N/A — no end-user-facing strings.
- [x] **New binaries:** N/A — no binaries added.
- [x] **Dev docs:** This PR *is* developer-facing documentation/tooling.
## Detailed Description of the Pull Request / Additional comments
Layout follows the repo's Agent Skill guidelines
(`.github/instructions/agent-skills.instructions.md`) and matches the
existing skills under `.github/skills/`:
```
.github/skills/powertoys-module-verification/
├── SKILL.md # single entry doc (name/description/license frontmatter)
├── LICENSE.txt # Apache 2.0 (matches existing skills)
├── scripts/ # 12 PowerShell helper utilities used by the agent
└── references/
├── winapp-ui-testing.md # UIA-mechanics prerequisite doc
├── pre-flight.md / reporting-format.md / environment-setup.md / explorer-context-menu-flow.md
├── modules/ # per-module verification profiles
└── release-checklist/ # per-module checklists + index
```
Notes for reviewers:
- **`references/winapp-ui-testing.md`** is adapted from the
`winui-ui-testing` skill in
[microsoft/win-dev-skills](https://github.com/microsoft/win-dev-skills)
(MIT, © Microsoft Corporation and Contributors), with PowerToys-specific
edits. Provenance is recorded in the file header. Its skill frontmatter
was intentionally stripped so it is treated as a reference doc, not a
separately-discovered skill.
- **Checklist scope:** only modules already verified end-to-end (with a
sign-off report) are included for now — Environment Variables, File
Locksmith, Image Resizer, New+, Peek, PowerRename. Remaining modules'
checklists will be added as each is verified.
- No existing files are modified; this is purely additive under
`.github/skills/`.
## Validation Steps Performed
- Validated the bundle against the Agent Skill checklist in
`.github/instructions/agent-skills.instructions.md`: valid `name` (≤64
chars) + `description` + `license` frontmatter; `SKILL.md` body under
the 500-line guidance; single `SKILL.md`; `scripts/` + `references/`
resource buckets; all resource references use relative paths.
- Verified internal cross-references resolve after the migration (no
stale `helpers/`, `Winapp-SKILL.md`, or absolute-path tokens;
`src/modules/...` source citations left intact).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
||
|
|
386a16ff94 |
Revert "[CmdPal][Dock] Fix performance meter showing '???' after restart" (#48835)
Reverts microsoft/PowerToys#48682 I'm quite sure that OP did not build or test these changes, and they should not have merged. |
||
|
|
ada75d040a |
CmdPal: Hide uninstall option for system apps (#48804)
Command Palette currently shows the "Uninstall" context menu option for system apps like Windows Settings, Registry Editor, and Task Manager. Users can accidentally trigger uninstall on packages that should not be removable. This PR hides the uninstall option for system apps. It's probably not a perfect solution, but seemed to catch all I tried to test. Fixes #46826 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
086bd06eaf |
CmdPal: Accurate GPU usage in Dock (#48710)
Closes #48677. ## Root cause `GPUStats.GetData()` summed the cooked `Utilization Percentage` value of every `engtype=3D` GPU-Engine performance-counter instance for a given physical adapter. Each instance is a `(process, engine)` pair. Summing across processes for a single engine is correct (gives total engine utilization), but summing across **multiple 3D engines** on the same adapter compounds them and produces values >100% (the 104%/118% screenshots in the issue). The displayed value `sum / 100` therefore exceeded 1.0, and the chart fed the raw inflated `sum` directly. ## Fix Mirroring the bounded-counter approach used for CPU in #46381: 1. Bucket cooked values by `(physId, engineId)` rather than just `physId`. 2. Reduce per-adapter to the **maximum** engine utilization (what Task Manager surfaces as the overall GPU number). 3. Clamp the per-adapter value to `[0, 100]` before storing it as a 0–1 fraction in `Data.Usage` and pushing to the chart. 4. Defensive checks: skip `NaN` / `Infinity` / negative cooked values, and skip instances whose engine id can't be parsed. Co-authored-by: root <root@io.bbq> |
||
|
|
205ae601ce |
CmdPal: Fix bookmark dock bands disappearing on restart (#48092)
## Summary
Bookmarks pinned to the CmdPal dock disappear after a restart.
## Root Cause
`BookmarksCommandProvider` did not override `GetCommandItem(string id)`.
When `InitializeCommands` in `CommandProviderWrapper` processes pinned
dock band settings, the fallback path calls
`provider.GetCommandItem(commandId)`, which hit the base-class no-op
returning `null`. Any bookmark band that `GetDockBands()` failed to
return (due to a race, transient file error, or exception) was
irreversibly lost from the dock.
## Fix
Added `GetCommandItem` override to `BookmarksCommandProvider`. Given a
`"Bookmarks.Launch.{guid}"` ID, it:
1. Parses the GUID suffix
2. Looks up the `BookmarkData` in `_bookmarksManager` (under lock)
3. Constructs a `BookmarkListItem` (with `asBand: true`) and wraps it in
a `WrappedDockItem`
Uses `BookmarkTitle` (maps to `_bookmark.Name`, set synchronously in the
constructor) rather than `Title` (set asynchronously after
classification completes), matching the pattern used by
`AllAppsCommandProvider`, `SystemCommandExtensionProvider`, and others.
Fixes #47576
Co-authored-by: root <root@io.bbq>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
||
|
|
80f2b9b07d | CmdPal: Fix 1px gap between dock window and screen edge (#48091) | ||
|
|
5f1b496bf2 |
Shortcut Guide: Rename Win+Q to "Open Click to Do" for Copilot+ PCs (#48439)
Win+Q and Win+S were both labeled "Open search" in Shortcut Guide. On Copilot+ PCs, Win+Q launches Click to Do — not Search — so the duplicate label was misleading. ## Changes - `+WindowsNT.Shell.en-US.yml`: Renamed Win+Q entry from `Open search` → `Open Click to Do` with description `On Copilot+ PCs`; Win+S retains `Open search` ## 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 The Windows key shortcuts manifest had two entries with identical names (`Open search`) mapped to Win+Q and Win+S respectively. On Copilot+ PCs, Win+Q opens Click to Do, not Search. The Win+Q entry is corrected to `Open Click to Do` with a `On Copilot+ PCs` description to scope its applicability. ## Validation Steps Performed - Visually reviewed the YAML diff to confirm only the Win+Q entry name and description changed; Win+S entry is unchanged. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> |
||
|
|
a2218b3c3b |
[KeyboardManager] Fix sticky Ctrl caused by stale AltGr flag (#46672)
## Summary Fixes #46693 - The `static bool isAltRightKeyInvoked` flag in `HandleShortcutRemapEvent` is set when AltGr (RAlt+LCtrl) is pressed, but only reset inside Case 1's else branch — which requires a shortcut to be actively invoked (`isShortcutInvoked == true`) - If the user presses and releases AltGr when **no shortcut is active**, the flag stays `true` permanently across all future calls - Once stale, the flag blocks modifier key restoration and state resets at 13 locations throughout the function (lines 646, 670, 791, 800, 866, 880, 889, 907, 927, 978, 996), and causes LCtrl key-up events to `break` out of the handler loop (line 620-622) instead of being properly processed - This makes LCtrl permanently stuck for any shortcut remap that uses LCtrl as a modifier ## Fix Reset `isAltRightKeyInvoked` when `VK_RMENU` (Right Alt) is released, regardless of whether a shortcut is currently invoked. This is added as an `else if` right after the existing flag-set condition. ## Test plan - [ ] Configure a shortcut remap using LCtrl (e.g. LCtrl+Y → Backspace) - [ ] Press and release AltGr without triggering any shortcut - [ ] Use the LCtrl shortcut — verify Ctrl does not become stuck - [ ] Verify AltGr-based shortcuts still work correctly - [ ] Verify normal AltGr character input (e.g. AltGr+Q for @ on German layout) is unaffected --------- Co-authored-by: fluffyspace <fluffyspace@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
47335149f3 |
[Settings] Extract HandleNavigationFailure and test all null permutations (#48410)
## Summary Follow-up to #48409. That PR rewrote `ShellViewModel.Frame_NavigationFailed` to set `e.Handled = true` and log instead of re-throwing, but the unit tests it added only covered the `GetPageDisplayName` formatting helper. The actual contract that matters - "this handler must never throw, regardless of which fields on `NavigationFailedEventArgs` happen to be null" - was not directly testable because `NavigationFailedEventArgs` is a sealed WinRT type that cannot be constructed from MSTest. ## Change Tiny refactor: split the failure-handling logic out of `Frame_NavigationFailed` into a pure static `HandleNavigationFailure(Type sourcePageType, Exception exception)`. The WinUI-shaped handler now just sets `Handled = true` and delegates. This makes the "must not throw" invariant testable in isolation - no WinUI Frame, no Microsoft.UI.Xaml.Navigation types needed. ## Tests Added four new cases under `ShellViewModelTests`, exercising all four `(SourcePageType, Exception)` null permutations: | `sourcePageType` | `exception` | | - | - | | null | null | | typeof(...) | null | | null | new Exception(...) | | typeof(...) | new Exception(...) | Each test simply calls the helper and relies on MSTest's default "if it throws, the test fails" behavior. Any future change that re-introduces an unguarded dereference of `e.SourcePageType` or `e.Exception` will turn the corresponding test red. ## Validation All six tests pass: ``` Passed GetPageDisplayName_ReturnsFullName_ForKnownType Passed GetPageDisplayName_ReturnsPlaceholder_ForNullType Passed HandleNavigationFailure_DoesNotThrow_ForNullInputs Passed HandleNavigationFailure_DoesNotThrow_ForNullException Passed HandleNavigationFailure_DoesNotThrow_ForNullPageType Passed HandleNavigationFailure_DoesNotThrow_ForBothInputsPresent Total tests: 6, Passed: 6 ``` `PowerToys.Settings.csproj` and `Settings.UI.UnitTests.csproj` both build clean (Release|x64). ## Note This PR is stacked on top of #48409 (same branch lineage). If #48409 is merged first this PR will rebase cleanly to a small diff on `ShellViewModel.cs` + the additional test cases. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
5c63486dcb |
build(deps): bump actions/checkout from 6 to 7 (#48743)
Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/releases">actions/checkout's releases</a>.</em></p> <blockquote> <h2>v7.0.0</h2> <h2>What's Changed</h2> <ul> <li>block checking out fork pr for pull_request_target and workflow_run by <a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2454">actions/checkout#2454</a></li> <li>Bump actions/publish-immutable-action from 0.0.3 to 0.0.4 in the minor-actions-dependencies group across 1 directory by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/actions/checkout/pull/2458">actions/checkout#2458</a></li> <li>Bump flatted from 3.3.1 to 3.4.2 by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/actions/checkout/pull/2460">actions/checkout#2460</a></li> <li>Bump js-yaml from 4.1.0 to 4.2.0 by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/actions/checkout/pull/2461">actions/checkout#2461</a></li> <li>Bump <code>@actions/core</code> and <code>@actions/tool-cache</code> and Remove uuid by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/actions/checkout/pull/2459">actions/checkout#2459</a></li> <li>upgrade module to esm and update dependencies by <a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2463">actions/checkout#2463</a></li> <li>Bump the minor-npm-dependencies group across 1 directory with 3 updates by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/actions/checkout/pull/2462">actions/checkout#2462</a></li> <li>getting ready for checkout v7 release by <a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2464">actions/checkout#2464</a></li> <li>update error wording by <a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2467">actions/checkout#2467</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> made their first contribution in <a href="https://redirect.github.com/actions/checkout/pull/2454">actions/checkout#2454</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/checkout/compare/v6.0.3...v7.0.0">https://github.com/actions/checkout/compare/v6.0.3...v7.0.0</a></p> <h2>v6.0.3</h2> <h2>What's Changed</h2> <ul> <li>Update changelog by <a href="https://github.com/ericsciple"><code>@ericsciple</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2357">actions/checkout#2357</a></li> <li>fix: expand merge commit SHA regex and add SHA-256 test cases by <a href="https://github.com/yaananth"><code>@yaananth</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2414">actions/checkout#2414</a></li> <li>Fix checkout init for SHA-256 repositories by <a href="https://github.com/yaananth"><code>@yaananth</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2439">actions/checkout#2439</a></li> <li>Update changelog for v6.0.3 by <a href="https://github.com/yaananth"><code>@yaananth</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2446">actions/checkout#2446</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/yaananth"><code>@yaananth</code></a> made their first contribution in <a href="https://redirect.github.com/actions/checkout/pull/2414">actions/checkout#2414</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/checkout/compare/v6...v6.0.3">https://github.com/actions/checkout/compare/v6...v6.0.3</a></p> <h2>v6.0.2</h2> <h2>What's Changed</h2> <ul> <li>Add orchestration_id to git user-agent when ACTIONS_ORCHESTRATION_ID is set by <a href="https://github.com/TingluoHuang"><code>@TingluoHuang</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2355">actions/checkout#2355</a></li> <li>Fix tag handling: preserve annotations and explicit fetch-tags by <a href="https://github.com/ericsciple"><code>@ericsciple</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2356">actions/checkout#2356</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/checkout/compare/v6.0.1...v6.0.2">https://github.com/actions/checkout/compare/v6.0.1...v6.0.2</a></p> <h2>v6.0.1</h2> <h2>What's Changed</h2> <ul> <li>Update all references from v5 and v4 to v6 by <a href="https://github.com/ericsciple"><code>@ericsciple</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2314">actions/checkout#2314</a></li> <li>Add worktree support for persist-credentials includeIf by <a href="https://github.com/ericsciple"><code>@ericsciple</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2327">actions/checkout#2327</a></li> <li>Clarify v6 README by <a href="https://github.com/ericsciple"><code>@ericsciple</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2328">actions/checkout#2328</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/checkout/compare/v6...v6.0.1">https://github.com/actions/checkout/compare/v6...v6.0.1</a></p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/blob/main/CHANGELOG.md">actions/checkout's changelog</a>.</em></p> <blockquote> <h1>Changelog</h1> <h2>v7.0.0</h2> <ul> <li>Block checking out fork PR for pull_request_target and workflow_run by <a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2454">actions/checkout#2454</a></li> <li>Bump actions/publish-immutable-action from 0.0.3 to 0.0.4 in the minor-actions-dependencies group across 1 directory by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/actions/checkout/pull/2458">actions/checkout#2458</a></li> <li>Bump flatted from 3.3.1 to 3.4.2 by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/actions/checkout/pull/2460">actions/checkout#2460</a></li> <li>Bump js-yaml from 4.1.0 to 4.2.0 by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/actions/checkout/pull/2461">actions/checkout#2461</a></li> <li>Bump <code>@actions/core</code> and <code>@actions/tool-cache</code> and Remove uuid by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/actions/checkout/pull/2459">actions/checkout#2459</a></li> <li>upgrade module to esm and update dependencies by <a href="https://github.com/aiqiaoy"><code>@aiqiaoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2463">actions/checkout#2463</a></li> <li>Bump the minor-npm-dependencies group across 1 directory with 3 updates by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/actions/checkout/pull/2462">actions/checkout#2462</a></li> </ul> <h2>v6.0.3</h2> <ul> <li>Fix checkout init for SHA-256 repositories by <a href="https://github.com/yaananth"><code>@yaananth</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2439">actions/checkout#2439</a></li> <li>fix: expand merge commit SHA regex and add SHA-256 test cases by <a href="https://github.com/yaananth"><code>@yaananth</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2414">actions/checkout#2414</a></li> </ul> <h2>v6.0.2</h2> <ul> <li>Fix tag handling: preserve annotations and explicit fetch-tags by <a href="https://github.com/ericsciple"><code>@ericsciple</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2356">actions/checkout#2356</a></li> </ul> <h2>v6.0.1</h2> <ul> <li>Add worktree support for persist-credentials includeIf by <a href="https://github.com/ericsciple"><code>@ericsciple</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2327">actions/checkout#2327</a></li> </ul> <h2>v6.0.0</h2> <ul> <li>Persist creds to a separate file by <a href="https://github.com/ericsciple"><code>@ericsciple</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2286">actions/checkout#2286</a></li> <li>Update README to include Node.js 24 support details and requirements by <a href="https://github.com/salmanmkc"><code>@salmanmkc</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2248">actions/checkout#2248</a></li> </ul> <h2>v5.0.1</h2> <ul> <li>Port v6 cleanup to v5 by <a href="https://github.com/ericsciple"><code>@ericsciple</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2301">actions/checkout#2301</a></li> </ul> <h2>v5.0.0</h2> <ul> <li>Update actions checkout to use node 24 by <a href="https://github.com/salmanmkc"><code>@salmanmkc</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2226">actions/checkout#2226</a></li> </ul> <h2>v4.3.1</h2> <ul> <li>Port v6 cleanup to v4 by <a href="https://github.com/ericsciple"><code>@ericsciple</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2305">actions/checkout#2305</a></li> </ul> <h2>v4.3.0</h2> <ul> <li>docs: update README.md by <a href="https://github.com/motss"><code>@motss</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1971">actions/checkout#1971</a></li> <li>Add internal repos for checking out multiple repositories by <a href="https://github.com/mouismail"><code>@mouismail</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1977">actions/checkout#1977</a></li> <li>Documentation update - add recommended permissions to Readme by <a href="https://github.com/benwells"><code>@benwells</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2043">actions/checkout#2043</a></li> <li>Adjust positioning of user email note and permissions heading by <a href="https://github.com/joshmgross"><code>@joshmgross</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2044">actions/checkout#2044</a></li> <li>Update README.md by <a href="https://github.com/nebuk89"><code>@nebuk89</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2194">actions/checkout#2194</a></li> <li>Update CODEOWNERS for actions by <a href="https://github.com/TingluoHuang"><code>@TingluoHuang</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2224">actions/checkout#2224</a></li> <li>Update package dependencies by <a href="https://github.com/salmanmkc"><code>@salmanmkc</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/2236">actions/checkout#2236</a></li> </ul> <h2>v4.2.2</h2> <ul> <li><code>url-helper.ts</code> now leverages well-known environment variables by <a href="https://github.com/jww3"><code>@jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1941">actions/checkout#1941</a></li> <li>Expand unit test coverage for <code>isGhes</code> by <a href="https://github.com/jww3"><code>@jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1946">actions/checkout#1946</a></li> </ul> <h2>v4.2.1</h2> <ul> <li>Check out other refs/* by commit if provided, fall back to ref by <a href="https://github.com/orhantoy"><code>@orhantoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1924">actions/checkout#1924</a></li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
bf6dbd8865 |
feat(Advanced Paste): Add setting to show/hide AI paste section (#45242)
## Summary of the Pull Request Adds a new "Show AI paste section" setting to Advanced Paste that allows users to hide the AI paste input box from the Advanced Paste window. This addresses user requests for a cleaner UI when the AI paste feature is not needed or desired. ## PR Checklist - [x] Closes: #32967 - [ ] **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 - [ ] **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 This PR implements a new boolean setting `ShowAIPaste` that controls the visibility of the AI paste input box (PromptBox) in the Advanced Paste window. ### Changes Made **Settings UI Library:** - `src/settings-ui/Settings.UI.Library/AdvancedPasteProperties.cs` - Added `ShowAIPaste` property with JSON serialization **Settings UI:** - `src/settings-ui/Settings.UI/ViewModels/AdvancedPasteViewModel.cs` - Added view model property with change notification - `src/settings-ui/Settings.UI/SettingsXAML/Views/AdvancedPastePage.xaml` - Added checkbox setting in the UI Behavior section - `src/settings-ui/Settings.UI/Strings/en-us/Resources.resw` - Added localized strings for header and description **Advanced Paste Module:** - `src/modules/AdvancedPaste/AdvancedPaste/Helpers/IUserSettings.cs` - Added interface property - `src/modules/AdvancedPaste/AdvancedPaste/Helpers/UserSettings.cs` - Implemented setting loading from properties - `src/modules/AdvancedPaste/AdvancedPaste/ViewModels/OptionsViewModel.cs` - Added `ShowAIPasteSection` property combining user setting with GPO policy - `src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Pages/MainPage.xaml` - Bound PromptBox visibility to new property **Tests:** - `src/modules/AdvancedPaste/AdvancedPaste.UnitTests/Mocks/IntegrationTestUserSettings.cs` - Added mock property - `src/modules/AdvancedPaste/UITest-AdvancedPaste/TestFiles/settings.json` - Updated test settings file ### Behavior - Default value is `true` (AI paste section visible) to maintain backward compatibility - The setting respects GPO policy - if AI is disabled by GPO, the section will be hidden regardless of user preference - Setting is persisted in the Advanced Paste settings JSON file ## Validation Steps Performed - [x] Verified setting appears in Settings UI under Advanced Paste → UI Behavior - [x] Verified toggling the setting hides/shows the AI paste input box in the Advanced Paste window - [x] Verified setting persists after closing and reopening Settings - [x] Verified default value is `true` (visible) for new installations - [x] Verified existing unit tests pass with updated mock Fixes #32967 --------- Co-authored-by: Niels Laute <niels.laute@live.nl> |
||
|
|
3c942ae356 |
Quick Accent: Add ¡ and ¿ to ! and ? quick accent menu (#20618) (#48599)
<!-- 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 addresses issue #20618 by adding the inverted exclamation mark (**¡**) to the **!** key (`VK_1`) and the inverted question mark (**¿**) to the **?** key (`VK_SLASH_`) for both Spanish (`SP`) and Catalan (`CA`) character mappings in Quick Accent. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #20618 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments Adds the inverted punctuation marks `¡` (inverted exclamation mark) and `¿` (inverted question mark) to the character mappings of Spanish (`SP`) and Catalan (`CA`) languages in `CharacterMappings.cs`. - `LetterKey.VK_1` (`!`) now maps to `¡` - `LetterKey.VK_SLASH_` (`?`) now maps to `¿` This enables quick accent popups when pressing these respective keys, aligning with the expected behavior for these languages. <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed 1. Verified character mapping changes build successfully. 2. Verified that the PowerToys CI pipeline checks completed successfully. |
||
|
|
be4c3a1afa |
ZoomIt: add WebP/JPG screenshot encoder (#48818)
<!-- 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 Add webp and jpg support for screenshots. <!-- 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 |
||
|
|
968a7ac4b6 |
[Peek] Stop fail-fast in AppWindow.Closing path; reset cached preview-handler factories on release (#48564)
## Summary
Harden Peek's `AppWindow.Closing` path so a stale cached preview-handler
factory can't fail-fast the Peek process. Also clean up the matching
path in RegistryPreview.
## Background
Spotted while reading through Peek's `MainWindow` teardown sequence and
the `ShellPreviewHandlerPreviewer` cache for an unrelated review of how
Peek manages out-of-process preview-handler lifetimes.
The Peek `MainWindow` subscribes to `AppWindow.Closing`. The handler
doesn't actually close the window — it sets `args.Cancel = true` and
calls `Uninitialize()`, which in turn calls
`ShellPreviewHandlerPreviewer.ReleaseHandlerFactories()`.
`ReleaseHandlerFactories()` looked like this:
```csharp
public static void ReleaseHandlerFactories()
{
foreach (var factory in HandlerFactories.Values)
{
try { Marshal.FinalReleaseComObject(factory); } catch { }
}
}
```
Two problems:
1. The static `HandlerFactories` dictionary is never cleared. After
`FinalReleaseComObject`, the entries still point at separated RCWs. A
subsequent activation that races with this cleanup (or a second close in
the same process) can pick up the dead RCW from the cache.
2. The cached factory had `LockServer(true)` called on it when it was
first cached, but the matching `LockServer(false)` was never paired.
Any managed exception that escapes a WinRT event callback is projected
back to CFlat as a failed HRESULT and the CsWinRT dispatcher fail-fasts
the process. So a single `InvalidComObjectException` (HRESULT
0x80131527) thrown out of `Uninitialize()` is enough to terminate Peek.
## Changes
* **`ShellPreviewHandlerPreviewer.ReleaseHandlerFactories`** — snapshot
then clear the dictionary up front so that a subsequent call (or a
concurrent `LoadPreviewAsync`) can't pick up a stale RCW. Call
`LockServer(false)` before `FinalReleaseComObject` to mirror the
cache-time `LockServer(true)`. Both COM calls remain individually
wrapped because the RCW may already be unreachable during process
teardown.
* **`Peek.UI/MainWindow.xaml.cs` — `AppWindow_Closing`** — wrap the body
in try/catch + `Logger.LogError`. Any future exception in
`Uninitialize()` (or its callees) will now log instead of fail-fasting
the process.
* **`RegistryPreview/MainWindow.Events.cs` — `AppWindow_Closing`** —
same defensive try/catch, plus null-guard `jsonWindowPlacement` before
`SetNamedValue`. The placement dictionary can legitimately be null on
first run or after a corrupt placement file; previously that would NRE →
fail-fast.
## Risk
Low. The `ReleaseHandlerFactories` change matches the documented
`LockServer`/`FinalReleaseComObject` pairing and only widens the
lifetime window of the cache by `Clear()`-ing earlier; nothing in Peek
calls this method outside of teardown. The two try/catch wrappers
strictly add defense — the success path is unchanged.
## Validation
Spot-built locally; this repo's `dotnet restore` runtime-pack issue
(unrelated to this PR — same NU1102 pattern that's affecting other open
PRs) prevents a full `Build.cmd` here. The C++ side of Peek is
untouched.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
ADO:
https://microsoft.visualstudio.com/DefaultCollection/OS/_workitems/edit/58765809/
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Boliang Zhang <122517415+LegendaryBlair@users.noreply.github.com>
|
||
|
|
dd26d86580 |
[FancyZones] Fix stuck drag state and swallowed keys when a window is destroyed mid-drag (#48569)
## Summary Fixes a class of "stuck drag" bugs in FancyZones where closing or destroying a window **while it is being dragged** leaves FancyZones in a half-dragging state — zone overlays stay on screen and subsequent keystrokes (notably number keys) are swallowed or misrouted. ## What this changes - **Subscribe to and dispatch `EVENT_OBJECT_DESTROY`.** `FancyZonesApp` never subscribed to the destroy event, and the consumer's `WM_PRIV_WINDOWDESTROYED` branch could therefore never fire. The event is now registered and routed through `HandleWinHookEvent`. - **Abort the drag (without snapping) when the dragged window is destroyed.** On `WM_PRIV_WINDOWDESTROYED`, if the destroyed HWND is the one being dragged, call the new `WindowMouseSnap::Abort()` (tears down overlays/highlights/transparency) instead of `MoveSizeEnd()`, which would try to snap the now-dead HWND and corrupt zone state. Dragging state is then disabled. - **Always clear dragging state in `MoveSizeEnd()`**, even when the snapper was already null, so the state can't get stranded. - **Require Win+Ctrl+Alt to switch layouts while dragging.** Previously any digit switched layouts while `dragging` was true; if drag state was stuck this "stole" number keys from the focused app. This is the root-cause fix for the number-key-stealing symptom. - **Only swallow the bare Shift key during a drag**, not `Shift+<other>` combos, so real keystrokes are no longer eaten by an in-progress drag. ## Testing - Builds Release x64 (FancyZones) clean against current `main`. - Manually verified drag → close window mid-drag no longer leaves overlays up or steals number keys. (FancyZones has no unit-test harness for this path.) This is one of a small set of related "stuck key / stuck state" hardening fixes; each stands alone. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Muyuan Li <116717757+MuyuanMS@users.noreply.github.com> |
||
|
|
4771f15b6c |
[Runner] Harden centralized keyboard hook against stuck/ghost keys (#48570)
## Summary Hardens the runner's centralized keyboard hook against stuck and "ghost" key activations — cases where a hotkey action fires after the key was already released, or a pending timer fires after the hook was torn down. ## What this changes - **`vkCodePressed` is now `std::atomic<DWORD>`.** It is read/written from the low-level hook callback and from the timer/teardown paths; the plain `DWORD` was a data race. - **Revalidate the key is still physically held before firing a held-key timer.** The pressed-key timer callback now checks `GetAsyncKeyState(virtualKey) & 0x8000` before invoking the action, preventing ghost activations after the user has let go. - **Tag the injected dummy `0xFF` key-up** with `CENTRALIZED_KEYBOARD_HOOK_DONT_TRIGGER_FLAG` so the hook does not reprocess its own synthetic event. - **`Stop()` kills all pending pressed-key timers and resets `vkCodePressed` before unhooking**, so a timer can't fire a callback into a half-removed hook. ## Testing - Builds Release x64 (runner / `PowerToys.exe`) clean against current `main`. This is one of a small set of related "stuck key" hardening fixes; each stands alone. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
ed93fb585a |
Fix ZoomIt module description to eliminate Chinese translation repetition bug (#47370)
The ZoomIt module description contained `"snip screenshots"` — both words map to the same Chinese term (截图), causing the translation system to emit the garbled `"截图截图截图"` in the Chinese UI. ## Changes - **`src/settings-ui/Settings.UI/Strings/en-us/Resources.resw`**: Changed `"to snip screenshots to the clipboard or to a file"` → `"to copy screenshots to the clipboard or to a file"` in both `ZoomIt.ModuleDescription` and `Oobe_ZoomIt.Description` - `copy` has an unambiguous, distinct Chinese translation (`复制`) with no overlap with `截图` - Consistent with the existing `ZoomIt_SnipGroup.Description` which already uses `"Copy a selected area of the screen to the clipboard or to a file"` ## 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 - [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 Before (zh-CN rendered): > 还可以使用 Zoomlt 将屏幕**截图截图截图**剪贴板或文件中 After (expected zh-CN): > 还可以使用 ZoomIt 将截图**复制到**剪贴板或文件中 Root cause: `snip` (Windows snipping action) and `screenshots` are both translated to `截图` by the localization pipeline, producing triple repetition. Replacing `snip` with `copy` — already used in the adjacent Snip group description — resolves the collision without changing the functional meaning. ## Validation Steps Performed - Verified both string keys (`ZoomIt.ModuleDescription`, `Oobe_ZoomIt.Description`) updated in `en-us/Resources.resw` - Confirmed no other occurrences of `"snip screenshots"` remain in the file --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: MuyuanMS <116717757+MuyuanMS@users.noreply.github.com> |
||
|
|
c3bec3935a |
Docs cleanup (#48813)
## Summary Removes outdated/unused documentation and asset files: - **`doc/unofficialInstallMethods.md`** — removed. - **`doc/planning/`** — removed entire folder (`awake.md`, `FancyZonesBacklog.md`, `PowerToysBacklog.md`, `ShortcutGuideBacklog.md`). - **`doc/images/icons/Video Conference Mute.png`** — removed (unused module icon, not referenced anywhere in the repo). Verified there are no remaining references to any of the removed files across tracked sources (checked literal and `%20`-encoded paths). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
334d1c8054 |
Validate cached installer filename from UpdateState.json in the updater (#48741)
## Summary of the Pull Request `PowerToys.Update` reads `downloadedInstallerFilename` from the persisted `UpdateState.json` and combines it with the `Updates` folder to locate the installer to run. If that cached state is stale, corrupted, or otherwise unexpected, the stored value could contain path separators or an absolute path, which would make the updater look for the installer outside the `Updates` folder. This PR validates that the cached value is a plain filename and that the resolved path stays inside the `Updates` folder before using it; otherwise the update is treated as unavailable. The normal update flow (a bare asset filename produced by the download step) is unaffected. ## PR Checklist - [ ] **Communication:** I've discussed this with core contributors already. - [x] **Tests:** Added/updated and all pass - [x] **Localization:** No end-user-facing strings added - [x] **Dev docs:** N/A - [x] **New binaries:** None ## Detailed Description of the Pull Request / Additional comments - The filename check is factored into an inline helper `updating::IsSafeDownloadedInstallerFilename` in `src/common/updating/updateLifecycle.h` (next to the other inline update helpers) so it can be unit-tested without a project reference. - `ObtainInstaller` in `src/Update/PowerToys.Update.cpp` now calls that helper and additionally confirms, via `weakly_canonical`, that the resolved installer path's parent is the `Updates` directory. - No behavior change for normal installer filenames, so the regular update flow does not regress. ## Validation Steps Performed - Added `IsSafeDownloadedInstallerFilenameTests` to `Updating.UnitTests` covering normal filenames, empty values, parent-directory components, nested path components, and absolute/drive-relative/UNC paths. - Built `Updating.UnitTests` (Debug x64): 0 warnings, 0 errors. - Ran the full `Updating.UnitTests` suite: 36/36 passed (30 existing + 6 new). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
5c16c97db5 |
[Settings] Fix FancyZones page scroll bounce at Excluded apps (#47937)
## Summary Fixes #25353 — the FancyZones Settings page bounces / jumps when the user scrolls down to the bottom (the **Excluded apps** expander). Several closed dupes report the same behavior: #31500, #34259, #30164, #45173, #32099, #32361. ## Root cause The Excluded-apps `TextBox` (lines 283-305 of `FancyZonesPage.xaml`) forced its own inner `ScrollViewer` to be permanently enabled with a visible scrollbar, nested inside the page-level `ScrollViewer` provided by `SettingsPageControl`: ```xml ScrollViewer.IsVerticalRailEnabled="True" ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollMode="Enabled" ``` The expander is `IsExpanded="True"` and sits at the very bottom of the page, so when you wheel-scroll down the page the pointer ends up over the TextBox. The TextBox''s inner scroller intercepts the wheel events; when it has nothing left to scroll the event bubbles back to the outer page scroller, which tries to over-scroll past content end. The result is the bounce/jump visible in the videos on the issue. The unbounded `MinHeight="160"` (with no `MaxHeight`) made it worse, because the box can grow as users type, triggering layout re-measures during scrolling. ## Fix Minimal change to the same TextBox: - Drop `ScrollViewer.IsVerticalRailEnabled` and `ScrollViewer.VerticalScrollMode` — `AcceptsReturn="True"` already wires up the inner scroller correctly. - Change `ScrollViewer.VerticalScrollBarVisibility` from `Visible` to `Auto`, so the inner scroller only competes with the outer one when there is actual overflow to scroll. - Add `MaxHeight="320"` so the box cannot keep growing as the user types. ## Validation - Builds clean (`tools\build\build.cmd` from `src\settings-ui\Settings.UI`, arm64 Debug, exit 0, 0 errors). - The same nested-scroller pattern exists on 9 other Settings pages (AlwaysOnTop, GrabAndMove, MouseUtils, MouseWithoutBorders, PowerAccent, PowerLauncher, ShortcutGuide). Keeping this PR atomic to the page called out in #25353; happy to follow up with a sibling PR for those if reviewers want them in the same pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
a255ece641 |
[File Locksmith] Fix crash (0xc000027b) when a listed process's image file no longer exists (#48719)
## Summary of the Pull Request `PidToIconConverter.Convert` called `Icon.ExtractAssociatedIcon(path)` without a guard. When a running process's image path is non-empty but the file no longer exists on disk, the call throws `FileNotFoundException`. The converter runs per-row while the process `ListView` virtualizes, so the exception reached `App_UnhandledException` (which only logs and never sets `e.Handled = true`) and WinUI 3 fast-failed the whole app (`0xc000027b`). This is routinely triggered by self-updating software that deletes its old versioned directory while the old process keeps running — e.g. Windows Defender (`SenseAPZ`, `MsMpEng`, `MpDefenderCoreService` under versioned `...\Platform\<ver>\` / `...\DataCollection\<ver>\` paths). Right-clicking a drive root enumerates every process and reliably includes such a stale-path process, so the crash is easy to hit in normal use. The fix wraps the icon extraction in a try/catch and falls through to the existing placeholder `BitmapImage`, logging a warning — mirroring the exception handling already present in `MainViewModel.WatchProcess`. ## PR Checklist - [x] Closes: #48693 - [ ] **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 — no existing test harness covers this WinUI converter path; validated manually (steps below) - [x] **Localization:** All end-user-facing strings can be localized — n/a; the only new string is a developer log warning, not end-user UI - [x] **Dev docs:** Added/updated — n/a - [x] **New binaries:** Added on the required places — n/a; no new binaries ## Detailed Description of the Pull Request / Additional comments `src/modules/FileLocksmith/FileLocksmithUI/Converters/PidToIconConverter.cs`: ```csharp if (!string.IsNullOrEmpty(y)) { try { icon = Icon.ExtractAssociatedIcon(y); } catch (Exception ex) { // The process image path can be non-empty but no longer exist on disk // (e.g. self-updating software that deletes its old versioned directory while // the old process is still running). ExtractAssociatedIcon then throws and, // because this converter runs per-row during ListView virtualization, the // exception would otherwise reach App_UnhandledException and fast-fail the app. // Fall through to the placeholder icon instead of crashing. Logger.LogWarning($"Couldn't extract the icon for '{y}'. {ex}"); } } ``` (+ `using ManagedCommon;` — already a project reference; `Logger` is used identically in `App.xaml.cs`.) Scope note: this keeps to the targeted converter guard. I deliberately did **not** also blanket-set `e.Handled = true` in `App_UnhandledException`, since that would mask unrelated genuine crashes; the converter guard fully addresses this crash. ## Validation Steps Performed 1. Reproduced on the installed 0.100 build: right-click `C:\` → **Unlock with File Locksmith** → scroll the list → crash (`0xc000027b`, faulting module `Microsoft.UI.Xaml.dll`; the FileLocksmith log shows an unhandled `FileNotFoundException` for `...\SenseAPZ.exe` in `MainPage...ProcessBindings` / `PidToIconConverter`). Reproduced twice. 2. Built `FileLocksmithUI` (x64/Release) with the fix — 0 warnings / 0 errors. 3. Ran the produced exe on `C:\` and scrolled ~40× over the same list (which includes the stale `SenseAPZ` row): - No crash; the process stayed alive and responsive. - The log shows the new warning firing for the exact `...\SenseAPZ.exe` path, confirming the catch branch executed on the previously-fatal row. - 0 unhandled exceptions in the session. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
106c970c8c |
Fix full rebuild: upgrade CalculatorEngineCommon to C++20 coroutines (#48790)
Remove _SILENCE_EXPERIMENTAL_COROUTINE_DEPRECATION_WARNINGS and upgrade LanguageStandard from stdcpp17 to stdcpp20 so that <coroutine> is used instead of the removed <experimental/coroutine> header on VS 2026. <img width="946" height="348" alt="image" src="https://github.com/user-attachments/assets/53392fd8-1a81-4852-9913-d84575f2f3e1" /> was part of https://github.com/microsoft/PowerToys/pull/48102 prior <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [ ] Closes: #xxx <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
ff8c1dbf85 |
Dock: Add a teachingtip to docks while pinning (#48726)
When you're pinning something to the dock with the dialog, I have _no_ idea what display is 1,2,3,4. That's meaningless to me. This attempts to resolve that by adding a teachingtip to each dock while pinning. When we open that pin to dock dialog, we'll display the teachingtips, and dismiss them when the dialog is closed. That way folks have at least some indication of where each display is when pinning. |
||
|
|
cd7465e22a |
CmdPal: Refactor TopLevelCommandManager to use IExtensionService implementations (#48417)
## Summary The `TopLevelCommandManager` handles **alot.** And by "alot" I mean too much. In preparation for future types of extensions, this PR attempts to pull out the methods for loading/managing extensions to individual `IExtensionService`s. These `ExtensionService`s will be injected the `TopLevelCommandManager` via dependency injection. It will iterate through them asking them to load their extensions. During that process, they will surface `ICommandProvider`s back to the `TopLevelCommandManager` for display in Command Palette. Currently, there are two types of `IExtensionService`s: `BuiltInExtensionService` and `WinRTExtensionService`. - The `BuiltInExtensionService` receives all `ICommandProvider`s registered with DI. - The `WinRTExtensionService` manages out-of-process WinRT AppExtension providers. ## Additional Changes - **Circular DI dependency resolved**: `BuiltInsCommandProvider` no longer depends on `IRootPageService`. Previously, it required the `IRootPageService` solely for the dock command to open Command Palette (using the RootPage as its command.) Now, it uses a new `GoHomeDockCommand` which returns `CommandResult.GoHome()` with the existing `onBeforeShowConfirmation` callback to show the palette at the dock button position. Also, fixes #48643 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
502dc40aa4 |
[Shortcut Guide] Prevent overlay crash on section navigation (#48448) (#48481)
## Summary of the Pull Request Shortcut Guide overlay crashes and closes when navigating between sidebar sections (e.g. clicking PowerToys, then clicking the Windows icon to come back). Repro and crash logs in #48448. Crash logs in #48441 show the same propagation path plus a follow-up access violation in coreclr, indicating exceptions that escape local catches. This PR fixes the immediate navigation race and adds broader crash hardening so future exceptions on the UI/background threads are logged instead of tearing down the overlay. ### Navigation-race fix (commit 1) Root cause: `WindowSelector_SelectionChanged` calls `App.TaskBarWindow.Activate()` and then `SetWindowPosition()` synchronously. `Activate()` runs a reentrant `Window_Activated` → `BringToFront` → `TaskbarWindow.Activated` chain that can leave `App.TaskBarWindow.AppWindow` momentarily null, so `SetWindowPosition` throws `NullReferenceException`. Because the initial `SelectedItem = MenuItems[0]` is set from `SetNavItems`, the NRE bubbles up into `InitializeNavItemsAsync`'s catch block — which sets `_closeType = "InitializationFailed"` and closes the window. That matches both user-visible symptoms: the overlay "flashes and disappears" (#48441) on open and "closes when clicking the Windows icon" (#48448). Edits in `src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs`: - **`SetWindowPosition`**: null-guard `App.TaskBarWindow?.AppWindow` and skip the taskbar-overlap height adjustment when it is not currently observable. Wrap the body in `try`/`catch` with `Logger.LogError` so any future positioning hiccup keeps the previous layout instead of taking down the overlay. - **`WindowSelector_SelectionChanged`**: null-guard `App.TaskBarWindow?.Hide()` / `Activate()` and wrap the body in `try`/`catch`. This breaks the propagation path that lets a navigation exception reach `InitializeNavItemsAsync`'s "fatal init failure" branch. ### Crash hardening (commit 2) Additional defensive changes to cover other unguarded paths surfaced while reviewing #48441: - **`App.xaml.cs`**: register `App.UnhandledException`, `AppDomain.CurrentDomain.UnhandledException`, and `TaskScheduler.UnobservedTaskException` so a stray exception (e.g. an IO failure during a fire-and-forget UI handler, or a background `Task` fault) gets logged instead of tearing the process down with an access violation in coreclr. Mirrors what Peek, AdvancedPaste, and CmdPal already do. - **`App.OnLaunched`**: wrap the launch sequence in `try`/`catch` and exit cleanly with an error log on failure (`LoadData` / `MainWindow` / `TaskbarWindow` ctors and `Activate` are all reachable failure points). - **`App.LoadData`**: broaden the `Pinned.json` deserialize catch to also handle `IOException` / `UnauthorizedAccessException`, and guard the round-trip `SaveSettings` call as best-effort with a warning log. - **`PinnedShortcutsHelper.Save`**: catch `IOException` / `UnauthorizedAccessException` / `JsonException` and log; `Pin` / `Unpin` runs from a synchronous UI handler so an unguarded `File.WriteAllText` would tear down the overlay on any disk hiccup. - **`TaskbarWindow.UpdateTasklistButtons`**: move the `AppWindow.Move` calls inside the existing `try` block, null-guard `App.MainWindow?.AppWindow` up front, and wrap the whole body so the method (which runs from the ctor and from `Activated`) cannot tear the overlay down when `MainWindow` is in a transient state. ## PR Checklist - [x] Closes: #48448 - [x] Likely also fixes: #48441 - [x] **Communication:** Defensive fix to known crash paths; no API change. - [ ] **Tests:** No automated tests added — the failures are reentrancy / timing races that are hard to deterministically trigger in CI. Validated with a synthetic repro (see below). - [x] **Localization:** N/A — only logger strings. - [x] **Dev docs:** N/A - [x] **New binaries:** N/A ## Detailed Description of the Pull Request / Additional comments The fix is intentionally defensive (rather than restructuring the reentrant activation flow) because the legacy taskbar UIA enumeration (`TasklistPositions.GetButtons`) on Windows 10 is what most reliably widens the race window and is out of scope to redesign for a hotfix. ## Validation Steps Performed - Build: `tools\build\build.cmd` from `src\modules\ShortcutGuide\ShortcutGuide.Ui` — exit 0, errors log empty for both commits. - Synthetic repro: temporarily injected `throw new NullReferenceException()` at the top of `SetWindowPosition` to exercise the exact propagation path the reporter's log shows (`SetWindowPosition` → `SelectionChanged` → `set_SelectedItem` → `InitializeNavItemsAsync.catch` → `Close("InitializationFailed")`). - Before fix: overlay flashes and closes, log shows `Failed to initialize navigation items.` with the NRE. - After fix: overlay stays open, page navigates, log shows `Failed to set Shortcut Guide window position; keeping previous layout.` from the new `catch`. - Did not reproduce the live race on a Win11 dev box; the reporter's repro is Windows 10 19045 / Microsoft Store install where the legacy taskbar UIA timing makes the reentrant chain more likely to expose the null. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |