Skip to content

CmdPal: Redesign the Performance Monitor Battery card - #51220

Open
Clint Rutkas (crutkas) wants to merge 1 commit into
crutkas-stack-10-gauge-donut-pie-chartsfrom
crutkas-stack-11-battery-card
Open

Clint Rutkas (crutkas) wants to merge 1 commit into
crutkas-stack-10-gauge-donut-pie-chartsfrom
crutkas-stack-11-battery-card

Conversation

@crutkas

Copy link
Copy Markdown
Member

Summary of the Pull Request

Layer 11 of 13 in a stack that splits #51125 (native Adaptive Cards charts and redesigned Performance Monitor cards) into reviewable PRs. See #51125 for the full picture. This layer is based on layer 10 (#51219, crutkas-stack-10-gauge-donut-pie-charts), so the diff shows only this layer. The Overview card and dock band follow in layer 12.

This layer redesigns the Performance Monitor Battery card with the native elements from the layers below:

  • The charge as a gauge (Chart.Gauge, layer 10). Its scale has attention (0–20%), warning (20–50%), and good (50–100%) segments, and the fill takes the color of the segment the charge is in.
  • The status as a badge with a battery icon: Charging, Plugged in, or On battery. The time remaining is under it, as before.
  • Tiles for the charge or discharge rate, the battery's health, and its full charge capacity. Each shows only when Windows reports it.
  • The charge rate shows only while charging, and the discharge rate only on battery power; see Charge and discharge rates.
Dark Light
main main's Battery card, dark theme main's Battery card, light theme
This PR Redesigned Battery card, plugged in and fully charged, dark theme Redesigned Battery card, plugged in and fully charged, light theme

The test machine was plugged in and fully charged, so the live card above has no rate tile. These states use sample data; see Screenshots:

Dark Light
Charging, 64% Battery card with sample data, charging at 64%, dark theme Battery card with sample data, charging at 64%, light theme
On battery, 38% Battery card with sample data, on battery at 38%, dark theme Battery card with sample data, on battery at 38%, light theme
On battery, 12% Battery card with sample data, on battery at 12%, dark theme Battery card with sample data, on battery at 12%, light theme

