From fdd1f47d850795e9eac9cde3d29bf84790208c35 Mon Sep 17 00:00:00 2001 From: leileizhang Date: Fri, 1 Aug 2025 13:57:39 +0800 Subject: [PATCH 01/45] [UI tests] Fix UI test pipeline to properly handle buildSource parameter conditions (#40899) ## Summary of the Pull Request Fixes a logic issue in the UI test automation pipeline where selecting `latestMainOfficialBuild` would still trigger a full PowerToys build instead of only building UI tests. ### Why The pipeline was using template variables in compilation-time conditions, which doesn't work correctly in pipeline ### fix Replace template variable references with direct parameter comparisons in compilation-time conditions ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed --- .pipelines/v2/templates/job-test-project.yml | 9 +- .../pipeline-ui-tests-automation.yml | 156 ++---------------- .../pipeline-ui-tests-full-build.yml | 80 +++++++++ .../pipeline-ui-tests-official-build.yml | 110 ++++++++++++ 4 files changed, 212 insertions(+), 143 deletions(-) create mode 100644 .pipelines/v2/templates/pipeline-ui-tests-full-build.yml create mode 100644 .pipelines/v2/templates/pipeline-ui-tests-official-build.yml diff --git a/.pipelines/v2/templates/job-test-project.yml b/.pipelines/v2/templates/job-test-project.yml index 9b9bdc3cc1..2c5fdc78ff 100644 --- a/.pipelines/v2/templates/job-test-project.yml +++ b/.pipelines/v2/templates/job-test-project.yml @@ -45,7 +45,6 @@ jobs: BuildConfiguration: ${{ parameters.configuration }} SrcPath: $(Build.Repository.LocalPath) TestArtifactsName: build-${{ variables.BuildPlatform }}-${{ parameters.configuration }}${{ parameters.inputArtifactStem }} - isBuildNow: ${{ eq(parameters.buildSource, 'buildNow') }} pool: ${{ if eq(variables['System.CollectionId'], 'cb55739e-4afe-46a3-970f-1b49d8ee7564') }}: ${{ if ne(parameters.platform, 'ARM64') }}: @@ -116,7 +115,7 @@ jobs: & '$(build.sourcesdirectory)\.pipelines\InstallWinAppDriver.ps1' displayName: Download and install WinAppDriver - - ${{ if not(variables.isBuildNow) }}: + - ${{ if ne(parameters.buildSource, 'buildNow') }}: - task: DownloadPipelineArtifact@2 inputs: buildType: 'specific' @@ -137,7 +136,7 @@ jobs: patterns: | **/PowerToysSetup*.exe - - ${{ if not(variables.isBuildNow) }}: + - ${{ if ne(parameters.buildSource, 'buildNow') }}: - ${{ if eq(parameters.installMode, 'peruser') }}: - pwsh: |- & "$(build.sourcesdirectory)\.pipelines\installPowerToys.ps1" -InstallMode "PerUser" @@ -173,7 +172,7 @@ jobs: !**\UITests-FancyZones\**\UITests-FancyZonesEditor.dll env: platform: '$(TestPlatform)' - useInstallerForTest: ${{ not(variables.isBuildNow) }} + useInstallerForTest: ${{ ne(parameters.buildSource, 'buildNow') }} - ${{ if ne(length(parameters.uiTestModules), 0) }}: - ${{ each module in parameters.uiTestModules }}: @@ -195,4 +194,4 @@ jobs: !**\UITests-FancyZones\**\UITests-FancyZonesEditor.dll env: platform: '$(TestPlatform)' - useInstallerForTest: ${{ not(variables.isBuildNow) }} + useInstallerForTest: ${{ ne(parameters.buildSource, 'buildNow') }} diff --git a/.pipelines/v2/templates/pipeline-ui-tests-automation.yml b/.pipelines/v2/templates/pipeline-ui-tests-automation.yml index d66d30b818..0682cc5e32 100644 --- a/.pipelines/v2/templates/pipeline-ui-tests-automation.yml +++ b/.pipelines/v2/templates/pipeline-ui-tests-automation.yml @@ -3,8 +3,6 @@ variables: value: false - name: EnablePipelineCache value: true - - name: isBuildNow - value: ${{ eq(parameters.buildSource, 'buildNow') }} parameters: - name: buildPlatforms @@ -39,140 +37,22 @@ parameters: stages: - ${{ each platform in parameters.buildPlatforms }}: - - ${{ if variables.isBuildNow }}: - - stage: Build_${{ platform }} - displayName: Build ${{ platform }} - dependsOn: [] - jobs: - - template: job-build-project.yml - parameters: - pool: - ${{ if eq(variables['System.CollectionId'], 'cb55739e-4afe-46a3-970f-1b49d8ee7564') }}: - name: SHINE-INT-L - ${{ else }}: - name: SHINE-OSS-L - ${{ if eq(parameters.useVSPreview, true) }}: - demands: ImageOverride -equals SHINE-VS17-Preview - buildPlatforms: - - ${{ platform }} - buildConfigurations: [Release] - enablePackageCaching: true - enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }} - runTests: false - buildTests: true - useVSPreview: ${{ parameters.useVSPreview }} - timeoutInMinutes: 90 + # Full build path: build PowerToys + UI tests + run tests + - ${{ if eq(parameters.buildSource, 'buildNow') }}: + - template: pipeline-ui-tests-full-build.yml + parameters: + platform: ${{ platform }} + enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }} + useVSPreview: ${{ parameters.useVSPreview }} + useLatestWebView2: ${{ parameters.useLatestWebView2 }} + uiTestModules: ${{ parameters.uiTestModules }} - - ${{ if not(variables.isBuildNow) }}: - - stage: BuildUITests_${{ platform }} - displayName: Build UI Tests Only - dependsOn: [] - jobs: - - template: job-build-ui-tests.yml - parameters: - pool: - ${{ if eq(variables['System.CollectionId'], 'cb55739e-4afe-46a3-970f-1b49d8ee7564') }}: - name: SHINE-INT-L - ${{ else }}: - name: SHINE-OSS-L - ${{ if eq(parameters.useVSPreview, true) }}: - demands: ImageOverride -equals SHINE-VS17-Preview - buildPlatforms: - - ${{ platform }} - uiTestModules: ${{ parameters.uiTestModules }} - - - ${{ if eq(platform, 'x64') }}: - - stage: Test_x64Win10 - displayName: Test x64Win10 - ${{ if not(variables.isBuildNow) }}: - dependsOn: - - BuildUITests_${{ platform }} - ${{ else }}: - dependsOn: - - Build_${{ platform }} - jobs: - - template: job-test-project.yml - parameters: - platform: x64Win10 - configuration: Release - useLatestWebView2: ${{ parameters.useLatestWebView2 }} - buildSource: ${{ parameters.buildSource }} - specificBuildId: ${{ parameters.specificBuildId }} - uiTestModules: ${{ parameters.uiTestModules }} - - # Additional per-user installation test - - ${{ if not(variables.isBuildNow) }}: - - template: job-test-project.yml - parameters: - platform: x64Win10 - configuration: Release - useLatestWebView2: ${{ parameters.useLatestWebView2 }} - buildSource: ${{ parameters.buildSource }} - specificBuildId: ${{ parameters.specificBuildId }} - uiTestModules: ${{ parameters.uiTestModules }} - installMode: 'peruser' - jobSuffix: '_PerUser' - - - ${{ if eq(platform, 'x64') }}: - - stage: Test_x64Win11 - displayName: Test x64Win11 - ${{ if not(variables.isBuildNow) }}: - dependsOn: - - BuildUITests_${{ platform }} - ${{ else }}: - dependsOn: - - Build_${{ platform }} - jobs: - - template: job-test-project.yml - parameters: - platform: x64Win11 - configuration: Release - useLatestWebView2: ${{ parameters.useLatestWebView2 }} - buildSource: ${{ parameters.buildSource }} - specificBuildId: ${{ parameters.specificBuildId }} - uiTestModules: ${{ parameters.uiTestModules }} - - # Additional per-user installation test - - ${{ if not(variables.isBuildNow) }}: - - template: job-test-project.yml - parameters: - platform: x64Win11 - configuration: Release - useLatestWebView2: ${{ parameters.useLatestWebView2 }} - buildSource: ${{ parameters.buildSource }} - specificBuildId: ${{ parameters.specificBuildId }} - uiTestModules: ${{ parameters.uiTestModules }} - installMode: 'peruser' - jobSuffix: '_PerUser' - - - ${{ if ne(platform, 'x64') }}: - - stage: Test_${{ platform }} - displayName: Test ${{ platform }} - ${{ if not(variables.isBuildNow) }}: - dependsOn: - - BuildUITests_${{ platform }} - ${{ else }}: - dependsOn: - - Build_${{ platform }} - jobs: - - template: job-test-project.yml - parameters: - platform: ${{ platform }} - configuration: Release - useLatestWebView2: ${{ parameters.useLatestWebView2 }} - buildSource: ${{ parameters.buildSource }} - specificBuildId: ${{ parameters.specificBuildId }} - uiTestModules: ${{ parameters.uiTestModules }} - - # Additional per-user installation test - - ${{ if not(variables.isBuildNow) }}: - - template: job-test-project.yml - parameters: - platform: ${{ platform }} - configuration: Release - useLatestWebView2: ${{ parameters.useLatestWebView2 }} - buildSource: ${{ parameters.buildSource }} - specificBuildId: ${{ parameters.specificBuildId }} - uiTestModules: ${{ parameters.uiTestModules }} - installMode: 'peruser' - jobSuffix: '_PerUser' + # Official build path: build UI tests only + download official build + run tests + - ${{ if ne(parameters.buildSource, 'buildNow') }}: + - template: pipeline-ui-tests-official-build.yml + parameters: + platform: ${{ platform }} + buildSource: ${{ parameters.buildSource }} + specificBuildId: ${{ parameters.specificBuildId }} + useLatestWebView2: ${{ parameters.useLatestWebView2 }} + uiTestModules: ${{ parameters.uiTestModules }} diff --git a/.pipelines/v2/templates/pipeline-ui-tests-full-build.yml b/.pipelines/v2/templates/pipeline-ui-tests-full-build.yml new file mode 100644 index 0000000000..a2373feb80 --- /dev/null +++ b/.pipelines/v2/templates/pipeline-ui-tests-full-build.yml @@ -0,0 +1,80 @@ +# Template for full build path: Build PowerToys + Build UI Tests + Run Tests +parameters: + - name: platform + type: string + - name: enableMsBuildCaching + type: boolean + default: false + - name: useVSPreview + type: boolean + default: false + - name: useLatestWebView2 + type: boolean + default: false + - name: uiTestModules + type: object + default: [] + +stages: + # Stage 1: Build full PowerToys project + - stage: Build_${{ parameters.platform }} + displayName: Build PowerToys ${{ parameters.platform }} + dependsOn: [] + jobs: + - template: job-build-project.yml + parameters: + pool: + ${{ if eq(variables['System.CollectionId'], 'cb55739e-4afe-46a3-970f-1b49d8ee7564') }}: + name: SHINE-INT-L + ${{ else }}: + name: SHINE-OSS-L + ${{ if eq(parameters.useVSPreview, true) }}: + demands: ImageOverride -equals SHINE-VS17-Preview + buildPlatforms: + - ${{ parameters.platform }} + buildConfigurations: [Release] + enablePackageCaching: true + enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }} + runTests: false + buildTests: true + useVSPreview: ${{ parameters.useVSPreview }} + timeoutInMinutes: 90 + + # Stage 2: Run UI Tests + - ${{ if eq(parameters.platform, 'x64') }}: + - stage: Test_x64Win10_FullBuild + displayName: Test x64Win10 (Full Build) + dependsOn: Build_${{ parameters.platform }} + jobs: + - template: job-test-project.yml + parameters: + platform: x64Win10 + configuration: Release + useLatestWebView2: ${{ parameters.useLatestWebView2 }} + buildSource: 'buildNow' + uiTestModules: ${{ parameters.uiTestModules }} + + - stage: Test_x64Win11_FullBuild + displayName: Test x64Win11 (Full Build) + dependsOn: Build_${{ parameters.platform }} + jobs: + - template: job-test-project.yml + parameters: + platform: x64Win11 + configuration: Release + useLatestWebView2: ${{ parameters.useLatestWebView2 }} + buildSource: 'buildNow' + uiTestModules: ${{ parameters.uiTestModules }} + + - ${{ if ne(parameters.platform, 'x64') }}: + - stage: Test_${{ parameters.platform }}_FullBuild + displayName: Test ${{ parameters.platform }} (Full Build) + dependsOn: Build_${{ parameters.platform }} + jobs: + - template: job-test-project.yml + parameters: + platform: ${{ parameters.platform }} + configuration: Release + useLatestWebView2: ${{ parameters.useLatestWebView2 }} + buildSource: 'buildNow' + uiTestModules: ${{ parameters.uiTestModules }} diff --git a/.pipelines/v2/templates/pipeline-ui-tests-official-build.yml b/.pipelines/v2/templates/pipeline-ui-tests-official-build.yml new file mode 100644 index 0000000000..1da11324fe --- /dev/null +++ b/.pipelines/v2/templates/pipeline-ui-tests-official-build.yml @@ -0,0 +1,110 @@ +# Template for official build path: Download Official Build + Build UI Tests Only + Run Tests +parameters: + - name: platform + type: string + - name: buildSource + type: string + - name: specificBuildId + type: string + default: 'xxxx' + - name: useLatestWebView2 + type: boolean + default: false + - name: uiTestModules + type: object + default: [] + +stages: + # Stage 1: Build UI Tests Only + - stage: BuildUITests_${{ parameters.platform }} + displayName: Build UI Tests Only ${{ parameters.platform }} + dependsOn: [] + jobs: + - template: job-build-ui-tests.yml + parameters: + pool: + ${{ if eq(variables['System.CollectionId'], 'cb55739e-4afe-46a3-970f-1b49d8ee7564') }}: + name: SHINE-INT-L + ${{ else }}: + name: SHINE-OSS-L + buildPlatforms: + - ${{ parameters.platform }} + uiTestModules: ${{ parameters.uiTestModules }} + + # Stage 2: Run UI Tests with Official Build + - ${{ if eq(parameters.platform, 'x64') }}: + - stage: Test_x64Win10_OfficialBuild + displayName: Test x64Win10 (Official Build) + dependsOn: BuildUITests_${{ parameters.platform }} + jobs: + - template: job-test-project.yml + parameters: + platform: x64Win10 + configuration: Release + useLatestWebView2: ${{ parameters.useLatestWebView2 }} + buildSource: ${{ parameters.buildSource }} + specificBuildId: ${{ parameters.specificBuildId }} + uiTestModules: ${{ parameters.uiTestModules }} + + # Additional per-user installation test + - template: job-test-project.yml + parameters: + platform: x64Win10 + configuration: Release + useLatestWebView2: ${{ parameters.useLatestWebView2 }} + buildSource: ${{ parameters.buildSource }} + specificBuildId: ${{ parameters.specificBuildId }} + uiTestModules: ${{ parameters.uiTestModules }} + installMode: 'peruser' + jobSuffix: '_PerUser' + + - stage: Test_x64Win11_OfficialBuild + displayName: Test x64Win11 (Official Build) + dependsOn: BuildUITests_${{ parameters.platform }} + jobs: + - template: job-test-project.yml + parameters: + platform: x64Win11 + configuration: Release + useLatestWebView2: ${{ parameters.useLatestWebView2 }} + buildSource: ${{ parameters.buildSource }} + specificBuildId: ${{ parameters.specificBuildId }} + uiTestModules: ${{ parameters.uiTestModules }} + + # Additional per-user installation test + - template: job-test-project.yml + parameters: + platform: x64Win11 + configuration: Release + useLatestWebView2: ${{ parameters.useLatestWebView2 }} + buildSource: ${{ parameters.buildSource }} + specificBuildId: ${{ parameters.specificBuildId }} + uiTestModules: ${{ parameters.uiTestModules }} + installMode: 'peruser' + jobSuffix: '_PerUser' + + - ${{ if ne(parameters.platform, 'x64') }}: + - stage: Test_${{ parameters.platform }}_OfficialBuild + displayName: Test ${{ parameters.platform }} (Official Build) + dependsOn: BuildUITests_${{ parameters.platform }} + jobs: + - template: job-test-project.yml + parameters: + platform: ${{ parameters.platform }} + configuration: Release + useLatestWebView2: ${{ parameters.useLatestWebView2 }} + buildSource: ${{ parameters.buildSource }} + specificBuildId: ${{ parameters.specificBuildId }} + uiTestModules: ${{ parameters.uiTestModules }} + + # Additional per-user installation test + - template: job-test-project.yml + parameters: + platform: ${{ parameters.platform }} + configuration: Release + useLatestWebView2: ${{ parameters.useLatestWebView2 }} + buildSource: ${{ parameters.buildSource }} + specificBuildId: ${{ parameters.specificBuildId }} + uiTestModules: ${{ parameters.uiTestModules }} + installMode: 'peruser' + jobSuffix: '_PerUser' From c91bef15175195fa41ba5eea6fe1c0594968105a Mon Sep 17 00:00:00 2001 From: Niels Laute Date: Tue, 5 Aug 2025 01:33:19 +0200 Subject: [PATCH 02/45] [UX] New dashboard & refactored KeyVisual (#40214) ### Updated `KeyVisual` and `Shortcut` control - Refactoring `KeyVisual` to remove redundant properties and UI elements, and using Styles for better customization. - Shortcut control now shows a "Configure shortcut" label when there's no shortcut configured. ### Other changes - Consolidated converters that were used across pages in `App.xaml.cs` with consistent naming. - Renamed templated controls (from `.cs` to `.xaml.cs`) and moving those to the `Controls` root folder vs. individual folders for a better overview. ## PR Checklist Closes #39520 Closes #32944 --------- Co-authored-by: Jay <65828559+Jay-o-Way@users.noreply.github.com> Co-authored-by: Jaylyn Barbee <51131738+Jaylyn-Barbee@users.noreply.github.com> --- .../Settings.UI.Library/HotkeySettings.cs | 4 +- .../Converters/KeyVisualTemplateSelector.cs | 23 - .../Converters/ModuleItemTemplateSelector.cs | 12 +- .../Settings.UI/PowerToys.Settings.csproj | 12 + .../Settings.UI/SettingsXAML/App.xaml | 23 +- .../SettingsXAML/Controls/Dashboard/Card.xaml | 70 ++ .../Controls/Dashboard/Card.xaml.cs | 73 ++ .../Dashboard/CheckUpdateControl.xaml | 80 ++ .../Dashboard/CheckUpdateControl.xaml.cs | 30 + .../Dashboard/ShortcutConflictControl.xaml | 33 + .../Dashboard/ShortcutConflictControl.xaml.cs | 40 + .../FlyoutMenuButton.xaml | 0 ...MenuButton.cs => FlyoutMenuButton.xaml.cs} | 0 .../IsEnabledTextBlock.xaml | 0 ...extBlock.cs => IsEnabledTextBlock.xaml.cs} | 0 .../Controls/KeyVisual/KeyCharPresenter.xaml | 73 ++ .../KeyVisual/KeyCharPresenter.xaml.cs | 32 + .../Controls/KeyVisual/KeyVisual.cs | 191 ----- .../Controls/KeyVisual/KeyVisual.xaml | 305 +++---- .../Controls/KeyVisual/KeyVisual.xaml.cs | 166 ++++ .../OOBEPageControl.xaml | 0 .../OOBEPageControl.xaml.cs | 0 .../Controls/PowerAccentShortcutControl.xaml | 3 +- ...SettingsGroup.cs => SettingsGroup.xaml.cs} | 0 .../SettingsPageControl.xaml | 12 +- .../ShortcutControl/ShortcutControl.xaml | 99 ++- .../ShortcutControl/ShortcutControl.xaml.cs | 39 +- .../ShortcutDialogContentControl.xaml | 14 +- .../ShortcutWithTextLabelControl.xaml | 6 +- .../SettingsXAML/Flyout/AppsListPage.xaml | 11 +- .../SettingsXAML/Flyout/LaunchPage.xaml | 3 +- .../SettingsXAML/Themes/Generic.xaml | 4 +- .../SettingsXAML/Views/CmdNotFoundPage.xaml | 7 - .../SettingsXAML/Views/ColorPickerPage.xaml | 6 - .../SettingsXAML/Views/DashboardPage.xaml | 790 +++++++----------- .../SettingsXAML/Views/DashboardPage.xaml.cs | 21 +- .../SettingsXAML/Views/GeneralPage.xaml | 1 - .../Views/KeyboardManagerPage.xaml | 19 +- .../SettingsXAML/Views/MouseUtilsPage.xaml | 6 +- .../Views/MouseWithoutBordersPage.xaml | 3 +- .../Settings.UI/Strings/en-us/Resources.resw | 110 ++- .../ViewModels/DashboardModuleItem.cs | 18 +- .../ViewModels/DashboardViewModel.cs | 296 ++----- 43 files changed, 1415 insertions(+), 1220 deletions(-) delete mode 100644 src/settings-ui/Settings.UI/Converters/KeyVisualTemplateSelector.cs create mode 100644 src/settings-ui/Settings.UI/SettingsXAML/Controls/Dashboard/Card.xaml create mode 100644 src/settings-ui/Settings.UI/SettingsXAML/Controls/Dashboard/Card.xaml.cs create mode 100644 src/settings-ui/Settings.UI/SettingsXAML/Controls/Dashboard/CheckUpdateControl.xaml create mode 100644 src/settings-ui/Settings.UI/SettingsXAML/Controls/Dashboard/CheckUpdateControl.xaml.cs create mode 100644 src/settings-ui/Settings.UI/SettingsXAML/Controls/Dashboard/ShortcutConflictControl.xaml create mode 100644 src/settings-ui/Settings.UI/SettingsXAML/Controls/Dashboard/ShortcutConflictControl.xaml.cs rename src/settings-ui/Settings.UI/SettingsXAML/Controls/{FlyoutMenuButton => }/FlyoutMenuButton.xaml (100%) rename src/settings-ui/Settings.UI/SettingsXAML/Controls/{FlyoutMenuButton/FlyoutMenuButton.cs => FlyoutMenuButton.xaml.cs} (100%) rename src/settings-ui/Settings.UI/SettingsXAML/Controls/{IsEnabledTextBlock => }/IsEnabledTextBlock.xaml (100%) rename src/settings-ui/Settings.UI/SettingsXAML/Controls/{IsEnabledTextBlock/IsEnabledTextBlock.cs => IsEnabledTextBlock.xaml.cs} (100%) create mode 100644 src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyCharPresenter.xaml create mode 100644 src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyCharPresenter.xaml.cs delete mode 100644 src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.cs create mode 100644 src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.xaml.cs rename src/settings-ui/Settings.UI/SettingsXAML/Controls/{OOBEPageControl => }/OOBEPageControl.xaml (100%) rename src/settings-ui/Settings.UI/SettingsXAML/Controls/{OOBEPageControl => }/OOBEPageControl.xaml.cs (100%) rename src/settings-ui/Settings.UI/SettingsXAML/Controls/SettingsGroup/{SettingsGroup.cs => SettingsGroup.xaml.cs} (100%) diff --git a/src/settings-ui/Settings.UI.Library/HotkeySettings.cs b/src/settings-ui/Settings.UI.Library/HotkeySettings.cs index ff588eafbd..89c1a1995d 100644 --- a/src/settings-ui/Settings.UI.Library/HotkeySettings.cs +++ b/src/settings-ui/Settings.UI.Library/HotkeySettings.cs @@ -120,9 +120,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library if (Shift) { - shortcutList.Add("Shift"); - - // shortcutList.Add(16); // The Shift key or button. + shortcutList.Add(16); // The Shift key or button. } if (Code > 0) diff --git a/src/settings-ui/Settings.UI/Converters/KeyVisualTemplateSelector.cs b/src/settings-ui/Settings.UI/Converters/KeyVisualTemplateSelector.cs deleted file mode 100644 index 43e993912a..0000000000 --- a/src/settings-ui/Settings.UI/Converters/KeyVisualTemplateSelector.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Microsoft Corporation -// The Microsoft Corporation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Microsoft.PowerToys.Settings.UI.Library; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; - -namespace Microsoft.PowerToys.Settings.UI.Converters -{ - internal sealed partial class KeyVisualTemplateSelector : DataTemplateSelector - { - public DataTemplate KeyVisualTemplate { get; set; } - - public DataTemplate CommaTemplate { get; set; } - - protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) - { - var stringValue = item as string; - return stringValue == KeysDataModel.CommaSeparator ? CommaTemplate : KeyVisualTemplate; - } - } -} diff --git a/src/settings-ui/Settings.UI/Converters/ModuleItemTemplateSelector.cs b/src/settings-ui/Settings.UI/Converters/ModuleItemTemplateSelector.cs index 1374c16482..bfc05b5deb 100644 --- a/src/settings-ui/Settings.UI/Converters/ModuleItemTemplateSelector.cs +++ b/src/settings-ui/Settings.UI/Converters/ModuleItemTemplateSelector.cs @@ -10,23 +10,17 @@ namespace Microsoft.PowerToys.Settings.UI.Converters { public partial class ModuleItemTemplateSelector : DataTemplateSelector { - public DataTemplate TextTemplate { get; set; } - - public DataTemplate ButtonTemplate { get; set; } - public DataTemplate ShortcutTemplate { get; set; } - public DataTemplate KBMTemplate { get; set; } + public DataTemplate ActivationTemplate { get; set; } protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) { switch (item) { - case DashboardModuleButtonItem: return ButtonTemplate; case DashboardModuleShortcutItem: return ShortcutTemplate; - case DashboardModuleTextItem: return TextTemplate; - case DashboardModuleKBMItem: return KBMTemplate; - default: return TextTemplate; + case DashboardModuleActivationItem: return ActivationTemplate; + default: return ActivationTemplate; } } } diff --git a/src/settings-ui/Settings.UI/PowerToys.Settings.csproj b/src/settings-ui/Settings.UI/PowerToys.Settings.csproj index 2451855cd2..13aef6df63 100644 --- a/src/settings-ui/Settings.UI/PowerToys.Settings.csproj +++ b/src/settings-ui/Settings.UI/PowerToys.Settings.csproj @@ -22,6 +22,9 @@ + + + @@ -132,6 +135,15 @@ Always + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + diff --git a/src/settings-ui/Settings.UI/SettingsXAML/App.xaml b/src/settings-ui/Settings.UI/SettingsXAML/App.xaml index c1a5392bdc..2de03f636f 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/App.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/App.xaml @@ -3,17 +3,20 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls" + xmlns:converters="using:Microsoft.PowerToys.Settings.UI.Converters" xmlns:tkconverters="using:CommunityToolkit.WinUI.Converters"> + + @@ -26,19 +29,28 @@ x:Key="BoolToVisibilityConverter" FalseValue="Collapsed" TrueValue="Visible" /> - - - + + + + 2 @@ -46,6 +58,7 @@ 16,0,0,0 240 + 1000 + + + diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyCharPresenter.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyCharPresenter.xaml.cs new file mode 100644 index 0000000000..43ba496712 --- /dev/null +++ b/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyCharPresenter.xaml.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Data; +using Microsoft.UI.Xaml.Documents; +using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Media; + +namespace Microsoft.PowerToys.Settings.UI.Controls; + +public sealed partial class KeyCharPresenter : Control +{ + public KeyCharPresenter() + { + DefaultStyleKey = typeof(KeyCharPresenter); + } + + public object Content + { + get => (object)GetValue(ContentProperty); + set => SetValue(ContentProperty, value); + } + + public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(nameof(Content), typeof(object), typeof(KeyCharPresenter), new PropertyMetadata(default(string))); +} diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.cs b/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.cs deleted file mode 100644 index 9d323c636d..0000000000 --- a/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.cs +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright (c) Microsoft Corporation -// The Microsoft Corporation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Markup; -using Windows.System; - -namespace Microsoft.PowerToys.Settings.UI.Controls -{ - [TemplatePart(Name = KeyPresenter, Type = typeof(ContentPresenter))] - [TemplateVisualState(Name = "Normal", GroupName = "CommonStates")] - [TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")] - [TemplateVisualState(Name = "Default", GroupName = "StateStates")] - [TemplateVisualState(Name = "Error", GroupName = "StateStates")] - public sealed partial class KeyVisual : Control - { - private const string KeyPresenter = "KeyPresenter"; - private KeyVisual _keyVisual; - private ContentPresenter _keyPresenter; - - public object Content - { - get => (object)GetValue(ContentProperty); - set => SetValue(ContentProperty, value); - } - - public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(object), typeof(KeyVisual), new PropertyMetadata(default(string), OnContentChanged)); - - public VisualType VisualType - { - get => (VisualType)GetValue(VisualTypeProperty); - set => SetValue(VisualTypeProperty, value); - } - - public static readonly DependencyProperty VisualTypeProperty = DependencyProperty.Register("VisualType", typeof(VisualType), typeof(KeyVisual), new PropertyMetadata(default(VisualType), OnSizeChanged)); - - public bool IsError - { - get => (bool)GetValue(IsErrorProperty); - set => SetValue(IsErrorProperty, value); - } - - public static readonly DependencyProperty IsErrorProperty = DependencyProperty.Register("IsError", typeof(bool), typeof(KeyVisual), new PropertyMetadata(false, OnIsErrorChanged)); - - public KeyVisual() - { - this.DefaultStyleKey = typeof(KeyVisual); - this.Style = GetStyleSize("TextKeyVisualStyle"); - } - - protected override void OnApplyTemplate() - { - IsEnabledChanged -= KeyVisual_IsEnabledChanged; - _keyVisual = (KeyVisual)this; - _keyPresenter = (ContentPresenter)_keyVisual.GetTemplateChild(KeyPresenter); - Update(); - SetEnabledState(); - SetErrorState(); - IsEnabledChanged += KeyVisual_IsEnabledChanged; - base.OnApplyTemplate(); - } - - private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((KeyVisual)d).Update(); - } - - private static void OnSizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((KeyVisual)d).Update(); - } - - private static void OnIsErrorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((KeyVisual)d).SetErrorState(); - } - - private void Update() - { - if (_keyVisual == null) - { - return; - } - - if (_keyVisual.Content != null) - { - if (_keyVisual.Content.GetType() == typeof(string)) - { - _keyVisual.Style = GetStyleSize("TextKeyVisualStyle"); - _keyVisual._keyPresenter.Content = _keyVisual.Content; - } - else - { - _keyVisual.Style = GetStyleSize("IconKeyVisualStyle"); - - switch ((int)_keyVisual.Content) - { - /* We can enable other glyphs in the future - case 13: // The Enter key or button. - _keyVisual._keyPresenter.Content = "\uE751"; break; - - case 8: // The Back key or button. - _keyVisual._keyPresenter.Content = "\uE750"; break; - - case 16: // The right Shift key or button. - case 160: // The left Shift key or button. - case 161: // The Shift key or button. - _keyVisual._keyPresenter.Content = "\uE752"; break; */ - - case 38: _keyVisual._keyPresenter.Content = "\uE0E4"; break; // The Up Arrow key or button. - case 40: _keyVisual._keyPresenter.Content = "\uE0E5"; break; // The Down Arrow key or button. - case 37: _keyVisual._keyPresenter.Content = "\uE0E2"; break; // The Left Arrow key or button. - case 39: _keyVisual._keyPresenter.Content = "\uE0E3"; break; // The Right Arrow key or button. - - case 91: // The left Windows key - case 92: // The right Windows key - PathIcon winIcon = XamlReader.Load(@"") as PathIcon; - Viewbox winIconContainer = new Viewbox(); - winIconContainer.Child = winIcon; - winIconContainer.HorizontalAlignment = HorizontalAlignment.Center; - winIconContainer.VerticalAlignment = VerticalAlignment.Center; - - double iconDimensions = GetIconSize(); - winIconContainer.Height = iconDimensions; - winIconContainer.Width = iconDimensions; - _keyVisual._keyPresenter.Content = winIconContainer; - break; - default: _keyVisual._keyPresenter.Content = ((VirtualKey)_keyVisual.Content).ToString(); break; - } - } - } - } - - public Style GetStyleSize(string styleName) - { - if (VisualType == VisualType.Small) - { - return (Style)App.Current.Resources["Small" + styleName]; - } - else if (VisualType == VisualType.SmallOutline) - { - return (Style)App.Current.Resources["SmallOutline" + styleName]; - } - else if (VisualType == VisualType.TextOnly) - { - return (Style)App.Current.Resources["Only" + styleName]; - } - else - { - return (Style)App.Current.Resources["Default" + styleName]; - } - } - - public double GetIconSize() - { - if (VisualType == VisualType.Small || VisualType == VisualType.SmallOutline) - { - return (double)App.Current.Resources["SmallIconSize"]; - } - else - { - return (double)App.Current.Resources["DefaultIconSize"]; - } - } - - private void KeyVisual_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) - { - SetEnabledState(); - } - - private void SetErrorState() - { - VisualStateManager.GoToState(this, IsError ? "Error" : "Default", true); - } - - private void SetEnabledState() - { - VisualStateManager.GoToState(this, IsEnabled ? "Normal" : "Disabled", true); - } - } - - public enum VisualType - { - Small, - SmallOutline, - TextOnly, - Large, - } -} diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.xaml index 00192a215a..9ec7f4a2ec 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.xaml @@ -1,66 +1,70 @@  + xmlns:local="using:Microsoft.PowerToys.Settings.UI.Controls"> - 16 - 12 - - - - - - - - - - - - - - \ No newline at end of file + diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.xaml.cs new file mode 100644 index 0000000000..b1a967fb16 --- /dev/null +++ b/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.xaml.cs @@ -0,0 +1,166 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Windows.System; + +namespace Microsoft.PowerToys.Settings.UI.Controls +{ + [TemplatePart(Name = KeyPresenter, Type = typeof(KeyCharPresenter))] + [TemplateVisualState(Name = NormalState, GroupName = "CommonStates")] + [TemplateVisualState(Name = DisabledState, GroupName = "CommonStates")] + [TemplateVisualState(Name = InvalidState, GroupName = "CommonStates")] + public sealed partial class KeyVisual : Control + { + private const string KeyPresenter = "KeyPresenter"; + private const string NormalState = "Normal"; + private const string DisabledState = "Disabled"; + private const string InvalidState = "Invalid"; + private KeyCharPresenter _keyPresenter; + + public object Content + { + get => (object)GetValue(ContentProperty); + set => SetValue(ContentProperty, value); + } + + public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(nameof(Content), typeof(object), typeof(KeyVisual), new PropertyMetadata(default(string), OnContentChanged)); + + public bool IsInvalid + { + get => (bool)GetValue(IsInvalidProperty); + set => SetValue(IsInvalidProperty, value); + } + + public static readonly DependencyProperty IsInvalidProperty = DependencyProperty.Register(nameof(IsInvalid), typeof(bool), typeof(KeyVisual), new PropertyMetadata(false, OnIsInvalidChanged)); + + public bool RenderKeyAsGlyph + { + get => (bool)GetValue(RenderKeyAsGlyphProperty); + set => SetValue(RenderKeyAsGlyphProperty, value); + } + + public static readonly DependencyProperty RenderKeyAsGlyphProperty = DependencyProperty.Register(nameof(RenderKeyAsGlyph), typeof(bool), typeof(KeyVisual), new PropertyMetadata(false, OnContentChanged)); + + public KeyVisual() + { + this.DefaultStyleKey = typeof(KeyVisual); + } + + protected override void OnApplyTemplate() + { + IsEnabledChanged -= KeyVisual_IsEnabledChanged; + _keyPresenter = (KeyCharPresenter)this.GetTemplateChild(KeyPresenter); + Update(); + SetVisualStates(); + IsEnabledChanged += KeyVisual_IsEnabledChanged; + base.OnApplyTemplate(); + } + + private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ((KeyVisual)d).SetVisualStates(); + } + + private static void OnIsInvalidChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ((KeyVisual)d).SetVisualStates(); + } + + private void SetVisualStates() + { + if (this != null) + { + if (IsInvalid) + { + VisualStateManager.GoToState(this, InvalidState, true); + } + else if (!IsEnabled) + { + VisualStateManager.GoToState(this, DisabledState, true); + } + else + { + VisualStateManager.GoToState(this, NormalState, true); + } + } + } + + private void Update() + { + if (Content == null) + { + return; + } + + if (Content is string) + { + _keyPresenter.Style = (Style)Application.Current.Resources["DefaultKeyCharPresenterStyle"]; + return; + } + + if (Content is int keyCode) + { + VirtualKey virtualKey = (VirtualKey)keyCode; + switch (virtualKey) + { + case VirtualKey.Enter: + SetGlyphOrText("\uE751", virtualKey); + break; + + case VirtualKey.Back: + SetGlyphOrText("\uE750", virtualKey); + break; + + case VirtualKey.Shift: + case (VirtualKey)160: // Left Shift + case (VirtualKey)161: // Right Shift + SetGlyphOrText("\uE752", virtualKey); + break; + + case VirtualKey.Up: + _keyPresenter.Content = "\uE0E4"; + break; + + case VirtualKey.Down: + _keyPresenter.Content = "\uE0E5"; + break; + + case VirtualKey.Left: + _keyPresenter.Content = "\uE0E2"; + break; + + case VirtualKey.Right: + _keyPresenter.Content = "\uE0E3"; + break; + + case VirtualKey.LeftWindows: + case VirtualKey.RightWindows: + _keyPresenter.Style = (Style)Application.Current.Resources["WindowsKeyCharPresenterStyle"]; + break; + } + } + } + + private void SetGlyphOrText(string glyph, VirtualKey key) + { + if (RenderKeyAsGlyph) + { + _keyPresenter.Content = glyph; + _keyPresenter.Style = (Style)Application.Current.Resources["GlyphKeyCharPresenterStyle"]; + } + else + { + _keyPresenter.Content = key.ToString(); + _keyPresenter.Style = (Style)Application.Current.Resources["DefaultKeyCharPresenterStyle"]; + } + } + + private void KeyVisual_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) + { + SetVisualStates(); + } + } +} diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/OOBEPageControl/OOBEPageControl.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Controls/OOBEPageControl.xaml similarity index 100% rename from src/settings-ui/Settings.UI/SettingsXAML/Controls/OOBEPageControl/OOBEPageControl.xaml rename to src/settings-ui/Settings.UI/SettingsXAML/Controls/OOBEPageControl.xaml diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/OOBEPageControl/OOBEPageControl.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Controls/OOBEPageControl.xaml.cs similarity index 100% rename from src/settings-ui/Settings.UI/SettingsXAML/Controls/OOBEPageControl/OOBEPageControl.xaml.cs rename to src/settings-ui/Settings.UI/SettingsXAML/Controls/OOBEPageControl.xaml.cs diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/PowerAccentShortcutControl.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Controls/PowerAccentShortcutControl.xaml index c115d1febe..09b2d7d26a 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Controls/PowerAccentShortcutControl.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Controls/PowerAccentShortcutControl.xaml @@ -31,8 +31,7 @@ VerticalAlignment="Center" AutomationProperties.AccessibilityView="Raw" Content="{Binding}" - IsTabStop="False" - VisualType="SmallOutline" /> + IsTabStop="False" /> diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/SettingsGroup/SettingsGroup.cs b/src/settings-ui/Settings.UI/SettingsXAML/Controls/SettingsGroup/SettingsGroup.xaml.cs similarity index 100% rename from src/settings-ui/Settings.UI/SettingsXAML/Controls/SettingsGroup/SettingsGroup.cs rename to src/settings-ui/Settings.UI/SettingsXAML/Controls/SettingsGroup/SettingsGroup.xaml.cs diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/SettingsPageControl/SettingsPageControl.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Controls/SettingsPageControl/SettingsPageControl.xaml index a49c93a518..118c9b7ca5 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Controls/SettingsPageControl/SettingsPageControl.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Controls/SettingsPageControl/SettingsPageControl.xaml @@ -6,20 +6,12 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls" - xmlns:tkconverters="using:CommunityToolkit.WinUI.Converters" Loaded="UserControl_Loaded" mc:Ignorable="d"> - 1000 1020 - - @@ -62,7 +54,7 @@ MaxWidth="160" HorizontalAlignment="Left" VerticalAlignment="Top" - CornerRadius="4"> + CornerRadius="{StaticResource OverlayCornerRadius}"> @@ -113,7 +105,7 @@ MaxWidth="{StaticResource PageMaxWidth}" AutomationProperties.Name="{x:Bind SecondaryLinksHeader}" Orientation="Vertical" - Visibility="{x:Bind SecondaryLinks.Count, Converter={StaticResource doubleToVisibilityConverter}}"> + Visibility="{x:Bind SecondaryLinks.Count, Converter={StaticResource DoubleToVisibilityConverter}}"> - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutControl.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutControl.xaml.cs index e33127572d..c75017300c 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutControl.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutControl.xaml.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System; - using CommunityToolkit.WinUI; using Microsoft.PowerToys.Settings.UI.Helpers; using Microsoft.PowerToys.Settings.UI.Library; @@ -11,6 +10,7 @@ using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Automation; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Input; +using Microsoft.Windows.ApplicationModel.Resources; using Windows.System; namespace Microsoft.PowerToys.Settings.UI.Controls @@ -36,6 +36,8 @@ namespace Microsoft.PowerToys.Settings.UI.Controls public static readonly DependencyProperty AllowDisableProperty = DependencyProperty.Register("AllowDisable", typeof(bool), typeof(ShortcutControl), new PropertyMetadata(false, OnAllowDisableChanged)); + private static ResourceLoader resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader; + private static void OnAllowDisableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var me = d as ShortcutControl; @@ -50,8 +52,6 @@ namespace Microsoft.PowerToys.Settings.UI.Controls return; } - var resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader; - var newValue = (bool)(e?.NewValue ?? false); var text = newValue ? resourceLoader.GetString("Activation_Shortcut_With_Disable_Description") : resourceLoader.GetString("Activation_Shortcut_Description"); @@ -103,8 +103,7 @@ namespace Microsoft.PowerToys.Settings.UI.Controls { hotkeySettings = value; SetValue(HotkeySettingsProperty, value); - PreviewKeysControl.ItemsSource = HotkeySettings.GetKeysList(); - AutomationProperties.SetHelpText(EditButton, HotkeySettings.ToString()); + SetKeys(); c.Keys = HotkeySettings.GetKeysList(); } } @@ -118,8 +117,6 @@ namespace Microsoft.PowerToys.Settings.UI.Controls this.Unloaded += ShortcutControl_Unloaded; this.Loaded += ShortcutControl_Loaded; - var resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader; - // We create the Dialog in C# because doing it in XAML is giving WinUI/XAML Island bugs when using dark theme. shortcutDialog = new ContentDialog { @@ -433,11 +430,9 @@ namespace Microsoft.PowerToys.Settings.UI.Controls hotkeySettings = null; SetValue(HotkeySettingsProperty, hotkeySettings); - PreviewKeysControl.ItemsSource = HotkeySettings.GetKeysList(); + SetKeys(); lastValidSettings = hotkeySettings; - - AutomationProperties.SetHelpText(EditButton, HotkeySettings.ToString()); shortcutDialog.Hide(); } @@ -448,8 +443,7 @@ namespace Microsoft.PowerToys.Settings.UI.Controls HotkeySettings = lastValidSettings with { }; } - PreviewKeysControl.ItemsSource = hotkeySettings.GetKeysList(); - AutomationProperties.SetHelpText(EditButton, HotkeySettings.ToString()); + SetKeys(); shortcutDialog.Hide(); } @@ -462,9 +456,7 @@ namespace Microsoft.PowerToys.Settings.UI.Controls var empty = new HotkeySettings(); HotkeySettings = empty; - - PreviewKeysControl.ItemsSource = HotkeySettings.GetKeysList(); - AutomationProperties.SetHelpText(EditButton, HotkeySettings.ToString()); + SetKeys(); shortcutDialog.Hide(); } @@ -525,5 +517,22 @@ namespace Microsoft.PowerToys.Settings.UI.Controls Dispose(disposing: true); GC.SuppressFinalize(this); } + + private void SetKeys() + { + var keys = HotkeySettings.GetKeysList(); + + if (keys != null && keys.Count > 0) + { + VisualStateManager.GoToState(this, "Configured", true); + PreviewKeysControl.ItemsSource = keys; + AutomationProperties.SetHelpText(EditButton, HotkeySettings.ToString()); + } + else + { + VisualStateManager.GoToState(this, "Normal", true); + AutomationProperties.SetHelpText(EditButton, resourceLoader.GetString("ConfigureShortcut")); + } + } } } diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutDialogContentControl.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutDialogContentControl.xaml index 8765a3d4b3..da982289e7 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutDialogContentControl.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutDialogContentControl.xaml @@ -14,9 +14,6 @@ - - - + Style="{StaticResource AccentKeyVisualStyle}" /> @@ -51,14 +51,12 @@ Orientation="Vertical" Spacing="8"> - - + FontSize="12" + IsTabStop="False" /> diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Flyout/AppsListPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Flyout/AppsListPage.xaml index 163922236e..dd8a40fb7e 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Flyout/AppsListPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Flyout/AppsListPage.xaml @@ -7,17 +7,8 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:tkconverters="using:CommunityToolkit.WinUI.Converters" xmlns:viewModels="using:Microsoft.PowerToys.Settings.UI.ViewModels" mc:Ignorable="d"> - - - - - @@ -89,7 +80,7 @@ VerticalAlignment="Center" FontSize="16" Glyph="" - Visibility="{x:Bind IsLocked, Converter={StaticResource BoolToInvertedVisibilityConverter}, ConverterParameter=True, Mode=OneWay}"> + Visibility="{x:Bind IsLocked, Converter={StaticResource ReverseBoolToVisibilityConverter}, ConverterParameter=True, Mode=OneWay}"> diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Flyout/LaunchPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Flyout/LaunchPage.xaml index 67d8030b16..a5e6f2de40 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Flyout/LaunchPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Flyout/LaunchPage.xaml @@ -21,7 +21,6 @@ - @@ -110,7 +109,7 @@ diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Themes/Generic.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Themes/Generic.xaml index b1c5f79256..6a68895c50 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Themes/Generic.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Themes/Generic.xaml @@ -2,7 +2,7 @@ - - + + diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/CmdNotFoundPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/CmdNotFoundPage.xaml index 5c4a09a9c4..34305e3529 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/CmdNotFoundPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/CmdNotFoundPage.xaml @@ -10,13 +10,6 @@ xmlns:ui="using:CommunityToolkit.WinUI" AutomationProperties.LandmarkType="Main" mc:Ignorable="d"> - - - - diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/ColorPickerPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/ColorPickerPage.xaml index 5295cf2df4..7ac03ead81 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/ColorPickerPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/ColorPickerPage.xaml @@ -14,14 +14,8 @@ d:DataContext="{d:DesignInstance Type=viewModels:ColorPickerViewModel}" AutomationProperties.LandmarkType="Main" mc:Ignorable="d"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 16 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + \ No newline at end of file diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml.cs index 394b1d6de6..2d6cf95bae 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml.cs @@ -5,10 +5,10 @@ using System; using System.Threading; using System.Threading.Tasks; - using ManagedCommon; using Microsoft.PowerToys.Settings.UI.Helpers; using Microsoft.PowerToys.Settings.UI.Library; +using Microsoft.PowerToys.Settings.UI.OOBE.Enums; using Microsoft.PowerToys.Settings.UI.OOBE.Views; using Microsoft.PowerToys.Settings.UI.ViewModels; using Microsoft.UI.Xaml; @@ -46,14 +46,23 @@ namespace Microsoft.PowerToys.Settings.UI.Views ViewModel.ModuleEnabledChangedOnSettingsPage(); } - private void SWVersionButtonClicked(object sender, RoutedEventArgs e) - { - ViewModel.SWVersionButtonClicked(); - } - private void DashboardListItemClick(object sender, RoutedEventArgs e) { ViewModel.DashboardListItemClick(sender); } + + private void WhatsNewButton_Click(object sender, RoutedEventArgs e) + { + if (App.GetOobeWindow() == null) + { + App.SetOobeWindow(new OobeWindow(PowerToysModules.WhatsNew)); + } + else + { + App.GetOobeWindow().SetAppWindow(PowerToysModules.WhatsNew); + } + + App.GetOobeWindow().Activate(); + } } } diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml index 51118fea10..da5bcd7e0c 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml @@ -12,7 +12,6 @@ mc:Ignorable="d"> - diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/KeyboardManagerPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/KeyboardManagerPage.xaml index f6e7a3fddb..b816fccf09 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/KeyboardManagerPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/KeyboardManagerPage.xaml @@ -14,22 +14,23 @@ - - - - + - + ## Summary of the Pull Request ## PR Checklist Fix a regression present on master where PowerRename is activated with empty file list where invoked Explorer context menu. Regression was caused by https://github.com/microsoft/PowerToys/pull/40393 - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed Verified that PowerRename shows file list when activated: - From Windows 11 Explorer context menu - From Legacy Explorer context menu - From command line passing some file paths --- .../PowerRenameUILib/PowerRenameXAML/App.xaml.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/modules/powerrename/PowerRenameUILib/PowerRenameXAML/App.xaml.cpp b/src/modules/powerrename/PowerRenameUILib/PowerRenameXAML/App.xaml.cpp index f8746ed878..67f1834499 100644 --- a/src/modules/powerrename/PowerRenameUILib/PowerRenameXAML/App.xaml.cpp +++ b/src/modules/powerrename/PowerRenameUILib/PowerRenameXAML/App.xaml.cpp @@ -126,11 +126,12 @@ void App::OnLaunched(LaunchActivatedEventArgs const&) } auto args = std::wstring{ GetCommandLine() }; - + size_t pipePos{ args.rfind(L"\\\\.\\pipe\\") }; + // Try to parse command line arguments first std::vector cmdLineFiles = ParseCommandLineArgs(args); - if (!cmdLineFiles.empty()) + if (pipePos == std::wstring::npos && !cmdLineFiles.empty()) { // Use command line arguments for UI testing for (const auto& filePath : cmdLineFiles) @@ -142,12 +143,10 @@ void App::OnLaunched(LaunchActivatedEventArgs const&) else { // Use original pipe/stdin logic for normal operation - size_t pos{ args.rfind(L"\\\\.\\pipe\\") }; - std::wstring pipe_name; - if (pos != std::wstring::npos) + if (pipePos != std::wstring::npos) { - pipe_name = args.substr(pos); + pipe_name = args.substr(pipePos); } HANDLE hStdin; From 281c88a620946f9bb576550175b7ce25464f96f4 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 5 Aug 2025 14:15:52 -0500 Subject: [PATCH 05/45] CmdPal: fix files not having an open command (#40990) Yea, it's that dumb. Regressed in #40768 --- .../ext/Microsoft.CmdPal.Ext.Indexer/Data/IndexerListItem.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Data/IndexerListItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Data/IndexerListItem.cs index 6cf0165e57..9e4d3a4387 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Data/IndexerListItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Data/IndexerListItem.cs @@ -85,6 +85,10 @@ internal sealed partial class IndexerListItem : ListItem commands.Add(new CommandContextItem(openCommand)); } } + else + { + commands.Add(new CommandContextItem(openCommand)); + } commands.Add(new CommandContextItem(new OpenWithCommand(fullPath))); commands.Add(new CommandContextItem(new ShowFileInFolderCommand(fullPath) { Name = Resources.Indexer_Command_ShowInFolder })); From a889f4d4bd8353a809568eadb1b33420e98fa1ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pol=C3=A1=C5=A1ek?= Date: Tue, 5 Aug 2025 23:26:05 +0200 Subject: [PATCH 06/45] CmdPal: Update a code comment using a wrong member name [nit] (#40987) ## Summary of the Pull Request (see title) ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed --- .../cmdpal/Microsoft.CmdPal.UI/Helpers/WindowExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/WindowExtensions.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/WindowExtensions.cs index 99ff327ea2..544f8455be 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/WindowExtensions.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/WindowExtensions.cs @@ -29,7 +29,7 @@ public static class WindowExtensions } catch (NotImplementedException) { - // SetShownInSwitchers failed. This can happen if the Explorer is not running. + // Setting IsShownInSwitchers failed. This can happen if the Explorer is not running. } } } From fa55cdb67f95eb257386548744f0f39f8b63af14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pol=C3=A1=C5=A1ek?= Date: Tue, 5 Aug 2025 23:26:22 +0200 Subject: [PATCH 07/45] CmdPal: properly dispose of the old backdrop controller (#40986) ## Summary of the Pull Request Properly disposes the old DesktopAcrylicController when replacing it with a new instance. ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed --- src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs index 3d2c9b8c47..d42c46abec 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs @@ -176,7 +176,11 @@ public sealed partial class MainWindow : WindowEx, private void UpdateAcrylic() { - _acrylicController?.RemoveAllSystemBackdropTargets(); + if (_acrylicController != null) + { + _acrylicController.RemoveAllSystemBackdropTargets(); + _acrylicController.Dispose(); + } _acrylicController = GetAcrylicConfig(Content); From 0997c1a013766b046547fea0414c82cf153db707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pol=C3=A1=C5=A1ek?= Date: Tue, 5 Aug 2025 23:26:50 +0200 Subject: [PATCH 08/45] CmdPal: Coalesce top-level commands list changes into a single task (#40943) ## Summary of the Pull Request Self-refresh of `MainListPage` introduced in #40132 causes unnecessary spawning of tasks by `ReapplySearchInBackground` and pushing the code down the scenic route instead of taking shortcut. This drop-in fix introduces a single-worker coalescing refresh loop to eliminate thread-pool churn and syncs state in early-return paths. ## PR Checklist - [x] Closes: #40916 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** no change - [ ] **Localization:** nothing - [ ] **Dev docs:** nothing - [ ] **New binaries:** none - [ ] **Documentation updated:** nothing ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed --- .../Commands/MainListPage.cs | 53 +++++++++++++++++-- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/MainListPage.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/MainListPage.cs index af2a3d76be..71c0a4e810 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/MainListPage.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/MainListPage.cs @@ -6,6 +6,7 @@ using System.Collections.Immutable; using System.Collections.Specialized; using CommunityToolkit.Mvvm.Messaging; using ManagedCommon; +using Microsoft.CmdPal.Common.Helpers; using Microsoft.CmdPal.Core.ViewModels.Messages; using Microsoft.CmdPal.Ext.Apps; using Microsoft.CommandPalette.Extensions; @@ -29,6 +30,9 @@ public partial class MainListPage : DynamicListPage, private bool _includeApps; private bool _filteredItemsIncludesApps; + private InterlockedBoolean _refreshRunning; + private InterlockedBoolean _refreshRequested; + public MainListPage(IServiceProvider serviceProvider) { Icon = IconHelpers.FromRelativePath("Assets\\StoreLogo.scale-200.png"); @@ -83,18 +87,47 @@ public partial class MainListPage : DynamicListPage, private void ReapplySearchInBackground() { - _ = Task.Run(() => + _refreshRequested.Set(); + if (!_refreshRunning.Set()) { - try + return; + } + + _ = Task.Run(RunRefreshLoop); + } + + private void RunRefreshLoop() + { + try + { + do { + _refreshRequested.Clear(); + lock (_tlcManager.TopLevelCommands) + { + if (_filteredItemsIncludesApps == _includeApps) + { + break; + } + } + var currentSearchText = SearchText; UpdateSearchText(currentSearchText, currentSearchText); } - catch (Exception e) + while (_refreshRequested.Value); + } + catch (Exception e) + { + Logger.LogError("Failed to reload search", e); + } + finally + { + _refreshRunning.Clear(); + if (_refreshRequested.Value && _refreshRunning.Set()) { - Logger.LogError("Failed to reload search", e); + _ = Task.Run(RunRefreshLoop); } - }); + } } public override IListItem[] GetItems() @@ -126,6 +159,15 @@ public partial class MainListPage : DynamicListPage, var aliases = _serviceProvider.GetService()!; if (aliases.CheckAlias(newSearch)) { + if (_filteredItemsIncludesApps != _includeApps) + { + lock (_tlcManager.TopLevelCommands) + { + _filteredItemsIncludesApps = _includeApps; + _filteredItems = null; + } + } + return; } } @@ -138,6 +180,7 @@ public partial class MainListPage : DynamicListPage, // Cleared out the filter text? easy. Reset _filteredItems, and bail out. if (string.IsNullOrEmpty(newSearch)) { + _filteredItemsIncludesApps = _includeApps; _filteredItems = null; RaiseItemsChanged(commands.Count); return; From fed6e523b6c59e90bef9b70cfb61949f4a7f0651 Mon Sep 17 00:00:00 2001 From: leileizhang Date: Wed, 6 Aug 2025 14:12:37 +0800 Subject: [PATCH 09/45] Fix: used wrong preview resize event from another handler (#40995) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary of the Pull Request Bug: Was using GcodePreviewResizeEvent, which will never work — switched to use Bgcode's own event ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed ## AI Summary This pull request makes a minor update to the event handling in the preview pane module. The change updates the event constant used for resizing the preview from `GcodePreviewResizeEvent` to `BgcodePreviewResizeEvent`, likely to improve naming consistency or to support a new event type. --- src/modules/previewpane/BgcodePreviewHandler/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/previewpane/BgcodePreviewHandler/Program.cs b/src/modules/previewpane/BgcodePreviewHandler/Program.cs index f1f1d0ed35..c513ac1e38 100644 --- a/src/modules/previewpane/BgcodePreviewHandler/Program.cs +++ b/src/modules/previewpane/BgcodePreviewHandler/Program.cs @@ -49,7 +49,7 @@ namespace Microsoft.PowerToys.PreviewHandler.Bgcode _previewHandlerControl.DoPreview(filePath); NativeEventWaiter.WaitForEventLoop( - Constants.GcodePreviewResizeEvent(), + Constants.BgcodePreviewResizeEvent(), () => { Rectangle s = default; From e93b044f39e2701bb38059bf0d672ab10579a711 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 6 Aug 2025 19:41:02 -0500 Subject: [PATCH 10/45] CmdPal: Once again, I am asking you to fix form submits (#41010) Closes #40979 Usually, you're supposed to try to cast the action to a specific type, and use those objects to get the data you need. However, there's something weird with AdaptiveCards and the way it works when we consume it when built in Release, with AOT (and trimming) enabled. Any sort of `action.As()` or similar will throw a System.InvalidCastException. Instead we have this horror show. The `action.ToJson()` blob ACTUALLY CONTAINS THE `type` field, which we can use to determine what kind of action it is. Then we can parse the JSON manually based on the type. --- .../ContentFormViewModel.cs | 116 ++++++++++++++---- .../Pages/SampleContentPage.cs | 5 + 2 files changed, 99 insertions(+), 22 deletions(-) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentFormViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentFormViewModel.cs index d561a0e00f..9728e8339e 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentFormViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentFormViewModel.cs @@ -98,35 +98,107 @@ public partial class ContentFormViewModel(IFormContent _form, WeakReference(new(openUrlAction.Url)); - return; - } + // BODGY circa GH #40979 + // Usually, you're supposed to try to cast the action to a specific + // type, and use those objects to get the data you need. + // However, there's something weird with AdaptiveCards and the way it + // works when we consume it when built in Release, with AOT (and + // trimming) enabled. Any sort of `action.As()` + // or similar will throw a System.InvalidCastException. + // + // Instead we have this horror show. + // + // The `action.ToJson()` blob ACTUALLY CONTAINS THE `type` field, which + // we can use to determine what kind of action it is. Then we can parse + // the JSON manually based on the type. + var actionJson = action.ToJson(); - if (action is AdaptiveSubmitAction or AdaptiveExecuteAction) + if (actionJson.TryGetValue("type", out var actionTypeValue)) { - // Get the data and inputs - var dataString = (action as AdaptiveSubmitAction)?.DataJson.Stringify() ?? string.Empty; - var inputString = inputs.Stringify(); + var actionTypeString = actionTypeValue.GetString(); + Logger.LogTrace($"atString={actionTypeString}"); - _ = Task.Run(() => + var actionType = actionTypeString switch { - try - { - var model = _formModel.Unsafe!; - if (model != null) + "Action.Submit" => ActionType.Submit, + "Action.Execute" => ActionType.Execute, + "Action.OpenUrl" => ActionType.OpenUrl, + _ => ActionType.Unsupported, + }; + + Logger.LogDebug($"{actionTypeString}->{actionType}"); + + switch (actionType) + { + case ActionType.OpenUrl: { - var result = model.SubmitForm(inputString, dataString); - WeakReferenceMessenger.Default.Send(new(new(result))); + HandleOpenUrlAction(action, actionJson); } - } - catch (Exception ex) - { - ShowException(ex); - } - }); + + break; + case ActionType.Submit: + case ActionType.Execute: + { + HandleSubmitAction(action, actionJson, inputs); + } + + break; + default: + Logger.LogError($"{actionType} was an unexpected action `type`"); + break; + } } + else + { + Logger.LogError($"actionJson.TryGetValue(type) failed"); + } + } + + private void HandleOpenUrlAction(IAdaptiveActionElement action, JsonObject actionJson) + { + if (actionJson.TryGetValue("url", out var actionUrlValue)) + { + var actionUrl = actionUrlValue.GetString() ?? string.Empty; + if (Uri.TryCreate(actionUrl, default(UriCreationOptions), out var uri)) + { + WeakReferenceMessenger.Default.Send(new(uri)); + } + else + { + Logger.LogError($"Failed to produce URI for {actionUrlValue}"); + } + } + } + + private void HandleSubmitAction( + IAdaptiveActionElement action, + JsonObject actionJson, + JsonObject inputs) + { + var dataString = string.Empty; + if (actionJson.TryGetValue("data", out var actionDataValue)) + { + dataString = actionDataValue.Stringify() ?? string.Empty; + } + + var inputString = inputs.Stringify(); + _ = Task.Run(() => + { + try + { + var model = _formModel.Unsafe!; + if (model != null) + { + var result = model.SubmitForm(inputString, dataString); + Logger.LogDebug($"SubmitForm() returned {result}"); + WeakReferenceMessenger.Default.Send(new(new(result))); + } + } + catch (Exception ex) + { + ShowException(ex); + } + }); } private static readonly string ErrorCardJson = """ diff --git a/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleContentPage.cs b/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleContentPage.cs index a602f74a00..1e5d3f6c5f 100644 --- a/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleContentPage.cs +++ b/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleContentPage.cs @@ -225,6 +225,11 @@ internal sealed partial class SampleContentForm : FormContent } ] } + }, + { + "type": "Action.OpenUrl", + "title": "Action.OpenUrl", + "url": "https://adaptivecards.microsoft.com/" } ] } From 0d4f3d851e47fb7bf479feb79d9cb4321bcaa5ef Mon Sep 17 00:00:00 2001 From: Jeremy Sinclair <4016293+snickler@users.noreply.github.com> Date: Thu, 7 Aug 2025 17:28:01 -0700 Subject: [PATCH 11/45] [Deps] Update .NET packages from 9.0.7 to 9.0.8 (#41039) ## Summary of the Pull Request Updates .NET 9 Runtime / Library packages to the latest 9.0.8 servicing release. ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed --- Directory.Packages.props | 42 +++++++++---------- NOTICE.md | 42 +++++++++---------- .../Directory.Packages.props | 2 +- 3 files changed, 43 insertions(+), 43 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 3487098f08..71bbda5042 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -34,22 +34,22 @@ - + - + - - - - - + + + + + - + - + - + - - - + + + - + - - + + - + - - - - + + + + diff --git a/NOTICE.md b/NOTICE.md index 4dcc82579d..d75fe99522 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -1519,23 +1519,23 @@ SOFTWARE. - Mages 3.0.0 - Markdig.Signed 0.34.0 - MessagePack 3.1.3 -- Microsoft.Bcl.AsyncInterfaces 9.0.7 +- Microsoft.Bcl.AsyncInterfaces 9.0.8 - Microsoft.Bot.AdaptiveExpressions.Core 4.23.0 - Microsoft.CodeAnalysis.NetAnalyzers 9.0.0 -- Microsoft.Data.Sqlite 9.0.7 +- Microsoft.Data.Sqlite 9.0.8 - Microsoft.Diagnostics.Tracing.TraceEvent 3.1.16 - Microsoft.DotNet.ILCompiler (A) -- Microsoft.Extensions.DependencyInjection 9.0.7 -- Microsoft.Extensions.Hosting 9.0.7 -- Microsoft.Extensions.Hosting.WindowsServices 9.0.7 -- Microsoft.Extensions.Logging 9.0.7 -- Microsoft.Extensions.Logging.Abstractions 9.0.7 +- Microsoft.Extensions.DependencyInjection 9.0.8 +- Microsoft.Extensions.Hosting 9.0.8 +- Microsoft.Extensions.Hosting.WindowsServices 9.0.8 +- Microsoft.Extensions.Logging 9.0.8 +- Microsoft.Extensions.Logging.Abstractions 9.0.8 - Microsoft.NET.ILLink.Tasks (A) - Microsoft.SemanticKernel 1.15.0 - Microsoft.Toolkit.Uwp.Notifications 7.1.2 - Microsoft.Web.WebView2 1.0.2903.40 -- Microsoft.Win32.SystemEvents 9.0.7 -- Microsoft.Windows.Compatibility 9.0.7 +- Microsoft.Win32.SystemEvents 9.0.8 +- Microsoft.Windows.Compatibility 9.0.8 - Microsoft.Windows.CsWin32 0.3.183 - Microsoft.Windows.CsWinRT 2.2.0 - Microsoft.Windows.SDK.BuildTools 10.0.26100.4188 @@ -1555,25 +1555,25 @@ SOFTWARE. - SkiaSharp.Views.WinUI 2.88.9 - StreamJsonRpc 2.21.69 - StyleCop.Analyzers 1.2.0-beta.556 -- System.CodeDom 9.0.7 +- System.CodeDom 9.0.8 - System.CommandLine 2.0.0-beta4.22272.1 -- System.ComponentModel.Composition 9.0.7 -- System.Configuration.ConfigurationManager 9.0.7 -- System.Data.OleDb 9.0.7 +- System.ComponentModel.Composition 9.0.8 +- System.Configuration.ConfigurationManager 9.0.8 +- System.Data.OleDb 9.0.8 - System.Data.SqlClient 4.9.0 -- System.Diagnostics.EventLog 9.0.7 -- System.Diagnostics.PerformanceCounter 9.0.7 -- System.Drawing.Common 9.0.7 +- System.Diagnostics.EventLog 9.0.8 +- System.Diagnostics.PerformanceCounter 9.0.8 +- System.Drawing.Common 9.0.8 - System.IO.Abstractions 22.0.13 - System.IO.Abstractions.TestingHelpers 22.0.13 -- System.Management 9.0.7 +- System.Management 9.0.8 - System.Net.Http 4.3.4 - System.Private.Uri 4.3.2 - System.Reactive 6.0.1 -- System.Runtime.Caching 9.0.7 -- System.ServiceProcess.ServiceController 9.0.7 -- System.Text.Encoding.CodePages 9.0.7 -- System.Text.Json 9.0.7 +- System.Runtime.Caching 9.0.8 +- System.ServiceProcess.ServiceController 9.0.8 +- System.Text.Encoding.CodePages 9.0.8 +- System.Text.Json 9.0.8 - System.Text.RegularExpressions 4.3.1 - UnicodeInformation 2.6.0 - UnitsNet 5.56.0 diff --git a/src/modules/cmdpal/ExtensionTemplate/TemplateCmdPalExtension/Directory.Packages.props b/src/modules/cmdpal/ExtensionTemplate/TemplateCmdPalExtension/Directory.Packages.props index 664b2d678a..d364f7da8b 100644 --- a/src/modules/cmdpal/ExtensionTemplate/TemplateCmdPalExtension/Directory.Packages.props +++ b/src/modules/cmdpal/ExtensionTemplate/TemplateCmdPalExtension/Directory.Packages.props @@ -12,6 +12,6 @@ - + From 062234c295339f9fc5c3f63cc89421927b8e9463 Mon Sep 17 00:00:00 2001 From: Kai Tao <69313318+vanzue@users.noreply.github.com> Date: Fri, 8 Aug 2025 16:38:46 +0800 Subject: [PATCH 12/45] Settings: Mouse utils setting crash (#41050) ## Summary of the Pull Request Fix a crash in settings page due to not found converter ## AI Summary This pull request makes a small update to the `MouseUtilsPage.xaml` file to use the correct resource for converting boolean values to visibility states in the UI. - Updated the `Visibility` binding on an `InfoBar` to use the `ReverseBoolToVisibilityConverter` instead of the incorrect `BoolToReverseVisibilityConverter` resource. ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments Regression caused by https://github.com/microsoft/PowerToys/pull/40214 ## Validation Steps Performed image --- .../Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml index e8ebc76f66..0ba74ca164 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml @@ -149,7 +149,7 @@ IsClosable="False" IsOpen="True" Severity="Informational" - Visibility="{x:Bind ViewModel.IsAnimationEnabledBySystem, Mode=OneWay, Converter={StaticResource BoolToReverseVisibilityConverter}}"> + Visibility="{x:Bind ViewModel.IsAnimationEnabledBySystem, Mode=OneWay, Converter={StaticResource ReverseBoolToVisibilityConverter}}"> From d72e0ab20d6ca3738b63d087e47525ada66df606 Mon Sep 17 00:00:00 2001 From: Shawn Yuan <128874481+shuaiyuanxx@users.noreply.github.com> Date: Fri, 8 Aug 2025 22:55:00 +0800 Subject: [PATCH 13/45] Fixed toggle switch not working issue. (#41049) ## Summary of the Pull Request Fixed toggle switch not working issue. ## AI Summary This pull request refactors how `DashboardListItem` objects are created and added to collections in the `DashboardViewModel`. The main improvement is to separate the instantiation of each `DashboardListItem` from the assignment of its `EnabledChangedCallback` property, which is now set after the object is added to the relevant collection. This change improves clarity and may help prevent issues related to object initialization order. Refactoring of `DashboardListItem` creation and initialization: * In the `AddDashboardListItem` method, the `DashboardListItem` object is now created and added to `AllModules` before its `EnabledChangedCallback` property is set, instead of setting this property during object initialization. * In the `GetShortcutModules` method, both `ShortcutModules` and `ActionModules` collections now receive `DashboardListItem` objects that are instantiated first, added to the collection, and then have their `EnabledChangedCallback` property set. This replaces the previous pattern of setting the callback during object creation. [[1]](diffhunk://#diff-aea3404667e7a3de2750bf9ab7ee8ff5e717892caa68ee1de86713cf8e21b44cL123-R136) [[2]](diffhunk://#diff-aea3404667e7a3de2750bf9ab7ee8ff5e717892caa68ee1de86713cf8e21b44cL144-R159) * ## PR Checklist - [x] Closes: #41046 - [ ] **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 It is an regression from https://github.com/microsoft/PowerToys/pull/40214 ## Validation Steps Performed --------- Signed-off-by: Shuai Yuan --- .../ViewModels/DashboardViewModel.cs | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs index 6e2bb2d432..8dd97c85fa 100644 --- a/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs @@ -69,16 +69,18 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private void AddDashboardListItem(ModuleType moduleType) { GpoRuleConfigured gpo = ModuleHelper.GetModuleGpoConfiguration(moduleType); - AllModules.Add(new DashboardListItem() + var newItem = new DashboardListItem() { Tag = moduleType, Label = resourceLoader.GetString(ModuleHelper.GetModuleLabelResourceName(moduleType)), IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && ModuleHelper.GetIsModuleEnabled(generalSettingsConfig, moduleType)), IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled, Icon = ModuleHelper.GetModuleTypeFluentIconName(moduleType), - EnabledChangedCallback = EnabledChangedOnUI, DashboardModuleItems = GetModuleItems(moduleType), - }); + }; + + AllModules.Add(newItem); + newItem.EnabledChangedCallback = EnabledChangedOnUI; } private void EnabledChangedOnUI(DashboardListItem dashboardListItem) @@ -120,16 +122,18 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels if (filteredItems.Count != 0) { - ShortcutModules.Add(new DashboardListItem + var newItem = new DashboardListItem { - EnabledChangedCallback = x.EnabledChangedCallback, Icon = x.Icon, IsLocked = x.IsLocked, Label = x.Label, Tag = x.Tag, IsEnabled = x.IsEnabled, DashboardModuleItems = new ObservableCollection(filteredItems), - }); + }; + + ShortcutModules.Add(newItem); + newItem.EnabledChangedCallback = x.EnabledChangedCallback; } } @@ -141,16 +145,18 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels if (filteredItems.Count != 0) { - ActionModules.Add(new DashboardListItem + var newItem = new DashboardListItem { - EnabledChangedCallback = x.EnabledChangedCallback, Icon = x.Icon, IsLocked = x.IsLocked, Label = x.Label, Tag = x.Tag, IsEnabled = x.IsEnabled, DashboardModuleItems = new ObservableCollection(filteredItems), - }); + }; + + ActionModules.Add(newItem); + newItem.EnabledChangedCallback = x.EnabledChangedCallback; } } } From 04b8234192593d7a0efe2801d657dc85a8db1e79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pol=C3=A1=C5=A1ek?= Date: Tue, 12 Aug 2025 01:12:05 +0200 Subject: [PATCH 14/45] CmdPal: Fix styles applied to MoreCommandsButton (#41059) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary of the Pull Request - Apply the same padding to the button as used for primary and secondary command buttons. - Use consistent spacing between keycap blocks. - Match keycap border style and inner text brush with other command buttons. - Add min width constraint to shortcut keycap element to make it at least square. image ## PR Checklist - [x] Closes: #41052 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed 👀 --- .../Controls/CommandBar.xaml | 68 +++++++------------ 1 file changed, 25 insertions(+), 43 deletions(-) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml index 9fb047641f..107db49939 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml @@ -59,8 +59,24 @@ + + + + + @@ -155,12 +171,7 @@ Style="{StaticResource CaptionTextBlockStyle}" Text="{x:Bind ViewModel.PrimaryCommand.Name, Mode=OneWay}" /> - + @@ -179,19 +190,10 @@ Text="{x:Bind ViewModel.SecondaryCommand.Name, Mode=OneWay}" /> - + - + @@ -199,7 +201,7 @@