Yu Leng
90d · built 2026-09-30
Performance
What Yu Leng shipped in the selected window, measured in ETV, and how it compares with the 90 days before it.
Effective capacity
+6.7engineers
delivers like 7.7 (7.7x pre-AI)
Output (ETV)
39.8ETV
+437.9% vs 7.4 prior
Features share
35.1%
+0.6 pp vs prior window
Fixes share
9.2%
−9.6 pp vs prior window
Work mix
35.1% Features8.8% Maintenance43.8% Tests3.2% Docs9.2% Fixes
31 commits over 90 days, ending 2026-09-30.
Where this dev ranks
Percentile against the global top-100 leaderboard (all-time totals).
- By commits
- Top 98 %
- By Features share
- Top 55 %
Daily performance
Daily ETV, stacked by Features, Maintenance, Tests, Docs and Fixes.
Repository spread
Where this developer's commits land. Concentrated work (top1 > 80%) vs polymath spread (top1 < 30%).
Most impactful commits
Top 10 by ETV in the last 90 days.
- 9.9ETVfeat(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>github.com-microsoft-PowerToys · 5c9c93d5 · 2026-07-16
- 6.0ETV[PowerOCR] migrate PowerOCR to WinUI 3 (#49431) ## Summary of the Pull Request Migrates Text Extractor (`PowerOCR`) from WPF to WinUI 3 while preserving its Runner integration, settings contract, activation behavior, telemetry, and UI Automation identifiers. - Replaces the WPF overlay with native WinUI 3 `WindowEx` overlays, one per display, with mixed-DPI and negative-origin coordinate handling. - Extracts OCR, bitmap preparation, text formatting, table analysis, and selection geometry into the UI-independent `PowerOCR.Core` library. - Migrates localization from `.resx` to `.resw`/`x:Uid`, and updates process lifetime, Named Event dispatch, clipboard handling, and deterministic resource cleanup. - Moves managed Text Extractor outputs into `WinUI3Apps` and updates the native launcher, signing manifest, installer resources, and installation verification list. - Adds Core unit tests and updates the existing PowerOCR UI automation/checklist for the WinUI controls. https://github.com/user-attachments/assets/16bbef72-fa5e-4c2b-8bd2-b1871a3e0e4c ## PR Checklist - [x] Closes: #49656 - [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 — Core tests pass, but interactive UI tests and several visual/multi-monitor checks remain environment-blocked as detailed below - [x] **Localization:** All end-user-facing strings can be localized - [x] **Dev docs:** Added/updated - [x] **New binaries:** Added on the required places - [x] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for `PowerToys.PowerOCR.Core.dll` and the WinUI3Apps paths - [x] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) — handled by the existing WinUI3Apps component generator; removed the obsolete PowerOCR satellite-resource component from `installer/PowerToysSetupVNext/Resources.wxs` - [x] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) — N/A; the new test project is included in `PowerToys.slnx` and uses existing test discovery - [x] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) — N/A; no per-module pipeline entry is required - [ ] **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 — N/A; no end-user behavior change ## Detailed Description of the Pull Request / Additional comments ### Core and project structure - Adds `src/modules/PowerOCR/PowerOCR.Core/` and `PowerOCR.Core.UnitTests/`. - Removes production `UseWPF`, `System.Windows`, WPF imaging types, MEF construction, and the WPF-only `Common.UI` dependency. - Converts `src/modules/PowerOCR/PowerOCR/PowerOCR.csproj` to an unpackaged, self-contained WinUI 3 application with XAML under `PowerOCRXAML/`. ### Overlay and OCR flow - Captures every display before showing overlays, then creates one borderless topmost overlay per `DisplayArea`. - Uses cached physical-pixel screenshots for clicked-word, region, single-line, and table OCR modes. - Converts WinUI DIP pointer coordinates through each window's rasterization scale and supports displays with negative virtual-desktop origins. - Replaces the WPF `CombinedGeometry` selection clip with four mask rectangles plus a selection `Border`. - Synchronizes language and formatting state across all overlay windows and preserves Escape, S, T, and D1-D9 keyboard behavior. ### Lifetime and compatibility - Preserves the existing process name, mutex, Runner PID argument, GPO behavior, Named Events, standalone keyboard hook, settings JSON, telemetry events, and existing AutomationIds. - Adds cancellation-aware Named Event handling and deterministic disposal for windows, screenshots, WinRT image sources, OCR crops, pointer capture, and cursor clipping. - Keeps `PowerOCRModuleInterface.dll` in the install root and launches `WinUI3Apps\PowerToys.PowerOCR.exe`. ## Validation Steps Performed - Built `PowerOCR.Core.UnitTests` for x64 Debug and ran all tests with `vstest.console.exe`: **23/23 passed**. - Built `PowerOCR-UITests` for x64 Debug successfully. - Built `PowerOCR` for x64 Release and ARM64 Release successfully. - Built `PowerOCRModuleInterface` for x64 Release and ARM64 Release successfully. - Ran XAML Styler against the branch: 3 PowerOCR XAML files processed with no changes. - Confirmed the required x64/ARM64 outputs, including `PowerToys.PowerOCR.Core.dll` and `PowerToys.PowerOCR.pri`, are generated in the expected locations. - Ran build+sideload checklist validation against the local WinUI 3 bits: **15 PASS, 0 FAIL, 16 BLOCKED**. - Blocked items require an attached interactive desktop, WinAppDriver v1.2.1, multiple displays/mixed DPI, real pointer drag/input, or visual theme inspection. - No product defects were observed in the checks that could be executed. - The legacy UI test runtime remains blocked because WinAppDriver is unavailable and the current RDP input desktop is detached; the tests compile successfully. --------- Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Niels Laute <nielslaute@microsoft.com> Copilot-Session: 64307790-5118-4071-9308-5e9ee9836310 Copilot-Session: e5ba1f54-e354-456c-bd2a-c716a143eb97github.com-microsoft-PowerToys · ca6e72c9 · 2026-09-10
- 5.1ETV[ColorPicker] Migrate from WPF to WinUI 3 (#49174) ## Summary of the Pull Request Migrates the **ColorPicker** module from WPF to WinUI 3 (Windows App SDK). The whole module — the picking overlay, the color editor, settings, the zoom magnifier, telemetry, and the Win32 input hooks — is ported off `System.Windows` onto `Microsoft.UI.Xaml`, MEF is replaced by `Microsoft.Extensions.DependencyInjection`, and the legacy WPF sources are removed once each piece is ported. > **Draft / WIP:** opened early for visibility and incremental review. The checklist below is intentionally left unchecked until the migration is finalized and fully validated on real hardware/DPI configurations. demo: https://github.com/user-attachments/assets/465f2a21-1760-4bcf-9d33-253fd6b06f64 ## PR Checklist - [x] Closes: #49000 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments High-level areas ported (see the commit history for the step-by-step breakdown): - **App shell & DI** — WinUI 3 entry point / `App` / `MainWindow`, a `Microsoft.Extensions.DependencyInjection` container replacing MEF, with direct WinUI view composition replacing the implicit WPF `DataTemplate` mapping. - **Picking overlay & editor** — a `TransparentWindow`-based overlay (cursor-following tooltip) plus `ColorEditorView` / `ColorPickerControl` / `ColorFormatControl` ported off WPF (`ContextMenu` → `MenuFlyout`, Visual State Manager, native WinUI styles merged into `App.xaml`). - **Zoom magnifier** — a Win2D `CanvasControl` that redraws the captured region with a brightness-adaptive pixel grid + center highlight (replacing the WPF `ShaderEffect`), plus a WinUI Storyboard resize that matches the WPF zoom-step timing and easing. - **Core & helpers** — color math + value converters on `Windows.UI.Color`, `MonitorResolutionHelper` on `Windows.Foundation.Rect`, `ThrottledActionInvoker` on `DispatcherQueueTimer`, the shared `ManagedCommon.ClipboardHelper`, and the Win32 mouse/keyboard hooks off WPF input types. - **Resources** — a `.resw` scaffold + `ResourceLoaderInstance` replacing the old `.resx` designer. - **Build & installer** — `ColorPickerUI` flipped to WinUI 3, launched from `WinUI3Apps\`; installer satellite + signing paths updated; leftover WPF sources removed. **Zoom parity fixes in this branch:** the magnifier is centered on the cursor once when the zoom session starts and stays anchored while the wheel changes levels. The resize now also matches the WPF behavior: 200 ms `SineEase/EaseOut` growth and `QuadraticEase/EaseIn` shrink, animation of the image only (fixed border chrome), and rapid/reversing wheel input handed off from the current rendered size instead of jumping back to the previous level. The 8x host was corrected from 430 to 432 DIP so its border is not clipped. ## Validation Steps Performed - `ColorPickerUI.UnitTests.csproj` and `ColorPicker.UITests.csproj` build clean (x64 Debug, exit code 0, using the configured host NuGet source). - `ColorPickerUI.UnitTests`: 482/482 passed, including the presentation-value resize plan, exact WPF easing selection, 200 ms duration, animated grid threshold, RGB byte-range validation, and export extension handling. - Real UI E2E: Settings enable/disable, activation hotkey, overlay HEX, 1x/4x/8x zoom, a 50 ms 4x → 8x → 4x → 8x reversal, pointer movement, clipboard capture, and editor display all passed. - Runtime frame trace at 150% DPI confirmed continuous handoff during rapid reversal (`214.0 → 213.33 DIP`, then a second handoff from `211.33 DIP` to 8x) with no jump to a nominal level; final frames landed within the 200 ms animation plus display-refresh quantization. - Manual UI validation at 150% DPI passed both activation modes, shortcut rebinding, mouse/keyboard actions, color-name and clipboard formats, history selection/removal/multiselect, format toggle/reorder/customization, adjust-color flows, screen edges, dark theme, corrupt-history recovery, named events, single-instance behavior, and 100-cycle lifecycle stress. - TXT/JSON export, cancel, single/multi-selection, Unicode paths, overwrite/truncation, and unsupported-extension preservation passed using the real Windows App SDK Save As dialog; no unexpected errors were added to the final-run log. - Supporting suites passed: ManagedCommon clipboard 30/30, Settings ColorPicker/navigation 5/5, DSC ColorPicker 6/6, and ColorPicker E2E 1/1 (524/524 automated tests total). - Environment-dependent validation across an elevated runner, multiple physical/mixed-DPI monitors, native ARM64, and installer upgrade/uninstall remains pending (draft). --------- 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> Co-authored-by: Niels Laute <niels.laute@live.nl> Copilot-Session: ed45e5c8-72b0-4fdf-9de3-ae10be595428 Copilot-Session: 364bf5dd-eac3-42bc-901b-59194c8df71a Copilot-Session: f7c58bff-df3f-41ee-b2e2-8af47508cd19 Copilot-Session: 99a6c348-a4d6-4cd3-9909-b2cb92695e90 Copilot-Session: 90411037-22d3-4fbb-bb74-bff7a69467a9 Copilot-Session: 0dcbe1a4-e4fd-4f19-bbdb-19781d2fb693 Copilot-Session: 17f1d101-a06a-452d-ad18-e1d164791dd5 Copilot-Session: b272ded1-04fe-441d-bf0c-a94979844399 Copilot-Session: d5afc36b-3356-46af-b8cb-071b87a64532github.com-microsoft-PowerToys · cd7f82c2 · 2026-09-04
- 3.0ETV[Image Resizer] Fix CLI input validation and diagnostics (#49854) ## Summary of the Pull Request Closes #49852. Image Resizer CLI previously accepted several invalid inputs as successful work: unknown options could be consumed as file arguments, invalid files were silently dropped, unsafe dimensions could reach the resize engine, and equivalent inputs could process the same source concurrently. This change makes `PowerToys.ImageResizerCLI.exe` strict, deterministic, and diagnosable while preserving the existing lenient command-line behavior used by the GUI and context-menu path. ## PR Checklist - [x] Closes: #49852 - [x] **Communication:** Discussed with core contributors - [x] **Tests:** Added/updated - [x] **Localization:** End-user-facing diagnostics are localizable - [x] **Dev docs:** Built-in CLI help and examples updated; no standalone dev-doc change required - [x] **New binaries:** No new binaries introduced - [x] **Documentation updated:** No external user-documentation change required ## Detailed Description ### Strict CLI parsing without breaking supported syntax - Adds a strict parse path for the public CLI while keeping the GUI/context-menu parser lenient. - Rejects unknown option-like positional tokens before processing. - Preserves `--`, response files, attached values such as `-w100`, legal bundles such as `-rq85`, and explicit attached boolean values such as `-rtrue`. - Preserves valid file, pipe, and destination values for lenient callers when another option fails conversion. ### Deterministic and diagnosable input resolution - Expands wildcards in the final path segment and reports zero-match patterns. - Reports missing, unsupported, invalid, and empty inputs instead of silently filtering them. - Processes valid files in mixed batches, reports every rejected input, and returns a non-zero exit code. - Canonicalizes filesystem paths before deduplication, covering normal, extended (`\\?\`), long, casing, and parent-reparse aliases while preserving distinct hard links, final symbolic links, and files in case-sensitive directories. - Applies the same strict validation and deduplication to public-CLI named-pipe input; the GUI/context-menu pipe remains lenient. - Treats an empty public-CLI pipe as an error. - Reads redirected stdin using the producing shell's output encoding with BOM detection, including non-ASCII paths from default cmd and PowerShell pipelines. ### Validation before file writes - Rejects negative, non-finite, zero/zero, grouped out-of-range, and otherwise unsupported custom dimensions. - Requires a positive effective width for percentage-based Fit and Fill sizes. - Treats an out-of-range preset index as an error instead of continuing with the current preset. - Validates resize-engine dimensions before integer conversion and before destination creation. - Rounds positive fractional Fill targets safely to at least one pixel. - Deduplicates equivalent paths before parallel processing so overlapping explicit/glob/pipe inputs cannot race under `--replace`. ### Diagnostics and compatibility - Includes exception type and HRESULT when a decoder exception has an empty message. - Documents and warns that shrink-only remains ignored for percentage-based sizes, preserving existing behavior. - Preserves the original UTC modified time after `KeepDateModified + Replace` by restoring it on the final replaced file. ## Validation Validation was repeated after merging the latest `main` (`e753ec51fb`) into the PR branch. 1. Restored with the configured host `NuGet.Config` and built `src/modules/imageresizer/ImageResizerCLI/ImageResizerCLI.csproj` in x64 Release using `tools/build/build.ps1`. - Result: exit code 0; errors log empty. 2. Restored and built `src/modules/imageresizer/tests/ImageResizer.UnitTests.csproj` in x64 Release with the same build script and configured package source. - Result: exit code 0; errors log empty. 3. Ran the complete x64 Release Image Resizer unit-test assembly with Visual Studio `vstest.console.exe`. - Result: **205 passed, 0 failed, 0 skipped**. 4. Ran 10 process-level CLI regressions covering: - attached boolean parsing (`-rtrue`); - grouped out-of-range dimensions without source modification; - positive fractional Fill producing a valid `1x100` image; - normal/extended/wildcard path deduplication; - non-ASCII redirected stdin from default PowerShell 7 and cmd pipelines; - empty, invalid, and duplicate named-pipe inputs; - `KeepDateModified + Replace`, including content change and exact UTC timestamp preservation. - Result: **10/10 passed**. 5. Confirmed both build error logs remained empty, all temporary fixtures were removed, and the real Image Resizer settings file retained its original length, timestamp, and SHA-256 hash. The new Image Resizer UI-test project added on `main` was not run locally because it requires the repository's WinAppDriver/local-VM UI-test environment; this PR does not change that UI-test project. --------- Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com>github.com-microsoft-PowerToys · 75df8d02 · 2026-08-17
- 2.9ETV[PowerDisplay] Add stable profile IDs (#49175) ## Summary of the Pull Request Gives every saved PowerDisplay profile a stable, auto-incrementing integer ID and makes the app address profiles by that ID instead of by name. Duplicate profile names are allowed, renames preserve identity, and LightSwitch stores stable profile references. > Split out of the PowerDisplay CLI branch (#48632). CLI-specific contracts and commands remain in that stacked PR. ## PR Checklist - [x] **Closes:** N/A - split from #48632. - [x] **Communication:** Discussed with core contributors. - [x] **Tests:** Added and passing in `PowerDisplay.Lib.UnitTests`. - [x] **Localization:** The composed profile label uses a shared localized format resource. - [x] **New binaries:** None. - [x] **Documentation updated:** `doc/devdocs/modules/powerdisplay/design.md`. ## Implementation ### Profile model and persistence - `PowerDisplayProfile.Id` is the stable JSON `id`; `0` means unassigned. - `PowerDisplayProfiles.NextId` is monotonic and IDs are never reused. - `SetProfile` assigns IDs to new profiles and replaces existing profiles by ID. - Duplicate names are supported; name lookup remains only for migration of legacy references. - `ProfileStore` serializes cross-process load/modify/save operations with a named mutex and atomically replaces `profiles.json`. - Production callers use asynchronous `ProfileHelper` APIs. ### Migration and application - Initial PowerDisplay discovery assigns missing profile IDs and migrates legacy monitor IDs. - LightSwitch legacy name references are reconciled to IDs and written back to the current typed settings schema. - Native LightSwitch publishes pure light/dark theme events; PowerDisplay exclusively validates profile enablement and stable IDs. - Settings UI and Named Pipe ApplyProfile actions send invariant positive profile IDs. - PowerDisplay validates the ID, loads the current profile, and applies its monitor settings. ### Settings UI - Create, edit, apply, and delete operations use stable IDs. - LightSwitch selectors store profile IDs and keep legacy name fields only for migration. - Profile lists use a localized name-and-ID label so duplicate names remain distinguishable. ## Accepted Trade-offs - Profile ID migration remains dependent on the initial monitor discovery; a failed or delayed discovery can temporarily hide legacy ID-less profiles. - The one-time PowerDisplay LightSwitch migration rewrites the complete current typed settings object and does not add a new cross-process settings transaction. ## Validation - Built the affected x64 Debug projects with the repository build scripts. - `PowerDisplay.Lib.UnitTests`: 186 passed, 0 failed. --------- Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-PowerToys · 2b8e6247 · 2026-07-16
- 2.5ETV[PowerDisplay] Add profile reordering (#50453) ## Summary of the Pull Request Allow users to reorder saved Power Display profiles without deleting and recreating them. Add drag-and-drop sorting and Move up/Move down menu actions, and persist the display position in a separate `order` field while retaining stable integer profile IDs. <img width="1599" height="982" alt="image" src="https://github.com/user-attachments/assets/2dc852d4-ef94-49e3-9085-d673cd911da8" /> <img width="1621" height="977" alt="image" src="https://github.com/user-attachments/assets/41f03551-6372-4ba5-aa78-03e32d1f362a" /> ## PR Checklist - [x] Closes: #50425 - [ ] **Communication:** Maintainer review is pending. - [x] **Tests:** Added/updated; 629 relevant tests pass locally. - [x] **Localization:** Added Settings UI strings use resource entries. - [x] **Dev docs:** Updated `doc/devdocs/modules/powerdisplay/design.md`. - [x] **New binaries:** Not applicable; no new projects, binaries, or dependencies. - [ ] **Documentation updated:** Public documentation follow-up is not included. ## Detailed Description of the Pull Request / Additional comments - In `src/settings-ui/Settings.UI/SettingsXAML/Views/PowerDisplayPage.xaml` and `src/settings-ui/Settings.UI/ViewModels/PowerDisplayViewModel.cs`, add a reorderable profile list with drag handles, bounded scrolling, and keyboard-accessible Move up/Move down actions. Elevated Settings retains menu-based sorting with native drag/drop disabled, following Mouse Without Borders. - In `src/modules/powerdisplay/PowerDisplay.Models/`, use a contiguous zero-based `order` field independently of integer `id` and the physical JSON array. Editing preserves the saved position; new profiles use the existing `nextId` counter and append to the display order. - Normalize missing or invalid order values under the existing profile-store mutex. Reordering changes only order values in the latest stored collection, preserves concurrent additions and edits, and refreshes the flyout through the existing settings notification. Failed saves/reloads retain the last known saved order in Settings. - Preserve integer profile IDs, Light Switch references, and CLI/IPC schema version `1.0`. ## Validation Steps Performed - Final Debug x64 builds succeeded for Settings UI and its test project, the Power Display app, and the Power Display Lib, Contracts, IPC, and CLI test projects. - Ran the newly built assemblies through `vstest.console.exe`: Lib **341**, Contracts **15**, IPC **139**, CLI **118**, and relevant Settings ViewModel tests **16**; **629 passed, 0 failed, 0 skipped**. - Coverage includes explicit order independent of array position and integer ID, stable IDs and `nextId`, order initialization, edit/append behavior, failed and concurrent writes, Light Switch references, elevated drag gating, CLI numeric-ID validation, and JSON/IPC round trips. - `git diff --check` and XAML/XML parsing passed. - Interactive UI validation remains pending: normal/elevated drag behavior, long-list scrolling, keyboard focus, and screen-reader behavior. This PR remains a draft. --------- Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com>github.com-microsoft-PowerToys · 4670e34e · 2026-09-14
- 1.8ETVPowerDisplay: Adjust brightness by scrolling over the tray icon (#49446) ## Summary of the Pull Request Scrolling the mouse wheel over the Power Display tray icon adjusts brightness, without opening the flyout. - New **Tray icon mouse wheel** setting: `Off` / `Primary display` / `All displays`, defaulting to **`Off`**. It is scoped to the tray icon — the flyout sliders accept wheel input regardless, as they always have. The existing **Mouse wheel increment** setting supplies the per-notch step. - **Off by default.** The gesture consumes a wheel notch that would otherwise reach the window under the pointer, and acting on it installs a system-wide `WH_MOUSE_LL` hook. Neither is something an existing installation should acquire silently on upgrade. With the setting `Off` no hook is ever installed and no notch is ever consumed, so this PR changes no existing behaviour until the user opts in: 1958 insertions, 2 deletions, and both deletions are refactors of lines this feature reuses. - **No feedback UI.** Brightness is self-evidencing — you scroll and the screen changes — so the display itself is the feedback. The notification icon is untouched: same tooltip, same text, same legacy notification-icon protocol. ## PR Checklist - [x] Closes: #49410 - [ ] **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 - [ ] **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 No new binaries or projects — everything lands in existing assemblies. Communication is unchecked because #49410 is still Needs-Triage. ## Detailed Description of the Pull Request / Additional comments ### Why a low-level hook The Shell does not forward `WM_MOUSEWHEEL` to a notification icon's callback window under any `NOTIFYICON_VERSION`, and a click-through overlay placed over the icon cannot receive wheel input either. `TrayIconMouseWheelListener` therefore installs a `WH_MOUSE_LL` hook — but only transiently, and only when it will act on the result: - Nothing is installed at all while the setting is `Off`, which is the default. - Installed in `EnsureHook()` when the UI thread confirms the pointer is inside the rectangle from `Shell_NotifyIconGetRect` **and** `CanAdjustBrightnessFromTrayWheel` says some monitor can accept a brightness write. - Removed in `DisarmCore()` as soon as either condition stops holding, the pointer leaves the rectangle, or the mode changes. - A notch is consumed (the hook proc returns non-zero) only while armed and only for points inside the armed rectangle, so a wheel event Power Display will not act on still reaches the window under the cursor. The hook runs on a dedicated background thread with its own message loop; the proc itself only enqueues a sample and posts a drain request. Deltas are marshalled to the UI thread in batches, and `WheelDeltaAccumulator` folds high-resolution deltas (precision wheels, touchpads) into whole notches. Each sample carries the hover generation it was captured under, so samples from a hover the UI thread has already retired are discarded rather than applied late. ### Hover detection The Shell sends `WM_MOUSEMOVE` to the icon's callback window while the pointer is over it. `TrayIconService.HandleTrayMouseMove` resolves the rectangle with `Shell_NotifyIconGetRect` and caches it for a second, because that message repeats for every pixel of travel. `TrayIconService` gains nothing else: no protocol change, no new hover UI, no polling. The rest of the file — and `MainWindow.xaml` — is untouched. ### Linked brightness While linked brightness is on, a notch has to move the whole group, so it goes through `MainViewModel.LinkedBrightness` rather than the individual monitor setters. The new master value is taken from the planner's value for the monitor the wheel named, **not** from the current master. The master is positional only — `SeedInitialLinkedBrightness` takes it from the lowest-numbered linked monitor and never writes hardware, and every monitor-list rebuild re-seeds it — so it can sit arbitrarily far from the monitor the wheel is aimed at. Stepping it relative to itself would apply a wrong-sized or wrong-signed change, and a master already clamped at 0/100 would swallow the notch while writing nothing at all. The setting description calls out that linked brightness widens the scope, so `Primary display` is not literally a single display while it is on. ### What is deliberately not here An earlier revision of this PR showed the target and percentage in a custom overlay as you scrolled. Doing that meant the standard Shell tooltip would not do (it cannot be shown on demand), which meant an own window, which meant suppressing the Shell tooltip so the two did not collide, which meant `NOTIFYICON_VERSION_4`, which changed the callback packing and made the app responsible for all hover text — including for keyboard and touch users, who never reach a cursor-anchored overlay and would have been left with no visible tooltip at all. That chain was about half the diff, for a readout that adds little on top of watching the screen change. It is gone. If a readout is wanted later it can be argued on its own merits, separately from this feature. The same revision also gated the flyout sliders on this setting. That bundled two unrelated things behind one switch — turning off tray scrolling would also have stopped the contrast and volume sliders responding to the wheel — so the setting is now scoped to the tray icon and named accordingly. An earlier revision also routed the tray **Exit** action through `Shutdown()`. That fixes a pre-existing teardown leak which has nothing to do with this feature, so it now lives in #49580 and is out of scope here. This branch does not depend on it: the hook thread is a background thread and the process is ending either way. ## Validation Steps Performed - Unit tests: `PowerDisplay.Lib.UnitTests` 215 passed, `Settings.UI.UnitTests` 165 passed. - Builds: `PowerDisplay` and Settings UI, x64 Debug, no warnings. - Automated coverage is in `PowerDisplay.Lib.UnitTests`: target selection per mode, wheel accumulation including negative deltas, partial notches and direction reversal, half-open rectangle containment, and settings serialization and round-trip for the new mode, including that a settings file predating the feature loads as `Off`. `Settings.UI.UnitTests` covers the view-model index mapping and pins the enum values to the ComboBox item order. - The Win32 glue in `TrayIconService` and `TrayIconMouseWheelListener` is not unit tested. Manual passes performed: scrolling over the icon in both modes, the icon parked in the notification overflow, high-resolution wheel input, brightness boundaries, live monitor refresh while hovering, tray icon hidden and re-enabled, Explorer restart, the context menu and left-click, `Off` stopping tray scrolling while the flyout sliders keep working, and confirming a notch that Power Display will not act on still reaches the window under the cursor. Not verified, needing hardware this branch has not been run on: - Multiple taskbars, where the tray icon is on a secondary display and `Primary display` mode adjusts a monitor the user may not be looking at. - Mixed-DPI setups, for the `Shell_NotifyIconGetRect` rectangle and the hook's physical-pixel hit test. --------- Co-authored-by: Yu Leng <yuleng@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Copilot-Session: 5d7f36fe-d175-4aa9-a3c7-b370d952d1d3github.com-microsoft-PowerToys · 8f634024 · 2026-07-31
- 1.7ETVPowerDisplay: Fall back to persisted VCP values when a monitor read fails (#49445) ## Summary of the Pull Request On a monitor whose DDC/CI engine answers intermittently, every discovery pass starts from nothing. A panel that reported its brightness a minute ago can lose that control — or drop out of the flyout entirely — because one pass happened to fail. This persists every range-valid VCP value read off a monitor, keyed by its canonical DevicePath. In Maximum compatibility mode a later discovery falls back to that value when the hardware will not answer. Scope is intermittent failure, not permanent failure: the cache can only replay a value the hardware answered at least once, so a panel that never reads a code successfully sees no change. This partially addresses #49342. ## PR Checklist - [x] Closes: #49342 - [ ] **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 — this PR adds none - [ ] **Dev docs:** Added/updated - [x] **New binaries:** Added on the required places — none added, so no signing JSON, installer WXS or CI YML change is required - [ ] **Documentation updated** ## Detailed Description of the Pull Request / Additional comments ### What is stored `MonitorStateManager` implements `IKnownGoodVcpStore`, so the cache rides in the existing `monitor_state.json` next to the user's saved brightness rather than in a new file. Each entry is a `KnownGoodVcpFeature`: code, current, maximum, and when it was last read. Only range-valid observations are stored, so the common `current=0 / max=0` garbage reply never enters — it fails `VcpFeatureValue.IsValid`. Writes are not gated on Maximum compatibility mode, only reads are. A monitor that reads cleanly today can start failing after a cable or dock change, and a lazily populated cache would be empty on exactly the first pass that needs it. ### How a cached value is used `VcpDiscoveryEvidence.Reconcile` gains the cache as a third source alongside the parsed capabilities string and this pass's probe: | this pass | cache | result | | --- | --- | --- | | read succeeded | — | live value wins, cache refreshed | | replied, range unusable | hit | cached value applied, `MonitorReadFlags` left clear | | no reply | hit | cached value applied, `MonitorReadFlags` left clear | | code never probed (caps parsed) | hit | value applied only after one live read is attempted | The last row matters: on the caps-parsed path nothing has confirmed the cached value this pass, so the hardware is asked first. On the probe path it has already been asked, and re-reading would be pure I2C noise. `MonitorReadFlags` stays clear for anything the hardware did not answer, so a cached value never masquerades as an observation — which #49577 depends on, since it made the restore path write whenever the flag is unset. One consequence is worth naming: the flyout draws a slider at the cached position while `powerdisplay get` reports that setting as unknown, because `MonitorDtoProjector` gates on `supported && read`. ### Keeping the cache current `RefreshKnownGoodAfterWrite` restamps an entry after a successful `SetVCPFeature`, so a slider move cannot leave the cache holding the pre-write value. It refreshes only an entry a real read established, and only when the value was scaled against the maximum that entry holds — a monitor whose discovery read failed still carries a placeholder max, and writing that back would mis-scale every later write. `RemoveKnownGoodFeatures` clears the cache for monitors a settings reconciliation observably dropped, leaving the user's saved values alone. Cleanup is driven by an observed drop, never by absence from the rebuilt list: a missing or corrupt `settings.json` yields a defaults object indistinguishable from a real one, and pruning by absence would wipe every monitor not connected at that instant. A re-observation that changes nothing refreshes the in-memory timestamp but does not mark the file dirty, so a discovery pass no longer rewrites `monitor_state.json` for a moved timestamp alone. ## Validation Steps Performed - `PowerDisplay.Lib`, `PowerDisplay.Lib.UnitTests` and `PowerDisplay` built for x64 Debug with VS MSBuild — 0 errors, 0 warnings; `PowerDisplay.Lib.UnitTests.dll` under `vstest.console.exe`: **301 passed, 0 failed** - **Affected-hardware validation on the AOC Q27G3XMN is still pending.** That monitor, or an equivalent controllable DDC/CI setup, was not available locally. The paths this PR changes are reachable only on hardware whose capabilities string is unusable or whose VCP reads fail intermittently, so this is the main outstanding risk. --------- Co-authored-by: Yu Leng <yuleng@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Copilot-Session: 6ea38c04-6f68-4c42-91d9-8a03b49bdd81github.com-microsoft-PowerToys · ba2e89c4 · 2026-08-03
- 1.0ETVAdd native CLI shims for PowerToys command-line tools (#48631) ## Summary of the Pull Request Adds a native C++ multi-call shim that exposes existing PowerToys CLIs through `PATH`. The shims are installed under the PowerToys `bin` subfolder and follow the `PowerToys.<ModuleName>.CLI.exe` naming convention. The launcher preserves the raw argument tail, shares the caller's console, and returns the target process exit code. | PATH-visible command | Target executable | | --- | --- | | `PowerToys.FancyZones.CLI.exe` | `FancyZonesCLI.exe` | | `PowerToys.ImageResizer.CLI.exe` | `WinUI3Apps/PowerToys.ImageResizerCLI.exe` | | `PowerToys.FileLocksmith.CLI.exe` | `FileLocksmithCLI.exe` | | `PowerToys.PowerDisplay.CLI.exe` | `WinUI3Apps/PowerToys.PowerDisplay.Cli.exe` | proof of this work: <img width="1044" height="294" alt="image" src="https://github.com/user-attachments/assets/b659c552-5c08-4430-85c3-eba48f286eb0" /> <img width="1137" height="244" alt="image" src="https://github.com/user-attachments/assets/5fed493f-dc30-428d-a618-bf612ccf3635" /> <img width="1727" height="868" alt="image" src="https://github.com/user-attachments/assets/5c32fd2e-4a3a-4138-b968-fb5434eebec3" /> ## PR Checklist - [x] Closes: #48634 - [x] **Communication:** Discussed with core contributors in this PR - [x] **Tests:** Added/updated and all pass - [ ] **Localization:** CLI diagnostic messages are not localized - [x] **Dev docs:** Updated CLI naming and installation conventions - [x] **New binaries:** Added on the required places - [x] Signing JSON - [x] WiX installer entries - [x] CI builds through `PowerToys.slnx`; no dedicated YML step is required - [x] The existing release pipeline covers the solution and installer - [x] **Documentation updated:** `doc/devdocs/cli-conventions.md` ## Detailed Description of the Pull Request / Additional comments - Uses one native launcher binary for all commands and resolves the target from the invoked shim filename. - Installs PATH-visible shims under `PowerToys\bin`. - Keeps the existing module CLI binaries and their deployment locations unchanged. - Rejects the previous unsuffixed and `*cli` command aliases. ## Validation Steps Performed - Built `tools/CliShim.UnitTests/CliShim.UnitTests.vcxproj` in `Release|x64`: 0 warnings, 0 errors. - Ran `CliShim.UnitTests.dll` with `vstest.console.exe`: 5/5 tests passed. - Verified the CLI manifest, WiX command names, and `bin` installation directory are synchronized. - Ran `git diff --check`. --------- 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> Copilot-Session: d11c4221-248f-44a9-85fb-7017ed43f4cegithub.com-microsoft-PowerToys · ae416c04 · 2026-08-14
- 1.0ETV[Power Display] Preserve profiles across unavailable monitors and capabilities (#50509) ## Summary of the Pull Request Editing a Power Display profile can drop settings when a saved monitor is missing or a capability is temporarily unavailable. Preserve the original monitor rows, fields, identity, and creation time when renaming, while honoring explicit removals and validating newly selected values. Keep color-preset selection synchronized as capabilities change, including empty selections and restored capabilities. Unavailable included fields remain visible for removal, and the editor releases its monitor subscriptions when closed. Compare capability values and names so same-size updates refresh the editor. This is an independent prerequisite extracted from #50458. It targets `main` and does not introduce VCP restriction settings or depend on the VCP editor. The settings-persistence PR can be reviewed and merged separately. ## PR Checklist - [ ] Closes: no automatic issue closure; related to #50458. - [ ] **Communication:** Draft for maintainer review. - [x] **Tests:** Generic profile regression tests added and validated. - [x] **Localization:** The preservation explanation uses an en-US resource string. - [ ] **Dev docs:** Not added. - [x] **New binaries:** Not applicable; no new binary or test project. - [ ] **Documentation updated:** No separate documentation PR. ## Validation Steps Performed - Checked out commit `5485193016f270f119b0f5df8a4fe9ad7e1f4be8` and built Settings UI and Settings.UI.UnitTests with the repository build script, x64 Debug: exit code 0. - Ran all **33 ProfileEditorViewModelTests** through Visual Studio vstest: 33 passed, none skipped. - Built and ran a native WinUI ComboBox probe using the generated XAML binding: capability-name refresh, empty selection, original-value preservation/restoration, and invalid new selections all passed; process exit code 0. - Verified the compiled assemblies contain the Profile fix but no VCP restriction model or `DisabledVcpValues` property. - `git diff --check` passed. The build retained the existing CsWinRT1028 warning in unchanged `ManagedCommon/HotkeySettingsControlHook.cs`. The tests and control probe use synthetic monitor data; no physical monitor, full dialog layout, or multi-monitor DPI verification is claimed. The persisted JSON shape is unchanged. Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com>github.com-microsoft-PowerToys · 84b6bf89 · 2026-09-22