2025-12-03 03:59:46 -06:00
|
|
|
<Solution>
|
|
|
|
|
<Configurations>
|
|
|
|
|
<Platform Name="ARM64" />
|
|
|
|
|
<Platform Name="x64" />
|
|
|
|
|
</Configurations>
|
|
|
|
|
<Folder Name="/common/">
|
|
|
|
|
<Project Path="src/common/CalculatorEngineCommon/CalculatorEngineCommon.vcxproj" Id="2cf78cf7-8feb-4be1-9591-55fa25b48fc6" />
|
|
|
|
|
<Project Path="src/common/Common.Search/Common.Search.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
[UITests] New framework around WinApp CLI, no WinAppDriver or Selenium. (#48467)
# Add winappcli-based UI test harness (no WinAppDriver / Selenium)
## Summary
Introduces a new UI test harness — `Microsoft.PowerToys.UITest.Next` —
that drives PowerToys
modules through Microsoft's
[winappcli](https://github.com/microsoft/WinAppCli) (UI Automation
CLI) instead of WinAppDriver + Selenium. Engine is a single executable
shelled out from
C#; no third-party NuGet packages, no driver process, no Appium server.
Adds two real consumers:
a full ColorPicker end-to-end scenario and a Settings shell navigation
smoke test.
This is opt-in and additive — the existing `UITestAutomation` library
and the
WinAppDriver-based test projects are untouched. Both can coexist while
we evaluate the new
harness.
Inspired in part by
[#48414](https://github.com/microsoft/PowerToys/pull/48414), which lands
the same architectural bet (winappcli, AutomationId selectors, no
WinAppDriver) at a smaller
scope. This PR generalizes it into a reusable library.
## Why
WinAppDriver + Selenium is a legacy pre-agentic solution that is no
longer actively maintained. It's unreliable, heavyweight, and slow. To
achieve 100% UI test coverage, we should leverage modern, reliable
solutions, and WinApp CLI is a strong candidate.
## What's in this PR
### Harness library —
[`src/common/UITestAutomation.Next/`](src/common/UITestAutomation.Next/)
| File | Purpose |
|---|---|
| [`WinappCli.cs`](src/common/UITestAutomation.Next/WinappCli.cs) |
Process wrapper around `winapp.exe`. `Invoke` / `InvokeAssertSuccess` /
`InvokeJson` / `IsAvailable` / `TryResolveExecutable`. `Result` carries
the args and emits `DescribeFailure()` like `winapp ui invoke X -w 12345
-> exit 1; stderr: ...` |
| [`Session.cs`](src/common/UITestAutomation.Next/Session.cs) | Test
session, scoped by either HWND (`-w`) or process (`-a`) via
`TargetScope`. `Find<T>` / `FindAll<T>` / `Inspect` / `Screenshot` /
`SendKeys`. `Session.FromProcess(...)` factory for the
single-window-per-process case |
|
[`SessionHelper.cs`](src/common/UITestAutomation.Next/SessionHelper.cs)
| Owns the launch + window-readiness flow. Static `EnsureRunning(scope,
timeout)` returns whether the call had to launch (so cleanup only kills
what we started). Uses `UseShellExecute=true` so child handles don't
keep MSTest hanging |
| [`UITestBase.cs`](src/common/UITestAutomation.Next/UITestBase.cs) |
MSTest base class. Pre-flights `WinappCli.IsAvailable()` once per
process and fails fast with the install hint if `winapp.exe` isn't on
PATH |
| [`Element/*.cs`](src/common/UITestAutomation.Next/Element/) |
`Element`, `Button`, `ToggleSwitch`, `TextBox`, `NavigationViewItem`,
`Window`. `Click` / `MouseClick` / `Focus` / `GetProperty` / `GetValue`
/ `HelpText` / `WaitForProperty` / `WaitForGone` plus coords
(`X`/`Y`/`Width`/`Height`) |
| [`By.cs`](src/common/UITestAutomation.Next/By.cs) | `By.Name` /
`By.AccessibilityId` / `By.Id` / `By.Slug` |
| [`Windows.cs`](src/common/UITestAutomation.Next/Windows.cs) |
`WindowsFinder.ListAll` / `ListByApp` / `WaitForWindowByApp` /
`WaitForWindowByProcess`. Notes the winappcli bug where unfiltered
`list-windows` drops untitled windows |
|
[`WindowControl.cs`](src/common/UITestAutomation.Next/WindowControl.cs)
| Tolerant Win32 helpers — `TryCloseByApp` / `TryFocusByApp` /
`SafeCloseAndFocus` / `TryKillProcess` — for `finally` blocks |
|
[`KeyboardHelper.cs`](src/common/UITestAutomation.Next/KeyboardHelper.cs)
| Hybrid `keybd_event` + `SendKeys.SendWait` chord sender — required for
global PowerToys hotkeys |
| [`MouseHelper.cs`](src/common/UITestAutomation.Next/MouseHelper.cs) |
`MoveTo` / `LeftClick` / `RightClick` / `LeftClickAt` Win32 wrappers |
|
[`ClipboardHelper.cs`](src/common/UITestAutomation.Next/ClipboardHelper.cs)
| STA-thread `Clipboard` access with `WaitForText` |
|
[`ModuleConfigData.cs`](src/common/UITestAutomation.Next/ModuleConfigData.cs)
| `PowerToysModule` enum + path/process-name resolution |
### Tests
**[`src/modules/colorPicker/ColorPicker.UITests/`](src/modules/colorPicker/ColorPicker.UITests/)**
— replaces the previous empty `UITest-ColorPicker` stub. One test,
[`ColorPickerEndToEndTests.NavigateReadShortcutActivateAndCapture`](src/modules/colorPicker/ColorPicker.UITests/ColorPickerEndToEndTests.cs),
drives the full E2E:
1. Navigate to the Color Picker page via the dashboard utilities stack
2. Toggle the module OFF, verify `PowerToys.ColorPickerUI` exits; toggle
ON, verify it respawns
3. Read the activation shortcut from the page's `ShortcutControl`
(`EditButton.HelpText`)
4. Clear clipboard, park cursor, send the chord
5. Wait for the picker overlay window
6. Read the displayed HEX from a hidden XAML automation peer (see below)
7. Left-click to capture; assert the clipboard value matches the peer's
HEX
8. Wait for the editor window and assert the captured color appears in
its tree
**[`src/settings-ui/Settings.UITests/`](src/settings-ui/Settings.UITests/)**
— `SettingsNavigationSmokeTests.NavigationItem_NavigatesWithoutCrashing`
is one `[TestMethod]` parameterized with `[DynamicData]`, producing 31
discrete results — one per `NavigationViewItem` in
[`ShellPage.xaml`](src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml).
For each item: navigate, settle 250ms, assert `PowerToys.Settings` is
still alive. Catches FailFast regressions in
`ShellViewModel.Frame_NavigationFailed` that pure-logic unit tests can't
reach (the failure path needs a `NavigationFailedEventArgs` which is a
sealed WinRT projection).
### Product change
**[`src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml`](src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml)**
— adds a hidden `TextBlock` automation peer:
```xml
<TextBlock
x:Name="ColorHexAutomationPeer"
AutomationProperties.AutomationId="ColorHexAutomationPeer"
IsHitTestVisible="False"
Opacity="0"
Text="{Binding ColorText}" />
```
The visible `ColorTextBlock` has `AutomationProperties.Name="{Binding
ColorName}"`, which masks the HEX value in the UIA tree (you see "White"
instead of `#FFFFFF`). This zero-impact peer mirrors `ColorText` so
tests can read the actually-displayed HEX. `Opacity=0` +
`IsHitTestVisible=False` keep it out of the visual layout and out of
accessibility focus.
### Project wiring
- [`PowerToys.slnx`](PowerToys.slnx) — registers `UITestAutomation.Next`
under `/common/`, `ColorPicker.UITests` under
`/modules/colorpicker/Tests/`, and `Settings.UITests` under
`/settings-ui/Tests/`. Original `UITest-ColorPicker` stub csproj
removed.
-
[`.github/actions/spell-check/expect.txt`](.github/actions/spell-check/expect.txt)
— adds `winapp` / `winappcli`.
### Not in this PR
- No pipeline changes. `winapp.exe` is expected to be pre-staged on the
test agent image. If it's missing, `UITestBase` fails the first test
with the install hint (`winget install Microsoft.winappcli`) rather than
producing 30 opaque per-test errors.
- No changes to the legacy `UITestAutomation` library or any of the
existing `*.UITests` projects.
## Validation
- All three projects build clean on `x64|Debug` (empty
`build.<config>.<plat>.errors.log`):
- `src/common/UITestAutomation.Next/`
- `src/modules/colorPicker/ColorPicker.UITests/`
- `src/settings-ui/Settings.UITests/`
- Both tests run in Test Explorer / `dotnet test` via
Microsoft.Testing.Platform (already enabled repo-wide in
`Directory.Build.props`).
- Local runs: ColorPicker E2E green; Settings smoke green across all 31
nav items.
- `winapp 0.3.2` from `winget install Microsoft.winappcli`.
## Notes for reviewers
- **`UseShellExecute = true`** in `SessionHelper.EnsureRunning` is
intentional — `false` makes child processes inherit the test host's
stdin/stdout/stderr handles, which keeps MTP/Test Explorer marking the
run as "in progress" until the spawned PowerToys exits.
- **Process-scope (`-a`) targeting** in the Settings smoke test handles
single-instance handoff: the EXE you launch may exit with code 0
immediately after signalling an existing owner, so the alive check uses
`Process.GetProcessesByName` rather than the launcher PID.
- **AutomationId-only selectors** in the Settings smoke list keep the
test localization-independent. Parent groups have
`SelectsOnInvoked="False"` and only expand on click — `Element.Click`
tries `InvokePattern → TogglePattern → SelectionItemPattern →
ExpandCollapsePattern` so the same call works for both leaves and
groups.
- **Untitled-window discovery**: filtered `winapp ui list-windows -a
<name>` returns windows that the unfiltered call drops (e.g. ColorPicker
editor). `WindowsFinder.ListByApp` uses the filtered form. Reported
upstream.
## Before Merge
- Add the `winappcli` install step to the UI-test pipeline.
2026-07-07 22:58:08 -07:00
|
|
|
<Project Path="src/common/Common.UI.Controls/Common.UI.Controls.csproj">
|
2025-12-03 03:59:46 -06:00
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
[UITests] New framework around WinApp CLI, no WinAppDriver or Selenium. (#48467)
# Add winappcli-based UI test harness (no WinAppDriver / Selenium)
## Summary
Introduces a new UI test harness — `Microsoft.PowerToys.UITest.Next` —
that drives PowerToys
modules through Microsoft's
[winappcli](https://github.com/microsoft/WinAppCli) (UI Automation
CLI) instead of WinAppDriver + Selenium. Engine is a single executable
shelled out from
C#; no third-party NuGet packages, no driver process, no Appium server.
Adds two real consumers:
a full ColorPicker end-to-end scenario and a Settings shell navigation
smoke test.
This is opt-in and additive — the existing `UITestAutomation` library
and the
WinAppDriver-based test projects are untouched. Both can coexist while
we evaluate the new
harness.
Inspired in part by
[#48414](https://github.com/microsoft/PowerToys/pull/48414), which lands
the same architectural bet (winappcli, AutomationId selectors, no
WinAppDriver) at a smaller
scope. This PR generalizes it into a reusable library.
## Why
WinAppDriver + Selenium is a legacy pre-agentic solution that is no
longer actively maintained. It's unreliable, heavyweight, and slow. To
achieve 100% UI test coverage, we should leverage modern, reliable
solutions, and WinApp CLI is a strong candidate.
## What's in this PR
### Harness library —
[`src/common/UITestAutomation.Next/`](src/common/UITestAutomation.Next/)
| File | Purpose |
|---|---|
| [`WinappCli.cs`](src/common/UITestAutomation.Next/WinappCli.cs) |
Process wrapper around `winapp.exe`. `Invoke` / `InvokeAssertSuccess` /
`InvokeJson` / `IsAvailable` / `TryResolveExecutable`. `Result` carries
the args and emits `DescribeFailure()` like `winapp ui invoke X -w 12345
-> exit 1; stderr: ...` |
| [`Session.cs`](src/common/UITestAutomation.Next/Session.cs) | Test
session, scoped by either HWND (`-w`) or process (`-a`) via
`TargetScope`. `Find<T>` / `FindAll<T>` / `Inspect` / `Screenshot` /
`SendKeys`. `Session.FromProcess(...)` factory for the
single-window-per-process case |
|
[`SessionHelper.cs`](src/common/UITestAutomation.Next/SessionHelper.cs)
| Owns the launch + window-readiness flow. Static `EnsureRunning(scope,
timeout)` returns whether the call had to launch (so cleanup only kills
what we started). Uses `UseShellExecute=true` so child handles don't
keep MSTest hanging |
| [`UITestBase.cs`](src/common/UITestAutomation.Next/UITestBase.cs) |
MSTest base class. Pre-flights `WinappCli.IsAvailable()` once per
process and fails fast with the install hint if `winapp.exe` isn't on
PATH |
| [`Element/*.cs`](src/common/UITestAutomation.Next/Element/) |
`Element`, `Button`, `ToggleSwitch`, `TextBox`, `NavigationViewItem`,
`Window`. `Click` / `MouseClick` / `Focus` / `GetProperty` / `GetValue`
/ `HelpText` / `WaitForProperty` / `WaitForGone` plus coords
(`X`/`Y`/`Width`/`Height`) |
| [`By.cs`](src/common/UITestAutomation.Next/By.cs) | `By.Name` /
`By.AccessibilityId` / `By.Id` / `By.Slug` |
| [`Windows.cs`](src/common/UITestAutomation.Next/Windows.cs) |
`WindowsFinder.ListAll` / `ListByApp` / `WaitForWindowByApp` /
`WaitForWindowByProcess`. Notes the winappcli bug where unfiltered
`list-windows` drops untitled windows |
|
[`WindowControl.cs`](src/common/UITestAutomation.Next/WindowControl.cs)
| Tolerant Win32 helpers — `TryCloseByApp` / `TryFocusByApp` /
`SafeCloseAndFocus` / `TryKillProcess` — for `finally` blocks |
|
[`KeyboardHelper.cs`](src/common/UITestAutomation.Next/KeyboardHelper.cs)
| Hybrid `keybd_event` + `SendKeys.SendWait` chord sender — required for
global PowerToys hotkeys |
| [`MouseHelper.cs`](src/common/UITestAutomation.Next/MouseHelper.cs) |
`MoveTo` / `LeftClick` / `RightClick` / `LeftClickAt` Win32 wrappers |
|
[`ClipboardHelper.cs`](src/common/UITestAutomation.Next/ClipboardHelper.cs)
| STA-thread `Clipboard` access with `WaitForText` |
|
[`ModuleConfigData.cs`](src/common/UITestAutomation.Next/ModuleConfigData.cs)
| `PowerToysModule` enum + path/process-name resolution |
### Tests
**[`src/modules/colorPicker/ColorPicker.UITests/`](src/modules/colorPicker/ColorPicker.UITests/)**
— replaces the previous empty `UITest-ColorPicker` stub. One test,
[`ColorPickerEndToEndTests.NavigateReadShortcutActivateAndCapture`](src/modules/colorPicker/ColorPicker.UITests/ColorPickerEndToEndTests.cs),
drives the full E2E:
1. Navigate to the Color Picker page via the dashboard utilities stack
2. Toggle the module OFF, verify `PowerToys.ColorPickerUI` exits; toggle
ON, verify it respawns
3. Read the activation shortcut from the page's `ShortcutControl`
(`EditButton.HelpText`)
4. Clear clipboard, park cursor, send the chord
5. Wait for the picker overlay window
6. Read the displayed HEX from a hidden XAML automation peer (see below)
7. Left-click to capture; assert the clipboard value matches the peer's
HEX
8. Wait for the editor window and assert the captured color appears in
its tree
**[`src/settings-ui/Settings.UITests/`](src/settings-ui/Settings.UITests/)**
— `SettingsNavigationSmokeTests.NavigationItem_NavigatesWithoutCrashing`
is one `[TestMethod]` parameterized with `[DynamicData]`, producing 31
discrete results — one per `NavigationViewItem` in
[`ShellPage.xaml`](src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml).
For each item: navigate, settle 250ms, assert `PowerToys.Settings` is
still alive. Catches FailFast regressions in
`ShellViewModel.Frame_NavigationFailed` that pure-logic unit tests can't
reach (the failure path needs a `NavigationFailedEventArgs` which is a
sealed WinRT projection).
### Product change
**[`src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml`](src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml)**
— adds a hidden `TextBlock` automation peer:
```xml
<TextBlock
x:Name="ColorHexAutomationPeer"
AutomationProperties.AutomationId="ColorHexAutomationPeer"
IsHitTestVisible="False"
Opacity="0"
Text="{Binding ColorText}" />
```
The visible `ColorTextBlock` has `AutomationProperties.Name="{Binding
ColorName}"`, which masks the HEX value in the UIA tree (you see "White"
instead of `#FFFFFF`). This zero-impact peer mirrors `ColorText` so
tests can read the actually-displayed HEX. `Opacity=0` +
`IsHitTestVisible=False` keep it out of the visual layout and out of
accessibility focus.
### Project wiring
- [`PowerToys.slnx`](PowerToys.slnx) — registers `UITestAutomation.Next`
under `/common/`, `ColorPicker.UITests` under
`/modules/colorpicker/Tests/`, and `Settings.UITests` under
`/settings-ui/Tests/`. Original `UITest-ColorPicker` stub csproj
removed.
-
[`.github/actions/spell-check/expect.txt`](.github/actions/spell-check/expect.txt)
— adds `winapp` / `winappcli`.
### Not in this PR
- No pipeline changes. `winapp.exe` is expected to be pre-staged on the
test agent image. If it's missing, `UITestBase` fails the first test
with the install hint (`winget install Microsoft.winappcli`) rather than
producing 30 opaque per-test errors.
- No changes to the legacy `UITestAutomation` library or any of the
existing `*.UITests` projects.
## Validation
- All three projects build clean on `x64|Debug` (empty
`build.<config>.<plat>.errors.log`):
- `src/common/UITestAutomation.Next/`
- `src/modules/colorPicker/ColorPicker.UITests/`
- `src/settings-ui/Settings.UITests/`
- Both tests run in Test Explorer / `dotnet test` via
Microsoft.Testing.Platform (already enabled repo-wide in
`Directory.Build.props`).
- Local runs: ColorPicker E2E green; Settings smoke green across all 31
nav items.
- `winapp 0.3.2` from `winget install Microsoft.winappcli`.
## Notes for reviewers
- **`UseShellExecute = true`** in `SessionHelper.EnsureRunning` is
intentional — `false` makes child processes inherit the test host's
stdin/stdout/stderr handles, which keeps MTP/Test Explorer marking the
run as "in progress" until the spawned PowerToys exits.
- **Process-scope (`-a`) targeting** in the Settings smoke test handles
single-instance handoff: the EXE you launch may exit with code 0
immediately after signalling an existing owner, so the alive check uses
`Process.GetProcessesByName` rather than the launcher PID.
- **AutomationId-only selectors** in the Settings smoke list keep the
test localization-independent. Parent groups have
`SelectsOnInvoked="False"` and only expand on click — `Element.Click`
tries `InvokePattern → TogglePattern → SelectionItemPattern →
ExpandCollapsePattern` so the same call works for both leaves and
groups.
- **Untitled-window discovery**: filtered `winapp ui list-windows -a
<name>` returns windows that the unfiltered call drops (e.g. ColorPicker
editor). `WindowsFinder.ListByApp` uses the filtered form. Reported
upstream.
## Before Merge
- Add the `winappcli` install step to the UI-test pipeline.
2026-07-07 22:58:08 -07:00
|
|
|
<Project Path="src/common/Common.UI/Common.UI.csproj">
|
2026-02-12 16:45:44 +01:00
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/common/COMUtils/COMUtils.vcxproj" Id="7319089e-46d6-4400-bc65-e39bdf1416ee" />
|
|
|
|
|
<Project Path="src/common/Display/Display.vcxproj" Id="caba8dfb-823b-4bf2-93ac-3f31984150d9" />
|
|
|
|
|
<Project Path="src/common/FilePreviewCommon/FilePreviewCommon.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/common/GPOWrapper/GPOWrapper.vcxproj" Id="e599c30b-9dc8-4e5a-bf27-93d4ccede788" />
|
|
|
|
|
<Project Path="src/common/GPOWrapperProjection/GPOWrapperProjection.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/common/LanguageModelProvider/LanguageModelProvider.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/common/ManagedCommon/ManagedCommon.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/common/ManagedCsWin32/ManagedCsWin32.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/common/ManagedTelemetry/Telemetry/ManagedTelemetry.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-23 21:07:44 +08:00
|
|
|
<Project Path="src/common/PowerToys.ModuleContracts/PowerToys.ModuleContracts.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/common/SettingsAPI/SettingsAPI.vcxproj" Id="6955446d-23f7-4023-9bb3-8657f904af99" />
|
|
|
|
|
<Project Path="src/common/Themes/Themes.vcxproj" Id="98537082-0fdb-40de-abd8-0dc5a4269bab" />
|
|
|
|
|
<Project Path="src/common/UITestAutomation/UITestAutomation.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
[UITests] New framework around WinApp CLI, no WinAppDriver or Selenium. (#48467)
# Add winappcli-based UI test harness (no WinAppDriver / Selenium)
## Summary
Introduces a new UI test harness — `Microsoft.PowerToys.UITest.Next` —
that drives PowerToys
modules through Microsoft's
[winappcli](https://github.com/microsoft/WinAppCli) (UI Automation
CLI) instead of WinAppDriver + Selenium. Engine is a single executable
shelled out from
C#; no third-party NuGet packages, no driver process, no Appium server.
Adds two real consumers:
a full ColorPicker end-to-end scenario and a Settings shell navigation
smoke test.
This is opt-in and additive — the existing `UITestAutomation` library
and the
WinAppDriver-based test projects are untouched. Both can coexist while
we evaluate the new
harness.
Inspired in part by
[#48414](https://github.com/microsoft/PowerToys/pull/48414), which lands
the same architectural bet (winappcli, AutomationId selectors, no
WinAppDriver) at a smaller
scope. This PR generalizes it into a reusable library.
## Why
WinAppDriver + Selenium is a legacy pre-agentic solution that is no
longer actively maintained. It's unreliable, heavyweight, and slow. To
achieve 100% UI test coverage, we should leverage modern, reliable
solutions, and WinApp CLI is a strong candidate.
## What's in this PR
### Harness library —
[`src/common/UITestAutomation.Next/`](src/common/UITestAutomation.Next/)
| File | Purpose |
|---|---|
| [`WinappCli.cs`](src/common/UITestAutomation.Next/WinappCli.cs) |
Process wrapper around `winapp.exe`. `Invoke` / `InvokeAssertSuccess` /
`InvokeJson` / `IsAvailable` / `TryResolveExecutable`. `Result` carries
the args and emits `DescribeFailure()` like `winapp ui invoke X -w 12345
-> exit 1; stderr: ...` |
| [`Session.cs`](src/common/UITestAutomation.Next/Session.cs) | Test
session, scoped by either HWND (`-w`) or process (`-a`) via
`TargetScope`. `Find<T>` / `FindAll<T>` / `Inspect` / `Screenshot` /
`SendKeys`. `Session.FromProcess(...)` factory for the
single-window-per-process case |
|
[`SessionHelper.cs`](src/common/UITestAutomation.Next/SessionHelper.cs)
| Owns the launch + window-readiness flow. Static `EnsureRunning(scope,
timeout)` returns whether the call had to launch (so cleanup only kills
what we started). Uses `UseShellExecute=true` so child handles don't
keep MSTest hanging |
| [`UITestBase.cs`](src/common/UITestAutomation.Next/UITestBase.cs) |
MSTest base class. Pre-flights `WinappCli.IsAvailable()` once per
process and fails fast with the install hint if `winapp.exe` isn't on
PATH |
| [`Element/*.cs`](src/common/UITestAutomation.Next/Element/) |
`Element`, `Button`, `ToggleSwitch`, `TextBox`, `NavigationViewItem`,
`Window`. `Click` / `MouseClick` / `Focus` / `GetProperty` / `GetValue`
/ `HelpText` / `WaitForProperty` / `WaitForGone` plus coords
(`X`/`Y`/`Width`/`Height`) |
| [`By.cs`](src/common/UITestAutomation.Next/By.cs) | `By.Name` /
`By.AccessibilityId` / `By.Id` / `By.Slug` |
| [`Windows.cs`](src/common/UITestAutomation.Next/Windows.cs) |
`WindowsFinder.ListAll` / `ListByApp` / `WaitForWindowByApp` /
`WaitForWindowByProcess`. Notes the winappcli bug where unfiltered
`list-windows` drops untitled windows |
|
[`WindowControl.cs`](src/common/UITestAutomation.Next/WindowControl.cs)
| Tolerant Win32 helpers — `TryCloseByApp` / `TryFocusByApp` /
`SafeCloseAndFocus` / `TryKillProcess` — for `finally` blocks |
|
[`KeyboardHelper.cs`](src/common/UITestAutomation.Next/KeyboardHelper.cs)
| Hybrid `keybd_event` + `SendKeys.SendWait` chord sender — required for
global PowerToys hotkeys |
| [`MouseHelper.cs`](src/common/UITestAutomation.Next/MouseHelper.cs) |
`MoveTo` / `LeftClick` / `RightClick` / `LeftClickAt` Win32 wrappers |
|
[`ClipboardHelper.cs`](src/common/UITestAutomation.Next/ClipboardHelper.cs)
| STA-thread `Clipboard` access with `WaitForText` |
|
[`ModuleConfigData.cs`](src/common/UITestAutomation.Next/ModuleConfigData.cs)
| `PowerToysModule` enum + path/process-name resolution |
### Tests
**[`src/modules/colorPicker/ColorPicker.UITests/`](src/modules/colorPicker/ColorPicker.UITests/)**
— replaces the previous empty `UITest-ColorPicker` stub. One test,
[`ColorPickerEndToEndTests.NavigateReadShortcutActivateAndCapture`](src/modules/colorPicker/ColorPicker.UITests/ColorPickerEndToEndTests.cs),
drives the full E2E:
1. Navigate to the Color Picker page via the dashboard utilities stack
2. Toggle the module OFF, verify `PowerToys.ColorPickerUI` exits; toggle
ON, verify it respawns
3. Read the activation shortcut from the page's `ShortcutControl`
(`EditButton.HelpText`)
4. Clear clipboard, park cursor, send the chord
5. Wait for the picker overlay window
6. Read the displayed HEX from a hidden XAML automation peer (see below)
7. Left-click to capture; assert the clipboard value matches the peer's
HEX
8. Wait for the editor window and assert the captured color appears in
its tree
**[`src/settings-ui/Settings.UITests/`](src/settings-ui/Settings.UITests/)**
— `SettingsNavigationSmokeTests.NavigationItem_NavigatesWithoutCrashing`
is one `[TestMethod]` parameterized with `[DynamicData]`, producing 31
discrete results — one per `NavigationViewItem` in
[`ShellPage.xaml`](src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml).
For each item: navigate, settle 250ms, assert `PowerToys.Settings` is
still alive. Catches FailFast regressions in
`ShellViewModel.Frame_NavigationFailed` that pure-logic unit tests can't
reach (the failure path needs a `NavigationFailedEventArgs` which is a
sealed WinRT projection).
### Product change
**[`src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml`](src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml)**
— adds a hidden `TextBlock` automation peer:
```xml
<TextBlock
x:Name="ColorHexAutomationPeer"
AutomationProperties.AutomationId="ColorHexAutomationPeer"
IsHitTestVisible="False"
Opacity="0"
Text="{Binding ColorText}" />
```
The visible `ColorTextBlock` has `AutomationProperties.Name="{Binding
ColorName}"`, which masks the HEX value in the UIA tree (you see "White"
instead of `#FFFFFF`). This zero-impact peer mirrors `ColorText` so
tests can read the actually-displayed HEX. `Opacity=0` +
`IsHitTestVisible=False` keep it out of the visual layout and out of
accessibility focus.
### Project wiring
- [`PowerToys.slnx`](PowerToys.slnx) — registers `UITestAutomation.Next`
under `/common/`, `ColorPicker.UITests` under
`/modules/colorpicker/Tests/`, and `Settings.UITests` under
`/settings-ui/Tests/`. Original `UITest-ColorPicker` stub csproj
removed.
-
[`.github/actions/spell-check/expect.txt`](.github/actions/spell-check/expect.txt)
— adds `winapp` / `winappcli`.
### Not in this PR
- No pipeline changes. `winapp.exe` is expected to be pre-staged on the
test agent image. If it's missing, `UITestBase` fails the first test
with the install hint (`winget install Microsoft.winappcli`) rather than
producing 30 opaque per-test errors.
- No changes to the legacy `UITestAutomation` library or any of the
existing `*.UITests` projects.
## Validation
- All three projects build clean on `x64|Debug` (empty
`build.<config>.<plat>.errors.log`):
- `src/common/UITestAutomation.Next/`
- `src/modules/colorPicker/ColorPicker.UITests/`
- `src/settings-ui/Settings.UITests/`
- Both tests run in Test Explorer / `dotnet test` via
Microsoft.Testing.Platform (already enabled repo-wide in
`Directory.Build.props`).
- Local runs: ColorPicker E2E green; Settings smoke green across all 31
nav items.
- `winapp 0.3.2` from `winget install Microsoft.winappcli`.
## Notes for reviewers
- **`UseShellExecute = true`** in `SessionHelper.EnsureRunning` is
intentional — `false` makes child processes inherit the test host's
stdin/stdout/stderr handles, which keeps MTP/Test Explorer marking the
run as "in progress" until the spawned PowerToys exits.
- **Process-scope (`-a`) targeting** in the Settings smoke test handles
single-instance handoff: the EXE you launch may exit with code 0
immediately after signalling an existing owner, so the alive check uses
`Process.GetProcessesByName` rather than the launcher PID.
- **AutomationId-only selectors** in the Settings smoke list keep the
test localization-independent. Parent groups have
`SelectsOnInvoked="False"` and only expand on click — `Element.Click`
tries `InvokePattern → TogglePattern → SelectionItemPattern →
ExpandCollapsePattern` so the same call works for both leaves and
groups.
- **Untitled-window discovery**: filtered `winapp ui list-windows -a
<name>` returns windows that the unfiltered call drops (e.g. ColorPicker
editor). `WindowsFinder.ListByApp` uses the filtered form. Reported
upstream.
## Before Merge
- Add the `winappcli` install step to the UI-test pipeline.
2026-07-07 22:58:08 -07:00
|
|
|
<Project Path="src/common/UITestAutomation.Next/UITestAutomation.Next.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
[UITests] Add UITest.Next suites (Image Resizer, Peek, File Explorer add‑ons, File Locksmith) + local‑VM tooling and CI test‑signing (#49671)
## Summary
Adds end‑to‑end UI tests on the `Microsoft.PowerToys.UITest.Next`
(winappcli) framework for three
modules, grows the shared `.Next` test framework with the helpers those
suites needed, and adds the
CI plumbing that lets shell‑extension tests exercise the **real**
Windows 11 modern context menu.
Also ships two agent skills that document how to write and run these
tests.
Product runtime behavior is **unchanged** — the only product edits are
test‑observability hooks in Peek
and a unit‑test project exclude.
Closes: https://github.com/microsoft/PowerToys/issues/40660
https://github.com/microsoft/PowerToys/issues/49424
https://github.com/microsoft/PowerToys/issues/40661
## What's added
### New UI test suites
- **Image Resizer** —
`src/modules/imageresizer/tests/ImageResizer.UITests`: context‑menu
enable/disable
tracking, the resize dialog, custom presets, every fit mode, every unit,
filename format, keep‑date,
shrink‑only, replace‑in‑place, and orientation.
- **Peek** — `src/modules/peek/Peek.UITests.Next`: file‑preview coverage
across image/text/archive/
markdown types with per‑arch visual baselines.
- **File Explorer add‑ons** —
`src/modules/previewpane/PreviewPane.UITests`: Preview Pane handlers and
thumbnail providers.
### `UITestAutomation.Next` framework
- New helpers: `ExplorerShell` (Shell selection/view‑mode interop),
`WaitHelper` (structured stable
waits), `WindowControl` (foreground/context‑menu/process control),
`VisualAssert` (image compare),
`WindowHelper`.
- Updates to `Session`, `UITestBase`, `SettingsConfigHelper`,
`WinappCli`.
- New `UITestAutomation.Next.UnitTests` project covering the new
wait/settings/CLI helpers.
### CI — sign sparse MSIX so the modern menu registers
- **`.pipelines/signSparsePackages.ps1`** — self‑signs each sparse
context‑menu MSIX with a
publisher‑matching test certificate and force‑trusts it (machine
stores), so
`AddPackageByUriAsync` succeeds on otherwise‑unsigned PR builds. Robust
`signtool` discovery with a
NuGet fallback; test‑only trust that asserts no security.
- Wired into **`.pipelines/v2/templates/job-test-project.yml`** as a
best‑effort step covering the
run‑in‑place, machine‑install, and per‑user‑install locations. Signs
nothing it can't (skips
already‑signed packages) and never fails the job.
### Product changes (test observability only)
- **Peek `FilePreview.xaml` / `.xaml.cs`** — a named `LoadingIndicator`
and a hidden automation peer
that exposes the current preview state as text, so tests can read load
state deterministically. No
runtime behavior change.
- **`ImageResizer.UnitTests.csproj`** — exclude the sibling
`ImageResizer.UITests\**` folder from the
unit‑test compilation.
### Agent skills & docs
- **New `ui-tests-local-vm` skill** — run `.Next` suites in persistent
dockur/windows VMs: setup,
agentic loop, image customization, troubleshooting, the shell‑extension
**signing** reference, plus
controller/guest scripts and VM templates.
- **Updated `ui-tests-migration` skill** — WinAppDriver/Selenium →
`.Next` porting guidance
(CI stability, Explorer/shell‑extension test design, patterns &
pitfalls).
- **`doc/devdocs/development/ui-tests.md`** — updated for the `.Next`
workflow.
## Testing
- All three suites pass locally and in CI across **x64 Win10**, **x64
Win11**, and **arm64** (machine
and per‑user install legs).
## Reviewer notes
- No product runtime behavior changes; product edits are limited to the
Peek test hooks above.
- The CI signing step is a **test‑only** trust anchor (self‑signed,
scoped to the agent) and is
best‑effort, so it can only add modern‑menu coverage and never regress
the job.
2026-08-10 10:55:03 -07:00
|
|
|
<Project Path="src/common/UITestAutomation.Next.UnitTests/UITestAutomation.Next.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/common/UnitTests-CommonLib/UnitTests-CommonLib.vcxproj" Id="1a066c63-64b3-45f8-92fe-664e1cce8077" />
|
2026-02-03 15:12:45 +08:00
|
|
|
<Project Path="src/common/UnitTests-CommonUtils/UnitTests-CommonUtils.vcxproj" Id="8b5cfb38-ccba-40a8-ad7a-89c57b070884" />
|
Fix auto-update relaunch, add config backup, enable auto-download by default (#46889)
## Summary
Addresses three critical issues with the PowerToys update experience
that cause user fragmentation across old versions.
### Changes
**1. Fix relaunch after update (Fixes #42004, #43011, #44071)**
- Stage 1 now passes the PowerToys install directory to Stage 2 as an
argument
- After successful install, Stage 2 relaunches `PowerToys.exe` with
`-report_update_success`
- Users will see a 'successfully updated' toast and PT resumes
automatically
**2. Config backup/restore (Fixes #46179)**
- `BackupConfigFiles()` snapshots all JSON configs to `ConfigBackup/`
before update begins
- `RestoreCorruptedConfigs()` checks for null-byte corruption after
install and auto-restores
- Protects Workspaces, FancyZones, Keyboard Manager, and all other
module settings
**3. Enable auto-download by default**
- New installations default `AutoDownloadUpdates` to `true` (was
`false`)
- Existing users' preferences are preserved — this only affects
first-run defaults
- The runner already defaulted to `true`; this aligns the C# settings
model
### Why this matters
The current updater kills all PowerToys processes, runs the installer,
then **exits without relaunching**. Users lose keyboard remappings,
FancyZones layouts, and Awake settings with no indication why. Combined
with auto-download being off by default, most users are multiple
versions behind.
### Testing
- Verified update flow: Stage 1 → Stage 2 → PT relaunches with success
toast
- Config backup creates mirror of all JSON settings before update
- Corruption detection catches null-byte pattern from #46179
- Graceful fallback: if install dir not provided (old Stage 1), logs
warning but doesn't crash
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Muyuan Li (from Dev Box) <muyuanli@microsoft.com>
Co-authored-by: Niels Laute <niels.laute@live.nl>
2026-05-21 23:01:56 -07:00
|
|
|
<Project Path="src/common/updating/UnitTests/UpdatingUnitTests.vcxproj" Id="a1b2c3d4-e5f6-7890-abcd-ef1234567890" />
|
[UITests] New framework around WinApp CLI, no WinAppDriver or Selenium. (#48467)
# Add winappcli-based UI test harness (no WinAppDriver / Selenium)
## Summary
Introduces a new UI test harness — `Microsoft.PowerToys.UITest.Next` —
that drives PowerToys
modules through Microsoft's
[winappcli](https://github.com/microsoft/WinAppCli) (UI Automation
CLI) instead of WinAppDriver + Selenium. Engine is a single executable
shelled out from
C#; no third-party NuGet packages, no driver process, no Appium server.
Adds two real consumers:
a full ColorPicker end-to-end scenario and a Settings shell navigation
smoke test.
This is opt-in and additive — the existing `UITestAutomation` library
and the
WinAppDriver-based test projects are untouched. Both can coexist while
we evaluate the new
harness.
Inspired in part by
[#48414](https://github.com/microsoft/PowerToys/pull/48414), which lands
the same architectural bet (winappcli, AutomationId selectors, no
WinAppDriver) at a smaller
scope. This PR generalizes it into a reusable library.
## Why
WinAppDriver + Selenium is a legacy pre-agentic solution that is no
longer actively maintained. It's unreliable, heavyweight, and slow. To
achieve 100% UI test coverage, we should leverage modern, reliable
solutions, and WinApp CLI is a strong candidate.
## What's in this PR
### Harness library —
[`src/common/UITestAutomation.Next/`](src/common/UITestAutomation.Next/)
| File | Purpose |
|---|---|
| [`WinappCli.cs`](src/common/UITestAutomation.Next/WinappCli.cs) |
Process wrapper around `winapp.exe`. `Invoke` / `InvokeAssertSuccess` /
`InvokeJson` / `IsAvailable` / `TryResolveExecutable`. `Result` carries
the args and emits `DescribeFailure()` like `winapp ui invoke X -w 12345
-> exit 1; stderr: ...` |
| [`Session.cs`](src/common/UITestAutomation.Next/Session.cs) | Test
session, scoped by either HWND (`-w`) or process (`-a`) via
`TargetScope`. `Find<T>` / `FindAll<T>` / `Inspect` / `Screenshot` /
`SendKeys`. `Session.FromProcess(...)` factory for the
single-window-per-process case |
|
[`SessionHelper.cs`](src/common/UITestAutomation.Next/SessionHelper.cs)
| Owns the launch + window-readiness flow. Static `EnsureRunning(scope,
timeout)` returns whether the call had to launch (so cleanup only kills
what we started). Uses `UseShellExecute=true` so child handles don't
keep MSTest hanging |
| [`UITestBase.cs`](src/common/UITestAutomation.Next/UITestBase.cs) |
MSTest base class. Pre-flights `WinappCli.IsAvailable()` once per
process and fails fast with the install hint if `winapp.exe` isn't on
PATH |
| [`Element/*.cs`](src/common/UITestAutomation.Next/Element/) |
`Element`, `Button`, `ToggleSwitch`, `TextBox`, `NavigationViewItem`,
`Window`. `Click` / `MouseClick` / `Focus` / `GetProperty` / `GetValue`
/ `HelpText` / `WaitForProperty` / `WaitForGone` plus coords
(`X`/`Y`/`Width`/`Height`) |
| [`By.cs`](src/common/UITestAutomation.Next/By.cs) | `By.Name` /
`By.AccessibilityId` / `By.Id` / `By.Slug` |
| [`Windows.cs`](src/common/UITestAutomation.Next/Windows.cs) |
`WindowsFinder.ListAll` / `ListByApp` / `WaitForWindowByApp` /
`WaitForWindowByProcess`. Notes the winappcli bug where unfiltered
`list-windows` drops untitled windows |
|
[`WindowControl.cs`](src/common/UITestAutomation.Next/WindowControl.cs)
| Tolerant Win32 helpers — `TryCloseByApp` / `TryFocusByApp` /
`SafeCloseAndFocus` / `TryKillProcess` — for `finally` blocks |
|
[`KeyboardHelper.cs`](src/common/UITestAutomation.Next/KeyboardHelper.cs)
| Hybrid `keybd_event` + `SendKeys.SendWait` chord sender — required for
global PowerToys hotkeys |
| [`MouseHelper.cs`](src/common/UITestAutomation.Next/MouseHelper.cs) |
`MoveTo` / `LeftClick` / `RightClick` / `LeftClickAt` Win32 wrappers |
|
[`ClipboardHelper.cs`](src/common/UITestAutomation.Next/ClipboardHelper.cs)
| STA-thread `Clipboard` access with `WaitForText` |
|
[`ModuleConfigData.cs`](src/common/UITestAutomation.Next/ModuleConfigData.cs)
| `PowerToysModule` enum + path/process-name resolution |
### Tests
**[`src/modules/colorPicker/ColorPicker.UITests/`](src/modules/colorPicker/ColorPicker.UITests/)**
— replaces the previous empty `UITest-ColorPicker` stub. One test,
[`ColorPickerEndToEndTests.NavigateReadShortcutActivateAndCapture`](src/modules/colorPicker/ColorPicker.UITests/ColorPickerEndToEndTests.cs),
drives the full E2E:
1. Navigate to the Color Picker page via the dashboard utilities stack
2. Toggle the module OFF, verify `PowerToys.ColorPickerUI` exits; toggle
ON, verify it respawns
3. Read the activation shortcut from the page's `ShortcutControl`
(`EditButton.HelpText`)
4. Clear clipboard, park cursor, send the chord
5. Wait for the picker overlay window
6. Read the displayed HEX from a hidden XAML automation peer (see below)
7. Left-click to capture; assert the clipboard value matches the peer's
HEX
8. Wait for the editor window and assert the captured color appears in
its tree
**[`src/settings-ui/Settings.UITests/`](src/settings-ui/Settings.UITests/)**
— `SettingsNavigationSmokeTests.NavigationItem_NavigatesWithoutCrashing`
is one `[TestMethod]` parameterized with `[DynamicData]`, producing 31
discrete results — one per `NavigationViewItem` in
[`ShellPage.xaml`](src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml).
For each item: navigate, settle 250ms, assert `PowerToys.Settings` is
still alive. Catches FailFast regressions in
`ShellViewModel.Frame_NavigationFailed` that pure-logic unit tests can't
reach (the failure path needs a `NavigationFailedEventArgs` which is a
sealed WinRT projection).
### Product change
**[`src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml`](src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml)**
— adds a hidden `TextBlock` automation peer:
```xml
<TextBlock
x:Name="ColorHexAutomationPeer"
AutomationProperties.AutomationId="ColorHexAutomationPeer"
IsHitTestVisible="False"
Opacity="0"
Text="{Binding ColorText}" />
```
The visible `ColorTextBlock` has `AutomationProperties.Name="{Binding
ColorName}"`, which masks the HEX value in the UIA tree (you see "White"
instead of `#FFFFFF`). This zero-impact peer mirrors `ColorText` so
tests can read the actually-displayed HEX. `Opacity=0` +
`IsHitTestVisible=False` keep it out of the visual layout and out of
accessibility focus.
### Project wiring
- [`PowerToys.slnx`](PowerToys.slnx) — registers `UITestAutomation.Next`
under `/common/`, `ColorPicker.UITests` under
`/modules/colorpicker/Tests/`, and `Settings.UITests` under
`/settings-ui/Tests/`. Original `UITest-ColorPicker` stub csproj
removed.
-
[`.github/actions/spell-check/expect.txt`](.github/actions/spell-check/expect.txt)
— adds `winapp` / `winappcli`.
### Not in this PR
- No pipeline changes. `winapp.exe` is expected to be pre-staged on the
test agent image. If it's missing, `UITestBase` fails the first test
with the install hint (`winget install Microsoft.winappcli`) rather than
producing 30 opaque per-test errors.
- No changes to the legacy `UITestAutomation` library or any of the
existing `*.UITests` projects.
## Validation
- All three projects build clean on `x64|Debug` (empty
`build.<config>.<plat>.errors.log`):
- `src/common/UITestAutomation.Next/`
- `src/modules/colorPicker/ColorPicker.UITests/`
- `src/settings-ui/Settings.UITests/`
- Both tests run in Test Explorer / `dotnet test` via
Microsoft.Testing.Platform (already enabled repo-wide in
`Directory.Build.props`).
- Local runs: ColorPicker E2E green; Settings smoke green across all 31
nav items.
- `winapp 0.3.2` from `winget install Microsoft.winappcli`.
## Notes for reviewers
- **`UseShellExecute = true`** in `SessionHelper.EnsureRunning` is
intentional — `false` makes child processes inherit the test host's
stdin/stdout/stderr handles, which keeps MTP/Test Explorer marking the
run as "in progress" until the spawned PowerToys exits.
- **Process-scope (`-a`) targeting** in the Settings smoke test handles
single-instance handoff: the EXE you launch may exit with code 0
immediately after signalling an existing owner, so the alive check uses
`Process.GetProcessesByName` rather than the launcher PID.
- **AutomationId-only selectors** in the Settings smoke list keep the
test localization-independent. Parent groups have
`SelectsOnInvoked="False"` and only expand on click — `Element.Click`
tries `InvokePattern → TogglePattern → SelectionItemPattern →
ExpandCollapsePattern` so the same call works for both leaves and
groups.
- **Untitled-window discovery**: filtered `winapp ui list-windows -a
<name>` returns windows that the unfiltered call drops (e.g. ColorPicker
editor). `WindowsFinder.ListByApp` uses the filtered form. Reported
upstream.
## Before Merge
- Add the `winappcli` install step to the UI-test pipeline.
2026-07-07 22:58:08 -07:00
|
|
|
<Project Path="src/common/updating/updating.vcxproj" Id="17da04df-e393-4397-9cf0-84dabe11032e" />
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/common/version/version.vcxproj" Id="cc6e41ac-8174-4e8a-8d22-85dd7f4851df" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/common/interop/">
|
|
|
|
|
<Project Path="src/common/interop/interop-tests/Common.Interop.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/common/interop/PowerToys.Interop.vcxproj" Id="f055103b-f80b-4d0c-bf48-057c55620033" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/common/log/">
|
Migrate spdlog from submodule to vcpkg (#48039)
## Summary
Migrate `deps/spdlog` from a git submodule to **vcpkg manifest mode**
with an overlay port pinned to the **exact same commit**
(`gabime/spdlog@616866fc`). Replaces the polyfill shim added in #47910
with a proper port-level patch.
This is the follow-up to PR #47928, which I closed after @zadjii-msft /
@DHowett clarified that the intended direction was a single combined
"move to vcpkg **and** apply a patch file" (one change, not two stepping
stones).
## Guidance honored
Per @zadjii-msft (offline):
- ✅ Convert each submodule to vcpkg **one at a time** — this PR is
**spdlog only**. `deps/expected-lite` stays a submodule (separate PR
next).
- ✅ Atomic commit per dep (multiple commits on the branch for review
traceability; squash on merge gives the requested single commit).
- ✅ **Don't bump the version.** Only variable changed: submodule →
vcpkg. Same commit (`616866fc`, v1.8.5 + 38) the submodule pointed at.
Per @DHowett
([review](https://github.com/microsoft/PowerToys/pull/48039#pullrequestreview-4338835150)):
- ✅ No vcpkg submodule — vswhere-first detection via a Terminal-style
`steps-install-vcpkg.yml` template; three-tier `VcpkgRoot` fallback (env
var → VS-shipped → runtime clone pinned to manifest baseline).
## Design
- **Repo-root manifest**: `vcpkg.json` declares only `spdlog`, with
`builtin-baseline` pinned. `vcpkg-configuration.json` registers
`deps/vcpkg-overlays/` as overlay-ports.
- **Overlay port** `deps/vcpkg-overlays/spdlog/`: `vcpkg_from_github(REF
616866fc...)` with bundled fmt preserved (`-DSPDLOG_FMT_EXTERNAL=OFF`);
the MSVC 14.51 fix from #47910 carried as a proper vcpkg patch on
`include/spdlog/fmt/bundled/format.h`.
- **vcpkg integration is global** (set in `Cpp.Build.props`, imported
via `ForceImportBeforeCppProps` for every `.vcxproj`). An earlier
attempt to make vcpkg per-project-opt-in via `deps/spdlog.props` failed
because ~85 PowerToys `.vcxproj` files import `spdlog.props` AFTER
`Microsoft.Cpp.targets`, by which point `vcpkg.props`' `ClCompile` hook
is dead-on-arrival. The trade-off (every C++ project invokes `vcpkg
install` once at build time, ~0.5 s on cache hits, manifest declares
only spdlog so install set is fixed) is documented in the expanded
`Cpp.Build.props` comment.
- **`deps/spdlog.props`** is now a thin shim that only sets the
historical `SPDLOG_*` preprocessor defines for source-compat.
- **`Cpp.Build.targets`** is a new file imported via
`ForceImportAfterCppTargets` to load `vcpkg.targets` after
`Microsoft.Cpp.targets`. A fail-fast `<Target>` errors with a clear
message if `vcpkg.props` can't be found at the resolved `VcpkgRoot`.
- **Removes** `deps/spdlog-msvc-fix/` polyfill, in-tree wrapper
`src/logging/`, spdlog submodule, the single `<ProjectReference>` in
`logger.vcxproj`, plus 3 `.slnf` refs and 2 `.slnx` refs
(`PowerToys.slnx` + `installer/PowerToysSetup.slnx`), plus 3 hard-coded
`..\deps\spdlog\include` entries in `<AdditionalIncludeDirectories>`.
- **CI**: new reusable `.pipelines/v2/templates/steps-install-vcpkg.yml`
(vswhere-first, manifest-baseline-pinned fallback clone, respects
`useVSPreview`). Gated `Cache@2` for `%LOCALAPPDATA%\vcpkg\archives`
keyed on overlay-port contents. Same vcpkg detection added to
`tools\build\build-essentials.ps1` for local devs.
## Verification
Local build matrix (all 4 configs of `logger.vcxproj` and a
representative late-import consumer):
| Config | Result | Notes |
|--------|--------|-------|
| Release \| x64 | ✅ | vcpkg install ~21 s, `logger.lib` produced |
| Debug \| x64 | ✅ | **Validates patch fixes the actual MSVC 14.51 bug**
(`_ITERATOR_DEBUG_LEVEL > 0` → `_SECURE_SCL`) |
| Release \| ARM64 | ✅ | vcpkg cross-installs `arm64-windows-static`
spdlog in ~16 s |
| Debug \| ARM64 | ✅ | **Previously DISABLED for the in-tree spdlog**
(per `<Build Solution="Debug\|ARM64" Project="false" />` in
`PowerToysSetup.slnx`); this migration FIXES that latent gap |
| FancyZonesLib (Release \| x64) | ✅ | Late-import-pattern consumer;
previously broke in v2 |
Full PowerToys CI (x64 + arm64 + CmdPal SDK + all GitHub Actions checks)
green.
**Consumer audit**: 72 `.vcxproj` files reference `logger.vcxproj`; all
72 also import `deps/spdlog.props`. No transitive-link breakage.
## Out of scope (intentional)
- `deps/expected-lite` migration — next PR per "one-at-a-time" rule.
- Remote vcpkg binary cache (Azure Artifacts NuGet feed). Local pipeline
`Cache@2` works for now, but a remote feed survives across pipelines and
is the long-term answer. Happy to split this into a follow-up.
## Notes for review
- Patch in the overlay port is identical content to PR #47928's patch
but regenerated with LF line endings (vcpkg's `vcpkg_apply_patches` is
strict; no `--ignore-whitespace`).
- Once PowerToys eventually bumps spdlog past v1.14 (which ships fmt
10.2 and drops the affected code path), the overlay port can be deleted
and we can use upstream vcpkg's `spdlog` directly.
- Re. official-release pipelines and terrapin / less-restricted network
isolation: VS-shipped vcpkg is the primary path (no network); the
fallback clone is only exercised when VS doesn't ship vcpkg. Happy to
wire terrapin into the fallback as a follow-up if the official build
template needs it.
Closes the work tracked in #47928 (which was closed unmerged).
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Dustin L. Howett <dustin@howett.net>
2026-05-27 15:45:24 +08:00
|
|
|
<Project Path="src/common/logger/logger.vcxproj" Id="d9b8fc84-322a-4f9f-bbb9-20915c47ddfd" />
|
2025-12-03 03:59:46 -06:00
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/common/notifications/">
|
|
|
|
|
<Project Path="src/common/notifications/BackgroundActivator/BackgroundActivator.vcxproj" Id="0b593a6c-4143-4337-860e-db5710fb87db" />
|
|
|
|
|
<Project Path="src/common/notifications/BackgroundActivatorDLL/BackgroundActivatorDLL.vcxproj" Id="031ac72e-fa28-4ab7-b690-6f7b9c28aa73">
|
|
|
|
|
<BuildDependency Project="src/common/notifications/BackgroundActivator/BackgroundActivator.vcxproj" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/common/notifications/notifications.vcxproj" Id="1d5be09d-78c0-4fd7-af00-ae7c1af7c525" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/common/Telemetry/">
|
|
|
|
|
<File Path="src/common/Telemetry/ProjectTelemetry.h" />
|
|
|
|
|
<File Path="src/common/Telemetry/TelemetryBase.cs" />
|
|
|
|
|
<File Path="src/common/Telemetry/TraceBase.h" />
|
|
|
|
|
<File Path="src/common/Telemetry/TraceLoggingDefines.h" />
|
|
|
|
|
<Project Path="src/common/Telemetry/EtwTrace/EtwTrace.vcxproj" Id="8f021b46-362b-485c-bfba-ccf83e820cbd" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/common/utils/">
|
|
|
|
|
<File Path="src/common/utils/appMutex.h" />
|
|
|
|
|
<File Path="src/common/utils/color.h" />
|
|
|
|
|
<File Path="src/common/utils/com_object_factory.h" />
|
|
|
|
|
<File Path="src/common/utils/elevation.h" />
|
|
|
|
|
<File Path="src/common/utils/EventLocker.h" />
|
|
|
|
|
<File Path="src/common/utils/EventWaiter.h" />
|
|
|
|
|
<File Path="src/common/utils/excluded_apps.h" />
|
|
|
|
|
<File Path="src/common/utils/exec.h" />
|
|
|
|
|
<File Path="src/common/utils/game_mode.h" />
|
|
|
|
|
<File Path="src/common/utils/gpo.h" />
|
|
|
|
|
<File Path="src/common/utils/HDropIterator.h" />
|
|
|
|
|
<File Path="src/common/utils/HttpClient.h" />
|
|
|
|
|
<File Path="src/common/utils/json.h" />
|
|
|
|
|
<File Path="src/common/utils/language_helper.h" />
|
|
|
|
|
<File Path="src/common/utils/logger_helper.h" />
|
|
|
|
|
<File Path="src/common/utils/modulesRegistry.h" />
|
|
|
|
|
<File Path="src/common/utils/MsiUtils.h" />
|
|
|
|
|
<File Path="src/common/utils/MsWindowsSettings.h" />
|
|
|
|
|
<File Path="src/common/utils/OnThreadExecutor.h" />
|
|
|
|
|
<File Path="src/common/utils/os-detect.h" />
|
|
|
|
|
<File Path="src/common/utils/package.h" />
|
|
|
|
|
<File Path="src/common/utils/ProcessWaiter.h" />
|
|
|
|
|
<File Path="src/common/utils/process_path.h" />
|
|
|
|
|
<File Path="src/common/utils/registry.h" />
|
|
|
|
|
<File Path="src/common/utils/resources.h" />
|
|
|
|
|
<File Path="src/common/utils/serialized.h" />
|
|
|
|
|
<File Path="src/common/utils/shell_ext_registration.h" />
|
|
|
|
|
<File Path="src/common/utils/string_utils.h" />
|
|
|
|
|
<File Path="src/common/utils/timeutil.h" />
|
|
|
|
|
<File Path="src/common/utils/UnhandledExceptionHandler.h" />
|
|
|
|
|
<File Path="src/common/utils/winapi_error.h" />
|
|
|
|
|
<File Path="src/common/utils/window.h" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/DSC/">
|
|
|
|
|
<Project Path="src/dsc/PowerToys.Settings.DSC.Schema.Generator/PowerToys.Settings.DSC.Schema.Generator.csproj">
|
|
|
|
|
<BuildDependency Project="src/settings-ui/Settings.UI/PowerToys.Settings.csproj" />
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/DSC/v3/">
|
|
|
|
|
<Project Path="src/dsc/v3/PowerToys.DSC.UnitTests/PowerToys.DSC.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/dsc/v3/PowerToys.DSC/PowerToys.DSC.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/" />
|
|
|
|
|
<Folder Name="/modules/AdvancedPaste/">
|
|
|
|
|
<Project Path="src/modules/AdvancedPaste/AdvancedPaste/AdvancedPaste.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
<Deploy />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/AdvancedPaste/AdvancedPasteModuleInterface/AdvancedPasteModuleInterface.vcxproj" Id="fc373b24-3293-453c-aaf5-cf2909dcee6a" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/AdvancedPaste/Tests/">
|
|
|
|
|
<Project Path="src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/AdvancedPaste.FuzzTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/AdvancedPaste/AdvancedPaste.UnitTests/AdvancedPaste.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
2026-07-30 22:42:05 -07:00
|
|
|
<Folder Name="/modules/AltWindowCycle/">
|
|
|
|
|
<Project Path="src/modules/AltWindowCycle/AltWindowCycle.vcxproj" Id="4d1d41c7-e22b-4a8b-8805-660a100e1d79" />
|
|
|
|
|
<Project Path="src/modules/AltWindowCycle/UnitTests/AltWindowCycleUnitTests.vcxproj" Id="9ebe5c3a-4a37-477e-9176-07c7cf0eba6e" />
|
|
|
|
|
</Folder>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Folder Name="/modules/AlwaysOnTop/">
|
|
|
|
|
<Project Path="src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj" Id="1dc3be92-ce89-43fb-8110-9c043a2fe7a2" />
|
|
|
|
|
<Project Path="src/modules/alwaysontop/AlwaysOnTopModuleInterface/AlwaysOnTopModuleInterface.vcxproj" Id="48a0a19e-a0be-4256-acf8-cc3b80291af9" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/awake/">
|
2025-12-23 21:07:44 +08:00
|
|
|
<Project Path="src/modules/awake/Awake.ModuleServices/Awake.ModuleServices.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2026-07-28 00:24:28 -07:00
|
|
|
<Project Path="src/modules/awake/Awake.ModuleServices.UnitTests/Awake.ModuleServices.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/modules/awake/Awake/Awake.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/awake/AwakeModuleInterface/AwakeModuleInterface.vcxproj" Id="5e7360a8-d048-4ed3-8f09-0bfd64c5529a" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/cmdNotFound/">
|
|
|
|
|
<Project Path="src/modules/cmdNotFound/CmdNotFoundModuleInterface/CmdNotFoundModuleInterface.vcxproj" Id="0014d652-901f-4456-8d65-06fc5f997fb0" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/colorpicker/">
|
2025-12-23 21:07:44 +08:00
|
|
|
<Project Path="src/modules/colorPicker/ColorPicker.ModuleServices/ColorPicker.ModuleServices.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/modules/colorPicker/ColorPicker/ColorPicker.vcxproj" Id="655c9af2-18d3-4da6-80e4-85504a7722ba">
|
|
|
|
|
<BuildDependency Project="src/common/logger/logger.vcxproj" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/colorPicker/ColorPickerUI/ColorPickerUI.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/colorpicker/Tests/">
|
|
|
|
|
<Project Path="src/modules/colorPicker/ColorPickerUI.UnitTests/ColorPickerUI.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
[UITests] New framework around WinApp CLI, no WinAppDriver or Selenium. (#48467)
# Add winappcli-based UI test harness (no WinAppDriver / Selenium)
## Summary
Introduces a new UI test harness — `Microsoft.PowerToys.UITest.Next` —
that drives PowerToys
modules through Microsoft's
[winappcli](https://github.com/microsoft/WinAppCli) (UI Automation
CLI) instead of WinAppDriver + Selenium. Engine is a single executable
shelled out from
C#; no third-party NuGet packages, no driver process, no Appium server.
Adds two real consumers:
a full ColorPicker end-to-end scenario and a Settings shell navigation
smoke test.
This is opt-in and additive — the existing `UITestAutomation` library
and the
WinAppDriver-based test projects are untouched. Both can coexist while
we evaluate the new
harness.
Inspired in part by
[#48414](https://github.com/microsoft/PowerToys/pull/48414), which lands
the same architectural bet (winappcli, AutomationId selectors, no
WinAppDriver) at a smaller
scope. This PR generalizes it into a reusable library.
## Why
WinAppDriver + Selenium is a legacy pre-agentic solution that is no
longer actively maintained. It's unreliable, heavyweight, and slow. To
achieve 100% UI test coverage, we should leverage modern, reliable
solutions, and WinApp CLI is a strong candidate.
## What's in this PR
### Harness library —
[`src/common/UITestAutomation.Next/`](src/common/UITestAutomation.Next/)
| File | Purpose |
|---|---|
| [`WinappCli.cs`](src/common/UITestAutomation.Next/WinappCli.cs) |
Process wrapper around `winapp.exe`. `Invoke` / `InvokeAssertSuccess` /
`InvokeJson` / `IsAvailable` / `TryResolveExecutable`. `Result` carries
the args and emits `DescribeFailure()` like `winapp ui invoke X -w 12345
-> exit 1; stderr: ...` |
| [`Session.cs`](src/common/UITestAutomation.Next/Session.cs) | Test
session, scoped by either HWND (`-w`) or process (`-a`) via
`TargetScope`. `Find<T>` / `FindAll<T>` / `Inspect` / `Screenshot` /
`SendKeys`. `Session.FromProcess(...)` factory for the
single-window-per-process case |
|
[`SessionHelper.cs`](src/common/UITestAutomation.Next/SessionHelper.cs)
| Owns the launch + window-readiness flow. Static `EnsureRunning(scope,
timeout)` returns whether the call had to launch (so cleanup only kills
what we started). Uses `UseShellExecute=true` so child handles don't
keep MSTest hanging |
| [`UITestBase.cs`](src/common/UITestAutomation.Next/UITestBase.cs) |
MSTest base class. Pre-flights `WinappCli.IsAvailable()` once per
process and fails fast with the install hint if `winapp.exe` isn't on
PATH |
| [`Element/*.cs`](src/common/UITestAutomation.Next/Element/) |
`Element`, `Button`, `ToggleSwitch`, `TextBox`, `NavigationViewItem`,
`Window`. `Click` / `MouseClick` / `Focus` / `GetProperty` / `GetValue`
/ `HelpText` / `WaitForProperty` / `WaitForGone` plus coords
(`X`/`Y`/`Width`/`Height`) |
| [`By.cs`](src/common/UITestAutomation.Next/By.cs) | `By.Name` /
`By.AccessibilityId` / `By.Id` / `By.Slug` |
| [`Windows.cs`](src/common/UITestAutomation.Next/Windows.cs) |
`WindowsFinder.ListAll` / `ListByApp` / `WaitForWindowByApp` /
`WaitForWindowByProcess`. Notes the winappcli bug where unfiltered
`list-windows` drops untitled windows |
|
[`WindowControl.cs`](src/common/UITestAutomation.Next/WindowControl.cs)
| Tolerant Win32 helpers — `TryCloseByApp` / `TryFocusByApp` /
`SafeCloseAndFocus` / `TryKillProcess` — for `finally` blocks |
|
[`KeyboardHelper.cs`](src/common/UITestAutomation.Next/KeyboardHelper.cs)
| Hybrid `keybd_event` + `SendKeys.SendWait` chord sender — required for
global PowerToys hotkeys |
| [`MouseHelper.cs`](src/common/UITestAutomation.Next/MouseHelper.cs) |
`MoveTo` / `LeftClick` / `RightClick` / `LeftClickAt` Win32 wrappers |
|
[`ClipboardHelper.cs`](src/common/UITestAutomation.Next/ClipboardHelper.cs)
| STA-thread `Clipboard` access with `WaitForText` |
|
[`ModuleConfigData.cs`](src/common/UITestAutomation.Next/ModuleConfigData.cs)
| `PowerToysModule` enum + path/process-name resolution |
### Tests
**[`src/modules/colorPicker/ColorPicker.UITests/`](src/modules/colorPicker/ColorPicker.UITests/)**
— replaces the previous empty `UITest-ColorPicker` stub. One test,
[`ColorPickerEndToEndTests.NavigateReadShortcutActivateAndCapture`](src/modules/colorPicker/ColorPicker.UITests/ColorPickerEndToEndTests.cs),
drives the full E2E:
1. Navigate to the Color Picker page via the dashboard utilities stack
2. Toggle the module OFF, verify `PowerToys.ColorPickerUI` exits; toggle
ON, verify it respawns
3. Read the activation shortcut from the page's `ShortcutControl`
(`EditButton.HelpText`)
4. Clear clipboard, park cursor, send the chord
5. Wait for the picker overlay window
6. Read the displayed HEX from a hidden XAML automation peer (see below)
7. Left-click to capture; assert the clipboard value matches the peer's
HEX
8. Wait for the editor window and assert the captured color appears in
its tree
**[`src/settings-ui/Settings.UITests/`](src/settings-ui/Settings.UITests/)**
— `SettingsNavigationSmokeTests.NavigationItem_NavigatesWithoutCrashing`
is one `[TestMethod]` parameterized with `[DynamicData]`, producing 31
discrete results — one per `NavigationViewItem` in
[`ShellPage.xaml`](src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml).
For each item: navigate, settle 250ms, assert `PowerToys.Settings` is
still alive. Catches FailFast regressions in
`ShellViewModel.Frame_NavigationFailed` that pure-logic unit tests can't
reach (the failure path needs a `NavigationFailedEventArgs` which is a
sealed WinRT projection).
### Product change
**[`src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml`](src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml)**
— adds a hidden `TextBlock` automation peer:
```xml
<TextBlock
x:Name="ColorHexAutomationPeer"
AutomationProperties.AutomationId="ColorHexAutomationPeer"
IsHitTestVisible="False"
Opacity="0"
Text="{Binding ColorText}" />
```
The visible `ColorTextBlock` has `AutomationProperties.Name="{Binding
ColorName}"`, which masks the HEX value in the UIA tree (you see "White"
instead of `#FFFFFF`). This zero-impact peer mirrors `ColorText` so
tests can read the actually-displayed HEX. `Opacity=0` +
`IsHitTestVisible=False` keep it out of the visual layout and out of
accessibility focus.
### Project wiring
- [`PowerToys.slnx`](PowerToys.slnx) — registers `UITestAutomation.Next`
under `/common/`, `ColorPicker.UITests` under
`/modules/colorpicker/Tests/`, and `Settings.UITests` under
`/settings-ui/Tests/`. Original `UITest-ColorPicker` stub csproj
removed.
-
[`.github/actions/spell-check/expect.txt`](.github/actions/spell-check/expect.txt)
— adds `winapp` / `winappcli`.
### Not in this PR
- No pipeline changes. `winapp.exe` is expected to be pre-staged on the
test agent image. If it's missing, `UITestBase` fails the first test
with the install hint (`winget install Microsoft.winappcli`) rather than
producing 30 opaque per-test errors.
- No changes to the legacy `UITestAutomation` library or any of the
existing `*.UITests` projects.
## Validation
- All three projects build clean on `x64|Debug` (empty
`build.<config>.<plat>.errors.log`):
- `src/common/UITestAutomation.Next/`
- `src/modules/colorPicker/ColorPicker.UITests/`
- `src/settings-ui/Settings.UITests/`
- Both tests run in Test Explorer / `dotnet test` via
Microsoft.Testing.Platform (already enabled repo-wide in
`Directory.Build.props`).
- Local runs: ColorPicker E2E green; Settings smoke green across all 31
nav items.
- `winapp 0.3.2` from `winget install Microsoft.winappcli`.
## Notes for reviewers
- **`UseShellExecute = true`** in `SessionHelper.EnsureRunning` is
intentional — `false` makes child processes inherit the test host's
stdin/stdout/stderr handles, which keeps MTP/Test Explorer marking the
run as "in progress" until the spawned PowerToys exits.
- **Process-scope (`-a`) targeting** in the Settings smoke test handles
single-instance handoff: the EXE you launch may exit with code 0
immediately after signalling an existing owner, so the alive check uses
`Process.GetProcessesByName` rather than the launcher PID.
- **AutomationId-only selectors** in the Settings smoke list keep the
test localization-independent. Parent groups have
`SelectsOnInvoked="False"` and only expand on click — `Element.Click`
tries `InvokePattern → TogglePattern → SelectionItemPattern →
ExpandCollapsePattern` so the same call works for both leaves and
groups.
- **Untitled-window discovery**: filtered `winapp ui list-windows -a
<name>` returns windows that the unfiltered call drops (e.g. ColorPicker
editor). `WindowsFinder.ListByApp` uses the filtered form. Reported
upstream.
## Before Merge
- Add the `winappcli` install step to the UI-test pipeline.
2026-07-07 22:58:08 -07:00
|
|
|
<Project Path="src/modules/colorPicker/ColorPicker.UITests/ColorPicker.UITests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/CommandPalette/">
|
|
|
|
|
<Project Path="src/modules/cmdpal/CmdPalKeyboardService/CmdPalKeyboardService.vcxproj" Id="5f63c743-f6ce-4dba-a200-2b3f8a14e8c2" />
|
|
|
|
|
<Project Path="src/modules/cmdpal/CmdPalModuleInterface/CmdPalModuleInterface.vcxproj" Id="0adeb797-c8c7-4ffa-acd5-2af6cad7ecd8" />
|
2026-02-23 04:05:09 -08:00
|
|
|
<Project Path="src/modules/cmdpal/Microsoft.CmdPal.Common/Microsoft.CmdPal.Common.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/CommandPalette/Built-in Extensions/">
|
[UITests] New framework around WinApp CLI, no WinAppDriver or Selenium. (#48467)
# Add winappcli-based UI test harness (no WinAppDriver / Selenium)
## Summary
Introduces a new UI test harness — `Microsoft.PowerToys.UITest.Next` —
that drives PowerToys
modules through Microsoft's
[winappcli](https://github.com/microsoft/WinAppCli) (UI Automation
CLI) instead of WinAppDriver + Selenium. Engine is a single executable
shelled out from
C#; no third-party NuGet packages, no driver process, no Appium server.
Adds two real consumers:
a full ColorPicker end-to-end scenario and a Settings shell navigation
smoke test.
This is opt-in and additive — the existing `UITestAutomation` library
and the
WinAppDriver-based test projects are untouched. Both can coexist while
we evaluate the new
harness.
Inspired in part by
[#48414](https://github.com/microsoft/PowerToys/pull/48414), which lands
the same architectural bet (winappcli, AutomationId selectors, no
WinAppDriver) at a smaller
scope. This PR generalizes it into a reusable library.
## Why
WinAppDriver + Selenium is a legacy pre-agentic solution that is no
longer actively maintained. It's unreliable, heavyweight, and slow. To
achieve 100% UI test coverage, we should leverage modern, reliable
solutions, and WinApp CLI is a strong candidate.
## What's in this PR
### Harness library —
[`src/common/UITestAutomation.Next/`](src/common/UITestAutomation.Next/)
| File | Purpose |
|---|---|
| [`WinappCli.cs`](src/common/UITestAutomation.Next/WinappCli.cs) |
Process wrapper around `winapp.exe`. `Invoke` / `InvokeAssertSuccess` /
`InvokeJson` / `IsAvailable` / `TryResolveExecutable`. `Result` carries
the args and emits `DescribeFailure()` like `winapp ui invoke X -w 12345
-> exit 1; stderr: ...` |
| [`Session.cs`](src/common/UITestAutomation.Next/Session.cs) | Test
session, scoped by either HWND (`-w`) or process (`-a`) via
`TargetScope`. `Find<T>` / `FindAll<T>` / `Inspect` / `Screenshot` /
`SendKeys`. `Session.FromProcess(...)` factory for the
single-window-per-process case |
|
[`SessionHelper.cs`](src/common/UITestAutomation.Next/SessionHelper.cs)
| Owns the launch + window-readiness flow. Static `EnsureRunning(scope,
timeout)` returns whether the call had to launch (so cleanup only kills
what we started). Uses `UseShellExecute=true` so child handles don't
keep MSTest hanging |
| [`UITestBase.cs`](src/common/UITestAutomation.Next/UITestBase.cs) |
MSTest base class. Pre-flights `WinappCli.IsAvailable()` once per
process and fails fast with the install hint if `winapp.exe` isn't on
PATH |
| [`Element/*.cs`](src/common/UITestAutomation.Next/Element/) |
`Element`, `Button`, `ToggleSwitch`, `TextBox`, `NavigationViewItem`,
`Window`. `Click` / `MouseClick` / `Focus` / `GetProperty` / `GetValue`
/ `HelpText` / `WaitForProperty` / `WaitForGone` plus coords
(`X`/`Y`/`Width`/`Height`) |
| [`By.cs`](src/common/UITestAutomation.Next/By.cs) | `By.Name` /
`By.AccessibilityId` / `By.Id` / `By.Slug` |
| [`Windows.cs`](src/common/UITestAutomation.Next/Windows.cs) |
`WindowsFinder.ListAll` / `ListByApp` / `WaitForWindowByApp` /
`WaitForWindowByProcess`. Notes the winappcli bug where unfiltered
`list-windows` drops untitled windows |
|
[`WindowControl.cs`](src/common/UITestAutomation.Next/WindowControl.cs)
| Tolerant Win32 helpers — `TryCloseByApp` / `TryFocusByApp` /
`SafeCloseAndFocus` / `TryKillProcess` — for `finally` blocks |
|
[`KeyboardHelper.cs`](src/common/UITestAutomation.Next/KeyboardHelper.cs)
| Hybrid `keybd_event` + `SendKeys.SendWait` chord sender — required for
global PowerToys hotkeys |
| [`MouseHelper.cs`](src/common/UITestAutomation.Next/MouseHelper.cs) |
`MoveTo` / `LeftClick` / `RightClick` / `LeftClickAt` Win32 wrappers |
|
[`ClipboardHelper.cs`](src/common/UITestAutomation.Next/ClipboardHelper.cs)
| STA-thread `Clipboard` access with `WaitForText` |
|
[`ModuleConfigData.cs`](src/common/UITestAutomation.Next/ModuleConfigData.cs)
| `PowerToysModule` enum + path/process-name resolution |
### Tests
**[`src/modules/colorPicker/ColorPicker.UITests/`](src/modules/colorPicker/ColorPicker.UITests/)**
— replaces the previous empty `UITest-ColorPicker` stub. One test,
[`ColorPickerEndToEndTests.NavigateReadShortcutActivateAndCapture`](src/modules/colorPicker/ColorPicker.UITests/ColorPickerEndToEndTests.cs),
drives the full E2E:
1. Navigate to the Color Picker page via the dashboard utilities stack
2. Toggle the module OFF, verify `PowerToys.ColorPickerUI` exits; toggle
ON, verify it respawns
3. Read the activation shortcut from the page's `ShortcutControl`
(`EditButton.HelpText`)
4. Clear clipboard, park cursor, send the chord
5. Wait for the picker overlay window
6. Read the displayed HEX from a hidden XAML automation peer (see below)
7. Left-click to capture; assert the clipboard value matches the peer's
HEX
8. Wait for the editor window and assert the captured color appears in
its tree
**[`src/settings-ui/Settings.UITests/`](src/settings-ui/Settings.UITests/)**
— `SettingsNavigationSmokeTests.NavigationItem_NavigatesWithoutCrashing`
is one `[TestMethod]` parameterized with `[DynamicData]`, producing 31
discrete results — one per `NavigationViewItem` in
[`ShellPage.xaml`](src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml).
For each item: navigate, settle 250ms, assert `PowerToys.Settings` is
still alive. Catches FailFast regressions in
`ShellViewModel.Frame_NavigationFailed` that pure-logic unit tests can't
reach (the failure path needs a `NavigationFailedEventArgs` which is a
sealed WinRT projection).
### Product change
**[`src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml`](src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml)**
— adds a hidden `TextBlock` automation peer:
```xml
<TextBlock
x:Name="ColorHexAutomationPeer"
AutomationProperties.AutomationId="ColorHexAutomationPeer"
IsHitTestVisible="False"
Opacity="0"
Text="{Binding ColorText}" />
```
The visible `ColorTextBlock` has `AutomationProperties.Name="{Binding
ColorName}"`, which masks the HEX value in the UIA tree (you see "White"
instead of `#FFFFFF`). This zero-impact peer mirrors `ColorText` so
tests can read the actually-displayed HEX. `Opacity=0` +
`IsHitTestVisible=False` keep it out of the visual layout and out of
accessibility focus.
### Project wiring
- [`PowerToys.slnx`](PowerToys.slnx) — registers `UITestAutomation.Next`
under `/common/`, `ColorPicker.UITests` under
`/modules/colorpicker/Tests/`, and `Settings.UITests` under
`/settings-ui/Tests/`. Original `UITest-ColorPicker` stub csproj
removed.
-
[`.github/actions/spell-check/expect.txt`](.github/actions/spell-check/expect.txt)
— adds `winapp` / `winappcli`.
### Not in this PR
- No pipeline changes. `winapp.exe` is expected to be pre-staged on the
test agent image. If it's missing, `UITestBase` fails the first test
with the install hint (`winget install Microsoft.winappcli`) rather than
producing 30 opaque per-test errors.
- No changes to the legacy `UITestAutomation` library or any of the
existing `*.UITests` projects.
## Validation
- All three projects build clean on `x64|Debug` (empty
`build.<config>.<plat>.errors.log`):
- `src/common/UITestAutomation.Next/`
- `src/modules/colorPicker/ColorPicker.UITests/`
- `src/settings-ui/Settings.UITests/`
- Both tests run in Test Explorer / `dotnet test` via
Microsoft.Testing.Platform (already enabled repo-wide in
`Directory.Build.props`).
- Local runs: ColorPicker E2E green; Settings smoke green across all 31
nav items.
- `winapp 0.3.2` from `winget install Microsoft.winappcli`.
## Notes for reviewers
- **`UseShellExecute = true`** in `SessionHelper.EnsureRunning` is
intentional — `false` makes child processes inherit the test host's
stdin/stdout/stderr handles, which keeps MTP/Test Explorer marking the
run as "in progress" until the spawned PowerToys exits.
- **Process-scope (`-a`) targeting** in the Settings smoke test handles
single-instance handoff: the EXE you launch may exit with code 0
immediately after signalling an existing owner, so the alive check uses
`Process.GetProcessesByName` rather than the launcher PID.
- **AutomationId-only selectors** in the Settings smoke list keep the
test localization-independent. Parent groups have
`SelectsOnInvoked="False"` and only expand on click — `Element.Click`
tries `InvokePattern → TogglePattern → SelectionItemPattern →
ExpandCollapsePattern` so the same call works for both leaves and
groups.
- **Untitled-window discovery**: filtered `winapp ui list-windows -a
<name>` returns windows that the unfiltered call drops (e.g. ColorPicker
editor). `WindowsFinder.ListByApp` uses the filtered form. Reported
upstream.
## Before Merge
- Add the `winappcli` install step to the UI-test pipeline.
2026-07-07 22:58:08 -07:00
|
|
|
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Actions/Microsoft.CmdPal.Ext.Actions.csproj">
|
2025-12-03 03:59:46 -06:00
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
[UITests] New framework around WinApp CLI, no WinAppDriver or Selenium. (#48467)
# Add winappcli-based UI test harness (no WinAppDriver / Selenium)
## Summary
Introduces a new UI test harness — `Microsoft.PowerToys.UITest.Next` —
that drives PowerToys
modules through Microsoft's
[winappcli](https://github.com/microsoft/WinAppCli) (UI Automation
CLI) instead of WinAppDriver + Selenium. Engine is a single executable
shelled out from
C#; no third-party NuGet packages, no driver process, no Appium server.
Adds two real consumers:
a full ColorPicker end-to-end scenario and a Settings shell navigation
smoke test.
This is opt-in and additive — the existing `UITestAutomation` library
and the
WinAppDriver-based test projects are untouched. Both can coexist while
we evaluate the new
harness.
Inspired in part by
[#48414](https://github.com/microsoft/PowerToys/pull/48414), which lands
the same architectural bet (winappcli, AutomationId selectors, no
WinAppDriver) at a smaller
scope. This PR generalizes it into a reusable library.
## Why
WinAppDriver + Selenium is a legacy pre-agentic solution that is no
longer actively maintained. It's unreliable, heavyweight, and slow. To
achieve 100% UI test coverage, we should leverage modern, reliable
solutions, and WinApp CLI is a strong candidate.
## What's in this PR
### Harness library —
[`src/common/UITestAutomation.Next/`](src/common/UITestAutomation.Next/)
| File | Purpose |
|---|---|
| [`WinappCli.cs`](src/common/UITestAutomation.Next/WinappCli.cs) |
Process wrapper around `winapp.exe`. `Invoke` / `InvokeAssertSuccess` /
`InvokeJson` / `IsAvailable` / `TryResolveExecutable`. `Result` carries
the args and emits `DescribeFailure()` like `winapp ui invoke X -w 12345
-> exit 1; stderr: ...` |
| [`Session.cs`](src/common/UITestAutomation.Next/Session.cs) | Test
session, scoped by either HWND (`-w`) or process (`-a`) via
`TargetScope`. `Find<T>` / `FindAll<T>` / `Inspect` / `Screenshot` /
`SendKeys`. `Session.FromProcess(...)` factory for the
single-window-per-process case |
|
[`SessionHelper.cs`](src/common/UITestAutomation.Next/SessionHelper.cs)
| Owns the launch + window-readiness flow. Static `EnsureRunning(scope,
timeout)` returns whether the call had to launch (so cleanup only kills
what we started). Uses `UseShellExecute=true` so child handles don't
keep MSTest hanging |
| [`UITestBase.cs`](src/common/UITestAutomation.Next/UITestBase.cs) |
MSTest base class. Pre-flights `WinappCli.IsAvailable()` once per
process and fails fast with the install hint if `winapp.exe` isn't on
PATH |
| [`Element/*.cs`](src/common/UITestAutomation.Next/Element/) |
`Element`, `Button`, `ToggleSwitch`, `TextBox`, `NavigationViewItem`,
`Window`. `Click` / `MouseClick` / `Focus` / `GetProperty` / `GetValue`
/ `HelpText` / `WaitForProperty` / `WaitForGone` plus coords
(`X`/`Y`/`Width`/`Height`) |
| [`By.cs`](src/common/UITestAutomation.Next/By.cs) | `By.Name` /
`By.AccessibilityId` / `By.Id` / `By.Slug` |
| [`Windows.cs`](src/common/UITestAutomation.Next/Windows.cs) |
`WindowsFinder.ListAll` / `ListByApp` / `WaitForWindowByApp` /
`WaitForWindowByProcess`. Notes the winappcli bug where unfiltered
`list-windows` drops untitled windows |
|
[`WindowControl.cs`](src/common/UITestAutomation.Next/WindowControl.cs)
| Tolerant Win32 helpers — `TryCloseByApp` / `TryFocusByApp` /
`SafeCloseAndFocus` / `TryKillProcess` — for `finally` blocks |
|
[`KeyboardHelper.cs`](src/common/UITestAutomation.Next/KeyboardHelper.cs)
| Hybrid `keybd_event` + `SendKeys.SendWait` chord sender — required for
global PowerToys hotkeys |
| [`MouseHelper.cs`](src/common/UITestAutomation.Next/MouseHelper.cs) |
`MoveTo` / `LeftClick` / `RightClick` / `LeftClickAt` Win32 wrappers |
|
[`ClipboardHelper.cs`](src/common/UITestAutomation.Next/ClipboardHelper.cs)
| STA-thread `Clipboard` access with `WaitForText` |
|
[`ModuleConfigData.cs`](src/common/UITestAutomation.Next/ModuleConfigData.cs)
| `PowerToysModule` enum + path/process-name resolution |
### Tests
**[`src/modules/colorPicker/ColorPicker.UITests/`](src/modules/colorPicker/ColorPicker.UITests/)**
— replaces the previous empty `UITest-ColorPicker` stub. One test,
[`ColorPickerEndToEndTests.NavigateReadShortcutActivateAndCapture`](src/modules/colorPicker/ColorPicker.UITests/ColorPickerEndToEndTests.cs),
drives the full E2E:
1. Navigate to the Color Picker page via the dashboard utilities stack
2. Toggle the module OFF, verify `PowerToys.ColorPickerUI` exits; toggle
ON, verify it respawns
3. Read the activation shortcut from the page's `ShortcutControl`
(`EditButton.HelpText`)
4. Clear clipboard, park cursor, send the chord
5. Wait for the picker overlay window
6. Read the displayed HEX from a hidden XAML automation peer (see below)
7. Left-click to capture; assert the clipboard value matches the peer's
HEX
8. Wait for the editor window and assert the captured color appears in
its tree
**[`src/settings-ui/Settings.UITests/`](src/settings-ui/Settings.UITests/)**
— `SettingsNavigationSmokeTests.NavigationItem_NavigatesWithoutCrashing`
is one `[TestMethod]` parameterized with `[DynamicData]`, producing 31
discrete results — one per `NavigationViewItem` in
[`ShellPage.xaml`](src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml).
For each item: navigate, settle 250ms, assert `PowerToys.Settings` is
still alive. Catches FailFast regressions in
`ShellViewModel.Frame_NavigationFailed` that pure-logic unit tests can't
reach (the failure path needs a `NavigationFailedEventArgs` which is a
sealed WinRT projection).
### Product change
**[`src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml`](src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml)**
— adds a hidden `TextBlock` automation peer:
```xml
<TextBlock
x:Name="ColorHexAutomationPeer"
AutomationProperties.AutomationId="ColorHexAutomationPeer"
IsHitTestVisible="False"
Opacity="0"
Text="{Binding ColorText}" />
```
The visible `ColorTextBlock` has `AutomationProperties.Name="{Binding
ColorName}"`, which masks the HEX value in the UIA tree (you see "White"
instead of `#FFFFFF`). This zero-impact peer mirrors `ColorText` so
tests can read the actually-displayed HEX. `Opacity=0` +
`IsHitTestVisible=False` keep it out of the visual layout and out of
accessibility focus.
### Project wiring
- [`PowerToys.slnx`](PowerToys.slnx) — registers `UITestAutomation.Next`
under `/common/`, `ColorPicker.UITests` under
`/modules/colorpicker/Tests/`, and `Settings.UITests` under
`/settings-ui/Tests/`. Original `UITest-ColorPicker` stub csproj
removed.
-
[`.github/actions/spell-check/expect.txt`](.github/actions/spell-check/expect.txt)
— adds `winapp` / `winappcli`.
### Not in this PR
- No pipeline changes. `winapp.exe` is expected to be pre-staged on the
test agent image. If it's missing, `UITestBase` fails the first test
with the install hint (`winget install Microsoft.winappcli`) rather than
producing 30 opaque per-test errors.
- No changes to the legacy `UITestAutomation` library or any of the
existing `*.UITests` projects.
## Validation
- All three projects build clean on `x64|Debug` (empty
`build.<config>.<plat>.errors.log`):
- `src/common/UITestAutomation.Next/`
- `src/modules/colorPicker/ColorPicker.UITests/`
- `src/settings-ui/Settings.UITests/`
- Both tests run in Test Explorer / `dotnet test` via
Microsoft.Testing.Platform (already enabled repo-wide in
`Directory.Build.props`).
- Local runs: ColorPicker E2E green; Settings smoke green across all 31
nav items.
- `winapp 0.3.2` from `winget install Microsoft.winappcli`.
## Notes for reviewers
- **`UseShellExecute = true`** in `SessionHelper.EnsureRunning` is
intentional — `false` makes child processes inherit the test host's
stdin/stdout/stderr handles, which keeps MTP/Test Explorer marking the
run as "in progress" until the spawned PowerToys exits.
- **Process-scope (`-a`) targeting** in the Settings smoke test handles
single-instance handoff: the EXE you launch may exit with code 0
immediately after signalling an existing owner, so the alive check uses
`Process.GetProcessesByName` rather than the launcher PID.
- **AutomationId-only selectors** in the Settings smoke list keep the
test localization-independent. Parent groups have
`SelectsOnInvoked="False"` and only expand on click — `Element.Click`
tries `InvokePattern → TogglePattern → SelectionItemPattern →
ExpandCollapsePattern` so the same call works for both leaves and
groups.
- **Untitled-window discovery**: filtered `winapp ui list-windows -a
<name>` returns windows that the unfiltered call drops (e.g. ColorPicker
editor). `WindowsFinder.ListByApp` uses the filtered form. Reported
upstream.
## Before Merge
- Add the `winappcli` install step to the UI-test pipeline.
2026-07-07 22:58:08 -07:00
|
|
|
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Microsoft.CmdPal.Ext.Apps.csproj">
|
2026-05-15 20:31:32 -05:00
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Microsoft.CmdPal.Ext.Bookmarks.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Microsoft.CmdPal.Ext.Calc.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Microsoft.CmdPal.Ext.ClipboardHistory.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Microsoft.CmdPal.Ext.Indexer.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
<Deploy />
|
|
|
|
|
</Project>
|
2026-02-10 06:00:27 -06:00
|
|
|
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PerformanceMonitor/Microsoft.CmdPal.Ext.PerformanceMonitor.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-23 21:07:44 +08:00
|
|
|
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Microsoft.CmdPal.Ext.PowerToys.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
<Deploy />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Microsoft.CmdPal.Ext.Registry.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.RemoteDesktop/Microsoft.CmdPal.Ext.RemoteDesktop.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Microsoft.CmdPal.Ext.Shell.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Microsoft.CmdPal.Ext.System.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Microsoft.CmdPal.Ext.TimeDate.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
<Deploy />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Microsoft.CmdPal.Ext.WebSearch.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Microsoft.CmdPal.Ext.WindowsServices.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Microsoft.CmdPal.Ext.WindowsSettings.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Microsoft.CmdPal.Ext.WindowsTerminal.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Microsoft.CmdPal.Ext.WindowWalker.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Microsoft.CmdPal.Ext.WinGet.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
<Deploy />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/CommandPalette/Extension SDK/">
|
|
|
|
|
<Project Path="src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/Microsoft.CommandPalette.Extensions.Toolkit.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions/Microsoft.CommandPalette.Extensions.vcxproj" Id="305dd37e-c85d-4b08-aafe-7381fa890463" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/CommandPalette/Sample Extensions/">
|
|
|
|
|
<Project Path="src/modules/cmdpal/ext/ProcessMonitorExtension/ProcessMonitorExtension.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
<Deploy />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/ext/SamplePagesExtension/SamplePagesExtension.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
<Deploy />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/CommandPalette/Tests/">
|
2026-02-23 04:05:09 -08:00
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Common.UnitTests/Microsoft.CmdPal.Common.UnitTests.csproj">
|
CmdPal: GEH per partes; part 1: error report builder, sanitizer and internals tools setting page (#44140)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
This PR adds three parts of the original big bad global error handler
(error report builder, sanitization and internal tools UI).
### Error Report Generation
- `ErrorReportBuilder`: Produces a detailed, technical report with
system context.
- Comprehensive data: OS version, architecture, culture, app version,
elevation status, etc.
- Exception analysis: Coalesces nested exception messages and HRESULT
details for clearer diagnostics.
<details><summary>Example</summary>
<pre>
This is an error report generated by Windows Command Palette.
If you are seeing this, it means something went a little sideways in the
app.
You can help us fix it by filing a report at
https://aka.ms/powerToysReportBug.
(While you’re at it, give the details below a quick skim — just to make
sure there’s nothing personal you’d prefer not to share. It’s rare, but
sometimes little surprises sneak in.)
============================================================
Summary:
Message: Test exception; thrown from the UI thread
Type: System.NotImplementedException
Source: Microsoft.CmdPal.UI
Time: 2025-08-25 18:54:44.3854569
HRESULT: 0x80004001 (-2147467263)
Context: MainThreadException
Application:
App version: 0.0.1.0
Is elevated: no
Environment:
OS version: Microsoft Windows 10.0.26120
OS architecture: X64
Runtime identifier: win-x64
Framework: .NET 9.0.8
Process architecture: X64
Culture: cs-CZ
UI culture: en-US
Stack Trace:
at
Microsoft.CmdPal.UI.Settings.InternalPage.ThrowPlainMainThreadException_Click(Object
sender, RoutedEventArgs e)
at
WinRT._EventSource_global__Microsoft_UI_Xaml_RoutedEventHandler.EventState.<GetEventInvoke>b__1_0(Object
sender, RoutedEventArgs e)
at ABI.Microsoft.UI.Xaml.RoutedEventHandler.Do_Abi_Invoke(IntPtr
thisPtr, IntPtr sender, IntPtr e)
------------------ Full Exception Details ------------------
System.NotImplementedException: Test exception; thrown from the UI
thread
at
Microsoft.CmdPal.UI.Settings.InternalPage.ThrowPlainMainThreadException_Click(Object
sender, RoutedEventArgs e)
at
WinRT._EventSource_global__Microsoft_UI_Xaml_RoutedEventHandler.EventState.<GetEventInvoke>b__1_0(Object
sender, RoutedEventArgs e)
at ABI.Microsoft.UI.Xaml.RoutedEventHandler.Do_Abi_Invoke(IntPtr
thisPtr, IntPtr sender, IntPtr e)
============================================================
</pre>
</details>
Real-world example: #41362
### PII Sanitization Framework
- `ErrorReportSanitizer`: Multi-layer sanitization pipeline for
sensitive data.
- Nine specialized rule providers:
- `PiiRuleProvider`: Personally identifiable information (emails, phone
numbers, SSNs).
- `ProfilePathAndUsernameRuleProvider`: Windows user profiles and
usernames.
- `NetworkRuleProvider`: IP addresses, MAC addresses, network
identifiers.
- `SecretKeyValueRulesProvider`: API keys, tokens, passwords in
key/value formats.
- `FilenameMaskRuleProvider`: Sensitive file paths and extensions.
- `UrlRuleProvider`: URLs and web addresses.
- `TokenRuleProvider`: JWT and other auth tokens.
- `ConnectionStringRuleProvider`: Database connection strings.
- `EnvironmentPropertiesRuleProvider`: Environment variables and system
properties.
### Internals Tools Page
A page in settings available in non-CI-builds:
<img width="1305" height="745" alt="image"
src="https://github.com/user-attachments/assets/3145ecfd-997f-491d-8c8a-6096634b6045"
/>
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx
<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-01-29 04:09:37 +01:00
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.Apps.UnitTests/Microsoft.CmdPal.Ext.Apps.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.Bookmarks.UnitTests/Microsoft.CmdPal.Ext.Bookmarks.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.Calc.UnitTests/Microsoft.CmdPal.Ext.Calc.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.ClipboardHistory.UnitTests/Microsoft.CmdPal.Ext.ClipboardHistory.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2026-04-20 17:41:27 +02:00
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.Indexer.UnitTests/Microsoft.CmdPal.Ext.Indexer.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2026-07-17 13:56:24 -04:00
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.PerformanceMonitor.UnitTests/Microsoft.CmdPal.Ext.PerformanceMonitor.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.Registry.UnitTests/Microsoft.CmdPal.Ext.Registry.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.RemoteDesktop.UnitTests/Microsoft.CmdPal.Ext.RemoteDesktop.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.Shell.UnitTests/Microsoft.CmdPal.Ext.Shell.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.System.UnitTests/Microsoft.CmdPal.Ext.System.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.TimeDate.UnitTests/Microsoft.CmdPal.Ext.TimeDate.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.UnitTestsBase/Microsoft.CmdPal.Ext.UnitTestBase.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.WebSearch.UnitTests/Microsoft.CmdPal.Ext.WebSearch.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
CmdPal: Add Control Panel tasks to Windows Settings search (#49252)
## Summary of the Pull Request
The Command Palette's Windows Settings extension only matches queries
against the
static `WindowsSettings.json` list, so Control Panel tasks that Windows
itself
exposes — "Set up USB game controllers", "File History", "Adjust the
appearance and
performance of Windows" — can never be found, even though Control
Panel's own
search finds them instantly.
This adds a second, dynamic source. At startup the extension enumerates
the Control
Panel tasks from the shell's "All Tasks" folder (the same data Control
Panel search
uses, ~150 tasks) and merges them into the searchable set, de-duplicated
against the
existing entries.
## PR Checklist
- [x] Closes: #48539
- [x] **Communication:** Discussed in #48539
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
## Detailed Description of the Pull Request / Additional comments
**Enumeration.** `ControlPanelTasksHelper` binds the shell "All Tasks"
folder
(`shell:::{ED7BA470-8E54-465E-825C-99712043E01C}`) to `IEnumShellItems`
and reads each
item's display name. Those names come from the shell **already
localized**, so the merge
deliberately runs *after* `TranslationHelper.TranslateAllSettings` —
they must not go
through resx translation. Merged entries are typed as Control Panel, so
their subtitle
reuses the existing localized string.
**Launching.** Control Panel task items have no executable command line,
and they cannot
be re-parsed from their parsing name (`SHParseDisplayName` fails on
them). Their shell id
list (PIDL) is therefore captured during enumeration via
`SHGetIDListFromObject` and
stored on the entry; invoking the result launches it with
`ShellExecuteEx(SEE_MASK_IDLIST)`.
**AOT.** All interop is source-generated (`LibraryImport` +
`GeneratedComInterface` with
`StrategyBasedComWrappers`), so the extension stays `IsAotCompatible`.
**Startup.** Enumeration runs on a background task so the provider
constructor never
blocks, and it degrades gracefully — if the shell namespace is
unavailable the helper logs
a warning and returns an empty list, leaving search exactly as it is
today.
**UX.** Merged entries get `AppHomepageScore = 0`, so they never appear
on an empty query.
De-duplication checks both `Name` and `AltNames` of existing settings.
**No pipeline changes needed:** the new unit test project follows the
same pattern as
`Microsoft.CmdPal.Ext.Registry.UnitTests` — registered in
`PowerToys.slnx` and the CmdPal
solution filters, and picked up by the existing `**\*UnitTest*.dll`
glob. No sibling CmdPal
unit test project is listed in `.pipelines`.
## Validation Steps Performed
**Automated** — added `Microsoft.CmdPal.Ext.WindowsSettings.UnitTests`
(this extension's
first test project). 8 tests, all passing:
- 7 unit tests over the merge: adds new tasks; skips duplicate names
case-insensitively;
skips names matching an existing entry's `AltNames`; skips entries
missing a name or
command; de-duplicates within the incoming list; returns 0 for an empty
list; preserves
the shell command prefix.
- 1 functional test that enumerates the real shell folder and asserts
every task has a
name, a `::{`-prefixed parsing name, a non-empty id list, and the
expected settings path.
**Manual (Windows 11, x64 Debug)** — built `Microsoft.CmdPal.UI` and
drove the real palette:
- `Windows Settings` → `game controllers` returns **Set up USB game
controllers**,
subtitle **Control Panel**.
- The File History and "appearance and performance" tasks are found.
- Invoking the result opens the real Windows **Game Controllers**
dialog; the performance
task opens **Performance Options**.
- Typing the exact task name at the root surfaces it via the fallback
item, without
entering the page.
- Regression: existing `power` → **Power and sleep** still resolves, the
empty query still
shows only the homepage entries, and there are no duplicate rows.
- No perceptible delay — results were available as soon as CmdPal
finished loading.
<img width="1000" height="600"
alt="01-windows-settings-game-controllers"
src="https://github.com/user-attachments/assets/04d6ad8e-a69d-4c95-b480-05146aef8784"
/>
<img width="1000" height="600" alt="02-existing-power-result"
src="https://github.com/user-attachments/assets/62e75ea8-4a99-489a-8e7c-f7bf5813185f"
/>
<img width="1000" height="600" alt="03-root-fallback-game-controllers"
src="https://github.com/user-attachments/assets/03eb8908-b8f9-4635-a02e-29b413f0ff24"
/>
<img width="581" height="1080" alt="04-game-controllers-dialog"
src="https://github.com/user-attachments/assets/c8fa24ec-7e41-4da4-b862-e888a88dab7b"
/>
---------
Co-authored-by: Jiří Polášek <me@jiripolasek.com>
2026-07-15 20:14:42 +05:30
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.WindowsSettings.UnitTests/Microsoft.CmdPal.Ext.WindowsSettings.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.WindowWalker.UnitTests/Microsoft.CmdPal.Ext.WindowWalker.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2026-08-07 19:40:13 +02:00
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.UI.UnitTests/Microsoft.CmdPal.UI.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.UI.ViewModels.UnitTests/Microsoft.CmdPal.UI.ViewModels.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.UITests/Microsoft.CmdPal.UITests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
CmdPal: Upgrade FuzzyStringMatcher in the Command Palette Extensions SDK (#44809)
## Summary of the Pull Request
This PR upgrades the `FuzzyStringMatcher` used in the Command Palette
Extensions SDK with a focus on performance, memory efficiency, and
improved matching behavior, while preserving compatibility with the
existing API. This PR is a backwards compatible alternative to
precomputed fuzzy matcher introduces in another PR.
The new implementation is designed as a drop-in replacement. Any
behavioral differences are intentional and primarily related to improved
diacritic handling, scoring consistency, and correctness of highlight
positions.
Changes:
- Keeps the existing public API intact and preserves behavior in nearly
all cases.
- Enables diacritics-insensitive matching by default, improving results
across accented and non-English languages.
- Significantly improves performance, with measured speedups in the
range of ~5–20 times, depending on scenario and input size.
- Reduces heap allocations to near zero by using stack allocation and
pooled buffers instead of large per-match DP arrays.
- Simplifies and optimizes matching logic:
- Folds the haystack only once per match.
- Uses rolling DP buffers instead of `O(query × target)` tables.
- Replaces large match tables with a compact bitset when tracking
highlight positions.
- Improves consistency and correctness:
- Normalizes path separators (`\` → `/`) during folding.
- Avoids returning highlight positions for PinYin-only matches where no
1:1 mapping exists.
- Introduces unit tests, including comparison tests against the legacy
implementation to validate compatibility.
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
- [x] Closes: #44066
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx
<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-01-29 04:23:12 +01:00
|
|
|
<Project Path="src/modules/cmdpal/Tests/Microsoft.CommandPalette.Extensions.Toolkit.UnitTests/Microsoft.CommandPalette.Extensions.Toolkit.UnitTests.csproj" Id="2eca18b7-33b7-4829-88f1-439b20fd60f6">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/CommandPalette/UI/">
|
|
|
|
|
<Project Path="src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Microsoft.CmdPal.UI.ViewModels.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/Microsoft.CmdPal.UI/Microsoft.CmdPal.UI.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
<Deploy />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/cmdpal/Microsoft.Terminal.UI/Microsoft.Terminal.UI.vcxproj" Id="6515f03f-e56d-4db4-b23d-ac4fb80db36f" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/CropAndLock/">
|
|
|
|
|
<Project Path="src/modules/CropAndLock/CropAndLock/CropAndLock.vcxproj" Id="f5e1146e-b7b3-4e11-85fd-270a500bd78c" />
|
|
|
|
|
<Project Path="src/modules/CropAndLock/CropAndLockModuleInterface/CropAndLockModuleInterface.vcxproj" Id="3157fa75-86cf-4ee2-8f62-c43f776493c6" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/EnvironmentVariables/">
|
|
|
|
|
<Project Path="src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariables.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/EnvironmentVariables/EnvironmentVariablesModuleInterface/EnvironmentVariablesModuleInterface.vcxproj" Id="b9420661-b0e4-4241-abd4-4a27a1f64250" />
|
|
|
|
|
<Project Path="src/modules/EnvironmentVariables/EnvironmentVariablesUILib/EnvironmentVariablesUILib.csproj" />
|
|
|
|
|
</Folder>
|
[EnvironmentVariables] Validation fixes, centralised validation, error message improvements (#46837)
## Summary of the Pull Request
This fixes several critical validation issues with the Environment
Variables utility, centralises the validation, guards registry writes,
and improves error messages for validation failures.
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
- [x] Closes: #46763
<!-- - [ ] 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
This PR fixes a reported critical vulnerability (#46763) where creating
an environment variable with an equals sign in the name reportedly
caused Windows to crash and enter a boot loop upon restarting. During
the investigation of the issue, several other environment variable
constraints were identified as missing, including there being no
prevention of leading or trailing spaces in names (meaning variables
could not be typed on the command line), no combined length checks and
so on. This PR introduces a centralised, robust validation pipeline for
UI and registry writes to prevent entering states which could corrupt
the Windows environment block.
## Changes
### Centralised validation logic
- All environment validation is now inside
EnvironmentVariablesHelper.cs, rather than split between this code and
the UI.
- Both the UI (via model validate bindings) and backend registry writes
now strictly evaluate against the same unified ruleset before applying
changes or enabling/disabling controls.
- Existing methods have been updated to report back their success or
failure, to enable errors to be tracked more effectively.
### Blocked OS-breaking characters
- In response to the user report, the equals character is now blocked
from both Variable and Profile names. `=` being disallowed is
[explicitly
mentioned](https://learn.microsoft.com/en-us/windows/win32/procthread/environment-variables)
in the Environment Variables Win32 documentation, so it's a surprise it
wasn't caught previously.
- All control characters (including `\0`, `\r` and `\n`) are also
disallowed, both to protect the integrity of the environment block and
the rendering of the strings in the UI.
- Leading and trailing whitespace is rejected to prevent orphaned
variables.
### Enforced Windows length constraints
- Variable Names and Profile Names are restricted to 259 characters, to
match the 260-character null-terminated string length limit in the
Windows Environment Variables Editor (via sysdm.cpl) and RegEdit. To be
clear: profile names may technically be longer, but we should choose to
abide by this authoring tool limit to maintain compatibility with other
editors. There was previously a 255-character limit on names in the
code, and a comment indicating this was a registry limit, but that was
incorrect and has been removed. The new limit constant is
`MaxEnvironmentVariableNameAuthoringLength`.
- In the prior code, there was no limit on the length of system variable
names. This was incorrect. The limit for both System and User name
fields is now the identical at 259 characters.
- There is a length limit on the full environment variable entry
`[VariableName]=[VariableValue]\0`, which is 32766 characters plus the
null-terminator. This is now enforced and the constant is
`MaxTotalEnvironmentVariableLength`. (There's no imposed limit on the
number of environment variables.)
### Fixed User Profile backup "overflows"
- Fixed a bug where a user could create a valid Profile Name and a valid
environment variable name, but applying them would silently fail to
apply the profile because the generated backup variable name
`[VariableName]_PowerToys_[ProfileName]` exceeded the previous authoring
limit of 255 characters.
- Backup variables are excluded from the 259-character limit, as they
are internal to the application, but the combined
`[VariableName]=[VariableVavlue]\0` length is still strictly constrained
to the 32767 environment variable length limit.
There are now separate paths through the code to deal with backup
variable persistence and validation.
### UI
- If an applied user profile's name is now rejected because of the new
rules (e.g. it contains `=`), the UI now shows a specific "Profile name
is invalid" warning rather than the generic "not applicable" message
from before, allowing the user to identify and fix the problem.
- Fixed a small issue in the Add New Variable dialog where a vertical
scrollbar was always present. There are other cases where this occurs,
too, but I've left them for a future PR.
<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
New unit tests project added with coverage of the new validation
functionality.
Also, manual testing...
Manual validation of each dialog:
- Add variable
- Edit variable
- Add variable via Profile Edit dialog
Test against:
- `=` being in either the Variable Name or the Profile Name
- A control character being present in the Variable Name or Profile Name
- Either the Variable Name or Profile Name containing one or more
trailing or leading whitespace characters
- The length of the Variable Name being longer than 259 characters
- The combined length of name + `=` + value being longer than 32766
characters
The dialog tests can be confirmed by checking to see if the Save button
is enabled:
<img width="1099" height="843" alt="image"
src="https://github.com/user-attachments/assets/685e561a-bd8d-4926-b9b2-a61dea4cc96a"
/>
Also confirm:
- An invalid Profile Name is caught. This can be confirmed by:
Editing the JSON file and adding an `=` character in the name:
<img width="497" height="197" alt="image"
src="https://github.com/user-attachments/assets/c6aa5d62-0672-499a-aac4-c639e8158b61"
/>
Then opening the application and trying to enable the profile:
<img width="1117" height="371" alt="image"
src="https://github.com/user-attachments/assets/bd887a44-5e65-4750-9c6f-9bf1b82a5ad6"
/>
Also confirm that in the Edit profile dialog, you can enable the
profile, but the Save button is disabled:
<img width="688" height="603" alt="image"
src="https://github.com/user-attachments/assets/10d186d9-17a0-4210-93e3-23b1e2723f5f"
/>
- Confirm that control characters cannot be part of the Variable Name:
First, run this from PowerShell, which adds a string containing the
newline character to the clipboard:
```pwsh
Set-Clipboard -Value "MyVar`nName"
```
Open the Add or Edit variable dialog and paste the value into the Name
field. Confirm that the character is not pasted and the string truncates
before it:
<img width="1424" height="732" alt="image"
src="https://github.com/user-attachments/assets/260ff728-57a2-438f-bb66-08d32a327b64"
/>
(For the null character specifically, use `Set-Clipboard -Value ("MyVar"
+ [char]0 + "Name")`.)
- The initial dialog button state. Re-open the Add New variable dialog
multiple times and confirm the Save button is disabled each time before
making any input.
- In the Add/Edit Variable dialogs, enter a valid variable name and then
clear it, confirming that the Save button enables and disables
correctly.
## Still outstanding
There are some flaws I've found which I'm choosing to leave for now,
mainly for expedience so the above issues can be prioritised:
- Handling duplicate profile names - there is the potential there for
duplicate variable names under identically-named profiles to conflict.
- Profile JSON import is still not sanitised.
These should be added in a future PR.
2026-08-05 09:42:25 +01:00
|
|
|
<Folder Name="/modules/EnvironmentVariables/Tests/">
|
|
|
|
|
<Project Path="src/modules/EnvironmentVariables/EnvironmentVariablesUILib.Tests/EnvironmentVariablesUILib.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Folder Name="/modules/fancyzones/">
|
|
|
|
|
<Project Path="src/modules/fancyzones/editor/FancyZonesEditor/FancyZonesEditor.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/fancyzones/FancyZones/FancyZones.vcxproj" Id="ff1d7936-842a-4bbb-8bea-e9fe796de700" />
|
Add FancyZones CLI for command-line layout management (#44078)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Adds a new command-line interface (CLI) tool for FancyZones, enabling
users and automation scripts to manage window layouts without the GUI.
**Commands:**
| Command | Aliases | Description |
|---------|---------|-------------|
| `help` | | Displays general help information for all commands |
| `open-editor` | `editor`, `e` | Launch FancyZones layout editor |
| `get-monitors` | `monitors`, `m` | List all monitors and their
properties |
| `get-layouts` | `layouts`, `ls` | List all available layouts with
ASCII art preview |
| `get-active-layout` | `active`, `a` | Show currently active layout |
| `set-layout <uuid>` | `set`, `s` | Apply layout by UUID or template
name |
| `open-settings` | `settings` | Open FancyZones settings page |
| `get-hotkeys` | `hotkeys`, `hk` | List all layout hotkeys |
| `set-hotkey <key> <uuid>` | `shk` | Assign hotkey (0-9) to custom
layout |
| `remove-hotkey <key>` | `rhk` | Remove hotkey assignment |
**Key Capabilities:**
- ASCII art visualization of layouts (grid, focus, priority-grid,
canvas)
- Support for both template layouts and custom layouts
- Monitor-specific layout targeting (`--monitor N` or `--all`)
- Real-time notification to FancyZones via Windows messages
- Native AOT compilation support for fast startup
### Example Usage
```bash
# List all layouts with visual previews
FancyZonesCLI.exe ls
# Apply "columns" template to all monitors
FancyZonesCLI.exe s columns --all
# Set custom layout on monitor 2
FancyZonesCLI.exe s {uuid} --monitor 2
# Assign hotkey Win+Ctrl+Alt+3 to a layout
FancyZonesCLI.exe shk 3 {uuid}
```
https://github.com/user-attachments/assets/2b141399-a4ca-4f64-8750-f123b7e0fea7
<!-- 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
2025-12-09 10:13:48 +08:00
|
|
|
<Project Path="src/modules/fancyzones/FancyZonesCLI/FancyZonesCLI.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/modules/fancyzones/FancyZonesEditorCommon/FancyZonesEditorCommon.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj" Id="f9c68edf-ac74-4b77-9af1-005d9c9f6a99" />
|
|
|
|
|
<Project Path="src/modules/fancyzones/FancyZonesModuleInterface/FancyZonesModuleInterface.vcxproj" Id="48804216-2a0e-4168-a6d8-9cd068d14227" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/fancyzones/Tests/">
|
|
|
|
|
<Project Path="src/modules/fancyzones/FancyZones.FuzzTests/FancyZones.FuzzTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/fancyzones/FancyZones.UITests/FancyZones.UITests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/fancyzones/FancyZonesEditor.UITests/FancyZonesEditor.UITests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/fancyzones/FancyZonesEditor.UnitTests/FancyZonesEditor.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/fancyzones/FancyZonesTests/UnitTests/UnitTests.vcxproj" Id="9c6a7905-72d4-4bf5-b256-abfdaef68ae9">
|
|
|
|
|
<BuildDependency Project="src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj" />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/FileLocksmith/">
|
2026-03-26 13:21:43 +01:00
|
|
|
<Project Path="src/modules/FileLocksmith/FileLocksmithCLI/FileLocksmithCLI.vcxproj" Id="49d456d3-f485-45af-8875-45b44f193ddc" />
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/modules/FileLocksmith/FileLocksmithContextMenu/FileLocksmithContextMenu.vcxproj" Id="799a50d8-de89-4ed1-8ff8-ad5a9ed8c0ca" />
|
|
|
|
|
<Project Path="src/modules/FileLocksmith/FileLocksmithExt/FileLocksmithExt.vcxproj" Id="57175ec7-92a5-4c1e-8244-e3fbca2a81de" />
|
|
|
|
|
<Project Path="src/modules/FileLocksmith/FileLocksmithLib/FileLocksmithLib.vcxproj" Id="9d52fd25-ef90-4f9a-a015-91efc5daf54f" />
|
|
|
|
|
<Project Path="src/modules/FileLocksmith/FileLocksmithLibInterop/FileLocksmithLibInterop.vcxproj" Id="c604b37e-9d0e-4484-8778-e8b31b0e1b3a" />
|
|
|
|
|
<Project Path="src/modules/FileLocksmith/FileLocksmithUI/FileLocksmithUI.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
2026-01-06 15:59:37 +08:00
|
|
|
<Folder Name="/modules/FileLocksmith/Tests/">
|
2026-03-26 13:21:43 +01:00
|
|
|
<Project Path="src/modules/FileLocksmith/FileLocksmithCLI/tests/FileLocksmithCLIUnitTests.vcxproj" Id="a1b2c3d4-e5f6-7890-1234-567890abcdef" />
|
[UITests] Add UITest.Next suites (Image Resizer, Peek, File Explorer add‑ons, File Locksmith) + local‑VM tooling and CI test‑signing (#49671)
## Summary
Adds end‑to‑end UI tests on the `Microsoft.PowerToys.UITest.Next`
(winappcli) framework for three
modules, grows the shared `.Next` test framework with the helpers those
suites needed, and adds the
CI plumbing that lets shell‑extension tests exercise the **real**
Windows 11 modern context menu.
Also ships two agent skills that document how to write and run these
tests.
Product runtime behavior is **unchanged** — the only product edits are
test‑observability hooks in Peek
and a unit‑test project exclude.
Closes: https://github.com/microsoft/PowerToys/issues/40660
https://github.com/microsoft/PowerToys/issues/49424
https://github.com/microsoft/PowerToys/issues/40661
## What's added
### New UI test suites
- **Image Resizer** —
`src/modules/imageresizer/tests/ImageResizer.UITests`: context‑menu
enable/disable
tracking, the resize dialog, custom presets, every fit mode, every unit,
filename format, keep‑date,
shrink‑only, replace‑in‑place, and orientation.
- **Peek** — `src/modules/peek/Peek.UITests.Next`: file‑preview coverage
across image/text/archive/
markdown types with per‑arch visual baselines.
- **File Explorer add‑ons** —
`src/modules/previewpane/PreviewPane.UITests`: Preview Pane handlers and
thumbnail providers.
### `UITestAutomation.Next` framework
- New helpers: `ExplorerShell` (Shell selection/view‑mode interop),
`WaitHelper` (structured stable
waits), `WindowControl` (foreground/context‑menu/process control),
`VisualAssert` (image compare),
`WindowHelper`.
- Updates to `Session`, `UITestBase`, `SettingsConfigHelper`,
`WinappCli`.
- New `UITestAutomation.Next.UnitTests` project covering the new
wait/settings/CLI helpers.
### CI — sign sparse MSIX so the modern menu registers
- **`.pipelines/signSparsePackages.ps1`** — self‑signs each sparse
context‑menu MSIX with a
publisher‑matching test certificate and force‑trusts it (machine
stores), so
`AddPackageByUriAsync` succeeds on otherwise‑unsigned PR builds. Robust
`signtool` discovery with a
NuGet fallback; test‑only trust that asserts no security.
- Wired into **`.pipelines/v2/templates/job-test-project.yml`** as a
best‑effort step covering the
run‑in‑place, machine‑install, and per‑user‑install locations. Signs
nothing it can't (skips
already‑signed packages) and never fails the job.
### Product changes (test observability only)
- **Peek `FilePreview.xaml` / `.xaml.cs`** — a named `LoadingIndicator`
and a hidden automation peer
that exposes the current preview state as text, so tests can read load
state deterministically. No
runtime behavior change.
- **`ImageResizer.UnitTests.csproj`** — exclude the sibling
`ImageResizer.UITests\**` folder from the
unit‑test compilation.
### Agent skills & docs
- **New `ui-tests-local-vm` skill** — run `.Next` suites in persistent
dockur/windows VMs: setup,
agentic loop, image customization, troubleshooting, the shell‑extension
**signing** reference, plus
controller/guest scripts and VM templates.
- **Updated `ui-tests-migration` skill** — WinAppDriver/Selenium →
`.Next` porting guidance
(CI stability, Explorer/shell‑extension test design, patterns &
pitfalls).
- **`doc/devdocs/development/ui-tests.md`** — updated for the `.Next`
workflow.
## Testing
- All three suites pass locally and in CI across **x64 Win10**, **x64
Win11**, and **arm64** (machine
and per‑user install legs).
## Reviewer notes
- No product runtime behavior changes; product edits are limited to the
Peek test hooks above.
- The CI signing step is a **test‑only** trust anchor (self‑signed,
scoped to the agent) and is
best‑effort, so it can only add modern‑menu coverage and never regress
the job.
2026-08-10 10:55:03 -07:00
|
|
|
<Project Path="src/modules/FileLocksmith/Tests/FileLocksmith.UITests/FileLocksmith.UITests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2026-01-06 15:59:37 +08:00
|
|
|
</Folder>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Folder Name="/modules/Hosts/">
|
|
|
|
|
<Project Path="src/modules/Hosts/Hosts/Hosts.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/Hosts/HostsModuleInterface/HostsModuleInterface.vcxproj" Id="b41b888c-7db8-4747-b262-4062e05a230d" />
|
|
|
|
|
<Project Path="src/modules/Hosts/HostsUILib/HostsUILib.csproj" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/Hosts/Tests/">
|
|
|
|
|
<Project Path="src/modules/Hosts/Hosts.FuzzTests/HostsEditor.FuzzTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/Hosts/Hosts.Tests/HostsEditor.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/Hosts/Hosts.UITests/HostsEditor.UITests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/imageresizer/">
|
|
|
|
|
<Project Path="src/modules/imageresizer/dll/ImageResizerExt.vcxproj" Id="0b43679e-edfa-4da0-ad30-f4628b308b1b" />
|
2026-03-26 13:21:43 +01:00
|
|
|
<Project Path="src/modules/imageresizer/ImageResizerCLI/ImageResizerCLI.csproj">
|
2025-12-03 03:59:46 -06:00
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2026-03-26 13:21:43 +01:00
|
|
|
<Project Path="src/modules/imageresizer/ImageResizerContextMenu/ImageResizerContextMenu.vcxproj" Id="93b72a06-c8bd-484f-a6f7-c9f280b150bf" />
|
|
|
|
|
<Project Path="src/modules/imageresizer/ImageResizerLib/ImageResizerLib.vcxproj" Id="18b3db45-4ffe-4d01-97d6-5223feee1853" />
|
|
|
|
|
<Project Path="src/modules/imageresizer/ui/ImageResizerUI.csproj">
|
Add standard CLI support for Image Resizer (#44287)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Adds a dedicated command-line interface (CLI) executable for Image
Resizer (PowerToys.ImageResizerCLI.exe)
## Command
`PowerToys.ImageResizerCLI.exe [options] [files...]`
## Options (High Level)
| Option (aliases) | Description |
|-----------------|-------------|
| `--help` | Show help |
| `--show-config` | Print current effective configuration |
| `--destination`, `-d` | Output directory (optional) |
| `--width`, `-w` | Width |
| `--height`, `-h` | Height |
| `--unit`, `-u` | Unit (Pixel / Percent / Inch / Centimeter) |
| `--fit`, `-f` | Fit mode (Fill / Fit / Stretch) |
| `--size`, `-s` | Preset size index (supports `0` for Custom) |
| `--shrink-only` | Only shrink (do not enlarge) |
| `--replace` | Replace original |
| `--ignore-orientation` | Ignore EXIF orientation |
| `--remove-metadata` | Strip metadata |
| `--quality`, `-q` | JPEG quality (1–100) |
| `--keep-date-modified` | Preserve source last-write time |
| `--file-name` | Output filename format |
## Example usage
```
# Show help
PowerToys.ImageResizerCLI.exe --help
# Show current config
PowerToys.ImageResizerCLI.exe --show-config
# Resize with explicit dimensions
PowerToys.ImageResizerCLI.exe --width 800 --height 600 .\image.png
# Use preset size 0 (Custom) and output to a folder
PowerToys.ImageResizerCLI.exe --size 0 -d "C:\Output" .\photo.png
# Preserve source LastWriteTime
PowerToys.ImageResizerCLI.exe --width 800 --height 600 --keep-date-modified -d "C:\Output" .\image.png
```

<!-- 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
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** All end-user-facing strings can be localized
- [x] **Dev docs:** Added/updated
- [x] **New binaries:** Added on the required places
- [ ] [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
2025-12-26 12:54:47 +08:00
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/imageresizer/Tests/">
|
|
|
|
|
<Project Path="src/modules/imageresizer/tests/ImageResizer.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
[UITests] Add UITest.Next suites (Image Resizer, Peek, File Explorer add‑ons, File Locksmith) + local‑VM tooling and CI test‑signing (#49671)
## Summary
Adds end‑to‑end UI tests on the `Microsoft.PowerToys.UITest.Next`
(winappcli) framework for three
modules, grows the shared `.Next` test framework with the helpers those
suites needed, and adds the
CI plumbing that lets shell‑extension tests exercise the **real**
Windows 11 modern context menu.
Also ships two agent skills that document how to write and run these
tests.
Product runtime behavior is **unchanged** — the only product edits are
test‑observability hooks in Peek
and a unit‑test project exclude.
Closes: https://github.com/microsoft/PowerToys/issues/40660
https://github.com/microsoft/PowerToys/issues/49424
https://github.com/microsoft/PowerToys/issues/40661
## What's added
### New UI test suites
- **Image Resizer** —
`src/modules/imageresizer/tests/ImageResizer.UITests`: context‑menu
enable/disable
tracking, the resize dialog, custom presets, every fit mode, every unit,
filename format, keep‑date,
shrink‑only, replace‑in‑place, and orientation.
- **Peek** — `src/modules/peek/Peek.UITests.Next`: file‑preview coverage
across image/text/archive/
markdown types with per‑arch visual baselines.
- **File Explorer add‑ons** —
`src/modules/previewpane/PreviewPane.UITests`: Preview Pane handlers and
thumbnail providers.
### `UITestAutomation.Next` framework
- New helpers: `ExplorerShell` (Shell selection/view‑mode interop),
`WaitHelper` (structured stable
waits), `WindowControl` (foreground/context‑menu/process control),
`VisualAssert` (image compare),
`WindowHelper`.
- Updates to `Session`, `UITestBase`, `SettingsConfigHelper`,
`WinappCli`.
- New `UITestAutomation.Next.UnitTests` project covering the new
wait/settings/CLI helpers.
### CI — sign sparse MSIX so the modern menu registers
- **`.pipelines/signSparsePackages.ps1`** — self‑signs each sparse
context‑menu MSIX with a
publisher‑matching test certificate and force‑trusts it (machine
stores), so
`AddPackageByUriAsync` succeeds on otherwise‑unsigned PR builds. Robust
`signtool` discovery with a
NuGet fallback; test‑only trust that asserts no security.
- Wired into **`.pipelines/v2/templates/job-test-project.yml`** as a
best‑effort step covering the
run‑in‑place, machine‑install, and per‑user‑install locations. Signs
nothing it can't (skips
already‑signed packages) and never fails the job.
### Product changes (test observability only)
- **Peek `FilePreview.xaml` / `.xaml.cs`** — a named `LoadingIndicator`
and a hidden automation peer
that exposes the current preview state as text, so tests can read load
state deterministically. No
runtime behavior change.
- **`ImageResizer.UnitTests.csproj`** — exclude the sibling
`ImageResizer.UITests\**` folder from the
unit‑test compilation.
### Agent skills & docs
- **New `ui-tests-local-vm` skill** — run `.Next` suites in persistent
dockur/windows VMs: setup,
agentic loop, image customization, troubleshooting, the shell‑extension
**signing** reference, plus
controller/guest scripts and VM templates.
- **Updated `ui-tests-migration` skill** — WinAppDriver/Selenium →
`.Next` porting guidance
(CI stability, Explorer/shell‑extension test design, patterns &
pitfalls).
- **`doc/devdocs/development/ui-tests.md`** — updated for the `.Next`
workflow.
## Testing
- All three suites pass locally and in CI across **x64 Win10**, **x64
Win11**, and **arm64** (machine
and per‑user install legs).
## Reviewer notes
- No product runtime behavior changes; product edits are limited to the
Peek test hooks above.
- The CI signing step is a **test‑only** trust anchor (self‑signed,
scoped to the agent) and is
best‑effort, so it can only add modern‑menu coverage and never regress
the job.
2026-08-10 10:55:03 -07:00
|
|
|
<Project Path="src/modules/imageresizer/tests/ImageResizer.UITests/ImageResizer.UITests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/interface/">
|
|
|
|
|
<File Path="src/modules/interface/powertoy_module_interface.h" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/keyboardmanager/">
|
|
|
|
|
<Project Path="src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj" Id="8affa899-0b73-49ec-8c50-0fadda57b2fc" />
|
|
|
|
|
<Project Path="src/modules/keyboardmanager/dll/KeyboardManager.vcxproj" Id="89f34af7-1c34-4a72-aa6e-534bcf972bd9" />
|
|
|
|
|
<Project Path="src/modules/keyboardmanager/KeyboardManagerEditor/KeyboardManagerEditor.vcxproj" Id="8df78b53-200e-451f-9328-01eb907193ae" />
|
|
|
|
|
<Project Path="src/modules/keyboardmanager/KeyboardManagerEditorLibrary/KeyboardManagerEditorLibrary.vcxproj" Id="23d2070d-e4ad-4add-85a7-083d9c76ad49" />
|
|
|
|
|
<Project Path="src/modules/keyboardmanager/KeyboardManagerEditorLibraryWrapper/KeyboardManagerEditorLibraryWrapper.vcxproj" Id="4382a954-179a-4078-92af-715187dfff50" />
|
|
|
|
|
<Project Path="src/modules/keyboardmanager/KeyboardManagerEditorUI/KeyboardManagerEditorUI.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/keyboardmanager/KeyboardManagerEngine/KeyboardManagerEngine.vcxproj" Id="ba661f5b-1d5a-4ffc-9bf1-fc39df280bdd" />
|
|
|
|
|
<Project Path="src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardManagerEngineLibrary.vcxproj" Id="e496b7fc-1e99-4bab-849b-0e8367040b02" />
|
[Keyboard Manager] Fix shortcut modifier display order in the new editor (#49707)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Fix shortcut key display order in the new Keyboard Manager editor (C#
WinUI). When recording a shortcut, modifier keys are now always
displayed in the standard canonical order (Win → Ctrl → Alt → Shift →
Action key), regardless of the order the user physically pressed them.
This matches the existing behavior of the old C++ editor's
`GetKeyVector` function.
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
- [x] Closes: #48943
- [ ] **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
**Bug:** In the new C# KBM editor (`KeyboardManagerEditorUI`), the
`GetFormattedKeyList()` method in `KeyboardHookHelper.cs` displayed
modifier keys in the order the user pressed them rather than the
standard display order. For example, pressing Shift before Win would
show `Shift + Win + S` instead of `Win + Shift + S`.
**Root cause:** The `modifierKeys` list was populated by iterating
`_keyPressOrder` (which preserves temporal press order), and was then
rendered directly without sorting.
**Fix:** Added a sort step before the display loop that sorts modifier
keys using the existing `KeyboardManagerInterop.GetKeyType()` P/Invoke,
which returns the `KeyType` enum value (Win=0, Ctrl=1, Alt=2, Shift=3).
This enforces the canonical order **Win → Ctrl → Alt → Shift → Action
key**, matching the old C++ `EditorHelpers::GetKeyVector()` behavior.
**Scope:** Single-line change in
`KeyboardHookHelper.GetFormattedKeyList()`. This is a display-only fix —
it does not affect the internal key tracking (`_keyPressOrder`),
save/load logic, or hook behavior.
**Changed file:**
-
`src/modules/keyboardmanager/KeyboardManagerEditorUI/Helpers/KeyboardHookHelper.cs`
<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
1. Open the new Keyboard Manager editor
2. Click the shortcut trigger button to start recording
3. Press modifier keys in non-standard order (e.g., press Shift first,
then Win, then S)
4. **Before fix:** UI shows `Shift + Win + S`
5. **After fix:** UI shows `Win + Shift + S` (correct canonical order)
6. Verified standard-order input (e.g., Win → Shift → S) still displays
correctly
7. Verified single modifier + action key shortcuts (e.g., Ctrl+C)
display correctly
8. Verified all four modifiers (Win+Ctrl+Alt+Shift+Key) display in
correct order regardless of press sequence
9. Verified saving and loading remappings is unaffected by the display
change
````
2026-08-06 15:14:00 +05:30
|
|
|
<Project Path="src/modules/keyboardmanager/KeyboardManagerEditorUI.UnitTests/KeyboardManagerEditorUI.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
</Folder>
|
2026-03-09 00:09:53 +08:00
|
|
|
<Folder Name="/modules/MouseUtils/">
|
2026-03-04 15:46:42 -05:00
|
|
|
<Project Path="src/modules/MouseUtils/CursorWrap/CursorWrap.vcxproj" Id="48a1db8c-5df8-4fb3-9e14-2b67f3f2d8b5" />
|
|
|
|
|
<Project Path="src/modules/MouseUtils/FindMyMouse/FindMyMouse.vcxproj" Id="e94fd11c-0591-456f-899f-efc0ca548336" />
|
|
|
|
|
<Project Path="src/modules/MouseUtils/MouseHighlighter/MouseHighlighter.vcxproj" Id="782a61be-9d85-4081-b35c-1ccc9dcc1e88" />
|
|
|
|
|
<Project Path="src/modules/MouseUtils/MouseJump.Common/MouseJump.Common.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
Ready for Review - [Mouse Jump] - port upstream WinUI3 code to Mouse Jump (microsoft#48290) (#48393)
<!-- 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
Changes for #48290 to convert Mouse Jump to a WinUI app and remove all
remaining dependencies on WinForms, based on work already done in the
original "FancyMouse" project
(https://github.com/mikeclayton/FancyMouse).
## Notes for reviewers
* the new WinUI build of the app is output into the "/WinUI3Apps"
subfolder
* there's 2 new assemblies that need to be added to the installation as
well - MouseJump.HotKeys.dll and MouseJump.Models.dll. I'm not sure how
to add those to the installer for signing / shipping...
---
### Summary of changes
* New thumbnail layout and rendering code
* WinUI rewrite (winforms version still committed)
* MouseJump.Kicker (dev launch tool)
* CsWin32 for interop
* New assemblies - code reorganised
---
### 1. New layout code
Incorporates latest FancyMouse core layout and rendering logic into
Mouse Jump:
* includes **support** for multiple devices in layout algorithms
* preview still only shows local machine though
* prerequisite for long-term goal #34126
<img width="650" height="709" alt="image"
src="https://github.com/user-attachments/assets/9d1d996d-ed05-4471-b8a5-bd93442f70dc"
/>
### 2. WinUI rewrite
Port latest stable FancyMouse WinUI implementation into Mouse Jump.
Existing WinForms UI left in-situ side-by-side for now - easy to delete
if not needed.
### 3. MouseJump.Kicker
A small dev utility to start Mouse Jump without needing to build the
runner project:
<img width="283" height="274" alt="image"
src="https://github.com/user-attachments/assets/c81bb3f5-5008-48ce-8bc0-eef18413dee6"
/>
### 4. Cswin32 for interop
All win32 interop is now accessed via CsWin32 bindings.
The original win32 bindings were heavily influenced by CsWin32 generated
code (e.g. ```BOOL```, ```HWND```, etc structs), so there's not actually
much change other than deleting a lot of boilerplate code.
### 5. New assemblies
Some code has been reorganised into new assemblies to make it easier to
keep Mouse Jump in sync with upstream FancyMouse
* MouseJump.HotKeys
* MouseJump.Models
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
- [x] Closes #48290
- [x] **Communication:** I've discussed this with core contributors
already. If 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
- all ui strings come from Resources.resw
- [x] **Dev docs:** Added/updated
- no changes required
- [x] **New binaries:** Added on the required places
- no changes required
- [x] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [x] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [x] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [x] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [x] **Documentation updated:** 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
- no changes required
<!-- 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
- **Workflow tests**
- [x] Automated tests passing locally
- [x] Minimal actions workflow (spelling check) passing for PR
- [ ] Full actions workflow (msbuild) passing for PR
- **UI tests**
- [x] Happy path
- [x] preview image appears when activated
- [x] clicking the preview image moves the mouse cursor to the correct
location
- [x] right-click dismisses the preview image without moving the mouse
- [x] pressing escape dismisses the preview image without moving the
mouse
- [x] left or right clicking another application / desktop dismisses the
preview image without moving the mouse
- [x] Works on multiple monitors with different dpi scaling settings
(e.g. 100% vs 150%)
*
https://github.com/microsoft/PowerToys/pull/23566#issuecomment-1411869418
*
https://github.com/microsoft/PowerToys/pull/23566#issuecomment-1412834413
- [x] Handling negative coordinates on non-primary monitors if higher or
"lefter" than primary monitor
*
https://github.com/microsoft/PowerToys/pull/23566#issuecomment-1404931694
- [x] Mouse crosshair moves when Mouse Jump moves the cursor (mouse
clicks *and* keyboard shortcuts)
* #24523
* #24527
- [x] Activating when the preview window is already visible moves the
form to the new mouse position
- [x] Number and key shortcuts (1-9, Home / End, Left / Right Arrow)
jump to the appropriate monitor
- [x] Number-pad shortcuts (1-9 jump to the appropriate monitor
- **Settings tests**
- [x] Changing thumbnail size settings updates the size of the thumbnail
- [x] Changing preview type between Compact, Bezelled and Custom shows
the correct preview type
- [x] Changing custom preview settings shows the correct settings
- [ ] Launching with settings version 1.0 upgrades settings to version
1.1, with "Bezelled" as the default style and the "Custom" settings
preconfigured to match "Bezelled"
- **Lifecycle tests**
- [x] Starting PowerToys Runner launches MouseJump exe when enabled, and
not when disabled
- [x] Enabling / disabling Mouse Jump in settings starts / stops
MouseJump exe
- [x] Exiting PowerToys Runner stops MouseJump exe
- [x] Killing runner exe via Task Manager stops MouseJump exe
- [x] Stopping Visual Studio local debug run stops MouseJump exe
- note - runner needs to be in *non*-admin mode otherwise Visual Studio
debugger disconnects at launch
- [x] Hotkey and size settings are automatically reloaded when config
file is modified from Settings UI
- [ ] ~~Hotkey and size settings are automatically reloaded when config
file is modified manually (e.g. in notepad) while runner and
MouseJumpUI.exe are running~~
- **[Internal Test
Suite](https://github.com/microsoft/PowerToys/blob/5bc7201ae2b75b53d3a4bc35119c867ecf71c5f6/doc/releases/tests-checklist-template.md#mouse-utils)**
- [x] Enable Mouse Jump. Then:
- [x] Press the activation shortcut and verify the screens preview
appears.
- [x] Change activation shortcut and verify that new shortcut triggers
Mouse Jump.
- [x] Click around the screen preview and ensure that mouse cursor
jumped to clicked location.
- [x] Reorder screens in Display settings and confirm that Mouse Jump
reflects the change and still works correctly.
- [x] Change scaling of screens and confirm that Mouse Jump still works
correctly.
- [ ] Unplug additional monitors and confirm that Mouse Jump still works
correctly.
- [x] Disable Mouse Jump and verify that the module is not activated
when you press the activation shortcut.
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Boliang Zhang (from Dev Box) <bozhang@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: moooyo <42196638+moooyo@users.noreply.github.com>
Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com>
Copilot-Session: 8e04a72e-3b0f-4ac4-8156-d04ea9b8bb85
2026-08-07 06:34:15 +01:00
|
|
|
<Project Path="src/modules/MouseUtils/MouseJump.HotKeys/MouseJump.HotKeys.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/MouseUtils/MouseJump.Models/MouseJump.Models.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/MouseUtils/MouseJump.WinUI3/MouseJump.WinUI3.csproj">
|
2026-03-04 15:46:42 -05:00
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
Ready for Review - [Mouse Jump] - port upstream WinUI3 code to Mouse Jump (microsoft#48290) (#48393)
<!-- 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
Changes for #48290 to convert Mouse Jump to a WinUI app and remove all
remaining dependencies on WinForms, based on work already done in the
original "FancyMouse" project
(https://github.com/mikeclayton/FancyMouse).
## Notes for reviewers
* the new WinUI build of the app is output into the "/WinUI3Apps"
subfolder
* there's 2 new assemblies that need to be added to the installation as
well - MouseJump.HotKeys.dll and MouseJump.Models.dll. I'm not sure how
to add those to the installer for signing / shipping...
---
### Summary of changes
* New thumbnail layout and rendering code
* WinUI rewrite (winforms version still committed)
* MouseJump.Kicker (dev launch tool)
* CsWin32 for interop
* New assemblies - code reorganised
---
### 1. New layout code
Incorporates latest FancyMouse core layout and rendering logic into
Mouse Jump:
* includes **support** for multiple devices in layout algorithms
* preview still only shows local machine though
* prerequisite for long-term goal #34126
<img width="650" height="709" alt="image"
src="https://github.com/user-attachments/assets/9d1d996d-ed05-4471-b8a5-bd93442f70dc"
/>
### 2. WinUI rewrite
Port latest stable FancyMouse WinUI implementation into Mouse Jump.
Existing WinForms UI left in-situ side-by-side for now - easy to delete
if not needed.
### 3. MouseJump.Kicker
A small dev utility to start Mouse Jump without needing to build the
runner project:
<img width="283" height="274" alt="image"
src="https://github.com/user-attachments/assets/c81bb3f5-5008-48ce-8bc0-eef18413dee6"
/>
### 4. Cswin32 for interop
All win32 interop is now accessed via CsWin32 bindings.
The original win32 bindings were heavily influenced by CsWin32 generated
code (e.g. ```BOOL```, ```HWND```, etc structs), so there's not actually
much change other than deleting a lot of boilerplate code.
### 5. New assemblies
Some code has been reorganised into new assemblies to make it easier to
keep Mouse Jump in sync with upstream FancyMouse
* MouseJump.HotKeys
* MouseJump.Models
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
- [x] Closes #48290
- [x] **Communication:** I've discussed this with core contributors
already. If 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
- all ui strings come from Resources.resw
- [x] **Dev docs:** Added/updated
- no changes required
- [x] **New binaries:** Added on the required places
- no changes required
- [x] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [x] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [x] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [x] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [x] **Documentation updated:** 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
- no changes required
<!-- 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
- **Workflow tests**
- [x] Automated tests passing locally
- [x] Minimal actions workflow (spelling check) passing for PR
- [ ] Full actions workflow (msbuild) passing for PR
- **UI tests**
- [x] Happy path
- [x] preview image appears when activated
- [x] clicking the preview image moves the mouse cursor to the correct
location
- [x] right-click dismisses the preview image without moving the mouse
- [x] pressing escape dismisses the preview image without moving the
mouse
- [x] left or right clicking another application / desktop dismisses the
preview image without moving the mouse
- [x] Works on multiple monitors with different dpi scaling settings
(e.g. 100% vs 150%)
*
https://github.com/microsoft/PowerToys/pull/23566#issuecomment-1411869418
*
https://github.com/microsoft/PowerToys/pull/23566#issuecomment-1412834413
- [x] Handling negative coordinates on non-primary monitors if higher or
"lefter" than primary monitor
*
https://github.com/microsoft/PowerToys/pull/23566#issuecomment-1404931694
- [x] Mouse crosshair moves when Mouse Jump moves the cursor (mouse
clicks *and* keyboard shortcuts)
* #24523
* #24527
- [x] Activating when the preview window is already visible moves the
form to the new mouse position
- [x] Number and key shortcuts (1-9, Home / End, Left / Right Arrow)
jump to the appropriate monitor
- [x] Number-pad shortcuts (1-9 jump to the appropriate monitor
- **Settings tests**
- [x] Changing thumbnail size settings updates the size of the thumbnail
- [x] Changing preview type between Compact, Bezelled and Custom shows
the correct preview type
- [x] Changing custom preview settings shows the correct settings
- [ ] Launching with settings version 1.0 upgrades settings to version
1.1, with "Bezelled" as the default style and the "Custom" settings
preconfigured to match "Bezelled"
- **Lifecycle tests**
- [x] Starting PowerToys Runner launches MouseJump exe when enabled, and
not when disabled
- [x] Enabling / disabling Mouse Jump in settings starts / stops
MouseJump exe
- [x] Exiting PowerToys Runner stops MouseJump exe
- [x] Killing runner exe via Task Manager stops MouseJump exe
- [x] Stopping Visual Studio local debug run stops MouseJump exe
- note - runner needs to be in *non*-admin mode otherwise Visual Studio
debugger disconnects at launch
- [x] Hotkey and size settings are automatically reloaded when config
file is modified from Settings UI
- [ ] ~~Hotkey and size settings are automatically reloaded when config
file is modified manually (e.g. in notepad) while runner and
MouseJumpUI.exe are running~~
- **[Internal Test
Suite](https://github.com/microsoft/PowerToys/blob/5bc7201ae2b75b53d3a4bc35119c867ecf71c5f6/doc/releases/tests-checklist-template.md#mouse-utils)**
- [x] Enable Mouse Jump. Then:
- [x] Press the activation shortcut and verify the screens preview
appears.
- [x] Change activation shortcut and verify that new shortcut triggers
Mouse Jump.
- [x] Click around the screen preview and ensure that mouse cursor
jumped to clicked location.
- [x] Reorder screens in Display settings and confirm that Mouse Jump
reflects the change and still works correctly.
- [x] Change scaling of screens and confirm that Mouse Jump still works
correctly.
- [ ] Unplug additional monitors and confirm that Mouse Jump still works
correctly.
- [x] Disable Mouse Jump and verify that the module is not activated
when you press the activation shortcut.
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Boliang Zhang (from Dev Box) <bozhang@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: moooyo <42196638+moooyo@users.noreply.github.com>
Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com>
Copilot-Session: 8e04a72e-3b0f-4ac4-8156-d04ea9b8bb85
2026-08-07 06:34:15 +01:00
|
|
|
<Project Path="src/modules/MouseUtils/MouseJump/MouseJump.vcxproj" Id="8a08d663-4995-40e3-b42c-3f910625f284" />
|
2026-03-04 15:46:42 -05:00
|
|
|
<Project Path="src/modules/MouseUtils/MousePointerCrosshairs/MousePointerCrosshairs.vcxproj" Id="eae14c0e-7a6b-45da-9080-a7d8c077ba6e" />
|
|
|
|
|
</Folder>
|
2026-03-09 00:09:53 +08:00
|
|
|
<Folder Name="/modules/MouseUtils/Tests/">
|
2026-03-04 15:46:42 -05:00
|
|
|
<Project Path="src/modules/MouseUtils/MouseJump.Common.UnitTests/MouseJump.Common.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
Ready for Review - [Mouse Jump] - port upstream WinUI3 code to Mouse Jump (microsoft#48290) (#48393)
<!-- 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
Changes for #48290 to convert Mouse Jump to a WinUI app and remove all
remaining dependencies on WinForms, based on work already done in the
original "FancyMouse" project
(https://github.com/mikeclayton/FancyMouse).
## Notes for reviewers
* the new WinUI build of the app is output into the "/WinUI3Apps"
subfolder
* there's 2 new assemblies that need to be added to the installation as
well - MouseJump.HotKeys.dll and MouseJump.Models.dll. I'm not sure how
to add those to the installer for signing / shipping...
---
### Summary of changes
* New thumbnail layout and rendering code
* WinUI rewrite (winforms version still committed)
* MouseJump.Kicker (dev launch tool)
* CsWin32 for interop
* New assemblies - code reorganised
---
### 1. New layout code
Incorporates latest FancyMouse core layout and rendering logic into
Mouse Jump:
* includes **support** for multiple devices in layout algorithms
* preview still only shows local machine though
* prerequisite for long-term goal #34126
<img width="650" height="709" alt="image"
src="https://github.com/user-attachments/assets/9d1d996d-ed05-4471-b8a5-bd93442f70dc"
/>
### 2. WinUI rewrite
Port latest stable FancyMouse WinUI implementation into Mouse Jump.
Existing WinForms UI left in-situ side-by-side for now - easy to delete
if not needed.
### 3. MouseJump.Kicker
A small dev utility to start Mouse Jump without needing to build the
runner project:
<img width="283" height="274" alt="image"
src="https://github.com/user-attachments/assets/c81bb3f5-5008-48ce-8bc0-eef18413dee6"
/>
### 4. Cswin32 for interop
All win32 interop is now accessed via CsWin32 bindings.
The original win32 bindings were heavily influenced by CsWin32 generated
code (e.g. ```BOOL```, ```HWND```, etc structs), so there's not actually
much change other than deleting a lot of boilerplate code.
### 5. New assemblies
Some code has been reorganised into new assemblies to make it easier to
keep Mouse Jump in sync with upstream FancyMouse
* MouseJump.HotKeys
* MouseJump.Models
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
- [x] Closes #48290
- [x] **Communication:** I've discussed this with core contributors
already. If 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
- all ui strings come from Resources.resw
- [x] **Dev docs:** Added/updated
- no changes required
- [x] **New binaries:** Added on the required places
- no changes required
- [x] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [x] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [x] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [x] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [x] **Documentation updated:** 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
- no changes required
<!-- 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
- **Workflow tests**
- [x] Automated tests passing locally
- [x] Minimal actions workflow (spelling check) passing for PR
- [ ] Full actions workflow (msbuild) passing for PR
- **UI tests**
- [x] Happy path
- [x] preview image appears when activated
- [x] clicking the preview image moves the mouse cursor to the correct
location
- [x] right-click dismisses the preview image without moving the mouse
- [x] pressing escape dismisses the preview image without moving the
mouse
- [x] left or right clicking another application / desktop dismisses the
preview image without moving the mouse
- [x] Works on multiple monitors with different dpi scaling settings
(e.g. 100% vs 150%)
*
https://github.com/microsoft/PowerToys/pull/23566#issuecomment-1411869418
*
https://github.com/microsoft/PowerToys/pull/23566#issuecomment-1412834413
- [x] Handling negative coordinates on non-primary monitors if higher or
"lefter" than primary monitor
*
https://github.com/microsoft/PowerToys/pull/23566#issuecomment-1404931694
- [x] Mouse crosshair moves when Mouse Jump moves the cursor (mouse
clicks *and* keyboard shortcuts)
* #24523
* #24527
- [x] Activating when the preview window is already visible moves the
form to the new mouse position
- [x] Number and key shortcuts (1-9, Home / End, Left / Right Arrow)
jump to the appropriate monitor
- [x] Number-pad shortcuts (1-9 jump to the appropriate monitor
- **Settings tests**
- [x] Changing thumbnail size settings updates the size of the thumbnail
- [x] Changing preview type between Compact, Bezelled and Custom shows
the correct preview type
- [x] Changing custom preview settings shows the correct settings
- [ ] Launching with settings version 1.0 upgrades settings to version
1.1, with "Bezelled" as the default style and the "Custom" settings
preconfigured to match "Bezelled"
- **Lifecycle tests**
- [x] Starting PowerToys Runner launches MouseJump exe when enabled, and
not when disabled
- [x] Enabling / disabling Mouse Jump in settings starts / stops
MouseJump exe
- [x] Exiting PowerToys Runner stops MouseJump exe
- [x] Killing runner exe via Task Manager stops MouseJump exe
- [x] Stopping Visual Studio local debug run stops MouseJump exe
- note - runner needs to be in *non*-admin mode otherwise Visual Studio
debugger disconnects at launch
- [x] Hotkey and size settings are automatically reloaded when config
file is modified from Settings UI
- [ ] ~~Hotkey and size settings are automatically reloaded when config
file is modified manually (e.g. in notepad) while runner and
MouseJumpUI.exe are running~~
- **[Internal Test
Suite](https://github.com/microsoft/PowerToys/blob/5bc7201ae2b75b53d3a4bc35119c867ecf71c5f6/doc/releases/tests-checklist-template.md#mouse-utils)**
- [x] Enable Mouse Jump. Then:
- [x] Press the activation shortcut and verify the screens preview
appears.
- [x] Change activation shortcut and verify that new shortcut triggers
Mouse Jump.
- [x] Click around the screen preview and ensure that mouse cursor
jumped to clicked location.
- [x] Reorder screens in Display settings and confirm that Mouse Jump
reflects the change and still works correctly.
- [x] Change scaling of screens and confirm that Mouse Jump still works
correctly.
- [ ] Unplug additional monitors and confirm that Mouse Jump still works
correctly.
- [x] Disable Mouse Jump and verify that the module is not activated
when you press the activation shortcut.
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Boliang Zhang (from Dev Box) <bozhang@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: moooyo <42196638+moooyo@users.noreply.github.com>
Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com>
Copilot-Session: 8e04a72e-3b0f-4ac4-8156-d04ea9b8bb85
2026-08-07 06:34:15 +01:00
|
|
|
<Project Path="src/modules/MouseUtils/MouseJump.HotKeys.UnitTests/MouseJump.HotKeys.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/MouseUtils/MouseJump.Models.UnitTests/MouseJump.Models.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2026-03-04 15:46:42 -05:00
|
|
|
<Project Path="src/modules/MouseUtils/MouseUtils.UITests/MouseUtils.UITests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Folder Name="/modules/keyboardmanager/Tests/">
|
|
|
|
|
<Project Path="src/modules/keyboardmanager/KeyboardManagerEditorTest/KeyboardManagerEditorTest.vcxproj" Id="62173d9a-6724-4c00-a1c8-fb646480a9ec" />
|
|
|
|
|
<Project Path="src/modules/keyboardmanager/KeyboardManagerEngineTest/KeyboardManagerEngineTest.vcxproj" Id="7f4b3a60-bc27-45a7-8000-68b0b6ea7466" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/launcher/">
|
|
|
|
|
<Project Path="src/modules/launcher/Microsoft.Launcher/Microsoft.Launcher.vcxproj" Id="e364f67b-bb12-4e91-b639-355866ebcd8b">
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/PowerLauncher/PowerLauncher.csproj" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/PowerLauncher.Telemetry/PowerLauncher.Telemetry.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/PowerLauncher/PowerLauncher.csproj">
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.UnitConverter/Community.PowerToys.Run.Plugin.UnitConverter.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.ValueGenerator/Community.PowerToys.Run.Plugin.ValueGenerator.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Community.PowerToys.Run.Plugin.VSCodeWorkspaces.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.WebSearch/Community.PowerToys.Run.Plugin.WebSearch.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Microsoft.Plugin.Folder.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Plugins/Microsoft.Plugin.Indexer/Microsoft.Plugin.Indexer.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Plugins/Microsoft.Plugin.Program/Microsoft.Plugin.Program.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Plugins/Microsoft.Plugin.Shell/Microsoft.Plugin.Shell.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Plugins/Microsoft.Plugin.Uri/Microsoft.Plugin.Uri.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Microsoft.Plugin.WindowWalker.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Microsoft.PowerToys.Run.Plugin.Calculator.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Microsoft.PowerToys.Run.Plugin.OneNote.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.PowerToys/Microsoft.PowerToys.Run.Plugin.PowerToys.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Registry/Microsoft.PowerToys.Run.Plugin.Registry.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Service/Microsoft.PowerToys.Run.Plugin.Service.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.System/Microsoft.PowerToys.Run.Plugin.System.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate/Microsoft.PowerToys.Run.Plugin.TimeDate.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.WindowsSettings/Microsoft.PowerToys.Run.Plugin.WindowsSettings.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.WindowsTerminal/Microsoft.PowerToys.Run.Plugin.WindowsTerminal.csproj" />
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Wox.Infrastructure/Wox.Infrastructure.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Wox.Plugin/Wox.Plugin.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/launcher/Plugins/">
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.UnitConverter/Community.PowerToys.Run.Plugin.UnitConverter.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.ValueGenerator/Community.PowerToys.Run.Plugin.ValueGenerator.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/Community.PowerToys.Run.Plugin.VSCodeWorkspaces.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.WebSearch/Community.PowerToys.Run.Plugin.WebSearch.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Microsoft.Plugin.Folder.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.Plugin.Indexer/Microsoft.Plugin.Indexer.csproj">
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Wox.Plugin/Wox.Plugin.csproj" />
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.Plugin.Program/Microsoft.Plugin.Program.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.Plugin.Shell/Microsoft.Plugin.Shell.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.Plugin.Uri/Microsoft.Plugin.Uri.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Microsoft.Plugin.WindowWalker.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Microsoft.PowerToys.Run.Plugin.Calculator.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.History/Microsoft.PowerToys.Run.Plugin.History.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Microsoft.PowerToys.Run.Plugin.OneNote.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.PowerToys/Microsoft.PowerToys.Run.Plugin.PowerToys.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Registry/Microsoft.PowerToys.Run.Plugin.Registry.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Service/Microsoft.PowerToys.Run.Plugin.Service.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.System/Microsoft.PowerToys.Run.Plugin.System.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate/Microsoft.PowerToys.Run.Plugin.TimeDate.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.WindowsSettings/Microsoft.PowerToys.Run.Plugin.WindowsSettings.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.WindowsTerminal/Microsoft.PowerToys.Run.Plugin.WindowsTerminal.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/launcher/Tests/">
|
2026-06-22 07:52:32 +02:00
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.Plugin.Folder.UnitTests/Microsoft.Plugin.Folder.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.UnitConverter.UnitTest/Community.PowerToys.Run.Plugin.UnitConverter.UnitTest.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.ValueGenerator.UnitTests/Community.PowerToys.Run.Plugin.ValueGenerator.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.Plugin.Program.UnitTests/Microsoft.Plugin.Program.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.Plugin.Uri.UnitTests/Microsoft.Plugin.Uri.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker.UnitTests/Microsoft.Plugin.WindowWalker.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator.UnitTest/Microsoft.PowerToys.Run.Plugin.Calculator.UnitTest.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Registry.UnitTest/Microsoft.PowerToys.Run.Plugin.Registry.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.System.UnitTests/Microsoft.PowerToys.Run.Plugin.System.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests/Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.WindowsTerminal.UnitTests/Microsoft.Plugin.WindowsTerminal.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/launcher/Wox.Test/Wox.Test.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/LightSwitch/">
|
[UI Tests][Light Switch] Fix tests: LS, Hosts, Worspaces, Mouse (#44754)
This pull request refactors the LightSwitch module to introduce a new
shared static library, `LightSwitchLib`, which centralizes theme
management logic and enables code sharing between the service and module
interface. The changes move theme-related code from the service and
module interface into this new library, update project references, and
clean up now-redundant files and includes.
**LightSwitchLib introduction and code deduplication:**
- Added a new static library project, `LightSwitchLib`, containing all
theme management logic (`SetSystemTheme`, `SetAppsTheme`,
`GetCurrentSystemTheme`, `GetCurrentAppsTheme`, `IsNightLightEnabled`)
and related files (`ThemeHelper.cpp`, `ThemeHelper.h`, `pch.h`,
`pch.cpp`). This code was previously duplicated in both the service and
module interface.
(`src/modules/LightSwitch/LightSwitchLib/LightSwitchLib.vcxproj`
[[1]](diffhunk://#diff-c38e95060ad294c9ed5c2bb769616bb52032a4330af7e268ad63d81a99dc1cadR1-R123)
`LightSwitchLib.vcxproj.filters`
[[2]](diffhunk://#diff-fcfc49f1628c274cd9a40aca385e03a1937f9e42958298f36155ad16a267ba9aR1-R33)
`ThemeHelper.cpp`
[[3]](diffhunk://#diff-f5ab83c022406172501172ee88e21294c7aba2a87fb30334d7c4d4fc9d736a56L1-R3)
`ThemeHelper.h`
[[4]](diffhunk://#diff-6609a7fc7abc61d4d0029f0fb605a9f4732511642af6e12851e86c234108169aR1-R10)
`pch.h`
[[5]](diffhunk://#diff-57e4d6ddad1d356a24555bce4d6cbb0d6a93386515254abf95573324454c94c2R1-R5)
`pch.cpp`
[[6]](diffhunk://#diff-87fbf215a559e7833ec06ff32aa7f8109fdf86d92b360fe44302fc16f1784d52R1)
- Updated the solution file and relevant project files to add and
reference `LightSwitchLib` from both `LightSwitchService` and
`LightSwitchModuleInterface`, ensuring both components use the shared
implementation. (`PowerToys.slnx`
[[1]](diffhunk://#diff-40c552fef4118125c3ccd6b156db518acec74b11150b193b31f18a2cc17a531eR668)
`LightSwitchService.vcxproj`
[[2]](diffhunk://#diff-51f54bd015aa96b38ddf4e96134ea542fac4b648566a23c2c86fe91a2b5a6bdaR58)
[[3]](diffhunk://#diff-51f54bd015aa96b38ddf4e96134ea542fac4b648566a23c2c86fe91a2b5a6bdaR113-R115)
`LightSwitchModuleInterface.vcxproj`
[[4]](diffhunk://#diff-72e859ee44b3f0087018e55708e850fb5040c5b8f72449d1cac30e8efb28e2c2R205-R207)
[[5]](diffhunk://#diff-72e859ee44b3f0087018e55708e850fb5040c5b8f72449d1cac30e8efb28e2c2L169-R179)
**Cleanup and removal of redundant code:**
- Removed old theme management code and headers from
`LightSwitchService` and `LightSwitchModuleInterface` now that logic
resides in `LightSwitchLib`. (`ThemeHelper.cpp`
[[1]](diffhunk://#diff-3e2766504c1cf989390508c613b2177cd5de14fb9de46df3b416f95f955338bfL1-L106)
`ThemeHelper.h`
[[2]](diffhunk://#diff-0e8540cace398ec3eebca416ca38d81262b689eca76a004584e686a605b7a242L1-L5)
`LightSwitchService.vcxproj`
[[3]](diffhunk://#diff-51f54bd015aa96b38ddf4e96134ea542fac4b648566a23c2c86fe91a2b5a6bdaL81)
[[4]](diffhunk://#diff-51f54bd015aa96b38ddf4e96134ea542fac4b648566a23c2c86fe91a2b5a6bdaL96)
`LightSwitchModuleInterface.vcxproj`
[[5]](diffhunk://#diff-72e859ee44b3f0087018e55708e850fb5040c5b8f72449d1cac30e8efb28e2c2L190)
- Removed duplicated registry path constants from `SettingsConstants.h`,
as they are now defined in the shared header. (`SettingsConstants.h`
[src/modules/LightSwitch/LightSwitchService/SettingsConstants.hL15-L17](diffhunk://#diff-e74db005ffb8b881a08c4dae1c1ead9dc732928a69cafb4c9e0bae8b86d4e24aL15-L17))
**Module interface improvements:**
- Added `ExportedFunctions.cpp` to the module interface, exposing theme
management functions as exports and using the shared library
implementation. (`ExportedFunctions.cpp`
[[1]](diffhunk://#diff-48acf3b77a8b6ac6fd1129afe1a677b34447ce39454e86ea04f1a1181a23b546R1-R22)
`LightSwitchModuleInterface.vcxproj`
[[2]](diffhunk://#diff-72e859ee44b3f0087018e55708e850fb5040c5b8f72449d1cac30e8efb28e2c2L169-R179)
**Minor test and logging adjustments:**
- Fixed a UI test to use the correct toggle name for the Hosts File
Editor. (`HostsSettingTests.cs`
[src/modules/Hosts/Hosts.UITests/HostsSettingTests.csL116-R116](diffhunk://#diff-3782109c99cd66a2c1b870a83d1f9d9807422479c89e03799b311ef5f13a2098L116-R116))
- Updated a log message to refer to `LightSwitchLib` instead of
`LightSwitchService` for clarity. (`ThemeHelper.cpp`
[src/modules/LightSwitch/LightSwitchLib/ThemeHelper.cppL66-R63](diffhunk://#diff-f5ab83c022406172501172ee88e21294c7aba2a87fb30334d7c4d4fc9d736a56L66-R63))
2026-01-16 13:58:51 -08:00
|
|
|
<Project Path="src/modules/LightSwitch/LightSwitchLib/LightSwitchLib.vcxproj" Id="79267138-2895-4346-9021-21408d65379f" />
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/modules/LightSwitch/LightSwitchModuleInterface/LightSwitchModuleInterface.vcxproj" Id="38177d56-6ad1-4adf-88c9-2843a7932166" />
|
|
|
|
|
<Project Path="src/modules/LightSwitch/LightSwitchService/LightSwitchService.vcxproj" Id="08e71c67-6a7e-4ca1-b04e-2fb336410bac" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/LightSwitch/Tests/">
|
|
|
|
|
<Project Path="src/modules/LightSwitch/Tests/LightSwitch.UITests/LightSwitch.UITests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
<Deploy />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
2026-02-03 13:53:25 +08:00
|
|
|
<Folder Name="/modules/PowerDisplay/">
|
[UITests] New framework around WinApp CLI, no WinAppDriver or Selenium. (#48467)
# Add winappcli-based UI test harness (no WinAppDriver / Selenium)
## Summary
Introduces a new UI test harness — `Microsoft.PowerToys.UITest.Next` —
that drives PowerToys
modules through Microsoft's
[winappcli](https://github.com/microsoft/WinAppCli) (UI Automation
CLI) instead of WinAppDriver + Selenium. Engine is a single executable
shelled out from
C#; no third-party NuGet packages, no driver process, no Appium server.
Adds two real consumers:
a full ColorPicker end-to-end scenario and a Settings shell navigation
smoke test.
This is opt-in and additive — the existing `UITestAutomation` library
and the
WinAppDriver-based test projects are untouched. Both can coexist while
we evaluate the new
harness.
Inspired in part by
[#48414](https://github.com/microsoft/PowerToys/pull/48414), which lands
the same architectural bet (winappcli, AutomationId selectors, no
WinAppDriver) at a smaller
scope. This PR generalizes it into a reusable library.
## Why
WinAppDriver + Selenium is a legacy pre-agentic solution that is no
longer actively maintained. It's unreliable, heavyweight, and slow. To
achieve 100% UI test coverage, we should leverage modern, reliable
solutions, and WinApp CLI is a strong candidate.
## What's in this PR
### Harness library —
[`src/common/UITestAutomation.Next/`](src/common/UITestAutomation.Next/)
| File | Purpose |
|---|---|
| [`WinappCli.cs`](src/common/UITestAutomation.Next/WinappCli.cs) |
Process wrapper around `winapp.exe`. `Invoke` / `InvokeAssertSuccess` /
`InvokeJson` / `IsAvailable` / `TryResolveExecutable`. `Result` carries
the args and emits `DescribeFailure()` like `winapp ui invoke X -w 12345
-> exit 1; stderr: ...` |
| [`Session.cs`](src/common/UITestAutomation.Next/Session.cs) | Test
session, scoped by either HWND (`-w`) or process (`-a`) via
`TargetScope`. `Find<T>` / `FindAll<T>` / `Inspect` / `Screenshot` /
`SendKeys`. `Session.FromProcess(...)` factory for the
single-window-per-process case |
|
[`SessionHelper.cs`](src/common/UITestAutomation.Next/SessionHelper.cs)
| Owns the launch + window-readiness flow. Static `EnsureRunning(scope,
timeout)` returns whether the call had to launch (so cleanup only kills
what we started). Uses `UseShellExecute=true` so child handles don't
keep MSTest hanging |
| [`UITestBase.cs`](src/common/UITestAutomation.Next/UITestBase.cs) |
MSTest base class. Pre-flights `WinappCli.IsAvailable()` once per
process and fails fast with the install hint if `winapp.exe` isn't on
PATH |
| [`Element/*.cs`](src/common/UITestAutomation.Next/Element/) |
`Element`, `Button`, `ToggleSwitch`, `TextBox`, `NavigationViewItem`,
`Window`. `Click` / `MouseClick` / `Focus` / `GetProperty` / `GetValue`
/ `HelpText` / `WaitForProperty` / `WaitForGone` plus coords
(`X`/`Y`/`Width`/`Height`) |
| [`By.cs`](src/common/UITestAutomation.Next/By.cs) | `By.Name` /
`By.AccessibilityId` / `By.Id` / `By.Slug` |
| [`Windows.cs`](src/common/UITestAutomation.Next/Windows.cs) |
`WindowsFinder.ListAll` / `ListByApp` / `WaitForWindowByApp` /
`WaitForWindowByProcess`. Notes the winappcli bug where unfiltered
`list-windows` drops untitled windows |
|
[`WindowControl.cs`](src/common/UITestAutomation.Next/WindowControl.cs)
| Tolerant Win32 helpers — `TryCloseByApp` / `TryFocusByApp` /
`SafeCloseAndFocus` / `TryKillProcess` — for `finally` blocks |
|
[`KeyboardHelper.cs`](src/common/UITestAutomation.Next/KeyboardHelper.cs)
| Hybrid `keybd_event` + `SendKeys.SendWait` chord sender — required for
global PowerToys hotkeys |
| [`MouseHelper.cs`](src/common/UITestAutomation.Next/MouseHelper.cs) |
`MoveTo` / `LeftClick` / `RightClick` / `LeftClickAt` Win32 wrappers |
|
[`ClipboardHelper.cs`](src/common/UITestAutomation.Next/ClipboardHelper.cs)
| STA-thread `Clipboard` access with `WaitForText` |
|
[`ModuleConfigData.cs`](src/common/UITestAutomation.Next/ModuleConfigData.cs)
| `PowerToysModule` enum + path/process-name resolution |
### Tests
**[`src/modules/colorPicker/ColorPicker.UITests/`](src/modules/colorPicker/ColorPicker.UITests/)**
— replaces the previous empty `UITest-ColorPicker` stub. One test,
[`ColorPickerEndToEndTests.NavigateReadShortcutActivateAndCapture`](src/modules/colorPicker/ColorPicker.UITests/ColorPickerEndToEndTests.cs),
drives the full E2E:
1. Navigate to the Color Picker page via the dashboard utilities stack
2. Toggle the module OFF, verify `PowerToys.ColorPickerUI` exits; toggle
ON, verify it respawns
3. Read the activation shortcut from the page's `ShortcutControl`
(`EditButton.HelpText`)
4. Clear clipboard, park cursor, send the chord
5. Wait for the picker overlay window
6. Read the displayed HEX from a hidden XAML automation peer (see below)
7. Left-click to capture; assert the clipboard value matches the peer's
HEX
8. Wait for the editor window and assert the captured color appears in
its tree
**[`src/settings-ui/Settings.UITests/`](src/settings-ui/Settings.UITests/)**
— `SettingsNavigationSmokeTests.NavigationItem_NavigatesWithoutCrashing`
is one `[TestMethod]` parameterized with `[DynamicData]`, producing 31
discrete results — one per `NavigationViewItem` in
[`ShellPage.xaml`](src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml).
For each item: navigate, settle 250ms, assert `PowerToys.Settings` is
still alive. Catches FailFast regressions in
`ShellViewModel.Frame_NavigationFailed` that pure-logic unit tests can't
reach (the failure path needs a `NavigationFailedEventArgs` which is a
sealed WinRT projection).
### Product change
**[`src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml`](src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml)**
— adds a hidden `TextBlock` automation peer:
```xml
<TextBlock
x:Name="ColorHexAutomationPeer"
AutomationProperties.AutomationId="ColorHexAutomationPeer"
IsHitTestVisible="False"
Opacity="0"
Text="{Binding ColorText}" />
```
The visible `ColorTextBlock` has `AutomationProperties.Name="{Binding
ColorName}"`, which masks the HEX value in the UIA tree (you see "White"
instead of `#FFFFFF`). This zero-impact peer mirrors `ColorText` so
tests can read the actually-displayed HEX. `Opacity=0` +
`IsHitTestVisible=False` keep it out of the visual layout and out of
accessibility focus.
### Project wiring
- [`PowerToys.slnx`](PowerToys.slnx) — registers `UITestAutomation.Next`
under `/common/`, `ColorPicker.UITests` under
`/modules/colorpicker/Tests/`, and `Settings.UITests` under
`/settings-ui/Tests/`. Original `UITest-ColorPicker` stub csproj
removed.
-
[`.github/actions/spell-check/expect.txt`](.github/actions/spell-check/expect.txt)
— adds `winapp` / `winappcli`.
### Not in this PR
- No pipeline changes. `winapp.exe` is expected to be pre-staged on the
test agent image. If it's missing, `UITestBase` fails the first test
with the install hint (`winget install Microsoft.winappcli`) rather than
producing 30 opaque per-test errors.
- No changes to the legacy `UITestAutomation` library or any of the
existing `*.UITests` projects.
## Validation
- All three projects build clean on `x64|Debug` (empty
`build.<config>.<plat>.errors.log`):
- `src/common/UITestAutomation.Next/`
- `src/modules/colorPicker/ColorPicker.UITests/`
- `src/settings-ui/Settings.UITests/`
- Both tests run in Test Explorer / `dotnet test` via
Microsoft.Testing.Platform (already enabled repo-wide in
`Directory.Build.props`).
- Local runs: ColorPicker E2E green; Settings smoke green across all 31
nav items.
- `winapp 0.3.2` from `winget install Microsoft.winappcli`.
## Notes for reviewers
- **`UseShellExecute = true`** in `SessionHelper.EnsureRunning` is
intentional — `false` makes child processes inherit the test host's
stdin/stdout/stderr handles, which keeps MTP/Test Explorer marking the
run as "in progress" until the spawned PowerToys exits.
- **Process-scope (`-a`) targeting** in the Settings smoke test handles
single-instance handoff: the EXE you launch may exit with code 0
immediately after signalling an existing owner, so the alive check uses
`Process.GetProcessesByName` rather than the launcher PID.
- **AutomationId-only selectors** in the Settings smoke list keep the
test localization-independent. Parent groups have
`SelectsOnInvoked="False"` and only expand on click — `Element.Click`
tries `InvokePattern → TogglePattern → SelectionItemPattern →
ExpandCollapsePattern` so the same call works for both leaves and
groups.
- **Untitled-window discovery**: filtered `winapp ui list-windows -a
<name>` returns windows that the unfiltered call drops (e.g. ColorPicker
editor). `WindowsFinder.ListByApp` uses the filtered form. Reported
upstream.
## Before Merge
- Add the `winappcli` install step to the UI-test pipeline.
2026-07-07 22:58:08 -07:00
|
|
|
<Project Path="src/modules/powerdisplay/PowerDisplay.Lib/PowerDisplay.Lib.csproj">
|
2026-04-10 15:14:41 +08:00
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
feat(powerdisplay): add CLI for monitor control (#48632)
## Summary of the Pull Request
Adds `PowerToys.PowerDisplay.Cli.exe`, a scriptable interface for
controlling monitors through the running PowerDisplay process. It
supports `list`, `get`, `set`, `up`, `down`, `capabilities`, `profiles`,
and `apply-profile`.
The CLI communicates over an authenticated, per-session named pipe;
PowerDisplay remains responsible for DDC/CI and WMI access.
## PR Checklist
- [x] Closes: #48713
- [x] **Communication:** Discussed with core contributors
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** Core errors are localizable; some help and
output text remains English-only
- [ ] **Dev docs:** N/A; built-in CLI help is the command reference
- [x] **New binaries:** Added on the required places
- [x] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
- [x] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetupVNext/Resources.wxs)
- [x] **YML for CI pipeline:** N/A; test assemblies are auto-discovered
- [x] **YML for signed pipeline:** N/A; signing is driven by
`ESRPSigning_core.json`
- [ ] **Documentation updated:** N/A
## Detailed Description of the Pull Request / Additional comments
- Adds an AOT-compatible CLI and shared request/response contracts.
- Uses a secured named-pipe server in PowerDisplay, with stable exit
codes and a bounded request timeout.
- Supports saved profiles by their existing stable profile IDs.
- Adds solution, signing, installer, and unit-test project integration.
## Validation Steps Performed
- PowerDisplay Lib, Contracts, CLI, and IPC unit-test suites pass.
- Native AOT publish completes without analyzer warnings.
- Manually validated the CLI on two DDC/CI monitors, including the
PowerDisplay-unavailable path.
- Rebuilt the PowerDisplay GUI after the shared-library changes.
---------
Co-authored-by: Yu Leng <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-16 23:08:27 +08:00
|
|
|
<Project Path="src/modules/powerdisplay/PowerDisplay.Contracts/PowerDisplay.Contracts.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/powerdisplay/PowerDisplay.Ipc/PowerDisplay.Ipc.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
[UITests] New framework around WinApp CLI, no WinAppDriver or Selenium. (#48467)
# Add winappcli-based UI test harness (no WinAppDriver / Selenium)
## Summary
Introduces a new UI test harness — `Microsoft.PowerToys.UITest.Next` —
that drives PowerToys
modules through Microsoft's
[winappcli](https://github.com/microsoft/WinAppCli) (UI Automation
CLI) instead of WinAppDriver + Selenium. Engine is a single executable
shelled out from
C#; no third-party NuGet packages, no driver process, no Appium server.
Adds two real consumers:
a full ColorPicker end-to-end scenario and a Settings shell navigation
smoke test.
This is opt-in and additive — the existing `UITestAutomation` library
and the
WinAppDriver-based test projects are untouched. Both can coexist while
we evaluate the new
harness.
Inspired in part by
[#48414](https://github.com/microsoft/PowerToys/pull/48414), which lands
the same architectural bet (winappcli, AutomationId selectors, no
WinAppDriver) at a smaller
scope. This PR generalizes it into a reusable library.
## Why
WinAppDriver + Selenium is a legacy pre-agentic solution that is no
longer actively maintained. It's unreliable, heavyweight, and slow. To
achieve 100% UI test coverage, we should leverage modern, reliable
solutions, and WinApp CLI is a strong candidate.
## What's in this PR
### Harness library —
[`src/common/UITestAutomation.Next/`](src/common/UITestAutomation.Next/)
| File | Purpose |
|---|---|
| [`WinappCli.cs`](src/common/UITestAutomation.Next/WinappCli.cs) |
Process wrapper around `winapp.exe`. `Invoke` / `InvokeAssertSuccess` /
`InvokeJson` / `IsAvailable` / `TryResolveExecutable`. `Result` carries
the args and emits `DescribeFailure()` like `winapp ui invoke X -w 12345
-> exit 1; stderr: ...` |
| [`Session.cs`](src/common/UITestAutomation.Next/Session.cs) | Test
session, scoped by either HWND (`-w`) or process (`-a`) via
`TargetScope`. `Find<T>` / `FindAll<T>` / `Inspect` / `Screenshot` /
`SendKeys`. `Session.FromProcess(...)` factory for the
single-window-per-process case |
|
[`SessionHelper.cs`](src/common/UITestAutomation.Next/SessionHelper.cs)
| Owns the launch + window-readiness flow. Static `EnsureRunning(scope,
timeout)` returns whether the call had to launch (so cleanup only kills
what we started). Uses `UseShellExecute=true` so child handles don't
keep MSTest hanging |
| [`UITestBase.cs`](src/common/UITestAutomation.Next/UITestBase.cs) |
MSTest base class. Pre-flights `WinappCli.IsAvailable()` once per
process and fails fast with the install hint if `winapp.exe` isn't on
PATH |
| [`Element/*.cs`](src/common/UITestAutomation.Next/Element/) |
`Element`, `Button`, `ToggleSwitch`, `TextBox`, `NavigationViewItem`,
`Window`. `Click` / `MouseClick` / `Focus` / `GetProperty` / `GetValue`
/ `HelpText` / `WaitForProperty` / `WaitForGone` plus coords
(`X`/`Y`/`Width`/`Height`) |
| [`By.cs`](src/common/UITestAutomation.Next/By.cs) | `By.Name` /
`By.AccessibilityId` / `By.Id` / `By.Slug` |
| [`Windows.cs`](src/common/UITestAutomation.Next/Windows.cs) |
`WindowsFinder.ListAll` / `ListByApp` / `WaitForWindowByApp` /
`WaitForWindowByProcess`. Notes the winappcli bug where unfiltered
`list-windows` drops untitled windows |
|
[`WindowControl.cs`](src/common/UITestAutomation.Next/WindowControl.cs)
| Tolerant Win32 helpers — `TryCloseByApp` / `TryFocusByApp` /
`SafeCloseAndFocus` / `TryKillProcess` — for `finally` blocks |
|
[`KeyboardHelper.cs`](src/common/UITestAutomation.Next/KeyboardHelper.cs)
| Hybrid `keybd_event` + `SendKeys.SendWait` chord sender — required for
global PowerToys hotkeys |
| [`MouseHelper.cs`](src/common/UITestAutomation.Next/MouseHelper.cs) |
`MoveTo` / `LeftClick` / `RightClick` / `LeftClickAt` Win32 wrappers |
|
[`ClipboardHelper.cs`](src/common/UITestAutomation.Next/ClipboardHelper.cs)
| STA-thread `Clipboard` access with `WaitForText` |
|
[`ModuleConfigData.cs`](src/common/UITestAutomation.Next/ModuleConfigData.cs)
| `PowerToysModule` enum + path/process-name resolution |
### Tests
**[`src/modules/colorPicker/ColorPicker.UITests/`](src/modules/colorPicker/ColorPicker.UITests/)**
— replaces the previous empty `UITest-ColorPicker` stub. One test,
[`ColorPickerEndToEndTests.NavigateReadShortcutActivateAndCapture`](src/modules/colorPicker/ColorPicker.UITests/ColorPickerEndToEndTests.cs),
drives the full E2E:
1. Navigate to the Color Picker page via the dashboard utilities stack
2. Toggle the module OFF, verify `PowerToys.ColorPickerUI` exits; toggle
ON, verify it respawns
3. Read the activation shortcut from the page's `ShortcutControl`
(`EditButton.HelpText`)
4. Clear clipboard, park cursor, send the chord
5. Wait for the picker overlay window
6. Read the displayed HEX from a hidden XAML automation peer (see below)
7. Left-click to capture; assert the clipboard value matches the peer's
HEX
8. Wait for the editor window and assert the captured color appears in
its tree
**[`src/settings-ui/Settings.UITests/`](src/settings-ui/Settings.UITests/)**
— `SettingsNavigationSmokeTests.NavigationItem_NavigatesWithoutCrashing`
is one `[TestMethod]` parameterized with `[DynamicData]`, producing 31
discrete results — one per `NavigationViewItem` in
[`ShellPage.xaml`](src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml).
For each item: navigate, settle 250ms, assert `PowerToys.Settings` is
still alive. Catches FailFast regressions in
`ShellViewModel.Frame_NavigationFailed` that pure-logic unit tests can't
reach (the failure path needs a `NavigationFailedEventArgs` which is a
sealed WinRT projection).
### Product change
**[`src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml`](src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml)**
— adds a hidden `TextBlock` automation peer:
```xml
<TextBlock
x:Name="ColorHexAutomationPeer"
AutomationProperties.AutomationId="ColorHexAutomationPeer"
IsHitTestVisible="False"
Opacity="0"
Text="{Binding ColorText}" />
```
The visible `ColorTextBlock` has `AutomationProperties.Name="{Binding
ColorName}"`, which masks the HEX value in the UIA tree (you see "White"
instead of `#FFFFFF`). This zero-impact peer mirrors `ColorText` so
tests can read the actually-displayed HEX. `Opacity=0` +
`IsHitTestVisible=False` keep it out of the visual layout and out of
accessibility focus.
### Project wiring
- [`PowerToys.slnx`](PowerToys.slnx) — registers `UITestAutomation.Next`
under `/common/`, `ColorPicker.UITests` under
`/modules/colorpicker/Tests/`, and `Settings.UITests` under
`/settings-ui/Tests/`. Original `UITest-ColorPicker` stub csproj
removed.
-
[`.github/actions/spell-check/expect.txt`](.github/actions/spell-check/expect.txt)
— adds `winapp` / `winappcli`.
### Not in this PR
- No pipeline changes. `winapp.exe` is expected to be pre-staged on the
test agent image. If it's missing, `UITestBase` fails the first test
with the install hint (`winget install Microsoft.winappcli`) rather than
producing 30 opaque per-test errors.
- No changes to the legacy `UITestAutomation` library or any of the
existing `*.UITests` projects.
## Validation
- All three projects build clean on `x64|Debug` (empty
`build.<config>.<plat>.errors.log`):
- `src/common/UITestAutomation.Next/`
- `src/modules/colorPicker/ColorPicker.UITests/`
- `src/settings-ui/Settings.UITests/`
- Both tests run in Test Explorer / `dotnet test` via
Microsoft.Testing.Platform (already enabled repo-wide in
`Directory.Build.props`).
- Local runs: ColorPicker E2E green; Settings smoke green across all 31
nav items.
- `winapp 0.3.2` from `winget install Microsoft.winappcli`.
## Notes for reviewers
- **`UseShellExecute = true`** in `SessionHelper.EnsureRunning` is
intentional — `false` makes child processes inherit the test host's
stdin/stdout/stderr handles, which keeps MTP/Test Explorer marking the
run as "in progress" until the spawned PowerToys exits.
- **Process-scope (`-a`) targeting** in the Settings smoke test handles
single-instance handoff: the EXE you launch may exit with code 0
immediately after signalling an existing owner, so the alive check uses
`Process.GetProcessesByName` rather than the launcher PID.
- **AutomationId-only selectors** in the Settings smoke list keep the
test localization-independent. Parent groups have
`SelectsOnInvoked="False"` and only expand on click — `Element.Click`
tries `InvokePattern → TogglePattern → SelectionItemPattern →
ExpandCollapsePattern` so the same call works for both leaves and
groups.
- **Untitled-window discovery**: filtered `winapp ui list-windows -a
<name>` returns windows that the unfiltered call drops (e.g. ColorPicker
editor). `WindowsFinder.ListByApp` uses the filtered form. Reported
upstream.
## Before Merge
- Add the `winappcli` install step to the UI-test pipeline.
2026-07-07 22:58:08 -07:00
|
|
|
<Project Path="src/modules/powerdisplay/PowerDisplay.Models/PowerDisplay.Models.csproj">
|
2026-02-03 13:53:25 +08:00
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/powerdisplay/PowerDisplay/PowerDisplay.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
feat(powerdisplay): add CLI for monitor control (#48632)
## Summary of the Pull Request
Adds `PowerToys.PowerDisplay.Cli.exe`, a scriptable interface for
controlling monitors through the running PowerDisplay process. It
supports `list`, `get`, `set`, `up`, `down`, `capabilities`, `profiles`,
and `apply-profile`.
The CLI communicates over an authenticated, per-session named pipe;
PowerDisplay remains responsible for DDC/CI and WMI access.
## PR Checklist
- [x] Closes: #48713
- [x] **Communication:** Discussed with core contributors
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** Core errors are localizable; some help and
output text remains English-only
- [ ] **Dev docs:** N/A; built-in CLI help is the command reference
- [x] **New binaries:** Added on the required places
- [x] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
- [x] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetupVNext/Resources.wxs)
- [x] **YML for CI pipeline:** N/A; test assemblies are auto-discovered
- [x] **YML for signed pipeline:** N/A; signing is driven by
`ESRPSigning_core.json`
- [ ] **Documentation updated:** N/A
## Detailed Description of the Pull Request / Additional comments
- Adds an AOT-compatible CLI and shared request/response contracts.
- Uses a secured named-pipe server in PowerDisplay, with stable exit
codes and a bounded request timeout.
- Supports saved profiles by their existing stable profile IDs.
- Adds solution, signing, installer, and unit-test project integration.
## Validation Steps Performed
- PowerDisplay Lib, Contracts, CLI, and IPC unit-test suites pass.
- Native AOT publish completes without analyzer warnings.
- Manually validated the CLI on two DDC/CI monitors, including the
PowerDisplay-unavailable path.
- Rebuilt the PowerDisplay GUI after the shared-library changes.
---------
Co-authored-by: Yu Leng <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-16 23:08:27 +08:00
|
|
|
<Project Path="src/modules/powerdisplay/PowerDisplay.Cli/PowerDisplay.Cli.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2026-02-03 13:53:25 +08:00
|
|
|
<Project Path="src/modules/powerdisplay/PowerDisplayModuleInterface/PowerDisplayModuleInterface.vcxproj" Id="d1234567-8901-2345-6789-abcdef012345" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/PowerDisplay/Tests/">
|
|
|
|
|
<Project Path="src/modules/powerdisplay/PowerDisplay.Lib.UnitTests/PowerDisplay.Lib.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
feat(powerdisplay): add CLI for monitor control (#48632)
## Summary of the Pull Request
Adds `PowerToys.PowerDisplay.Cli.exe`, a scriptable interface for
controlling monitors through the running PowerDisplay process. It
supports `list`, `get`, `set`, `up`, `down`, `capabilities`, `profiles`,
and `apply-profile`.
The CLI communicates over an authenticated, per-session named pipe;
PowerDisplay remains responsible for DDC/CI and WMI access.
## PR Checklist
- [x] Closes: #48713
- [x] **Communication:** Discussed with core contributors
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** Core errors are localizable; some help and
output text remains English-only
- [ ] **Dev docs:** N/A; built-in CLI help is the command reference
- [x] **New binaries:** Added on the required places
- [x] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
- [x] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetupVNext/Resources.wxs)
- [x] **YML for CI pipeline:** N/A; test assemblies are auto-discovered
- [x] **YML for signed pipeline:** N/A; signing is driven by
`ESRPSigning_core.json`
- [ ] **Documentation updated:** N/A
## Detailed Description of the Pull Request / Additional comments
- Adds an AOT-compatible CLI and shared request/response contracts.
- Uses a secured named-pipe server in PowerDisplay, with stable exit
codes and a bounded request timeout.
- Supports saved profiles by their existing stable profile IDs.
- Adds solution, signing, installer, and unit-test project integration.
## Validation Steps Performed
- PowerDisplay Lib, Contracts, CLI, and IPC unit-test suites pass.
- Native AOT publish completes without analyzer warnings.
- Manually validated the CLI on two DDC/CI monitors, including the
PowerDisplay-unavailable path.
- Rebuilt the PowerDisplay GUI after the shared-library changes.
---------
Co-authored-by: Yu Leng <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-16 23:08:27 +08:00
|
|
|
<Project Path="src/modules/powerdisplay/PowerDisplay.Cli.UnitTests/PowerDisplay.Cli.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/powerdisplay/PowerDisplay.Contracts.UnitTests/PowerDisplay.Contracts.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/powerdisplay/PowerDisplay.Ipc.UnitTests/PowerDisplay.Ipc.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2026-02-03 13:53:25 +08:00
|
|
|
</Folder>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Folder Name="/modules/MeasureTool/">
|
|
|
|
|
<Project Path="src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj" Id="54a93af7-60c7-4f6c-99d2-fbb1f75f853a">
|
|
|
|
|
<BuildDependency Project="src/common/Display/Display.vcxproj" />
|
|
|
|
|
<BuildDependency Project="src/common/SettingsAPI/SettingsAPI.vcxproj" />
|
|
|
|
|
<BuildDependency Project="src/common/version/version.vcxproj" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/MeasureTool/MeasureToolModuleInterface/MeasureToolModuleInterface.vcxproj" Id="92c39820-9f84-4529-bc7d-22aae514d63b" />
|
|
|
|
|
<Project Path="src/modules/MeasureTool/MeasureToolUI/MeasureToolUI.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/MeasureTool/Tests/">
|
|
|
|
|
<Project Path="src/modules/MeasureTool/Tests/ScreenRuler.UITests/ScreenRuler.UITests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2026-07-08 20:02:54 -07:00
|
|
|
<Project Path="src/modules/MeasureTool/Tests/ScreenRuler.UITests.Next/ScreenRuler.UITests.Next.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/MouseWithoutBorders/">
|
|
|
|
|
<Project Path="src/modules/MouseWithoutBorders/App/Helper/MouseWithoutBordersHelper.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/MouseWithoutBorders/App/MouseWithoutBorders.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/MouseWithoutBorders/App/Service/MouseWithoutBordersService.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/MouseWithoutBorders/ModuleInterface/MouseWithoutBordersModuleInterface.vcxproj" Id="2833c9c6-ab32-4048-a5c7-a70898337b57" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/MouseWithoutBorders/Tests/">
|
|
|
|
|
<Project Path="src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/MouseWithoutBorders.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/New+/">
|
|
|
|
|
<Project Path="src/modules/NewPlus/NewShellExtensionContextMenu.win10/NewPlus.ShellExtension.win10.vcxproj" Id="0db0f63a-d2f8-4da3-a650-2d0b8724218e" />
|
|
|
|
|
<Project Path="src/modules/NewPlus/NewShellExtensionContextMenu/NewShellExtensionContextMenu.vcxproj" Id="8acb33d9-c95b-47d4-8363-9731ee0930a0" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/Peek/">
|
|
|
|
|
<Project Path="src/modules/peek/Peek.Common/Peek.Common.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
Add Peek.Common unit tests (MathHelper, PathHelper) (#49105)
## Summary
Adds a **Peek.Common.UnitTests** project (MSTest) with unit coverage for
Peek.Common.Helpers:
- **MathHelper.Modulo** — positive/zero results, negative-dividend
wrap-around, large values, and the new non-positive-divisor guard.
- **MathHelper.NumberOfDigits** — single/multi-digit, negative, and 9/10
& 99/100 boundary values.
- **PathHelper.IsUncPath** — standard UNC, subfolders, dotted-server and
IP hosts, plus negatives: drive-letter, relative, empty, HTTP URL,
ile:// URI, single backslash, and null.
Also adds a small correctness guard to MathHelper.Modulo: a non-positive
divisor now throws ArgumentOutOfRangeException instead of silently
throwing DivideByZeroException (b == 0) or returning a misleading result
(b < 0). Registers the test project in `PowerToys.slnx` (ARM64 + x64).
**37 tests pass** locally (x64 Debug).
## Context
This is a clean, **tests-only split of #46684** (the Peek.Common
portion), intentionally **without** the bundled global dependency bump
from that PR. The PowerAccent.Core portion of #46684 was shipped
separately in #49104.
## Test coverage
| Area | Tests |
|------|-------|
| MathHelper.Modulo / NumberOfDigits | included |
| PathHelper.IsUncPath | included |
No production behavior changes beyond the Modulo argument guard, which
is covered by the new tests.
Co-authored-by: Clint Rutkas <crutkas@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-28 07:46:33 -07:00
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/peek/Peek.Common.UnitTests/Peek.Common.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
2025-12-03 03:59:46 -06:00
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/peek/Peek.FilePreviewer/Peek.FilePreviewer.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/peek/Peek.UI/Peek.UI.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
<Deploy />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/peek/Peek.UITests/Peek.UITests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
[UITests] Add UITest.Next suites (Image Resizer, Peek, File Explorer add‑ons, File Locksmith) + local‑VM tooling and CI test‑signing (#49671)
## Summary
Adds end‑to‑end UI tests on the `Microsoft.PowerToys.UITest.Next`
(winappcli) framework for three
modules, grows the shared `.Next` test framework with the helpers those
suites needed, and adds the
CI plumbing that lets shell‑extension tests exercise the **real**
Windows 11 modern context menu.
Also ships two agent skills that document how to write and run these
tests.
Product runtime behavior is **unchanged** — the only product edits are
test‑observability hooks in Peek
and a unit‑test project exclude.
Closes: https://github.com/microsoft/PowerToys/issues/40660
https://github.com/microsoft/PowerToys/issues/49424
https://github.com/microsoft/PowerToys/issues/40661
## What's added
### New UI test suites
- **Image Resizer** —
`src/modules/imageresizer/tests/ImageResizer.UITests`: context‑menu
enable/disable
tracking, the resize dialog, custom presets, every fit mode, every unit,
filename format, keep‑date,
shrink‑only, replace‑in‑place, and orientation.
- **Peek** — `src/modules/peek/Peek.UITests.Next`: file‑preview coverage
across image/text/archive/
markdown types with per‑arch visual baselines.
- **File Explorer add‑ons** —
`src/modules/previewpane/PreviewPane.UITests`: Preview Pane handlers and
thumbnail providers.
### `UITestAutomation.Next` framework
- New helpers: `ExplorerShell` (Shell selection/view‑mode interop),
`WaitHelper` (structured stable
waits), `WindowControl` (foreground/context‑menu/process control),
`VisualAssert` (image compare),
`WindowHelper`.
- Updates to `Session`, `UITestBase`, `SettingsConfigHelper`,
`WinappCli`.
- New `UITestAutomation.Next.UnitTests` project covering the new
wait/settings/CLI helpers.
### CI — sign sparse MSIX so the modern menu registers
- **`.pipelines/signSparsePackages.ps1`** — self‑signs each sparse
context‑menu MSIX with a
publisher‑matching test certificate and force‑trusts it (machine
stores), so
`AddPackageByUriAsync` succeeds on otherwise‑unsigned PR builds. Robust
`signtool` discovery with a
NuGet fallback; test‑only trust that asserts no security.
- Wired into **`.pipelines/v2/templates/job-test-project.yml`** as a
best‑effort step covering the
run‑in‑place, machine‑install, and per‑user‑install locations. Signs
nothing it can't (skips
already‑signed packages) and never fails the job.
### Product changes (test observability only)
- **Peek `FilePreview.xaml` / `.xaml.cs`** — a named `LoadingIndicator`
and a hidden automation peer
that exposes the current preview state as text, so tests can read load
state deterministically. No
runtime behavior change.
- **`ImageResizer.UnitTests.csproj`** — exclude the sibling
`ImageResizer.UITests\**` folder from the
unit‑test compilation.
### Agent skills & docs
- **New `ui-tests-local-vm` skill** — run `.Next` suites in persistent
dockur/windows VMs: setup,
agentic loop, image customization, troubleshooting, the shell‑extension
**signing** reference, plus
controller/guest scripts and VM templates.
- **Updated `ui-tests-migration` skill** — WinAppDriver/Selenium →
`.Next` porting guidance
(CI stability, Explorer/shell‑extension test design, patterns &
pitfalls).
- **`doc/devdocs/development/ui-tests.md`** — updated for the `.Next`
workflow.
## Testing
- All three suites pass locally and in CI across **x64 Win10**, **x64
Win11**, and **arm64** (machine
and per‑user install legs).
## Reviewer notes
- No product runtime behavior changes; product edits are limited to the
Peek test hooks above.
- The CI signing step is a **test‑only** trust anchor (self‑signed,
scoped to the agent) and is
best‑effort, so it can only add modern‑menu coverage and never regress
the job.
2026-08-10 10:55:03 -07:00
|
|
|
<Project Path="src/modules/peek/Peek.UITests.Next/Peek.UITests.Next.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/modules/peek/peek/peek.vcxproj" Id="a1425b53-3d61-4679-8623-e64a0d3d0a48" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/PowerAccent/">
|
[Quick Accent] Move language data to PowerAccent.Common library, refactor (#47211)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Language data for Quick Accent was previously defined in
**PowerAccent.Core/Languages.cs**, internal to the Quick Accent
application itself. The Settings application had no access to the list
and had to maintain a parallel, manually-synchronised list of the
language names and groups, and there was no single place to look up the
complete set of languages.
This PR resolves this and extracts the language data into a new
**PowerAccent.Common** project with no external or UI dependencies,
making it the single source of truth for both the character popup and
Settings UI.
The implicit and non-obvious ordering of the old **Languages.cs** has
been replaced with explicit ordering of the language groups and
languages list.
A new unit test project for the application has also been added.
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
- [x] Closes: #47159
- [x] Closes: #30000
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx
<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
The following changes and additions have been made:
New project **PowerAccent.Common** contains:
- **Language.cs** - an enum of Quick Accent's pseudo-ISO identifiers for
each of the supported languages
- **LetterKey.cs** - mirrors the LetterKey enum defined in the
KeyboardListener.idl, and must be kept in sync with that. This exposes
the VK_* data to the Settings UI without it having to reference the
PowerAccentKeyboardService project
- **LanguageGroup.cs** - classifies languages as `Language` (for spoken
languages), `Special` (for sets like Currency and International Phonetic
Alphabet), or `UserDefined` (reserved for future work)
- **LanguageInfo.cs** - a record which combines a language's identity,
group, resource identifier, and character mappings
- **CharacterMappings.cs** - a new version of the old **Languages.cs**,
providing:
- `All` - the canonical registry of every `LanguageInfo` entry
- `DisplayOrder` - the explicit within-group ordering for languages, for
the default popup ordering, i.e. when the user has not got
frequency-based ordering enabled. This is a culturally-neutral
alphabetical ordering by our pseudo-ISO language IDs, and close to the
previous order, minimising any impact to users' muscle memory
- `GroupDisplayOrder` - the explicit ordering of language groups for
both the popup and the Settings UI
- `LanguageLookup` - new _O(1)_ `Language` to `LanguageInfo` dictionary
- `GetCharacters(LetterKey, Language[])` - a deduplicating character
collector and sorter
A significant improvement over the old **Languages.cs** is that language
ordering is now explicit and in one place. Previously, popup ordering
was an implicit side-effect of a large Union chain across all language
mappings, with the enum, the language mapping declarations and the union
all carrying different orderings. This was a source of confusion and
made adding new languages fragile.
The original **Languages.cs** has been deleted. There's now a thin
`CharacterMappings` adapter that casts the `LetterKey` to the managed
equivalent by numeric value. This is another effort to decouple the
Settings UI and Quick Accent and only share the required elements.
In Settings, the `PowerAccentViewModel` class has been updated. It now
derives the language list directly from `CharacterMappings.All`; the
`InitializeLanguages()` call handles localisation, sorting and grouping
in a single place using `GroupDisplayOrder`.
A new unit test project covers `CharacterMappings`, the `LetterKey`
IDL-to-managed code bridge and general language declaration checks. The
application is now much more robust against changes which alter the
declared order, introduce empty/null elements, and so on. It is now
impossible to add a new language and forget a constituent part (the enum
entry, its place in the display order, the character mappings
themselves) without a test failing.
<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
See new unit test project for comprehensive tests.
Manually confirmed:
- Triggering Quick Accent with no language selected does not report an
error
- Language order is consistent in the popup, no matter what order the
languages are selected in Settings
- The order of languages in Settings is consistent, alphabetically by
localised name
- All declared languages are present in Settings and no resource IDs
were missed
---------
Co-authored-by: Muyuan Li (from Dev Box) <muyuanli@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-22 07:24:26 +00:00
|
|
|
<Project Path="src/modules/poweraccent/PowerAccent.Common.UnitTests/PowerAccent.Common.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
[Quick Accent] Migrate UI to WinUI 3 (#48891)
## Summary of the Pull Request
Migrates the **Quick Accent (PowerAccent)** module's UI from WPF
(`System.Windows.*`) to **WinUI 3 (Windows App SDK)**, following the
pattern used by other migrated modules (ImageResizer, PowerDisplay). The
accent selector is now a self-contained WinUI 3 app
(`PowerToys.PowerAccent.exe`) shipped under `WinUI3Apps`, and
`PowerAccent.Core` is UI-framework-agnostic.
demo:
https://github.com/user-attachments/assets/400c33ee-0fc0-491e-841b-a546438edf91
## PR Checklist
- [x] Closes: #48889
- [x] **Communication:** Tracked task (#48889) agreed with core
contributors
- [x] **Tests:** Added/updated and all pass — new
`PowerAccent.Core.UnitTests` (21 tests for the positioning / DPI math);
existing `PowerAccent.Common.UnitTests` unaffected
- [x] **Localization:** No new localizable end-user strings — new
accessibility metadata uses non-localized
`AutomationProperties.AutomationId`, and the window title is the brand
name `"Quick Accent"` (literal, matching ColorPicker)
- [x] **Dev docs:** Updated `doc/devdocs/modules/quickaccent.md`
- [x] **New binaries:** Added on the required places
- [x] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json):
the `WinUI3Apps\` PowerAccent payloads are listed in
`ESRPSigning_core.json`
- [x] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs):
no manual `Product.wxs` entry — the self-contained `WinUI3Apps` output
(exe + `.pri` + Windows App SDK runtime) is harvested by the
`WinUI3ApplicationsFiles` glob (same as ImageResizer)
- [x] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml):
no change needed — `PowerAccent.Core.UnitTests` is discovered by the
existing `**\*UnitTest*.dll` VSTest glob
- [x] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml):
covered by `ESRPSigning_core.json`; no `release.yml` change needed
- [ ] **Documentation updated:** N/A — internal UI-framework migration
with no user-facing behavior change
## Detailed Description of the Pull Request / Additional comments
The migration spans three areas (tracked in #48889):
**UI (WPF → WinUI 3)**
- `PowerAccent.UI` is now a WinUI 3 app shell (custom `Program.Main`,
`WindowsPackageType=None`, `WindowsAppSDKSelfContained=true`).
- The accent selector is a non-activating `TransparentWindow` overlay
shown with `SW_SHOWNA` (never steals focus). It is made always-on-top
only while shown — the WinUIEx `WindowEx.IsAlwaysOnTop` property is
toggled `true` on show / `false` on hide in `OnChangeDisplay` (matching
the WPF original's `Topmost = isActive`), so the dormant,
never-destroyed overlay does not pin a discrete GPU awake on
hybrid-graphics laptops (issue #34849 / PR #41044).
- The accent "pill" selection visual is reproduced with
`VisualStateManager` (WinUI 3 has no `Style.Triggers`).
- **WinUI 3 gotcha:** x:Bind on a Window-rooted XAML initializes only on
`Window.Activated`, which never fires for this `SW_SHOWNA` overlay — so
the selector calls `Bindings.Update()` after `InitializeComponent()`;
without it the `ListView` renders empty.
- **Theme:** the long-lived, never-activated process follows the system
app theme automatically — `App.xaml` leaves `Application.RequestedTheme`
unset, so WinUI re-resolves the `{ThemeResource}` brushes (and retints
the acrylic) on a live light/dark switch with no manual `ThemeListener`
needed.
- **Layout parity with the WPF original:** the bar width hugs its
content (`itemCount × 48`, clamped to the monitor width — computed, not
measured, to avoid a racy `ListView` measure), and each cell pins
`MinWidth=48` (WinUI's `ListViewItem` defaults to 88, which would
otherwise leave wide gaps).
- **Accessibility:** UIA window name + `AutomationId`s on the character
list and description.
**Dependency**
- `PowerAccent.Core` no longer depends on WPF — it raises events and
takes an injected UI-thread marshaller.
- WinForms `SendKeys` → `SendInput` (CsWin32 P/Invoke); WPF-UI (Lepo)
removed; language data moved to the UI-/WinRT-agnostic
`PowerAccent.Common`.
- MVVM via CommunityToolkit.Mvvm with `[ObservableProperty]` **partial
properties** (WinRT-correct, clears MVVMTK0045).
**CI / Build / Installer**
- Signing config, WinUI3Apps glob harvest, and the new unit-test project
— see the checklist above.
## Validation Steps Performed
- **Build:** `x64 Debug` builds with **0 warnings / 0 errors**.
- **Unit tests:** `PowerAccent.Core.UnitTests` — **21/21 pass** (9
anchor positions × DPI 1.0/1.5/2.0, the offset and negative-origin
monitors, caret centering + edge clamping + flip-below).
- **XamlStyler:** `PowerAccentXAML/MainWindow.xaml` passes the passive
format check (CI mode).
- **Manual (single monitor, Top-center, light theme):**
- Accent popup appears with the full accent list rendered.
- Bar hugs the characters and is centered; cell spacing matches the WPF
original.
- Switching the system theme (light/dark) is followed live by the popup.
- With `show_description` enabled, the description row is wide (≥600px)
and readable, with the accent bar centered above it.
- **Remaining manual validation** (tracked in #48889): multi-monitor,
per-monitor DPI, all 9 `toolbar_position` values, and high-contrast
theme.
---------
Co-authored-by: Yu Leng <yuleng@microsoft.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Niels Laute <niels.laute@live.nl>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-03 16:58:04 +08:00
|
|
|
<Project Path="src/modules/poweraccent/PowerAccent.Core.UnitTests/PowerAccent.Core.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
[Quick Accent] Move language data to PowerAccent.Common library, refactor (#47211)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Language data for Quick Accent was previously defined in
**PowerAccent.Core/Languages.cs**, internal to the Quick Accent
application itself. The Settings application had no access to the list
and had to maintain a parallel, manually-synchronised list of the
language names and groups, and there was no single place to look up the
complete set of languages.
This PR resolves this and extracts the language data into a new
**PowerAccent.Common** project with no external or UI dependencies,
making it the single source of truth for both the character popup and
Settings UI.
The implicit and non-obvious ordering of the old **Languages.cs** has
been replaced with explicit ordering of the language groups and
languages list.
A new unit test project for the application has also been added.
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
- [x] Closes: #47159
- [x] Closes: #30000
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx
<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
The following changes and additions have been made:
New project **PowerAccent.Common** contains:
- **Language.cs** - an enum of Quick Accent's pseudo-ISO identifiers for
each of the supported languages
- **LetterKey.cs** - mirrors the LetterKey enum defined in the
KeyboardListener.idl, and must be kept in sync with that. This exposes
the VK_* data to the Settings UI without it having to reference the
PowerAccentKeyboardService project
- **LanguageGroup.cs** - classifies languages as `Language` (for spoken
languages), `Special` (for sets like Currency and International Phonetic
Alphabet), or `UserDefined` (reserved for future work)
- **LanguageInfo.cs** - a record which combines a language's identity,
group, resource identifier, and character mappings
- **CharacterMappings.cs** - a new version of the old **Languages.cs**,
providing:
- `All` - the canonical registry of every `LanguageInfo` entry
- `DisplayOrder` - the explicit within-group ordering for languages, for
the default popup ordering, i.e. when the user has not got
frequency-based ordering enabled. This is a culturally-neutral
alphabetical ordering by our pseudo-ISO language IDs, and close to the
previous order, minimising any impact to users' muscle memory
- `GroupDisplayOrder` - the explicit ordering of language groups for
both the popup and the Settings UI
- `LanguageLookup` - new _O(1)_ `Language` to `LanguageInfo` dictionary
- `GetCharacters(LetterKey, Language[])` - a deduplicating character
collector and sorter
A significant improvement over the old **Languages.cs** is that language
ordering is now explicit and in one place. Previously, popup ordering
was an implicit side-effect of a large Union chain across all language
mappings, with the enum, the language mapping declarations and the union
all carrying different orderings. This was a source of confusion and
made adding new languages fragile.
The original **Languages.cs** has been deleted. There's now a thin
`CharacterMappings` adapter that casts the `LetterKey` to the managed
equivalent by numeric value. This is another effort to decouple the
Settings UI and Quick Accent and only share the required elements.
In Settings, the `PowerAccentViewModel` class has been updated. It now
derives the language list directly from `CharacterMappings.All`; the
`InitializeLanguages()` call handles localisation, sorting and grouping
in a single place using `GroupDisplayOrder`.
A new unit test project covers `CharacterMappings`, the `LetterKey`
IDL-to-managed code bridge and general language declaration checks. The
application is now much more robust against changes which alter the
declared order, introduce empty/null elements, and so on. It is now
impossible to add a new language and forget a constituent part (the enum
entry, its place in the display order, the character mappings
themselves) without a test failing.
<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
See new unit test project for comprehensive tests.
Manually confirmed:
- Triggering Quick Accent with no language selected does not report an
error
- Language order is consistent in the popup, no matter what order the
languages are selected in Settings
- The order of languages in Settings is consistent, alphabetically by
localised name
- All declared languages are present in Settings and no resource IDs
were missed
---------
Co-authored-by: Muyuan Li (from Dev Box) <muyuanli@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-22 07:24:26 +00:00
|
|
|
<Project Path="src/modules/poweraccent/PowerAccent.Common/PowerAccent.Common.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/modules/poweraccent/PowerAccent.Core/PowerAccent.Core.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/poweraccent/PowerAccent.UI/PowerAccent.UI.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/poweraccent/PowerAccentKeyboardService/PowerAccentKeyboardService.vcxproj" Id="c97d9a5d-206c-454e-997e-009e227d7f02" />
|
|
|
|
|
<Project Path="src/modules/poweraccent/PowerAccentModuleInterface/PowerAccentModuleInterface.vcxproj" Id="34a354c5-23c7-4343-916c-c52daf4fc39d" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/PowerOCR/">
|
|
|
|
|
<Project Path="src/modules/PowerOCR/PowerOCR/PowerOCR.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/PowerOCR/PowerOCRModuleInterface/PowerOCRModuleInterface.vcxproj" Id="6ab6a2d6-f859-4a82-9184-0bd29c9f07d1" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/PowerOCR/Tests/">
|
|
|
|
|
<Project Path="src/modules/PowerOCR/PowerOCR-UITests/PowerOCR.UITests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/powerrename/">
|
|
|
|
|
<Project Path="src/modules/powerrename/dll/PowerRenameExt.vcxproj" Id="b25ac7a5-fb9f-4789-b392-d5c85e948670">
|
|
|
|
|
<BuildDependency Project="src/modules/powerrename/lib/PowerRenameLib.vcxproj" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/powerrename/lib/PowerRenameLib.vcxproj" Id="51920f1f-c28c-4adf-8660-4238766796c2" />
|
|
|
|
|
<Project Path="src/modules/powerrename/PowerRenameContextMenu/PowerRenameContextMenu.vcxproj" Id="1dbbb112-4bb1-444b-8ebb-e66555c76ba6" />
|
|
|
|
|
<Project Path="src/modules/powerrename/PowerRenameUILib/PowerRenameUI.vcxproj" Id="27718999-c175-450a-861c-89f911e16a88" />
|
|
|
|
|
<Project Path="src/modules/powerrename/testapp/PowerRenameTest.vcxproj" Id="a3935cf4-46c5-4a88-84d3-6b12e16e6ba2" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/powerrename/Tests/">
|
|
|
|
|
<Project Path="src/modules/powerrename/PowerRename.FuzzingTest/PowerRename.FuzzingTest.vcxproj" Id="2694e2fb-dcd5-4bff-a418-b6c3c7ce3b8e">
|
|
|
|
|
<Build Solution="*|ARM64" Project="false" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/powerrename/PowerRenameUITest/PowerRename.UITests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/powerrename/unittests/PowerRenameLibUnitTests.vcxproj" Id="2151f984-e006-4a9f-92ef-c6dde3dc8413">
|
|
|
|
|
<BuildDependency Project="src/modules/powerrename/dll/PowerRenameExt.vcxproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/powerrename/lib/PowerRenameLib.vcxproj" />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/previewpane/">
|
|
|
|
|
<Project Path="src/modules/previewpane/BgcodePreviewHandler/BgcodePreviewHandler.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/BgcodePreviewHandlerCpp/BgcodePreviewHandlerCpp.vcxproj" Id="f6088a11-1c9e-4420-aa90-cf7e78dd7f1c" />
|
|
|
|
|
<Project Path="src/modules/previewpane/BgcodeThumbnailProvider/BgcodeThumbnailProvider.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/BgcodeThumbnailProviderCpp/BgcodeThumbnailProviderCpp.vcxproj" Id="47b0678c-806b-4fe1-9f50-46ba88989532" />
|
|
|
|
|
<Project Path="src/modules/previewpane/Common/PreviewHandlerCommon.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/GcodePreviewHandler/GcodePreviewHandler.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/GcodePreviewHandlerCpp/GcodePreviewHandlerCpp.vcxproj" Id="5a5dd09d-723a-44d3-8f2b-293584c3d731" />
|
|
|
|
|
<Project Path="src/modules/previewpane/GcodeThumbnailProvider/GcodeThumbnailProvider.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/GcodeThumbnailProviderCpp/GcodeThumbnailProviderCpp.vcxproj" Id="56cc2f10-6e41-453d-be16-c593a5e58482" />
|
|
|
|
|
<Project Path="src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandler.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/MarkdownPreviewHandlerCpp/MarkdownPreviewHandlerCpp.vcxproj" Id="ed9a1ac6-aeb0-4569-a6e9-e1696182b545" />
|
|
|
|
|
<Project Path="src/modules/previewpane/MonacoPreviewHandler/MonacoPreviewHandler.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/MonacoPreviewHandlerCpp/MonacoPreviewHandlerCpp.vcxproj" Id="b3e869c4-8210-4ebd-a621-ff4c4afcbfa9" />
|
|
|
|
|
<Project Path="src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandler.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/PdfPreviewHandlerCpp/PdfPreviewHandlerCpp.vcxproj" Id="54f7c616-fd41-4e62-bff9-015686914f4d" />
|
|
|
|
|
<Project Path="src/modules/previewpane/PdfThumbnailProvider/PdfThumbnailProvider.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/PdfThumbnailProviderCpp/PdfThumbnailProviderCpp.vcxproj" Id="ca5518ed-0458-4b09-8f53-4122b9888655" />
|
|
|
|
|
<Project Path="src/modules/previewpane/powerpreview/powerpreview.vcxproj" Id="217df501-135c-4e38-bfc8-99d4821032ea">
|
|
|
|
|
<BuildDependency Project="src/common/version/version.vcxproj" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/QoiPreviewHandler/QoiPreviewHandler.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/QoiPreviewHandlerCpp/QoiPreviewHandlerCpp.vcxproj" Id="3baf9c81-a194-4925-a035-5e24a5d1e542" />
|
|
|
|
|
<Project Path="src/modules/previewpane/QoiThumbnailProvider/QoiThumbnailProvider.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/QoiThumbnailProviderCpp/QoiThumbnailProviderCpp.vcxproj" Id="ccb5e44f-84d9-4203-83c6-1c9ec9302bc7" />
|
|
|
|
|
<Project Path="src/modules/previewpane/StlThumbnailProvider/StlThumbnailProvider.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/StlThumbnailProviderCpp/StlThumbnailProviderCpp.vcxproj" Id="d6dcc3ae-18c0-488a-b978-baa9e3cff09d" />
|
|
|
|
|
<Project Path="src/modules/previewpane/SvgPreviewHandler/SvgPreviewHandler.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/SvgPreviewHandlerCpp/SvgPreviewHandlerCpp.vcxproj" Id="143f13e3-d2e3-4d83-b035-356612d99956" />
|
|
|
|
|
<Project Path="src/modules/previewpane/SvgThumbnailProvider/SvgThumbnailProvider.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/SvgThumbnailProviderCpp/SvgThumbnailProviderCpp.vcxproj" Id="2bbc9e33-21ec-401c-84da-bb6590a9b2aa" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/previewpane/Tests/">
|
[UITests] Add UITest.Next suites (Image Resizer, Peek, File Explorer add‑ons, File Locksmith) + local‑VM tooling and CI test‑signing (#49671)
## Summary
Adds end‑to‑end UI tests on the `Microsoft.PowerToys.UITest.Next`
(winappcli) framework for three
modules, grows the shared `.Next` test framework with the helpers those
suites needed, and adds the
CI plumbing that lets shell‑extension tests exercise the **real**
Windows 11 modern context menu.
Also ships two agent skills that document how to write and run these
tests.
Product runtime behavior is **unchanged** — the only product edits are
test‑observability hooks in Peek
and a unit‑test project exclude.
Closes: https://github.com/microsoft/PowerToys/issues/40660
https://github.com/microsoft/PowerToys/issues/49424
https://github.com/microsoft/PowerToys/issues/40661
## What's added
### New UI test suites
- **Image Resizer** —
`src/modules/imageresizer/tests/ImageResizer.UITests`: context‑menu
enable/disable
tracking, the resize dialog, custom presets, every fit mode, every unit,
filename format, keep‑date,
shrink‑only, replace‑in‑place, and orientation.
- **Peek** — `src/modules/peek/Peek.UITests.Next`: file‑preview coverage
across image/text/archive/
markdown types with per‑arch visual baselines.
- **File Explorer add‑ons** —
`src/modules/previewpane/PreviewPane.UITests`: Preview Pane handlers and
thumbnail providers.
### `UITestAutomation.Next` framework
- New helpers: `ExplorerShell` (Shell selection/view‑mode interop),
`WaitHelper` (structured stable
waits), `WindowControl` (foreground/context‑menu/process control),
`VisualAssert` (image compare),
`WindowHelper`.
- Updates to `Session`, `UITestBase`, `SettingsConfigHelper`,
`WinappCli`.
- New `UITestAutomation.Next.UnitTests` project covering the new
wait/settings/CLI helpers.
### CI — sign sparse MSIX so the modern menu registers
- **`.pipelines/signSparsePackages.ps1`** — self‑signs each sparse
context‑menu MSIX with a
publisher‑matching test certificate and force‑trusts it (machine
stores), so
`AddPackageByUriAsync` succeeds on otherwise‑unsigned PR builds. Robust
`signtool` discovery with a
NuGet fallback; test‑only trust that asserts no security.
- Wired into **`.pipelines/v2/templates/job-test-project.yml`** as a
best‑effort step covering the
run‑in‑place, machine‑install, and per‑user‑install locations. Signs
nothing it can't (skips
already‑signed packages) and never fails the job.
### Product changes (test observability only)
- **Peek `FilePreview.xaml` / `.xaml.cs`** — a named `LoadingIndicator`
and a hidden automation peer
that exposes the current preview state as text, so tests can read load
state deterministically. No
runtime behavior change.
- **`ImageResizer.UnitTests.csproj`** — exclude the sibling
`ImageResizer.UITests\**` folder from the
unit‑test compilation.
### Agent skills & docs
- **New `ui-tests-local-vm` skill** — run `.Next` suites in persistent
dockur/windows VMs: setup,
agentic loop, image customization, troubleshooting, the shell‑extension
**signing** reference, plus
controller/guest scripts and VM templates.
- **Updated `ui-tests-migration` skill** — WinAppDriver/Selenium →
`.Next` porting guidance
(CI stability, Explorer/shell‑extension test design, patterns &
pitfalls).
- **`doc/devdocs/development/ui-tests.md`** — updated for the `.Next`
workflow.
## Testing
- All three suites pass locally and in CI across **x64 Win10**, **x64
Win11**, and **arm64** (machine
and per‑user install legs).
## Reviewer notes
- No product runtime behavior changes; product edits are limited to the
Peek test hooks above.
- The CI signing step is a **test‑only** trust anchor (self‑signed,
scoped to the agent) and is
best‑effort, so it can only add modern‑menu coverage and never regress
the job.
2026-08-10 10:55:03 -07:00
|
|
|
<Project Path="src/modules/previewpane/PreviewPane.UITests/PreviewPane.UITests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/modules/previewpane/UnitTests-BgcodePreviewHandler/Preview.BgcodePreviewHandler.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/UnitTests-BgcodeThumbnailProvider/Preview.BgcodeThumbnailProvider.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/UnitTests-GcodePreviewHandler/Preview.GcodePreviewHandler.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/UnitTests-GcodeThumbnailProvider/Preview.GcodeThumbnailProvider.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/UnitTests-MarkdownPreviewHandler/Preview.MarkdownPreviewHandler.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/UnitTests-PdfPreviewHandler/Preview.PdfPreviewHandler.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/UnitTests-PdfThumbnailProvider/Preview.PdfThumbnailProvider.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/UnitTests-PreviewHandlerCommon/Preview.PreviewHandlerCommon.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/UnitTests-QoiPreviewHandler/Preview.QoiPreviewHandler.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/UnitTests-QoiThumbnailProvider/Preview.QoiThumbnailProvider.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/UnitTests-StlThumbnailProvider/Preview.StlThumbnailProvider.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/UnitTests-SvgPreviewHandler/Preview.SvgPreviewHandler.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/previewpane/UnitTests-SvgThumbnailProvider/Preview.SvgThumbnailProvider.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/RegistryPreview/">
|
|
|
|
|
<Project Path="src/modules/registrypreview/RegistryPreview/RegistryPreview.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/registrypreview/RegistryPreviewExt/RegistryPreviewExt.vcxproj" Id="697c6af9-0a48-49a9-866c-67da12384015" />
|
|
|
|
|
<Project Path="src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewUILib.csproj" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/RegistryPreview/Test/">
|
|
|
|
|
<Project Path="src/modules/registrypreview/RegistryPreview.FuzzTests/RegistryPreview.FuzzTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
2026-05-21 17:27:52 +02:00
|
|
|
<Folder Name="/modules/ShortcutGuide/">
|
|
|
|
|
<Project Path="src/modules/ShortcutGuide/ShortcutGuide.IndexYmlGenerator/ShortcutGuide.IndexYmlGenerator.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj">
|
feat(shortcut-guide): add Postman manifest and fix numbered-key display (#48461)
## Summary of the Pull Request
Adds a Shortcut Guide manifest for **Postman** and fixes a rendering bug
where single-digit keys in manifests displayed incorrectly.
- **Fix numbered-key rendering** —
`src/modules/ShortcutGuide/ShortcutGuide.Ui/Converters/ShortcutDescriptionToKeysConverter.cs`:
a single digit (`0`–`9`) in a manifest's `Keys` was treated as a Windows
virtual-key code instead of the literal digit. Since VK `1` is the left
mouse button, VK `9` is Tab, and VK `0` is undefined, shortcuts such as
`Ctrl+0` (reset zoom) and `Ctrl+9` (last tab) rendered as
blank/incorrect glyphs. Single digits are now rendered as the literal
character.
- **Add Postman shortcuts** —
`src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/Manifests/Postman.Postman.en-US.yml`:
new manifest for `Postman.exe` covering Tabs, Sidebar, Request,
Interface, Window and modals, and Console. Auto-included via the
existing `Manifests/*.yml` glob in `ShortcutGuide.Ui.csproj`.
- **Show tab-number ranges** — Edge, Chrome, Firefox, and Postman
manifests: the "switch to a specific tab" entry used the literal key
`1`, which (after the fix above) read as `Ctrl + 1`. It now uses a `1 -
8` range so the keycap conveys "any tab number 1 through 8". The
separate "last tab" (`9`) and "reset zoom" (`0`) entries remain literal
single keys.
- **Add unit tests** — new `ShortcutGuide.UnitTests` (MSTest) project
covering `ShortcutDescriptionToKeysConverter.GetKeysList`, including the
single-digit regression.
## PR Checklist
- [x] Closes: #48460
- [ ] **Communication:** I've discussed this with core contributors
already. <!-- Filed #48460; the v0.100 announcement invites app-shortcut
contributions via PR. -->
- [x] **Tests:** Added/updated and all pass <!-- New
ShortcutGuide.UnitTests (MSTest); 8 tests pass locally via
vstest.console. -->
- [x] **Localization:** All end-user-facing strings can be localized
<!-- Shortcut names live in per-language manifest files (`*.en-US.yml`);
other locales fall back to en-US, consistent with existing manifests.
-->
- [ ] **Dev docs:** Added/updated <!-- N/A: no behavior requiring
dev-doc changes. -->
- [ ] **New binaries:** Added on the required places <!-- N/A: the new
manifest is a data asset under an already-shipped, globbed folder. The
new test project is auto-discovered by the existing `**\*UnitTest*.dll`
VSTest glob, so no CI pipeline change is required. -->
- [ ] **Documentation updated:** <!-- N/A -->
## Detailed Description of the Pull Request / Additional comments
The Shortcut Guide displays per-app shortcuts from YAML manifests,
matched to the foreground window via `WindowFilter`. Keys are converted
to keycaps by `ShortcutDescriptionToKeysConverter`. Numeric key strings
were unconditionally parsed as virtual-key codes, so literal-digit
shortcuts rendered wrong. The fix adds a `>= 0 and <= 9` case that emits
the digit character as-is; non-digit numeric codes (arrows, etc.) are
unchanged.
The new Postman manifest exercises this with `Ctrl+0` / `Ctrl+9`. The
browser/Postman "specific tab" entries were updated from the literal `1`
to the `1 - 8` range string, rendered verbatim by `KeyVisual` (the same
path used by the existing `Number (1-9)` key in the Windows Explorer
manifest).
A new `ShortcutGuide.UnitTests` (MSTest) project covers the converter:
single digits render literally (regression test), modifier ordering,
non-numeric passthrough (e.g. `1 - 8`), and arrow-key VK mapping.
## Validation Steps Performed
Built and ran locally (x64 Debug):
- Built `ShortcutGuideModuleInterface`, `ShortcutGuide.Ui`, and
`ShortcutGuide.IndexYmlGenerator`; launched the Debug `PowerToys.exe`.
- Triggered Shortcut Guide (`Win+Shift+/`) with **Postman** focused: the
Postman section renders with all categories, and `Ctrl+1` / `Ctrl+9` /
`Ctrl+0` display correctly (previously blank/incorrect).
- Verified the "specific tab" entry renders as `Ctrl + 1 - 8` in
**Edge**, **Chrome**, **Firefox**, and **Postman**.
- Built `ShortcutGuide.UnitTests` and ran via `vstest.console.exe`:
**8/8 tests pass**.
<img width="845" height="1432" alt="PowerToys Shortcut Guide Running
Postman"
src="https://github.com/user-attachments/assets/6359617e-3e2c-48b0-8005-b3684594ec94"
/>
Co-Authored-By: Claude Opus 4.8
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 22:40:29 -06:00
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/ShortcutGuide/ShortcutGuide.UnitTests/ShortcutGuide.UnitTests.csproj">
|
2026-05-21 17:27:52 +02:00
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/ShortcutGuide/ShortcutGuideModuleInterface/ShortcutGuideModuleInterface.vcxproj" Id="e487304a-b1fb-4e6b-8e70-014051af5b99" />
|
2025-12-03 03:59:46 -06:00
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/Workspaces/">
|
2025-12-23 21:07:44 +08:00
|
|
|
<Project Path="src/modules/Workspaces/Workspaces.ModuleServices/Workspaces.ModuleServices.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/modules/Workspaces/WorkspacesCsharpLibrary/WorkspacesCsharpLibrary.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/Workspaces/WorkspacesEditor/WorkspacesEditor.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/Workspaces/WorkspacesLauncher/WorkspacesLauncher.vcxproj" Id="2cac093e-5fcf-4102-9c2c-ac7dd5d9eb96" />
|
|
|
|
|
<Project Path="src/modules/Workspaces/WorkspacesLauncherUI/WorkspacesLauncherUI.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/Workspaces/WorkspacesLib/WorkspacesLib.vcxproj" Id="b31fcc55-b5a4-4ea7-b414-2dceae6af332" />
|
|
|
|
|
<Project Path="src/modules/Workspaces/WorkspacesModuleInterface/WorkspacesModuleInterface.vcxproj" Id="45285df2-9742-4eca-9ac9-58951fc26489" />
|
|
|
|
|
<Project Path="src/modules/Workspaces/WorkspacesSnapshotTool/WorkspacesSnapshotTool.vcxproj" Id="3d63307b-9d27-44fd-b033-b26f39245b85" />
|
|
|
|
|
<Project Path="src/modules/Workspaces/WorkspacesWindowArranger/WorkspacesWindowArranger.vcxproj" Id="37d07516-4185-43a4-924f-3c7a5d95ecf6" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/Workspaces/Tests/">
|
|
|
|
|
<Project Path="src/modules/Workspaces/WorkspacesEditorUITest/Workspaces.Editor.UITests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/Workspaces/WorkspacesLib.UnitTests/WorkspacesLibUnitTests.vcxproj" Id="a85d4d9f-9a39-4b5d-8b5a-9f2d5c9a8b4c" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/Workspaces/WindowProperties/">
|
|
|
|
|
<File Path="src/modules/Workspaces/WindowProperties/WorkspacesWindowPropertyUtils.h" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/Workspaces/workspaces-common/">
|
|
|
|
|
<File Path="src/modules/Workspaces/workspaces-common/GuidUtils.h" />
|
|
|
|
|
<File Path="src/modules/Workspaces/workspaces-common/InvokePoint.h" />
|
|
|
|
|
<File Path="src/modules/Workspaces/workspaces-common/MonitorEnumerator.h" />
|
|
|
|
|
<File Path="src/modules/Workspaces/workspaces-common/MonitorUtils.h" />
|
|
|
|
|
<File Path="src/modules/Workspaces/workspaces-common/VirtualDesktop.h" />
|
|
|
|
|
<File Path="src/modules/Workspaces/workspaces-common/WindowEnumerator.h" />
|
|
|
|
|
<File Path="src/modules/Workspaces/workspaces-common/WindowFilter.h" />
|
|
|
|
|
<File Path="src/modules/Workspaces/workspaces-common/WindowUtils.h" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/modules/ZoomIt/">
|
2026-03-26 13:21:43 +01:00
|
|
|
<Project Path="src/modules/ZoomIt/ZoomIt/ZoomIt.vcxproj" Id="0a84f764-3a88-44cd-aa96-41bdbd48627b">
|
|
|
|
|
<BuildDependency Project="src/modules/ZoomIt/ZoomItBreak/ZoomItBreak.vcxproj" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/modules/ZoomIt/ZoomItBreak/ZoomItBreak.vcxproj" Id="94ba3051-c8d7-454a-9d46-1a7c78e228a3" />
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/modules/ZoomIt/ZoomItModuleInterface/ZoomItModuleInterface.vcxproj" Id="e4585179-2ac1-4d5f-a3ff-cfc5392f694c" />
|
|
|
|
|
<Project Path="src/modules/ZoomIt/ZoomItSettingsInterop/ZoomItSettingsInterop.vcxproj" Id="ca7d8106-30b9-4aec-9d05-b69b31b8c461" />
|
|
|
|
|
</Folder>
|
2026-04-15 15:13:56 +08:00
|
|
|
<Folder Name="/modules/GrabAndMove/">
|
|
|
|
|
<Project Path="src/modules/GrabAndMove/GrabAndMove/GrabAndMove.vcxproj" Id="568c4c30-2e3c-4c2c-a691-007362073765" />
|
|
|
|
|
<Project Path="src/modules/GrabAndMove/GrabAndMoveModuleInterface/GrabAndMoveModuleInterface.vcxproj" Id="2c3f7770-4e57-46b7-8dc1-7428a383d0db" />
|
|
|
|
|
</Folder>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Folder Name="/settings-ui/">
|
2026-01-07 16:38:09 +08:00
|
|
|
<Project Path="src/settings-ui/QuickAccess.UI/PowerToys.QuickAccess.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/settings-ui/Settings.UI.Controls/Settings.UI.Controls.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="src/settings-ui/Settings.UI.Library/Settings.UI.Library.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/settings-ui/Settings.UI.XamlIndexBuilder/Settings.UI.XamlIndexBuilder.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/settings-ui/Settings.UI/PowerToys.Settings.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
|
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/settings-ui/Tests/">
|
|
|
|
|
<Project Path="src/settings-ui/Settings.UI.UnitTests/Settings.UI.UnitTests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
[UITests] New framework around WinApp CLI, no WinAppDriver or Selenium. (#48467)
# Add winappcli-based UI test harness (no WinAppDriver / Selenium)
## Summary
Introduces a new UI test harness — `Microsoft.PowerToys.UITest.Next` —
that drives PowerToys
modules through Microsoft's
[winappcli](https://github.com/microsoft/WinAppCli) (UI Automation
CLI) instead of WinAppDriver + Selenium. Engine is a single executable
shelled out from
C#; no third-party NuGet packages, no driver process, no Appium server.
Adds two real consumers:
a full ColorPicker end-to-end scenario and a Settings shell navigation
smoke test.
This is opt-in and additive — the existing `UITestAutomation` library
and the
WinAppDriver-based test projects are untouched. Both can coexist while
we evaluate the new
harness.
Inspired in part by
[#48414](https://github.com/microsoft/PowerToys/pull/48414), which lands
the same architectural bet (winappcli, AutomationId selectors, no
WinAppDriver) at a smaller
scope. This PR generalizes it into a reusable library.
## Why
WinAppDriver + Selenium is a legacy pre-agentic solution that is no
longer actively maintained. It's unreliable, heavyweight, and slow. To
achieve 100% UI test coverage, we should leverage modern, reliable
solutions, and WinApp CLI is a strong candidate.
## What's in this PR
### Harness library —
[`src/common/UITestAutomation.Next/`](src/common/UITestAutomation.Next/)
| File | Purpose |
|---|---|
| [`WinappCli.cs`](src/common/UITestAutomation.Next/WinappCli.cs) |
Process wrapper around `winapp.exe`. `Invoke` / `InvokeAssertSuccess` /
`InvokeJson` / `IsAvailable` / `TryResolveExecutable`. `Result` carries
the args and emits `DescribeFailure()` like `winapp ui invoke X -w 12345
-> exit 1; stderr: ...` |
| [`Session.cs`](src/common/UITestAutomation.Next/Session.cs) | Test
session, scoped by either HWND (`-w`) or process (`-a`) via
`TargetScope`. `Find<T>` / `FindAll<T>` / `Inspect` / `Screenshot` /
`SendKeys`. `Session.FromProcess(...)` factory for the
single-window-per-process case |
|
[`SessionHelper.cs`](src/common/UITestAutomation.Next/SessionHelper.cs)
| Owns the launch + window-readiness flow. Static `EnsureRunning(scope,
timeout)` returns whether the call had to launch (so cleanup only kills
what we started). Uses `UseShellExecute=true` so child handles don't
keep MSTest hanging |
| [`UITestBase.cs`](src/common/UITestAutomation.Next/UITestBase.cs) |
MSTest base class. Pre-flights `WinappCli.IsAvailable()` once per
process and fails fast with the install hint if `winapp.exe` isn't on
PATH |
| [`Element/*.cs`](src/common/UITestAutomation.Next/Element/) |
`Element`, `Button`, `ToggleSwitch`, `TextBox`, `NavigationViewItem`,
`Window`. `Click` / `MouseClick` / `Focus` / `GetProperty` / `GetValue`
/ `HelpText` / `WaitForProperty` / `WaitForGone` plus coords
(`X`/`Y`/`Width`/`Height`) |
| [`By.cs`](src/common/UITestAutomation.Next/By.cs) | `By.Name` /
`By.AccessibilityId` / `By.Id` / `By.Slug` |
| [`Windows.cs`](src/common/UITestAutomation.Next/Windows.cs) |
`WindowsFinder.ListAll` / `ListByApp` / `WaitForWindowByApp` /
`WaitForWindowByProcess`. Notes the winappcli bug where unfiltered
`list-windows` drops untitled windows |
|
[`WindowControl.cs`](src/common/UITestAutomation.Next/WindowControl.cs)
| Tolerant Win32 helpers — `TryCloseByApp` / `TryFocusByApp` /
`SafeCloseAndFocus` / `TryKillProcess` — for `finally` blocks |
|
[`KeyboardHelper.cs`](src/common/UITestAutomation.Next/KeyboardHelper.cs)
| Hybrid `keybd_event` + `SendKeys.SendWait` chord sender — required for
global PowerToys hotkeys |
| [`MouseHelper.cs`](src/common/UITestAutomation.Next/MouseHelper.cs) |
`MoveTo` / `LeftClick` / `RightClick` / `LeftClickAt` Win32 wrappers |
|
[`ClipboardHelper.cs`](src/common/UITestAutomation.Next/ClipboardHelper.cs)
| STA-thread `Clipboard` access with `WaitForText` |
|
[`ModuleConfigData.cs`](src/common/UITestAutomation.Next/ModuleConfigData.cs)
| `PowerToysModule` enum + path/process-name resolution |
### Tests
**[`src/modules/colorPicker/ColorPicker.UITests/`](src/modules/colorPicker/ColorPicker.UITests/)**
— replaces the previous empty `UITest-ColorPicker` stub. One test,
[`ColorPickerEndToEndTests.NavigateReadShortcutActivateAndCapture`](src/modules/colorPicker/ColorPicker.UITests/ColorPickerEndToEndTests.cs),
drives the full E2E:
1. Navigate to the Color Picker page via the dashboard utilities stack
2. Toggle the module OFF, verify `PowerToys.ColorPickerUI` exits; toggle
ON, verify it respawns
3. Read the activation shortcut from the page's `ShortcutControl`
(`EditButton.HelpText`)
4. Clear clipboard, park cursor, send the chord
5. Wait for the picker overlay window
6. Read the displayed HEX from a hidden XAML automation peer (see below)
7. Left-click to capture; assert the clipboard value matches the peer's
HEX
8. Wait for the editor window and assert the captured color appears in
its tree
**[`src/settings-ui/Settings.UITests/`](src/settings-ui/Settings.UITests/)**
— `SettingsNavigationSmokeTests.NavigationItem_NavigatesWithoutCrashing`
is one `[TestMethod]` parameterized with `[DynamicData]`, producing 31
discrete results — one per `NavigationViewItem` in
[`ShellPage.xaml`](src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml).
For each item: navigate, settle 250ms, assert `PowerToys.Settings` is
still alive. Catches FailFast regressions in
`ShellViewModel.Frame_NavigationFailed` that pure-logic unit tests can't
reach (the failure path needs a `NavigationFailedEventArgs` which is a
sealed WinRT projection).
### Product change
**[`src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml`](src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml)**
— adds a hidden `TextBlock` automation peer:
```xml
<TextBlock
x:Name="ColorHexAutomationPeer"
AutomationProperties.AutomationId="ColorHexAutomationPeer"
IsHitTestVisible="False"
Opacity="0"
Text="{Binding ColorText}" />
```
The visible `ColorTextBlock` has `AutomationProperties.Name="{Binding
ColorName}"`, which masks the HEX value in the UIA tree (you see "White"
instead of `#FFFFFF`). This zero-impact peer mirrors `ColorText` so
tests can read the actually-displayed HEX. `Opacity=0` +
`IsHitTestVisible=False` keep it out of the visual layout and out of
accessibility focus.
### Project wiring
- [`PowerToys.slnx`](PowerToys.slnx) — registers `UITestAutomation.Next`
under `/common/`, `ColorPicker.UITests` under
`/modules/colorpicker/Tests/`, and `Settings.UITests` under
`/settings-ui/Tests/`. Original `UITest-ColorPicker` stub csproj
removed.
-
[`.github/actions/spell-check/expect.txt`](.github/actions/spell-check/expect.txt)
— adds `winapp` / `winappcli`.
### Not in this PR
- No pipeline changes. `winapp.exe` is expected to be pre-staged on the
test agent image. If it's missing, `UITestBase` fails the first test
with the install hint (`winget install Microsoft.winappcli`) rather than
producing 30 opaque per-test errors.
- No changes to the legacy `UITestAutomation` library or any of the
existing `*.UITests` projects.
## Validation
- All three projects build clean on `x64|Debug` (empty
`build.<config>.<plat>.errors.log`):
- `src/common/UITestAutomation.Next/`
- `src/modules/colorPicker/ColorPicker.UITests/`
- `src/settings-ui/Settings.UITests/`
- Both tests run in Test Explorer / `dotnet test` via
Microsoft.Testing.Platform (already enabled repo-wide in
`Directory.Build.props`).
- Local runs: ColorPicker E2E green; Settings smoke green across all 31
nav items.
- `winapp 0.3.2` from `winget install Microsoft.winappcli`.
## Notes for reviewers
- **`UseShellExecute = true`** in `SessionHelper.EnsureRunning` is
intentional — `false` makes child processes inherit the test host's
stdin/stdout/stderr handles, which keeps MTP/Test Explorer marking the
run as "in progress" until the spawned PowerToys exits.
- **Process-scope (`-a`) targeting** in the Settings smoke test handles
single-instance handoff: the EXE you launch may exit with code 0
immediately after signalling an existing owner, so the alive check uses
`Process.GetProcessesByName` rather than the launcher PID.
- **AutomationId-only selectors** in the Settings smoke list keep the
test localization-independent. Parent groups have
`SelectsOnInvoked="False"` and only expand on click — `Element.Click`
tries `InvokePattern → TogglePattern → SelectionItemPattern →
ExpandCollapsePattern` so the same call works for both leaves and
groups.
- **Untitled-window discovery**: filtered `winapp ui list-windows -a
<name>` returns windows that the unfiltered call drops (e.g. ColorPicker
editor). `WindowsFinder.ListByApp` uses the filtered form. Reported
upstream.
## Before Merge
- Add the `winappcli` install step to the UI-test pipeline.
2026-07-07 22:58:08 -07:00
|
|
|
<Project Path="src/settings-ui/Settings.UITests/Settings.UITests.csproj">
|
|
|
|
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
|
|
|
<Platform Solution="*|x64" Project="x64" />
|
|
|
|
|
</Project>
|
2025-12-03 03:59:46 -06:00
|
|
|
</Folder>
|
|
|
|
|
<Folder Name="/Solution Items/">
|
|
|
|
|
<File Path=".vsconfig" />
|
|
|
|
|
<File Path="Cpp.Build.props" />
|
|
|
|
|
<File Path="Directory.Build.props" />
|
|
|
|
|
<File Path="Directory.Build.targets" />
|
|
|
|
|
<File Path="Directory.Packages.props" />
|
|
|
|
|
<File Path="src/.editorconfig" />
|
|
|
|
|
<File Path="src/Common.Dotnet.AotCompatibility.props" />
|
|
|
|
|
<File Path="src/Common.Dotnet.CsWinRT.props" />
|
[Build] Separate WinRT props from common .NET props, make verify script more robust and faster (#48059)
<!-- 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
Separates out the common .NET build properties from
**Common.Dotnet.CsWinRT.props** into a new file so POCO libraries don't
have to import WinRT or add exclusions to **verifyCommonProps.ps1**.
Also updates the verify script for robustness and speed.
<!-- 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 is a follow-on from #47211, which included a C# project that didn't
target WinRT. Previously, all C# projects were mandated to include
**Common.Dotnet.CsWinRT.props**, even if they didn't need the WinRT
import, because the common .NET build properties like `TargetFramework`
and Debug/Release configuration were included in the same file.
This PR separates out the non-WinRT information into a new
**Common.Dotnet.props** file. The existing
**Common.Dotnet.CsWinRT.props** file imports this, meaning no changes
are required for existing C# projects.
Additionally, the **verifyCommonProps.ps1** script has been updated to
remove redundant exclusions, add checks for malformed XML, and to speed
up the scan.
### Changes to verifyCommonProps.ps1
The following updates were made:
- Added descriptive header and param info.
- Now using .NET's `EnumerateFiles()` instead of Powershell's slow file
enumeration.
- Now using `XmlDocument.Load()` to quickly load the content of the
file.
- Parsing the document now uses `GetElementsByTagName()` with a '*'
wildcard for the namespace to pull out `Import` tags regardless of
location or ns prefix.
- Removed prior exclusions for **Microsoft.CmdPal.Core.*** and
**Microsoft.CmdPal.Ext.Shell** projects. There are no Core projects any
longer and the **Microsoft.CmdPal.Ext.Shell** project already includes
an import for **Common.Dotnet.CsWinRT.props**.
- Filename comparisons now use an exact match to the filename itself
rather than a wildcard substring match. This means the check is robust
against project names with the same suffix.
- Early exit `break` on successful match, so the whole file need not be
scanned.
- `try/catch` added to prevent a .csproj XML parsing error from breaking
the CI.
<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
- Built all Quick Accent projects and confirmed all unit tests passed.
- Edited a .csproj to exclude the end tag. Ran **verifyCommonProps.ps1**
to confirm the parsing error was reported.
- Edited **verifyCommonProps.ps1** to remove the exclusion for
**TemplateCmdPalExtension.csproj**. Ran the script to confirm that the
file was correctly flagged.
- Edited **PowerAccent.Common.csproj** to remove the Import for
**Common.Dotnet.props**. Ran the verify script to confirm that the file
was correctly flagged.
- Edited **PowerAccent.Core.csproj** to remove the Import for
**Common.Dotnet.CsWinRT.props**. Ran the verify script to confirm that
the file was correctly flagged.
## Verify Script Performance
File cache|Before (ms)|After (ms)
--|--|--
Cold|3123|1739
Warm|1849|686
2026-08-18 07:44:10 +01:00
|
|
|
<File Path="src/Common.Dotnet.props" />
|
2025-12-03 03:59:46 -06:00
|
|
|
<File Path="src/Common.SelfContained.props" />
|
|
|
|
|
<File Path="src/Monaco.props" />
|
|
|
|
|
<File Path="src/Solution.props" />
|
|
|
|
|
<File Path="src/Version.props" />
|
|
|
|
|
</Folder>
|
|
|
|
|
<Project Path="src/ActionRunner/ActionRunner.vcxproj" Id="d29ddd63-e2cf-4657-9fd5-2aede4257e5d">
|
|
|
|
|
<BuildDependency Project="src/common/updating/updating.vcxproj" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/PackageIdentity/PackageIdentity.vcxproj" Id="e2a5a82e-1e5b-4c8d-9a4f-2b1a8f9e5c3d" />
|
|
|
|
|
<Project Path="src/runner/runner.vcxproj" Id="9412d5c6-2cf2-4fc2-a601-b55508ea9b27">
|
|
|
|
|
<BuildDependency Project="src/ActionRunner/ActionRunner.vcxproj" />
|
|
|
|
|
<BuildDependency Project="src/common/notifications/BackgroundActivator/BackgroundActivator.vcxproj" />
|
|
|
|
|
<BuildDependency Project="src/common/notifications/BackgroundActivatorDLL/BackgroundActivatorDLL.vcxproj" />
|
|
|
|
|
<BuildDependency Project="src/common/updating/updating.vcxproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/awake/Awake/Awake.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/awake/AwakeModuleInterface/AwakeModuleInterface.vcxproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/colorPicker/ColorPicker/ColorPicker.vcxproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/colorPicker/ColorPickerUI/ColorPickerUI.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/fancyzones/editor/FancyZonesEditor/FancyZonesEditor.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/fancyzones/FancyZonesModuleInterface/FancyZonesModuleInterface.vcxproj" />
|
[UITests] New framework around WinApp CLI, no WinAppDriver or Selenium. (#48467)
# Add winappcli-based UI test harness (no WinAppDriver / Selenium)
## Summary
Introduces a new UI test harness — `Microsoft.PowerToys.UITest.Next` —
that drives PowerToys
modules through Microsoft's
[winappcli](https://github.com/microsoft/WinAppCli) (UI Automation
CLI) instead of WinAppDriver + Selenium. Engine is a single executable
shelled out from
C#; no third-party NuGet packages, no driver process, no Appium server.
Adds two real consumers:
a full ColorPicker end-to-end scenario and a Settings shell navigation
smoke test.
This is opt-in and additive — the existing `UITestAutomation` library
and the
WinAppDriver-based test projects are untouched. Both can coexist while
we evaluate the new
harness.
Inspired in part by
[#48414](https://github.com/microsoft/PowerToys/pull/48414), which lands
the same architectural bet (winappcli, AutomationId selectors, no
WinAppDriver) at a smaller
scope. This PR generalizes it into a reusable library.
## Why
WinAppDriver + Selenium is a legacy pre-agentic solution that is no
longer actively maintained. It's unreliable, heavyweight, and slow. To
achieve 100% UI test coverage, we should leverage modern, reliable
solutions, and WinApp CLI is a strong candidate.
## What's in this PR
### Harness library —
[`src/common/UITestAutomation.Next/`](src/common/UITestAutomation.Next/)
| File | Purpose |
|---|---|
| [`WinappCli.cs`](src/common/UITestAutomation.Next/WinappCli.cs) |
Process wrapper around `winapp.exe`. `Invoke` / `InvokeAssertSuccess` /
`InvokeJson` / `IsAvailable` / `TryResolveExecutable`. `Result` carries
the args and emits `DescribeFailure()` like `winapp ui invoke X -w 12345
-> exit 1; stderr: ...` |
| [`Session.cs`](src/common/UITestAutomation.Next/Session.cs) | Test
session, scoped by either HWND (`-w`) or process (`-a`) via
`TargetScope`. `Find<T>` / `FindAll<T>` / `Inspect` / `Screenshot` /
`SendKeys`. `Session.FromProcess(...)` factory for the
single-window-per-process case |
|
[`SessionHelper.cs`](src/common/UITestAutomation.Next/SessionHelper.cs)
| Owns the launch + window-readiness flow. Static `EnsureRunning(scope,
timeout)` returns whether the call had to launch (so cleanup only kills
what we started). Uses `UseShellExecute=true` so child handles don't
keep MSTest hanging |
| [`UITestBase.cs`](src/common/UITestAutomation.Next/UITestBase.cs) |
MSTest base class. Pre-flights `WinappCli.IsAvailable()` once per
process and fails fast with the install hint if `winapp.exe` isn't on
PATH |
| [`Element/*.cs`](src/common/UITestAutomation.Next/Element/) |
`Element`, `Button`, `ToggleSwitch`, `TextBox`, `NavigationViewItem`,
`Window`. `Click` / `MouseClick` / `Focus` / `GetProperty` / `GetValue`
/ `HelpText` / `WaitForProperty` / `WaitForGone` plus coords
(`X`/`Y`/`Width`/`Height`) |
| [`By.cs`](src/common/UITestAutomation.Next/By.cs) | `By.Name` /
`By.AccessibilityId` / `By.Id` / `By.Slug` |
| [`Windows.cs`](src/common/UITestAutomation.Next/Windows.cs) |
`WindowsFinder.ListAll` / `ListByApp` / `WaitForWindowByApp` /
`WaitForWindowByProcess`. Notes the winappcli bug where unfiltered
`list-windows` drops untitled windows |
|
[`WindowControl.cs`](src/common/UITestAutomation.Next/WindowControl.cs)
| Tolerant Win32 helpers — `TryCloseByApp` / `TryFocusByApp` /
`SafeCloseAndFocus` / `TryKillProcess` — for `finally` blocks |
|
[`KeyboardHelper.cs`](src/common/UITestAutomation.Next/KeyboardHelper.cs)
| Hybrid `keybd_event` + `SendKeys.SendWait` chord sender — required for
global PowerToys hotkeys |
| [`MouseHelper.cs`](src/common/UITestAutomation.Next/MouseHelper.cs) |
`MoveTo` / `LeftClick` / `RightClick` / `LeftClickAt` Win32 wrappers |
|
[`ClipboardHelper.cs`](src/common/UITestAutomation.Next/ClipboardHelper.cs)
| STA-thread `Clipboard` access with `WaitForText` |
|
[`ModuleConfigData.cs`](src/common/UITestAutomation.Next/ModuleConfigData.cs)
| `PowerToysModule` enum + path/process-name resolution |
### Tests
**[`src/modules/colorPicker/ColorPicker.UITests/`](src/modules/colorPicker/ColorPicker.UITests/)**
— replaces the previous empty `UITest-ColorPicker` stub. One test,
[`ColorPickerEndToEndTests.NavigateReadShortcutActivateAndCapture`](src/modules/colorPicker/ColorPicker.UITests/ColorPickerEndToEndTests.cs),
drives the full E2E:
1. Navigate to the Color Picker page via the dashboard utilities stack
2. Toggle the module OFF, verify `PowerToys.ColorPickerUI` exits; toggle
ON, verify it respawns
3. Read the activation shortcut from the page's `ShortcutControl`
(`EditButton.HelpText`)
4. Clear clipboard, park cursor, send the chord
5. Wait for the picker overlay window
6. Read the displayed HEX from a hidden XAML automation peer (see below)
7. Left-click to capture; assert the clipboard value matches the peer's
HEX
8. Wait for the editor window and assert the captured color appears in
its tree
**[`src/settings-ui/Settings.UITests/`](src/settings-ui/Settings.UITests/)**
— `SettingsNavigationSmokeTests.NavigationItem_NavigatesWithoutCrashing`
is one `[TestMethod]` parameterized with `[DynamicData]`, producing 31
discrete results — one per `NavigationViewItem` in
[`ShellPage.xaml`](src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml).
For each item: navigate, settle 250ms, assert `PowerToys.Settings` is
still alive. Catches FailFast regressions in
`ShellViewModel.Frame_NavigationFailed` that pure-logic unit tests can't
reach (the failure path needs a `NavigationFailedEventArgs` which is a
sealed WinRT projection).
### Product change
**[`src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml`](src/modules/colorPicker/ColorPickerUI/Views/MainView.xaml)**
— adds a hidden `TextBlock` automation peer:
```xml
<TextBlock
x:Name="ColorHexAutomationPeer"
AutomationProperties.AutomationId="ColorHexAutomationPeer"
IsHitTestVisible="False"
Opacity="0"
Text="{Binding ColorText}" />
```
The visible `ColorTextBlock` has `AutomationProperties.Name="{Binding
ColorName}"`, which masks the HEX value in the UIA tree (you see "White"
instead of `#FFFFFF`). This zero-impact peer mirrors `ColorText` so
tests can read the actually-displayed HEX. `Opacity=0` +
`IsHitTestVisible=False` keep it out of the visual layout and out of
accessibility focus.
### Project wiring
- [`PowerToys.slnx`](PowerToys.slnx) — registers `UITestAutomation.Next`
under `/common/`, `ColorPicker.UITests` under
`/modules/colorpicker/Tests/`, and `Settings.UITests` under
`/settings-ui/Tests/`. Original `UITest-ColorPicker` stub csproj
removed.
-
[`.github/actions/spell-check/expect.txt`](.github/actions/spell-check/expect.txt)
— adds `winapp` / `winappcli`.
### Not in this PR
- No pipeline changes. `winapp.exe` is expected to be pre-staged on the
test agent image. If it's missing, `UITestBase` fails the first test
with the install hint (`winget install Microsoft.winappcli`) rather than
producing 30 opaque per-test errors.
- No changes to the legacy `UITestAutomation` library or any of the
existing `*.UITests` projects.
## Validation
- All three projects build clean on `x64|Debug` (empty
`build.<config>.<plat>.errors.log`):
- `src/common/UITestAutomation.Next/`
- `src/modules/colorPicker/ColorPicker.UITests/`
- `src/settings-ui/Settings.UITests/`
- Both tests run in Test Explorer / `dotnet test` via
Microsoft.Testing.Platform (already enabled repo-wide in
`Directory.Build.props`).
- Local runs: ColorPicker E2E green; Settings smoke green across all 31
nav items.
- `winapp 0.3.2` from `winget install Microsoft.winappcli`.
## Notes for reviewers
- **`UseShellExecute = true`** in `SessionHelper.EnsureRunning` is
intentional — `false` makes child processes inherit the test host's
stdin/stdout/stderr handles, which keeps MTP/Test Explorer marking the
run as "in progress" until the spawned PowerToys exits.
- **Process-scope (`-a`) targeting** in the Settings smoke test handles
single-instance handoff: the EXE you launch may exit with code 0
immediately after signalling an existing owner, so the alive check uses
`Process.GetProcessesByName` rather than the launcher PID.
- **AutomationId-only selectors** in the Settings smoke list keep the
test localization-independent. Parent groups have
`SelectsOnInvoked="False"` and only expand on click — `Element.Click`
tries `InvokePattern → TogglePattern → SelectionItemPattern →
ExpandCollapsePattern` so the same call works for both leaves and
groups.
- **Untitled-window discovery**: filtered `winapp ui list-windows -a
<name>` returns windows that the unfiltered call drops (e.g. ColorPicker
editor). `WindowsFinder.ListByApp` uses the filtered form. Reported
upstream.
## Before Merge
- Add the `winappcli` install step to the UI-test pipeline.
2026-07-07 22:58:08 -07:00
|
|
|
<BuildDependency Project="src/modules/GrabAndMove/GrabAndMove/GrabAndMove.vcxproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/GrabAndMove/GrabAndMoveModuleInterface/GrabAndMoveModuleInterface.vcxproj" />
|
2025-12-03 03:59:46 -06:00
|
|
|
<BuildDependency Project="src/modules/imageresizer/dll/ImageResizerExt.vcxproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/imageresizer/ui/ImageResizerUI.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/keyboardmanager/dll/KeyboardManager.vcxproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/launcher/Microsoft.Launcher/Microsoft.Launcher.vcxproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/LightSwitch/LightSwitchModuleInterface/LightSwitchModuleInterface.vcxproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/LightSwitch/LightSwitchService/LightSwitchService.vcxproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/powerrename/dll/PowerRenameExt.vcxproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/powerrename/lib/PowerRenameLib.vcxproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/previewpane/Common/PreviewHandlerCommon.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandler.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandler.csproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/previewpane/powerpreview/powerpreview.vcxproj" />
|
|
|
|
|
<BuildDependency Project="src/modules/previewpane/SvgPreviewHandler/SvgPreviewHandler.csproj" />
|
|
|
|
|
<BuildDependency Project="src/PackageIdentity/PackageIdentity.vcxproj" />
|
|
|
|
|
</Project>
|
|
|
|
|
<Project Path="src/Update/PowerToys.Update.vcxproj" Id="44ce9ae1-4390-42c5-bacc-0fd6b40aa203" />
|
2026-07-28 07:45:20 -07:00
|
|
|
<Project Path="src/runner/UnitTests/UnitTests-Runner.vcxproj" Id="97bdacf8-261d-4e23-a708-a27e0b60e444" />
|
2025-12-03 03:59:46 -06:00
|
|
|
<Project Path="tools/project_template/ModuleTemplate/ModuleTemplateCompileTest.vcxproj" Id="64a80062-4d8b-4229-8a38-dfa1d7497749" />
|
2026-08-14 14:32:27 +08:00
|
|
|
<Project Path="tools/CliShim/CliShim.vcxproj" Id="8a7fb7fa-65ea-4004-ba73-1b237435a57b" />
|
|
|
|
|
<Project Path="tools/CliShim.UnitTests/CliShim.UnitTests.vcxproj" Id="d4b0ed68-867d-46b4-a03f-ec52b9fbebe5" />
|
2025-12-03 03:59:46 -06:00
|
|
|
</Solution>
|
[Quick Accent] Move language data to PowerAccent.Common library, refactor (#47211)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Language data for Quick Accent was previously defined in
**PowerAccent.Core/Languages.cs**, internal to the Quick Accent
application itself. The Settings application had no access to the list
and had to maintain a parallel, manually-synchronised list of the
language names and groups, and there was no single place to look up the
complete set of languages.
This PR resolves this and extracts the language data into a new
**PowerAccent.Common** project with no external or UI dependencies,
making it the single source of truth for both the character popup and
Settings UI.
The implicit and non-obvious ordering of the old **Languages.cs** has
been replaced with explicit ordering of the language groups and
languages list.
A new unit test project for the application has also been added.
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
- [x] Closes: #47159
- [x] Closes: #30000
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx
<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
The following changes and additions have been made:
New project **PowerAccent.Common** contains:
- **Language.cs** - an enum of Quick Accent's pseudo-ISO identifiers for
each of the supported languages
- **LetterKey.cs** - mirrors the LetterKey enum defined in the
KeyboardListener.idl, and must be kept in sync with that. This exposes
the VK_* data to the Settings UI without it having to reference the
PowerAccentKeyboardService project
- **LanguageGroup.cs** - classifies languages as `Language` (for spoken
languages), `Special` (for sets like Currency and International Phonetic
Alphabet), or `UserDefined` (reserved for future work)
- **LanguageInfo.cs** - a record which combines a language's identity,
group, resource identifier, and character mappings
- **CharacterMappings.cs** - a new version of the old **Languages.cs**,
providing:
- `All` - the canonical registry of every `LanguageInfo` entry
- `DisplayOrder` - the explicit within-group ordering for languages, for
the default popup ordering, i.e. when the user has not got
frequency-based ordering enabled. This is a culturally-neutral
alphabetical ordering by our pseudo-ISO language IDs, and close to the
previous order, minimising any impact to users' muscle memory
- `GroupDisplayOrder` - the explicit ordering of language groups for
both the popup and the Settings UI
- `LanguageLookup` - new _O(1)_ `Language` to `LanguageInfo` dictionary
- `GetCharacters(LetterKey, Language[])` - a deduplicating character
collector and sorter
A significant improvement over the old **Languages.cs** is that language
ordering is now explicit and in one place. Previously, popup ordering
was an implicit side-effect of a large Union chain across all language
mappings, with the enum, the language mapping declarations and the union
all carrying different orderings. This was a source of confusion and
made adding new languages fragile.
The original **Languages.cs** has been deleted. There's now a thin
`CharacterMappings` adapter that casts the `LetterKey` to the managed
equivalent by numeric value. This is another effort to decouple the
Settings UI and Quick Accent and only share the required elements.
In Settings, the `PowerAccentViewModel` class has been updated. It now
derives the language list directly from `CharacterMappings.All`; the
`InitializeLanguages()` call handles localisation, sorting and grouping
in a single place using `GroupDisplayOrder`.
A new unit test project covers `CharacterMappings`, the `LetterKey`
IDL-to-managed code bridge and general language declaration checks. The
application is now much more robust against changes which alter the
declared order, introduce empty/null elements, and so on. It is now
impossible to add a new language and forget a constituent part (the enum
entry, its place in the display order, the character mappings
themselves) without a test failing.
<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
See new unit test project for comprehensive tests.
Manually confirmed:
- Triggering Quick Accent with no language selected does not report an
error
- Language order is consistent in the popup, no matter what order the
languages are selected in Settings
- The order of languages in Settings is consistent, alphabetically by
localised name
- All declared languages are present in Settings and no resource IDs
were missed
---------
Co-authored-by: Muyuan Li (from Dev Box) <muyuanli@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-22 07:24:26 +00:00
|
|
|
|