PR Checklist

  • Communication: I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected
  • Tests: Added/updated and all pass
  • Localization: All end-user-facing strings can be localized (4 new Battery_Widget_Template/* strings in the extension's Resources.resw)
  • Dev docs: Added/updated (N/A)
  • New binaries: Added on the required places (N/A, no new binaries)
  • Documentation updated: If checked, please file a pull request on our docs repo and link it here: #xxx

Detailed Description of the Pull Request / Additional comments

The card

SystemBatteryTemplate.json is rewritten with Chart.Gauge (layer 10), and Badge and rounded, bordered Container tiles (layer 3). The gauge falls back to the charge as large text, and the badge to the status as bold text. SystemBatteryUsageWidgetPage fills it:

  • batteryPercent: the charge as a number for the gauge, or 0 when it's unknown or there's no battery.
  • batteryStatusStyle: the badge's style: good while charging, informative when plugged in, and accent on battery power.
  • batteryIcon: BatteryCharge while charging, otherwise Battery0 to Battery10 by charge (GetChargeIconName). An unknown charge has no icon.
  • batteryColor: good while charging or above 50%, then warning above 20%, then attention, or accent when the charge is unknown (GetChargeColor). This card's gauge takes its colors from its segments; the Overview card in layer 12 uses batteryColor.
  • batteryRateLabel and batteryRate: Charge rate or Discharge rate, in watts, such as 9.6 W (GetDisplayedRate).
  • batteryHealth: the full charge capacity as a percentage of the design capacity, at most 100%. batteryFullCapacity: the full charge capacity, such as 86.3 Wh. The page also sets batteryDesignCapacity, as CmdPal: Native Adaptive Cards charts and redesigned Performance Monitor cards #51125 does, though no template uses it.

The Status label goes, since the badge shows the status.

Battery report

BatteryStats.ReadReport (new) reads the charge rate, design capacity, and full charge capacity from Battery.AggregateBattery.GetReport() (Windows.Devices.Power), which combines all of the device's batteries. The page reads it with each update, once a second while the Battery item, dock band, or card is showing, and only when there's a battery. If it throws, the three values are null and their tiles are hidden. The charge, status, and time remaining still come from GetSystemPowerStatus, as on main.

Charge and discharge rates

The report's rate is positive while charging and negative while discharging. Plugged in with a full battery, the battery is idle, and small readings in either direction come and go. So GetDisplayedRate shows a rate only while charging (a positive rate) or on battery power (a negative rate). A reading that disagrees with the charging state, a zero, or no reading isn't shown.

Strings

4 new Battery_Widget_Template/* strings in the extension's Resources.resw, each with a comment for translators: Charge rate, Discharge rate, Health, and Full charge capacity.

Screenshots

The screenshots come from a local card harness (not in the repo). It renders the real template through IncrementalAdaptiveCardUpdater, with the polyfills registered, main's host config, and the real CardOverrideStyles from ContentFormControl.xaml. The cards are 776 px wide. #51205's host config isn't part of this stack, so padding and spacing are main's. main's card is main's template, which this branch's base still has, rendered with the same live data; the page sets the three values it uses as main does.

The test machine, a Surface, was plugged in and fully charged. The sample states render the real template with data built the way SystemBatteryUsageWidgetPage builds it, with its GetChargeColor, GetChargeIconName, and GetDisplayedRate, and this machine's capacities. Their charge levels, rates, and times remaining are made up.

Validation Steps Performed

Validated on layer 10's head (b69e2cc134, with layer 9's two fixes).

The 2 files taken whole are identical to their versions at #51125's head (8858a9e0a7): BatteryStats.cs and SystemBatteryTemplate.json. So are SystemBatteryUsageWidgetPage, the 4 strings, and the 3 tests in CardFormattingTests.cs. Other files differ from #51125 only where other PRs change them: the Overview card's code, strings, and test (layer 12), and layer 9's decimal bit rates.

ARM64 Debug builds, run from a subst drive (common build options: -nologo -m -restore -t:Build -v:minimal -p:Configuration=Debug -p:Platform=ARM64 -p:RuntimeIdentifier=win-arm64 -p:CIBuild=false -p:GeneratePackageLocally=false -p:GenerateAppxPackageOnBuild=false -p:PublishAppxPackage=false -p:SkipLongPathsCheck=true):

  • MSBuild.exe src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.PerformanceMonitor\Microsoft.CmdPal.Ext.PerformanceMonitor.csproj <options>, with -t:Rebuild: exit code 0. The only warning is LNK4075 from the native Microsoft.CommandPalette.Extensions.vcxproj dependency. The extension imports Common.Dotnet.AotCompatibility.props, so the trim and AOT analyzers run over the new code.
  • MSBuild.exe src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.PerformanceMonitor.UnitTests\Microsoft.CmdPal.Ext.PerformanceMonitor.UnitTests.csproj <options>: exit code 0, no warnings from the extension or its tests.
  • vstest.console.arm64.exe ARM64\Debug\WinUI3Apps\CmdPal\tests\Microsoft.CmdPal.Ext.PerformanceMonitor.UnitTests.dll /Platform:ARM64: 173 passed, 0 failed. 3 are new, in CardFormattingTests.cs:
    • ChargeColorReflectsTheChargeLevel.
    • ChargeIconReflectsTheChargeLevel.
    • RateIsShownOnlyWhileChargingOrOnBattery: charging, on battery, plugged in and idle in both directions, readings that disagree with the state, no reading, and zero.
  • A local approximation of check-spelling over this diff (the repo's workflow is disabled): no unknown words or forbidden patterns.

Card harness under JIT, dark and light:

  • The Battery card for 8 seconds: no parse warnings or missing strings, and it renders as shown. All 12 updates patched the card in place; none replaced it.

  • Every card this branch has, for 8 seconds: CPU, Memory, GPU, Disk, Network, Battery, the gauges card, and the Icon fallback card. No strings are missing. The only parse warnings are for the fallback card's Bot icon, which has no glyph on purpose. No update replaced the Memory, GPU, Disk, Network, Battery, gauges, or fallback card. The CPU card was replaced once in each theme, when its top processes and per-core chart first appeared.

  • A simulated Aquatic contrast theme: the card takes the contrast colors, and the gauge draws its segments full width with a needle.

  • The values match Windows. A script polled GetSystemPowerStatus (through .NET's SystemInformation.PowerStatus), the aggregate battery report, and WMI's BatteryStatus once a second while the harness ran. This table compares the card's capture at 12:18:47 with the script's reading in the same second:

    Card Windows
    Charge 100% GetSystemPowerStatus: 100%
    Status Plugged in, no rate tile On AC power. Aggregate report: Idle, 0 mW. WMI: charge and discharge rates 0
    Full charge capacity 86.3 Wh Aggregate report and powercfg /batteryreport: 86,340 mWh
    Health 96% 86,340 of 89,290 mWh design capacity: 96.7%

    Settings > System > Power & battery said "Your battery is fully charged. The remaining battery life is 100%" at 12:20:58, and the card showed 100% at 12:21:01. Settings doesn't show a health percentage on this build. The card truncates percentages, as the other cards do (FloatToPercentString), so 96.7% shows as 96%.

Not run: a native AOT publish of the harness; the extension's trim and AOT analyzers pass. The charge and discharge rates weren't seen live, since the machine stayed plugged in and full; the unit tests and the sample states cover them.

@github-actions github-actions Bot added Product-Command Palette Refers to the Command Palette utility Ready for review labels Oct 12, 2026
@github-actions

Copy link
Copy Markdown

🧭 PR intake

Visual evidence: Not needed — The changed files do not indicate a visible UI change. Visual evidence was detected in the PR description.

Recommendation

Link the issue this PR fixes using a closing keyword such as Closes #123.

✅ Ready for review

This PR passed the automated intake checks and is ready for maintainer review.

Automated PR intake; PowerToys maintainers make final decisions.

Redraw the Battery card with the native Adaptive Cards elements from
the layers below: a Chart.Gauge of the charge, which fills in warning
below 50% and attention below 20%, next to a status badge with a
battery icon (Charging, Plugged in, or On battery) and the time
remaining. Tiles below show the charge or discharge rate, the battery's
health, and its full charge capacity, each only when Windows reports it.

BatteryStats now reads the aggregate battery report for the charge
rate, design capacity, and full charge capacity. Health is the full
charge capacity as a percentage of the design capacity. The card shows
the charge rate only while charging, and the discharge rate only on
battery power: plugged in and idle, small readings come and go.

Layer 11 of 13 in a stack that splits #51125.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Product-Command Palette Refers to the Command Palette utility Ready for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant