From ee6336c47ddfb2e528e43d89b7793fb48e1e5a6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pol=C3=A1=C5=A1ek?= Date: Wed, 30 Jul 2025 18:27:02 +0200 Subject: [PATCH 01/99] Change filter box placeholder for main list page only (#40799) ## Summary of the Pull Request Changes the placeholder in the filter box only on the main list page to "Search for apps, files and commands...": image The default value remains unchanged as "Type here to search..." for all other pages (both built-in and internal), unless the author overrides it: image ## PR Checklist - [x] Closes: #40763 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [x] **Dev docs:** Added/updated - [x] **New binaries:** none - [x] **Documentation updated:** ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed --- .../Commands/MainListPage.cs | 1 + .../Properties/Resources.Designer.cs | 9 +++++++++ .../Properties/Resources.resx | 3 +++ 3 files changed, 13 insertions(+) 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 2817ab9824..af2a3d76be 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/MainListPage.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/MainListPage.cs @@ -32,6 +32,7 @@ public partial class MainListPage : DynamicListPage, public MainListPage(IServiceProvider serviceProvider) { Icon = IconHelpers.FromRelativePath("Assets\\StoreLogo.scale-200.png"); + PlaceholderText = Properties.Resources.builtin_main_list_page_searchbar_placeholder; _serviceProvider = serviceProvider; _tlcManager = _serviceProvider.GetService()!; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Properties/Resources.Designer.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Properties/Resources.Designer.cs index 4c1339ae7d..1deb9cdf74 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Properties/Resources.Designer.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Properties/Resources.Designer.cs @@ -321,6 +321,15 @@ namespace Microsoft.CmdPal.UI.ViewModels.Properties { } } + /// + /// Looks up a localized string similar to Search for apps, files and commands.... + /// + public static string builtin_main_list_page_searchbar_placeholder { + get { + return ResourceManager.GetString("builtin_main_list_page_searchbar_placeholder", resourceCulture); + } + } + /// /// Looks up a localized string similar to Creates a project for a new Command Palette extension. /// diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Properties/Resources.resx b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Properties/Resources.resx index ce4061a58a..0d341e3981 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Properties/Resources.resx +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Properties/Resources.resx @@ -227,4 +227,7 @@ Disabled + + Search for apps, files and commands... + \ No newline at end of file From d26ef36e315bae6416cd636f491301445b24a9e2 Mon Sep 17 00:00:00 2001 From: Kai Tao <69313318+vanzue@users.noreply.github.com> Date: Thu, 31 Jul 2025 09:48:24 +0800 Subject: [PATCH 02/99] [Doc] Add doc for a script to build installer locally, and doc for testing winget install locally (#40805) ## Summary of the Pull Request ## 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 1. Add instructions to build installer locally with a script 2. Add doc explaining how to install an installer by winget locally. ## Validation Steps Performed --- .github/actions/spell-check/expect.txt | 2 ++ doc/devdocs/core/installer.md | 7 ++++ .../test-winget-install-locally.md | 33 +++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 doc/devdocs/development/test-winget-install-locally.md diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index 885a8e5aae..9c9ed952df 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -1440,6 +1440,7 @@ secpol securestring SEEMASKINVOKEIDLIST SELCHANGE +selfhost SENDCHANGE sendvirtualinput serverside @@ -1879,6 +1880,7 @@ winexe winforms winget wingetcreate +wingetpkgs Winhook WINL winlogon diff --git a/doc/devdocs/core/installer.md b/doc/devdocs/core/installer.md index 781f31d682..b4619e26cd 100644 --- a/doc/devdocs/core/installer.md +++ b/doc/devdocs/core/installer.md @@ -87,6 +87,13 @@ ### Building PowerToys Locally +#### One stop script for building installer +1. Open developer powershell for vs 2022 +2. Run tools\build\build-installer.ps1 +> For the first-time setup, please run the installer as an administrator. This ensures that the Wix tool can move wix.target to the desired location and trust the certificate used to sign the MSIX packages. + +The following manual steps will not install the MSIX apps (such as Command Palette) on your local installer. + #### Prerequisites for building the MSI installer 1. Install the [WiX Toolset Visual Studio 2022 Extension](https://marketplace.visualstudio.com/items?itemName=WixToolset.WixToolsetVisualStudio2022Extension). diff --git a/doc/devdocs/development/test-winget-install-locally.md b/doc/devdocs/development/test-winget-install-locally.md new file mode 100644 index 0000000000..a59d32c52d --- /dev/null +++ b/doc/devdocs/development/test-winget-install-locally.md @@ -0,0 +1,33 @@ +## If for any reason, you'd like to test winget install scenario, you can follow this doc: + +### Powertoys winget manifest definition: +[winget repository](https://github.com/microsoft/winget-pkgs/tree/master/manifests/m/Microsoft/PowerToys) + +### How to test a winget installation locally: +1. Get artifacts from release CI pipeline Pipelines - Runs for PowerToys Signed YAML Release Build, or you can build one yourself by execute the + 'tools\build\build-installer.ps1' script + +2. Get the artifact hash, this is required to define winget manifest +```powershell +cd /path/to/your/directory/contains/installer +Get-FileHash -Path ".\.exe" -Algorithm SHA256 +``` + 3. Host your installer.exe - Attention: staged github release artifacts or artifacts in release pipeline is not OK in this step +You can self-host it or you can upload to a publicly available endpoint +**How to selfhost it** (A extremely simple way): +```powershell +python -m http.server 8000 +``` + +4. Download a version folder from wingetpkgs like: [version 0.92.1](https://github.com/microsoft/winget-pkgs/tree/master/manifests/m/Microsoft/PowerToys/0.92.1) +and you get **a folder contains 3 yml files** +>note: Do not put any files other than these three in this folder + +5. Modify the yml files based on your version and the self hosted artifact link, and modify the sha256 hash for the installer you'd like to use + +6. Start winget install: +```powershell +#execute as admin +winget settings --enable LocalManifestFiles +winget install --manifest "" --architecture x64 --scope user +``` \ No newline at end of file From 9a998b2056514001e3066b63d862ed2e25270a2f Mon Sep 17 00:00:00 2001 From: leileizhang Date: Thu, 31 Jul 2025 13:55:23 +0800 Subject: [PATCH 03/99] [UI Tests] Enhance UI Test Automation and Pipeline Support for CmdPal Module (#40871) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary of the Pull Request This pull request introduces enhancements to UI test automation, improvements to pipeline configuration, and project structure updates. The goal is to improve flexibility, maintainability, and efficiency in PowerToys’ CI/CD processes. ### UI Test Enhancements: Delayed Text Input Support - UI tests now support character-by-character text input with configurable delays. - This serves as a workaround for a known CmdPal bug where input is swallowed too quickly. The delay mitigates the issue until it is fixed in CmdPal. Centralized Environment Management - Introduced a new class to centralize environment variable access for UI test configuration. CmdPal Launch Handling in Pipelines - Adjusted test logic to handle CmdPal module startup specifically in CI pipelines ### Pipeline Configuration Updates: Build Artifact Customization - Included test-related folders in pipeline build outputs for better traceability. Support for Build ID Targeting - Added support for specifying PowerToys build IDs in test pipelines, with conditional logic for specific or latest build selection. image ### Project Structure Updates: Added Peek.UITests back to the solution which removed by https://github.com/microsoft/PowerToys/pull/40754 ## 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 --- .../v2/templates/job-build-ui-tests.yml | 2 +- .pipelines/v2/templates/job-test-project.yml | 30 +-- .../pipeline-ui-tests-automation.yml | 71 +++---- PowerToys.sln | 11 ++ doc/devdocs/UITests.md | 44 ++--- .../UITestAutomation/Element/TextBox.cs | 37 +++- .../UITestAutomation/EnvironmentConfig.cs | 45 +++++ .../UITestAutomation/ModuleConfigData.cs | 4 +- src/common/UITestAutomation/SessionHelper.cs | 117 ++++++++---- src/common/UITestAutomation/UITestBase.cs | 177 +++++++++++++++++- src/common/UITestAutomation/VisualAssert.cs | 8 +- .../Microsoft.CmdPal.UITests/BasicTests.cs | 11 +- .../CommandPaletteTestBase.cs | 23 +++ .../Microsoft.CmdPal.UITests/IndexerTests.cs | 25 ++- 14 files changed, 466 insertions(+), 139 deletions(-) create mode 100644 src/common/UITestAutomation/EnvironmentConfig.cs diff --git a/.pipelines/v2/templates/job-build-ui-tests.yml b/.pipelines/v2/templates/job-build-ui-tests.yml index ca99c00932..b9fad16d44 100644 --- a/.pipelines/v2/templates/job-build-ui-tests.yml +++ b/.pipelines/v2/templates/job-build-ui-tests.yml @@ -123,7 +123,7 @@ jobs: displayName: Stage UI Test Build Outputs inputs: sourceFolder: '$(Build.SourcesDirectory)' - contents: '$(BuildPlatform)/$(BuildConfiguration)/**/*' + contents: '**/$(BuildPlatform)/$(BuildConfiguration)/tests/**/*' targetFolder: '$(JobOutputDirectory)\$(BuildPlatform)\$(BuildConfiguration)' - publish: $(JobOutputDirectory) diff --git a/.pipelines/v2/templates/job-test-project.yml b/.pipelines/v2/templates/job-test-project.yml index 6b52351222..9b9bdc3cc1 100644 --- a/.pipelines/v2/templates/job-test-project.yml +++ b/.pipelines/v2/templates/job-test-project.yml @@ -11,12 +11,14 @@ parameters: - name: useLatestWebView2 type: boolean default: false - - name: useLatestOfficialBuild - type: boolean - default: true - - name: useCurrentBranchBuild - type: boolean - default: false + - name: buildSource + type: string + default: "latestMainOfficialBuild" + displayName: "Build Source" + - name: specificBuildId + type: string + default: "xxxx" + displayName: "Build ID (for specific builds)" - name: uiTestModules type: object default: [] @@ -43,6 +45,7 @@ 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') }}: @@ -113,16 +116,17 @@ jobs: & '$(build.sourcesdirectory)\.pipelines\InstallWinAppDriver.ps1' displayName: Download and install WinAppDriver - - ${{ if eq(parameters.useLatestOfficialBuild, true) }}: + - ${{ if not(variables.isBuildNow) }}: - task: DownloadPipelineArtifact@2 inputs: buildType: 'specific' project: 'Dart' definition: '76541' - buildVersionToDownload: 'latestFromBranch' - ${{ if eq(parameters.useCurrentBranchBuild, true) }}: - branchName: '$(Build.SourceBranch)' + ${{ if eq(parameters.buildSource, 'specificBuildId') }}: + buildVersionToDownload: 'specific' + buildId: '${{ parameters.specificBuildId }}' ${{ else }}: + buildVersionToDownload: 'latestFromBranch' branchName: 'refs/heads/main' artifactName: 'build-$(BuildPlatform)-Release' targetPath: '$(Build.ArtifactStagingDirectory)' @@ -133,7 +137,7 @@ jobs: patterns: | **/PowerToysSetup*.exe - - ${{ if eq(parameters.useLatestOfficialBuild, true) }}: + - ${{ if not(variables.isBuildNow) }}: - ${{ if eq(parameters.installMode, 'peruser') }}: - pwsh: |- & "$(build.sourcesdirectory)\.pipelines\installPowerToys.ps1" -InstallMode "PerUser" @@ -169,7 +173,7 @@ jobs: !**\UITests-FancyZones\**\UITests-FancyZonesEditor.dll env: platform: '$(TestPlatform)' - useInstallerForTest: ${{ parameters.useLatestOfficialBuild }} + useInstallerForTest: ${{ not(variables.isBuildNow) }} - ${{ if ne(length(parameters.uiTestModules), 0) }}: - ${{ each module in parameters.uiTestModules }}: @@ -191,4 +195,4 @@ jobs: !**\UITests-FancyZones\**\UITests-FancyZonesEditor.dll env: platform: '$(TestPlatform)' - useInstallerForTest: ${{ parameters.useLatestOfficialBuild }} + useInstallerForTest: ${{ not(variables.isBuildNow) }} diff --git a/.pipelines/v2/templates/pipeline-ui-tests-automation.yml b/.pipelines/v2/templates/pipeline-ui-tests-automation.yml index f5e90e45d9..d66d30b818 100644 --- a/.pipelines/v2/templates/pipeline-ui-tests-automation.yml +++ b/.pipelines/v2/templates/pipeline-ui-tests-automation.yml @@ -3,6 +3,8 @@ variables: value: false - name: EnablePipelineCache value: true + - name: isBuildNow + value: ${{ eq(parameters.buildSource, 'buildNow') }} parameters: - name: buildPlatforms @@ -19,22 +21,25 @@ parameters: - name: useLatestWebView2 type: boolean default: false - - name: useLatestOfficialBuild - type: boolean - default: true - - name: testBothInstallModes - type: boolean - default: true - - name: useCurrentBranchBuild - type: boolean - default: false + - name: buildSource + type: string + default: "latestMainOfficialBuild" + displayName: "Build Source" + values: + - latestMainOfficialBuild + - buildNow + - specificBuildId + - name: specificBuildId + type: string + default: 'xxxx' + displayName: "Build ID (only used when Build Source = specificBuildId)" - name: uiTestModules type: object default: [] stages: - ${{ each platform in parameters.buildPlatforms }}: - - ${{ if eq(parameters.useLatestOfficialBuild, false) }}: + - ${{ if variables.isBuildNow }}: - stage: Build_${{ platform }} displayName: Build ${{ platform }} dependsOn: [] @@ -58,7 +63,7 @@ stages: useVSPreview: ${{ parameters.useVSPreview }} timeoutInMinutes: 90 - - ${{ if eq(parameters.useLatestOfficialBuild, true) }}: + - ${{ if not(variables.isBuildNow) }}: - stage: BuildUITests_${{ platform }} displayName: Build UI Tests Only dependsOn: [] @@ -79,7 +84,7 @@ stages: - ${{ if eq(platform, 'x64') }}: - stage: Test_x64Win10 displayName: Test x64Win10 - ${{ if eq(parameters.useLatestOfficialBuild, true) }}: + ${{ if not(variables.isBuildNow) }}: dependsOn: - BuildUITests_${{ platform }} ${{ else }}: @@ -91,19 +96,19 @@ stages: platform: x64Win10 configuration: Release useLatestWebView2: ${{ parameters.useLatestWebView2 }} - useLatestOfficialBuild: ${{ parameters.useLatestOfficialBuild }} - useCurrentBranchBuild: ${{ parameters.useCurrentBranchBuild }} + buildSource: ${{ parameters.buildSource }} + specificBuildId: ${{ parameters.specificBuildId }} uiTestModules: ${{ parameters.uiTestModules }} - # Additional per-user installation test (when both modes are enabled) - - ${{ if and(eq(parameters.useLatestOfficialBuild, true), eq(parameters.testBothInstallModes, true)) }}: + # Additional per-user installation test + - ${{ if not(variables.isBuildNow) }}: - template: job-test-project.yml parameters: platform: x64Win10 configuration: Release useLatestWebView2: ${{ parameters.useLatestWebView2 }} - useLatestOfficialBuild: ${{ parameters.useLatestOfficialBuild }} - useCurrentBranchBuild: ${{ parameters.useCurrentBranchBuild }} + buildSource: ${{ parameters.buildSource }} + specificBuildId: ${{ parameters.specificBuildId }} uiTestModules: ${{ parameters.uiTestModules }} installMode: 'peruser' jobSuffix: '_PerUser' @@ -111,7 +116,7 @@ stages: - ${{ if eq(platform, 'x64') }}: - stage: Test_x64Win11 displayName: Test x64Win11 - ${{ if eq(parameters.useLatestOfficialBuild, true) }}: + ${{ if not(variables.isBuildNow) }}: dependsOn: - BuildUITests_${{ platform }} ${{ else }}: @@ -123,19 +128,19 @@ stages: platform: x64Win11 configuration: Release useLatestWebView2: ${{ parameters.useLatestWebView2 }} - useLatestOfficialBuild: ${{ parameters.useLatestOfficialBuild }} - useCurrentBranchBuild: ${{ parameters.useCurrentBranchBuild }} + buildSource: ${{ parameters.buildSource }} + specificBuildId: ${{ parameters.specificBuildId }} uiTestModules: ${{ parameters.uiTestModules }} - # Additional per-user installation test (when both modes are enabled) - - ${{ if and(eq(parameters.useLatestOfficialBuild, true), eq(parameters.testBothInstallModes, true)) }}: + # Additional per-user installation test + - ${{ if not(variables.isBuildNow) }}: - template: job-test-project.yml parameters: platform: x64Win11 configuration: Release useLatestWebView2: ${{ parameters.useLatestWebView2 }} - useLatestOfficialBuild: ${{ parameters.useLatestOfficialBuild }} - useCurrentBranchBuild: ${{ parameters.useCurrentBranchBuild }} + buildSource: ${{ parameters.buildSource }} + specificBuildId: ${{ parameters.specificBuildId }} uiTestModules: ${{ parameters.uiTestModules }} installMode: 'peruser' jobSuffix: '_PerUser' @@ -143,7 +148,7 @@ stages: - ${{ if ne(platform, 'x64') }}: - stage: Test_${{ platform }} displayName: Test ${{ platform }} - ${{ if eq(parameters.useLatestOfficialBuild, true) }}: + ${{ if not(variables.isBuildNow) }}: dependsOn: - BuildUITests_${{ platform }} ${{ else }}: @@ -155,19 +160,19 @@ stages: platform: ${{ platform }} configuration: Release useLatestWebView2: ${{ parameters.useLatestWebView2 }} - useLatestOfficialBuild: ${{ parameters.useLatestOfficialBuild }} - useCurrentBranchBuild: ${{ parameters.useCurrentBranchBuild }} + buildSource: ${{ parameters.buildSource }} + specificBuildId: ${{ parameters.specificBuildId }} uiTestModules: ${{ parameters.uiTestModules }} - # Additional per-user installation test (when both modes are enabled) - - ${{ if and(eq(parameters.useLatestOfficialBuild, true), eq(parameters.testBothInstallModes, true)) }}: + # Additional per-user installation test + - ${{ if not(variables.isBuildNow) }}: - template: job-test-project.yml parameters: platform: ${{ platform }} configuration: Release useLatestWebView2: ${{ parameters.useLatestWebView2 }} - useLatestOfficialBuild: ${{ parameters.useLatestOfficialBuild }} - useCurrentBranchBuild: ${{ parameters.useCurrentBranchBuild }} + buildSource: ${{ parameters.buildSource }} + specificBuildId: ${{ parameters.specificBuildId }} uiTestModules: ${{ parameters.uiTestModules }} installMode: 'peruser' - jobSuffix: '_PerUser' \ No newline at end of file + jobSuffix: '_PerUser' diff --git a/PowerToys.sln b/PowerToys.sln index 4a94baa77f..00986aae29 100644 --- a/PowerToys.sln +++ b/PowerToys.sln @@ -461,6 +461,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Peek.Common", "src\modules\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Peek.FilePreviewer", "src\modules\peek\Peek.FilePreviewer\Peek.FilePreviewer.csproj", "{AA9F0AF8-7924-4D59-BAA1-E36F1304E0DC}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Peek.UITests", "src\modules\peek\Peek.UITests\Peek.UITests.csproj", "{4E0AE3A4-2EE0-44D7-A2D0-8769977254A5}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MarkdownPreviewHandlerCpp", "src\modules\previewpane\MarkdownPreviewHandlerCpp\MarkdownPreviewHandlerCpp.vcxproj", "{ED9A1AC6-AEB0-4569-A6E9-E1696182B545}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GcodePreviewHandlerCpp", "src\modules\previewpane\GcodePreviewHandlerCpp\GcodePreviewHandlerCpp.vcxproj", "{5A5DD09D-723A-44D3-8F2B-293584C3D731}" @@ -1854,6 +1856,14 @@ Global {AA9F0AF8-7924-4D59-BAA1-E36F1304E0DC}.Release|ARM64.Build.0 = Release|ARM64 {AA9F0AF8-7924-4D59-BAA1-E36F1304E0DC}.Release|x64.ActiveCfg = Release|x64 {AA9F0AF8-7924-4D59-BAA1-E36F1304E0DC}.Release|x64.Build.0 = Release|x64 + {4E0AE3A4-2EE0-44D7-A2D0-8769977254A5}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {4E0AE3A4-2EE0-44D7-A2D0-8769977254A5}.Debug|ARM64.Build.0 = Debug|ARM64 + {4E0AE3A4-2EE0-44D7-A2D0-8769977254A5}.Debug|x64.ActiveCfg = Debug|x64 + {4E0AE3A4-2EE0-44D7-A2D0-8769977254A5}.Debug|x64.Build.0 = Debug|x64 + {4E0AE3A4-2EE0-44D7-A2D0-8769977254A5}.Release|ARM64.ActiveCfg = Release|ARM64 + {4E0AE3A4-2EE0-44D7-A2D0-8769977254A5}.Release|ARM64.Build.0 = Release|ARM64 + {4E0AE3A4-2EE0-44D7-A2D0-8769977254A5}.Release|x64.ActiveCfg = Release|x64 + {4E0AE3A4-2EE0-44D7-A2D0-8769977254A5}.Release|x64.Build.0 = Release|x64 {ED9A1AC6-AEB0-4569-A6E9-E1696182B545}.Debug|ARM64.ActiveCfg = Debug|ARM64 {ED9A1AC6-AEB0-4569-A6E9-E1696182B545}.Debug|ARM64.Build.0 = Debug|ARM64 {ED9A1AC6-AEB0-4569-A6E9-E1696182B545}.Debug|x64.ActiveCfg = Debug|x64 @@ -2998,6 +3008,7 @@ Global {9D7A6DE0-7D27-424D-ABAE-41B2161F9A03} = {17B4FA70-001E-4D33-BBBB-0D142DBC2E20} {17A99C7C-0BFF-45BB-A9FD-63A0DDC105BB} = {17B4FA70-001E-4D33-BBBB-0D142DBC2E20} {AA9F0AF8-7924-4D59-BAA1-E36F1304E0DC} = {17B4FA70-001E-4D33-BBBB-0D142DBC2E20} + {4E0AE3A4-2EE0-44D7-A2D0-8769977254A5} = {17B4FA70-001E-4D33-BBBB-0D142DBC2E20} {ED9A1AC6-AEB0-4569-A6E9-E1696182B545} = {2F305555-C296-497E-AC20-5FA1B237996A} {5A5DD09D-723A-44D3-8F2B-293584C3D731} = {2F305555-C296-497E-AC20-5FA1B237996A} {B3E869C4-8210-4EBD-A621-FF4C4AFCBFA9} = {2F305555-C296-497E-AC20-5FA1B237996A} diff --git a/doc/devdocs/UITests.md b/doc/devdocs/UITests.md index 2a829d6e90..63bddb0591 100644 --- a/doc/devdocs/UITests.md +++ b/doc/devdocs/UITests.md @@ -22,23 +22,23 @@ The PowerToys UI test pipeline provides flexible options for building and testin ### Pipeline Options -- **useLatestOfficialBuild**: When checked, downloads the latest official PowerToys build and installs it for testing. This skips the full solution build and only builds UI test projects. +- **buildSource**: Select the build type for testing: + - `latestMainOfficialBuild`: Downloads and uses the latest official PowerToys build from main branch + - `buildNow`: Builds PowerToys from current source code and uses it for testing + - `specificBuildId`: Downloads a specific PowerToys build using the build ID specified in `specificBuildId` parameter -- **useCurrentBranchBuild**: When checked along with `useLatestOfficialBuild`, downloads the official build from the current branch instead of main. + **Default value**: `latestMainOfficialBuild` - **Default value**: `false` (downloads from main branch) +- **specificBuildId**: When `buildSource` is set to `specificBuildId`, specify the exact PowerToys build ID to download and test against. + + **Default value**: `"xxxx"` (placeholder, enter actual build ID when using specificBuildId option) **When to use this**: - - **Default scenario**: The pipeline tests against the latest signed PowerToys build from the `main` branch, regardless of which branch your test code changes are from - - **Custom branch testing**: Only specify `true` when: - - Your branch has produced its own signed PowerToys build via the official build pipeline - - You want to test against that specific branch's PowerToys build instead of main - - You are testing PowerToys functionality changes that are only available in your branch's build + - Testing against a specific known build for reproducibility + - Regression testing against a particular build version + - Validating fixes in a specific build before release - **Important notes**: - - The test pipeline itself runs from your specified branch, but by default tests against the main branch's PowerToys build - - Not all branches have signed builds available - only use this if you're certain your branch has a signed build - - If enabled but no build exists for your branch, the pipeline may fail or fall back to main + **Usage**: Enter the build ID number (e.g., `12345`) to download that specific build. Only used when `buildSource` is set to `specificBuildId`. - **uiTestModules**: Specify which UI test modules to build and run. This parameter controls both the `.csproj` projects to build and the `.dll` test assemblies to execute. Examples: - `['UITests-FancyZones']` - Only FancyZones UI tests @@ -50,19 +50,19 @@ The PowerToys UI test pipeline provides flexible options for building and testin ### Build Modes -1. **Official Build + Selective Testing** (`useLatestOfficialBuild = true`) - - Downloads and installs official PowerToys build - - Builds only specified UI test projects - - Runs specified UI tests against installed PowerToys - - Controlled by `uiTestModules` parameter +1. **Official Build Testing** (`buildSource = latestMainOfficialBuild` or `specificBuildId`) + - Downloads and installs official PowerToys build (latest from main or specific build ID) + - Builds only UI test projects (all or specific based on `uiTestModules`) + - Runs UI tests against installed PowerToys + - Tests both machine-level and per-user installation modes automatically -2. **Full Build + Testing** (`useLatestOfficialBuild = false`) - - Builds entire PowerToys solution +2. **Current Source Build Testing** (`buildSource = buildNow`) + - Builds entire PowerToys solution from current source code - Builds UI test projects (all or specific based on `uiTestModules`) - - Runs UI tests (all or specific based on `uiTestModules`) - - Uses freshly built PowerToys for testing + - Runs UI tests against freshly built PowerToys + - Uses artifacts from current pipeline build -> **Note**: Both modes support the `uiTestModules` parameter to control which specific UI test modules to build and run. +> **Note**: All modes support the `uiTestModules` parameter to control which specific UI test modules to build and run. Both machine-level and per-user installation modes are tested automatically when using official builds. ### Pipeline Access - Pipeline: https://microsoft.visualstudio.com/Dart/_build?definitionId=161438&_a=summary diff --git a/src/common/UITestAutomation/Element/TextBox.cs b/src/common/UITestAutomation/Element/TextBox.cs index 4ffb1a23e5..c2fc49e791 100644 --- a/src/common/UITestAutomation/Element/TextBox.cs +++ b/src/common/UITestAutomation/Element/TextBox.cs @@ -2,6 +2,8 @@ // 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.Threading.Tasks; + namespace Microsoft.PowerToys.UITest { /// @@ -25,8 +27,9 @@ namespace Microsoft.PowerToys.UITest /// /// The text to set. /// A value indicating whether to clear the text before setting it. Default value is true + /// Delay in milliseconds between each character. Default is 0 (no delay). /// The current TextBox instance. - public TextBox SetText(string value, bool clearText = true) + public TextBox SetText(string value, bool clearText = true, int charDelayMS = 0) { if (clearText) { @@ -39,10 +42,36 @@ namespace Microsoft.PowerToys.UITest Task.Delay(500).Wait(); } - PerformAction((actions, windowElement) => + // TODO: CmdPal bug – when inputting text, characters are swallowed too quickly. + // This should be fixed within CmdPal itself. + // Temporary workaround: introduce a delay between character inputs to avoid the issue + if (charDelayMS > 0 || EnvironmentConfig.IsInPipeline) { - windowElement.SendKeys(value); - }); + // Send text character by character with delay (if specified or in pipeline) + PerformAction((actions, windowElement) => + { + foreach (char c in value) + { + windowElement.SendKeys(c.ToString()); + if (charDelayMS > 0) + { + Task.Delay(charDelayMS).Wait(); + } + else if (EnvironmentConfig.IsInPipeline) + { + Task.Delay(50).Wait(); + } + } + }); + } + else + { + // No character delay - send all text at once (original behavior) + PerformAction((actions, windowElement) => + { + windowElement.SendKeys(value); + }); + } return this; } diff --git a/src/common/UITestAutomation/EnvironmentConfig.cs b/src/common/UITestAutomation/EnvironmentConfig.cs new file mode 100644 index 0000000000..ac0f1fa456 --- /dev/null +++ b/src/common/UITestAutomation/EnvironmentConfig.cs @@ -0,0 +1,45 @@ +// 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; + +namespace Microsoft.PowerToys.UITest +{ + /// + /// Centralized configuration for all environment variables used in UI tests. + /// + public static class EnvironmentConfig + { + private static readonly Lazy _isInPipeline = new(() => + !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("platform"))); + + private static readonly Lazy _useInstallerForTest = new(() => + { + string? envValue = Environment.GetEnvironmentVariable("useInstallerForTest") ?? + Environment.GetEnvironmentVariable("USEINSTALLERFORTEST"); + return !string.IsNullOrEmpty(envValue) && bool.TryParse(envValue, out bool result) && result; + }); + + private static readonly Lazy _platform = new(() => + Environment.GetEnvironmentVariable("platform")); + + /// + /// Gets a value indicating whether the tests are running in a CI/CD pipeline. + /// Determined by the presence of the "platform" environment variable. + /// + public static bool IsInPipeline => _isInPipeline.Value; + + /// + /// Gets a value indicating whether to use installer paths for testing. + /// Checks both "useInstallerForTest" and "USEINSTALLERFORTEST" environment variables. + /// + public static bool UseInstallerForTest => _useInstallerForTest.Value; + + /// + /// Gets the platform name from the environment variable. + /// Typically used in CI/CD pipelines to identify the build platform. + /// + public static string? Platform => _platform.Value; + } +} diff --git a/src/common/UITestAutomation/ModuleConfigData.cs b/src/common/UITestAutomation/ModuleConfigData.cs index 456e893659..d3d33b94d3 100644 --- a/src/common/UITestAutomation/ModuleConfigData.cs +++ b/src/common/UITestAutomation/ModuleConfigData.cs @@ -92,9 +92,7 @@ namespace Microsoft.PowerToys.UITest private ModuleConfigData() { // Check if we should use installer paths from environment variable - string? useInstallerForTestEnv = - Environment.GetEnvironmentVariable("useInstallerForTest") ?? Environment.GetEnvironmentVariable("USEINSTALLERFORTEST"); - UseInstallerForTest = !string.IsNullOrEmpty(useInstallerForTestEnv) && bool.TryParse(useInstallerForTestEnv, out bool result) && result; + UseInstallerForTest = EnvironmentConfig.UseInstallerForTest; // Module information including executable name, window name, and optional subdirectory ModuleInfo = new Dictionary diff --git a/src/common/UITestAutomation/SessionHelper.cs b/src/common/UITestAutomation/SessionHelper.cs index 0d7b6e6532..0ca3eb3ddd 100644 --- a/src/common/UITestAutomation/SessionHelper.cs +++ b/src/common/UITestAutomation/SessionHelper.cs @@ -5,6 +5,7 @@ using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; @@ -37,6 +38,9 @@ namespace Microsoft.PowerToys.UITest private PowerToysModule scope; private string[]? commandLineArgs; + /// + /// Gets a value indicating whether to use installer paths for testing. + /// private bool UseInstallerForTest { get; } [UnconditionalSuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", Justification = "")] @@ -45,9 +49,7 @@ namespace Microsoft.PowerToys.UITest this.scope = scope; this.commandLineArgs = commandLineArgs; this.sessionPath = ModuleConfigData.Instance.GetModulePath(scope); - string? useInstallerForTestEnv = - Environment.GetEnvironmentVariable("useInstallerForTest") ?? Environment.GetEnvironmentVariable("USEINSTALLERFORTEST"); - UseInstallerForTest = !string.IsNullOrEmpty(useInstallerForTestEnv) && bool.TryParse(useInstallerForTestEnv, out bool result) && result; + UseInstallerForTest = EnvironmentConfig.UseInstallerForTest; this.locationPath = UseInstallerForTest ? string.Empty : Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); CheckWinAppDriverAndRoot(); @@ -136,6 +138,10 @@ namespace Microsoft.PowerToys.UITest { TryLaunchPowerToysSettings(opts); } + else if (scope == PowerToysModule.CommandPalette && UseInstallerForTest) + { + TryLaunchCommandPalette(opts); + } else { opts.AddAdditionalCapability("app", appPath); @@ -163,48 +169,77 @@ namespace Microsoft.PowerToys.UITest private void TryLaunchPowerToysSettings(AppiumOptions opts) { - CheckWinAppDriverAndRoot(); - - var runnerProcessInfo = new ProcessStartInfo + try { - FileName = locationPath + runnerPath, - Verb = "runas", - Arguments = "--open-settings", - }; - - ExitExe(runnerProcessInfo.FileName); - runner = Process.Start(runnerProcessInfo); - Thread.Sleep(5000); - - // Exit CmdPal UI before launching new process if use installer for test - ExitExeByName("Microsoft.CmdPal.UI"); - - if (root != null) - { - const int maxRetries = 5; - const int delayMs = 5000; - var windowName = "PowerToys Settings"; - - for (int attempt = 1; attempt <= maxRetries; attempt++) + var runnerProcessInfo = new ProcessStartInfo { - var settingsWindow = ApiHelper.FindDesktopWindowHandler( - [windowName, AdministratorPrefix + windowName]); + FileName = locationPath + runnerPath, + Verb = "runas", + Arguments = "--open-settings", + }; - if (settingsWindow.Count > 0) - { - var hexHwnd = settingsWindow[0].HWnd.ToString("x"); - opts.AddAdditionalCapability("appTopLevelWindow", hexHwnd); - return; - } + ExitExe(runnerProcessInfo.FileName); + runner = Process.Start(runnerProcessInfo); - if (attempt < maxRetries) - { - Thread.Sleep(delayMs); - } - else - { - throw new TimeoutException("Failed to find PowerToys Settings window after multiple attempts."); - } + WaitForWindowAndSetCapability(opts, "PowerToys Settings", 5000, 5); + + // Exit CmdPal UI before launching new process if use installer for test + ExitExeByName("Microsoft.CmdPal.UI"); + } + catch (Exception ex) + { + throw new InvalidOperationException($"Failed to launch PowerToys Settings: {ex.Message}", ex); + } + } + + private void TryLaunchCommandPalette(AppiumOptions opts) + { + try + { + // Exit any existing CmdPal UI process + ExitExeByName("Microsoft.CmdPal.UI"); + + var processStartInfo = new ProcessStartInfo + { + FileName = "cmd.exe", + Arguments = "/c start shell:appsFolder\\Microsoft.CommandPalette_8wekyb3d8bbwe!App", + UseShellExecute = false, + CreateNoWindow = true, + WindowStyle = ProcessWindowStyle.Hidden, + }; + + var process = Process.Start(processStartInfo); + process?.WaitForExit(); + + WaitForWindowAndSetCapability(opts, "Command Palette", 5000, 10); + } + catch (Exception ex) + { + throw new InvalidOperationException($"Failed to launch Command Palette: {ex.Message}", ex); + } + } + + private void WaitForWindowAndSetCapability(AppiumOptions opts, string windowName, int delayMs, int maxRetries) + { + for (int attempt = 1; attempt <= maxRetries; attempt++) + { + var window = ApiHelper.FindDesktopWindowHandler( + [windowName, AdministratorPrefix + windowName]); + + if (window.Count > 0) + { + var hexHwnd = window[0].HWnd.ToString("x"); + opts.AddAdditionalCapability("appTopLevelWindow", hexHwnd); + return; + } + + if (attempt < maxRetries) + { + Thread.Sleep(delayMs); + } + else + { + throw new TimeoutException($"Failed to find {windowName} window after multiple attempts."); } } } diff --git a/src/common/UITestAutomation/UITestBase.cs b/src/common/UITestAutomation/UITestBase.cs index c92f8527e8..f44c62ab62 100644 --- a/src/common/UITestAutomation/UITestBase.cs +++ b/src/common/UITestAutomation/UITestBase.cs @@ -5,6 +5,7 @@ using System.Collections.ObjectModel; using System.Diagnostics; using System.Runtime.InteropServices; +using System.Text.RegularExpressions; using Microsoft.VisualStudio.TestTools.UnitTesting; using OpenQA.Selenium; @@ -20,6 +21,9 @@ namespace Microsoft.PowerToys.UITest public required Session Session { get; set; } + /// + /// Gets a value indicating whether the tests are running in a CI/CD pipeline. + /// public bool IsInPipeline { get; } public string? ScreenshotDirectory { get; set; } @@ -34,8 +38,8 @@ namespace Microsoft.PowerToys.UITest public UITestBase(PowerToysModule scope = PowerToysModule.PowerToysSettings, WindowSize size = WindowSize.UnSpecified, string[]? commandLineArgs = null) { - this.IsInPipeline = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("platform")); - Console.WriteLine($"Running tests on platform: {Environment.GetEnvironmentVariable("platform")}"); + this.IsInPipeline = EnvironmentConfig.IsInPipeline; + Console.WriteLine($"Running tests on platform: {EnvironmentConfig.Platform}"); if (IsInPipeline) { NativeMethods.ChangeDisplayResolution(1920, 1080); @@ -56,6 +60,7 @@ namespace Microsoft.PowerToys.UITest [TestInitialize] public void TestInit() { + KeyboardHelper.SendKeys(Key.Win, Key.M); CloseOtherApplications(); if (IsInPipeline) { @@ -247,6 +252,174 @@ namespace Microsoft.PowerToys.UITest return this.Session.Has(name, timeoutMS, global); } + /// + /// Finds an element using partial name matching (contains). + /// Useful for finding windows with variable titles like "filename.txt - Notepad" or "filename - Notepad". + /// + /// The class of the element, should be Element or its derived class. + /// Part of the name to search for. + /// The timeout in milliseconds (default is 5000). + /// The found element. + protected T FindByPartialName(string partialName, int timeoutMS = 5000, bool global = false) + where T : Element, new() + { + return Session.Find(By.XPath($"//*[contains(@Name, '{partialName}')]"), timeoutMS, global); + } + + /// + /// Finds an element using partial name matching (contains). + /// + /// Part of the name to search for. + /// The timeout in milliseconds (default is 5000). + /// The found element. + protected Element FindByPartialName(string partialName, int timeoutMS = 5000, bool global = false) + { + return FindByPartialName(partialName, timeoutMS, global); + } + + /// + /// Base method for finding elements by selector and filtering by name pattern. + /// + /// The class of the element, should be Element or its derived class. + /// The selector to find initial candidates. + /// Pattern to match against the Name attribute. Supports regex patterns. + /// The timeout in milliseconds (default is 5000). + /// Custom error message when no element is found. + /// The found element. + private T FindByNamePattern(By selector, string namePattern, int timeoutMS = 5000, bool global = false, string? errorMessage = null) + where T : Element, new() + { + var elements = Session.FindAll(selector, timeoutMS, global); + var regex = new Regex(namePattern, RegexOptions.IgnoreCase); + + foreach (var element in elements) + { + var name = element.GetAttribute("Name"); + if (!string.IsNullOrEmpty(name) && regex.IsMatch(name)) + { + return element; + } + } + + throw new NoSuchElementException(errorMessage ?? $"No element found matching pattern: {namePattern}"); + } + + /// + /// Finds an element using regular expression pattern matching. + /// + /// The class of the element, should be Element or its derived class. + /// Regular expression pattern to match against the Name attribute. + /// The timeout in milliseconds (default is 5000). + /// The found element. + protected T FindByPattern(string pattern, int timeoutMS = 5000, bool global = false) + where T : Element, new() + { + return FindByNamePattern(By.XPath("//*[@Name]"), pattern, timeoutMS, global, $"No element found matching pattern: {pattern}"); + } + + /// + /// Finds an element using regular expression pattern matching. + /// + /// Regular expression pattern to match against the Name attribute. + /// The timeout in milliseconds (default is 5000). + /// The found element. + protected Element FindByPattern(string pattern, int timeoutMS = 5000, bool global = false) + { + return FindByPattern(pattern, timeoutMS, global); + } + + /// + /// Finds an element by ClassName only. + /// Returns the first element found with the specified ClassName. + /// + /// The class of the element, should be Element or its derived class. + /// The ClassName to search for (e.g., "Notepad", "CabinetWClass"). + /// The timeout in milliseconds (default is 5000). + /// The found element. + protected T FindByClassName(string className, int timeoutMS = 5000, bool global = false) + where T : Element, new() + { + return Session.Find(By.ClassName(className), timeoutMS, global); + } + + /// + /// Finds an element by ClassName only. + /// Returns the first element found with the specified ClassName. + /// + /// The ClassName to search for (e.g., "Notepad", "CabinetWClass"). + /// The timeout in milliseconds (default is 5000). + /// The found element. + protected Element FindByClassName(string className, int timeoutMS = 5000, bool global = false) + { + return FindByClassName(className, timeoutMS, global); + } + + /// + /// Finds an element by ClassName and matches its Name attribute using regex pattern matching. + /// + /// The class of the element, should be Element or its derived class. + /// The ClassName to search for (e.g., "Notepad", "CabinetWClass"). + /// Pattern to match against the Name attribute. Supports regex patterns. + /// The timeout in milliseconds (default is 5000). + /// The found element. + protected T FindByClassNameAndNamePattern(string className, string namePattern, int timeoutMS = 5000, bool global = false) + where T : Element, new() + { + return FindByNamePattern(By.ClassName(className), namePattern, timeoutMS, global, $"No element with ClassName '{className}' found matching name pattern: {namePattern}"); + } + + /// + /// Finds an element by ClassName and matches its Name attribute using regex pattern matching. + /// + /// The ClassName to search for (e.g., "Notepad", "CabinetWClass"). + /// Pattern to match against the Name attribute. Supports regex patterns. + /// The timeout in milliseconds (default is 5000). + /// The found element. + protected Element FindByClassNameAndNamePattern(string className, string namePattern, int timeoutMS = 5000, bool global = false) + { + return FindByClassNameAndNamePattern(className, namePattern, timeoutMS, global); + } + + /// + /// Finds a Notepad window regardless of whether the file extension is shown in the title. + /// Handles both "filename.txt - Notepad" and "filename - Notepad" formats. + /// Uses ClassName to efficiently find Notepad windows first, then matches the filename. + /// + /// The base filename without extension (e.g., "test" for "test.txt"). + /// The timeout in milliseconds (default is 5000). + /// The found Notepad window element. + protected Element FindNotepadWindow(string baseFileName, int timeoutMS = 5000, bool global = false) + { + string pattern = $@"^{Regex.Escape(baseFileName)}(\.\w+)?(\s*-\s*|\s+)Notepad$"; + return FindByClassNameAndNamePattern("Notepad", pattern, timeoutMS, global); + } + + /// + /// Finds an Explorer window regardless of the folder or file name display format. + /// Handles various Explorer window title formats like "FolderName", "FileName", "FolderName - File Explorer", etc. + /// Uses ClassName to efficiently find Explorer windows first, then matches the folder or file name. + /// + /// The folder or file name to search for (e.g., "Documents", "Desktop", "test.txt"). + /// The timeout in milliseconds (default is 5000). + /// The found Explorer window element. + protected Element FindExplorerWindow(string folderName, int timeoutMS = 5000, bool global = false) + { + string pattern = $@"^{Regex.Escape(folderName)}(\s*-\s*(File\s+Explorer|Windows\s+Explorer))?$"; + return FindByClassNameAndNamePattern("CabinetWClass", pattern, timeoutMS, global); + } + + /// + /// Finds an Explorer window by partial folder path. + /// Useful when the full path might be displayed in the title. + /// + /// Part of the folder path to search for. + /// The timeout in milliseconds (default is 5000). + /// The found Explorer window element. + protected Element FindExplorerByPartialPath(string partialPath, int timeoutMS = 5000, bool global = false) + { + return FindByPartialName(partialPath, timeoutMS, global); + } + /// /// Finds all elements by selector. /// Shortcut for this.Session.FindAll(by, timeoutMS) diff --git a/src/common/UITestAutomation/VisualAssert.cs b/src/common/UITestAutomation/VisualAssert.cs index 844db5b027..f08ba780d9 100644 --- a/src/common/UITestAutomation/VisualAssert.cs +++ b/src/common/UITestAutomation/VisualAssert.cs @@ -27,10 +27,8 @@ namespace Microsoft.PowerToys.UITest [RequiresUnreferencedCode("This method uses reflection which may not be compatible with trimming.")] public static void AreEqual(TestContext? testContext, Element element, string scenarioSubname = "") { - var pipelinePlatform = Environment.GetEnvironmentVariable("platform"); - // Perform visual validation only in the pipeline - if (string.IsNullOrEmpty(pipelinePlatform)) + if (!EnvironmentConfig.IsInPipeline) { Console.WriteLine("Skip visual validation in the local run."); return; @@ -55,11 +53,11 @@ namespace Microsoft.PowerToys.UITest if (string.IsNullOrWhiteSpace(scenarioSubname)) { - scenarioSubname = string.Join("_", callerClassName, callerName, pipelinePlatform); + scenarioSubname = string.Join("_", callerClassName, callerName, EnvironmentConfig.Platform); } else { - scenarioSubname = string.Join("_", callerClassName, callerName, scenarioSubname.Trim(), pipelinePlatform); + scenarioSubname = string.Join("_", callerClassName, callerName, scenarioSubname.Trim(), EnvironmentConfig.Platform); } var baselineImageResourceName = callerMethod!.DeclaringType!.Assembly.GetManifestResourceNames().Where(name => name.Contains(scenarioSubname)).FirstOrDefault(); diff --git a/src/modules/cmdpal/Tests/Microsoft.CmdPal.UITests/BasicTests.cs b/src/modules/cmdpal/Tests/Microsoft.CmdPal.UITests/BasicTests.cs index 872f1270f1..78cd82062a 100644 --- a/src/modules/cmdpal/Tests/Microsoft.CmdPal.UITests/BasicTests.cs +++ b/src/modules/cmdpal/Tests/Microsoft.CmdPal.UITests/BasicTests.cs @@ -67,9 +67,8 @@ public class BasicTests : CommandPaletteTestBase Assert.AreEqual(searchFileItem.Name, "Open Windows Terminal Profiles"); searchFileItem.DoubleClick(); - SetSearchBox("PowerShell"); - - Assert.IsNotNull(this.Find("PowerShell")); + // SetSearchBox("PowerShell"); + // Assert.IsNotNull(this.Find("PowerShell")); } [TestMethod] @@ -95,9 +94,9 @@ public class BasicTests : CommandPaletteTestBase Assert.AreEqual(searchFileItem.Name, "Registry"); searchFileItem.DoubleClick(); - SetSearchBox("HKEY_LOCAL_MACHINE"); - - Assert.IsNotNull(this.Find("HKEY_LOCAL_MACHINE\\SECURITY")); + // Type the string will cause strange behavior.so comment it out for now. + // SetSearchBox(@"HKEY_LOCAL_MACHINE"); + // Assert.IsNotNull(this.Find(@"HKEY_LOCAL_MACHINE\SECURITY")); } [TestMethod] diff --git a/src/modules/cmdpal/Tests/Microsoft.CmdPal.UITests/CommandPaletteTestBase.cs b/src/modules/cmdpal/Tests/Microsoft.CmdPal.UITests/CommandPaletteTestBase.cs index da259e3b18..ab7dac1a3a 100644 --- a/src/modules/cmdpal/Tests/Microsoft.CmdPal.UITests/CommandPaletteTestBase.cs +++ b/src/modules/cmdpal/Tests/Microsoft.CmdPal.UITests/CommandPaletteTestBase.cs @@ -45,4 +45,27 @@ public class CommandPaletteTestBase : UITestBase Assert.IsNotNull(contextMenuButton, "Context menu button not found."); contextMenuButton.Click(); } + + protected void FindDefaultAppDialogAndClickButton() + { + try + { + // win11 + var chooseDialog = FindByClassName("NamedContainerAutomationPeer", global: true); + + chooseDialog.Find - + + + + + + + + + + + + + + \ 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 08/99] 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 09/99] 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 10/99] 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 11/99] 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 12/99] 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 13/99] 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 14/99] [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 15/99] 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 16/99] 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 17/99] 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 @@ /// Use CultureInfo.CurrentCulture if something is user facing - public static CalculateResult Interpret(SettingsManager settings, string input, CultureInfo cultureInfo, out string error) + public static CalculateResult Interpret(ISettingsInterface settings, string input, CultureInfo cultureInfo, out string error) { error = default; diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/ISettingsInterface.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/ISettingsInterface.cs new file mode 100644 index 0000000000..f4b7a50644 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/ISettingsInterface.cs @@ -0,0 +1,18 @@ +// 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.CmdPal.Ext.Calc.Helper; + +namespace Microsoft.CmdPal.Ext.Calc.Helper; + +public interface ISettingsInterface +{ + public CalculateEngine.TrigMode TrigUnit { get; } + + public bool InputUseEnglishFormat { get; } + + public bool OutputUseEnglishFormat { get; } + + public bool CloseOnEnter { get; } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/QueryHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/QueryHelper.cs index b6c41f3831..99f782d714 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/QueryHelper.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/QueryHelper.cs @@ -12,7 +12,7 @@ namespace Microsoft.CmdPal.Ext.Calc.Helper; public static partial class QueryHelper { - public static ListItem Query(string query, SettingsManager settings, bool isFallbackSearch, TypedEventHandler handleSave = null) + public static ListItem Query(string query, ISettingsInterface settings, bool isFallbackSearch, TypedEventHandler handleSave = null) { ArgumentNullException.ThrowIfNull(query); if (!isFallbackSearch) diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/ResultHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/ResultHelper.cs index c729086543..f53fadaa52 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/ResultHelper.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/ResultHelper.cs @@ -13,7 +13,7 @@ namespace Microsoft.CmdPal.Ext.Calc.Helper; public static class ResultHelper { - public static ListItem CreateResult(decimal? roundedResult, CultureInfo inputCulture, CultureInfo outputCulture, string query, SettingsManager settings, TypedEventHandler handleSave) + public static ListItem CreateResult(decimal? roundedResult, CultureInfo inputCulture, CultureInfo outputCulture, string query, ISettingsInterface settings, TypedEventHandler handleSave) { // Return null when the expression is not a valid calculator query. if (roundedResult == null) diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/SettingsManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/SettingsManager.cs index cb5104011e..cea59e170f 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/SettingsManager.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/SettingsManager.cs @@ -8,7 +8,7 @@ using Microsoft.CommandPalette.Extensions.Toolkit; namespace Microsoft.CmdPal.Ext.Calc.Helper; -public class SettingsManager : JsonSettingsManager +public class SettingsManager : JsonSettingsManager, ISettingsInterface { private static readonly string _namespace = "calculator"; diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/CalculatorListPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/CalculatorListPage.cs index 4b0cf29d64..d4b7f6d135 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/CalculatorListPage.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/CalculatorListPage.cs @@ -23,7 +23,7 @@ namespace Microsoft.CmdPal.Ext.Calc.Pages; public sealed partial class CalculatorListPage : DynamicListPage { private readonly Lock _resultsLock = new(); - private readonly SettingsManager _settingsManager; + private readonly ISettingsInterface _settingsManager; private readonly List _items = []; private readonly List history = []; private readonly ListItem _emptyItem; @@ -32,7 +32,7 @@ public sealed partial class CalculatorListPage : DynamicListPage // We need to avoid the double calculation. This may cause some wierd behaviors. private string skipQuerySearchText = string.Empty; - public CalculatorListPage(SettingsManager settings) + public CalculatorListPage(ISettingsInterface settings) { _settingsManager = settings; Icon = Icons.CalculatorIcon; diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/FallbackCalculatorItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/FallbackCalculatorItem.cs index 10d305bb7c..5dc85ae51f 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/FallbackCalculatorItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/FallbackCalculatorItem.cs @@ -11,9 +11,9 @@ namespace Microsoft.CmdPal.Ext.Calc.Pages; public sealed partial class FallbackCalculatorItem : FallbackCommandItem { private readonly CopyTextCommand _copyCommand = new(string.Empty); - private readonly SettingsManager _settings; + private readonly ISettingsInterface _settings; - public FallbackCalculatorItem(SettingsManager settings) + public FallbackCalculatorItem(ISettingsInterface settings) : base(new NoOpCommand(), Resources.calculator_title) { Command = _copyCommand; diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/ISettingsInterface.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/ISettingsInterface.cs new file mode 100644 index 0000000000..bec1fb3271 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/ISettingsInterface.cs @@ -0,0 +1,17 @@ +// 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.Text; +using System.Threading.Tasks; + +namespace Microsoft.CmdPal.Ext.Registry.Helpers; + +public interface ISettingsInterface +{ + // Add registry-specific settings methods here if needed + // For now, this can be empty if there are no settings for Registry +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/SettingsManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/SettingsManager.cs new file mode 100644 index 0000000000..aaf5d2cce0 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/SettingsManager.cs @@ -0,0 +1,37 @@ +// 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.IO; +using Microsoft.CommandPalette.Extensions.Toolkit; + +namespace Microsoft.CmdPal.Ext.Registry.Helpers; + +public class SettingsManager : JsonSettingsManager, ISettingsInterface +{ + private static readonly string _namespace = "registry"; + + private static string Namespaced(string propertyName) => $"{_namespace}.{propertyName}"; + + internal static string SettingsJsonPath() + { + var directory = Utilities.BaseSettingsPath("Microsoft.CmdPal"); + Directory.CreateDirectory(directory); + + // now, the state is just next to the exe + return Path.Combine(directory, "settings.json"); + } + + public SettingsManager() + { + FilePath = SettingsJsonPath(); + + // Add settings here when needed + // Settings.Add(setting); + + // Load settings from file upon initialization + LoadSettings(); + + Settings.SettingsChanged += (s, a) => this.SaveSettings(); + } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Pages/RegistryListPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Pages/RegistryListPage.cs index fbc80d5d1e..b37f0bc313 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Pages/RegistryListPage.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Pages/RegistryListPage.cs @@ -18,12 +18,14 @@ internal sealed partial class RegistryListPage : DynamicListPage public static IconInfo RegistryIcon { get; } = new("\uE74C"); // OEM private readonly CommandItem _emptyMessage; + private readonly ISettingsInterface _settingsManager; - public RegistryListPage() + public RegistryListPage(ISettingsInterface settingsManager) { Icon = Icons.RegistryIcon; Name = Title = Resources.Registry_Page_Title; Id = "com.microsoft.cmdpal.registry"; + _settingsManager = settingsManager; _emptyMessage = new CommandItem() { Icon = Icons.RegistryIcon, diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/RegistryCommandsProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/RegistryCommandsProvider.cs index 3f4218c81b..22eca4cc3f 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/RegistryCommandsProvider.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/RegistryCommandsProvider.cs @@ -2,6 +2,7 @@ // 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.CmdPal.Ext.Registry.Helpers; using Microsoft.CmdPal.Ext.Registry.Properties; using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions.Toolkit; @@ -10,6 +11,8 @@ namespace Microsoft.CmdPal.Ext.Registry; public partial class RegistryCommandsProvider : CommandProvider { + private static readonly ISettingsInterface _settingsManager = new SettingsManager(); + public RegistryCommandsProvider() { Id = "Windows.Registry"; @@ -20,7 +23,7 @@ public partial class RegistryCommandsProvider : CommandProvider public override ICommandItem[] TopLevelCommands() { return [ - new CommandItem(new RegistryListPage()) + new CommandItem(new RegistryListPage(_settingsManager)) { Title = "Registry", Subtitle = "Navigate the Windows registry", diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/FallbackTimeDateItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/FallbackTimeDateItem.cs index 3b797e4cfb..cc757bcd88 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/FallbackTimeDateItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/FallbackTimeDateItem.cs @@ -16,10 +16,10 @@ namespace Microsoft.CmdPal.Ext.TimeDate; internal sealed partial class FallbackTimeDateItem : FallbackCommandItem { private readonly HashSet _validOptions; - private SettingsManager _settingsManager; + private ISettingsInterface _settingsManager; private DateTime? _timestamp; - public FallbackTimeDateItem(SettingsManager settings, DateTime? timestamp = null) + public FallbackTimeDateItem(ISettingsInterface settings, DateTime? timestamp = null) : base(new NoOpCommand(), Resources.Microsoft_plugin_timedate_fallback_display_title) { Title = string.Empty; diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/AvailableResultsList.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/AvailableResultsList.cs index 38366345c4..0966c0d3df 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/AvailableResultsList.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/AvailableResultsList.cs @@ -22,7 +22,7 @@ internal static class AvailableResultsList /// Required for UnitTest: Use custom first week of the year instead of the plugin setting. /// Required for UnitTest: Use custom first day of the week instead the plugin setting. /// List of results - internal static List GetList(bool isKeywordSearch, SettingsManager settings, bool? timeLongFormat = null, bool? dateLongFormat = null, DateTime? timestamp = null, CalendarWeekRule? firstWeekOfYear = null, DayOfWeek? firstDayOfWeek = null) + internal static List GetList(bool isKeywordSearch, ISettingsInterface settings, bool? timeLongFormat = null, bool? dateLongFormat = null, DateTime? timestamp = null, CalendarWeekRule? firstWeekOfYear = null, DayOfWeek? firstDayOfWeek = null) { var results = new List(); var calendar = CultureInfo.CurrentCulture.Calendar; diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/ISettingsInterface.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/ISettingsInterface.cs new file mode 100644 index 0000000000..12e53ccf11 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/ISettingsInterface.cs @@ -0,0 +1,26 @@ +// 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.Text; +using System.Threading.Tasks; + +namespace Microsoft.CmdPal.Ext.TimeDate.Helpers; + +public interface ISettingsInterface +{ + public int FirstWeekOfYear { get; } + + public int FirstDayOfWeek { get; } + + public bool EnableFallbackItems { get; } + + public bool TimeWithSecond { get; } + + public bool DateWithWeekday { get; } + + public List CustomFormats { get; } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/SettingsManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/SettingsManager.cs index 7b351fe3b8..727c5258aa 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/SettingsManager.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/SettingsManager.cs @@ -11,7 +11,7 @@ using Microsoft.CommandPalette.Extensions.Toolkit; namespace Microsoft.CmdPal.Ext.TimeDate.Helpers; -public class SettingsManager : JsonSettingsManager +public class SettingsManager : JsonSettingsManager, ISettingsInterface { // Line break character used in WinUI3 TextBox and TextBlock. private const char TEXTBOXNEWLINE = '\r'; diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/TimeDateCalculator.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/TimeDateCalculator.cs index 38f417ad5b..6128ef56ad 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/TimeDateCalculator.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/TimeDateCalculator.cs @@ -27,7 +27,7 @@ public sealed partial class TimeDateCalculator /// /// Search query object /// List of Wox s. - public static List ExecuteSearch(SettingsManager settings, string query) + public static List ExecuteSearch(ISettingsInterface settings, string query) { var isEmptySearchInput = string.IsNullOrWhiteSpace(query); List availableFormats = new List(); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Pages/TimeDateExtensionPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Pages/TimeDateExtensionPage.cs index 4eb95034b7..36eb39461f 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Pages/TimeDateExtensionPage.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Pages/TimeDateExtensionPage.cs @@ -19,9 +19,9 @@ internal sealed partial class TimeDateExtensionPage : DynamicListPage private IList _results = new List(); private bool _dataLoaded; - private SettingsManager _settingsManager; + private ISettingsInterface _settingsManager; - public TimeDateExtensionPage(SettingsManager settingsManager) + public TimeDateExtensionPage(ISettingsInterface settingsManager) { Icon = Icons.TimeDateExtIcon; Title = Resources.Microsoft_plugin_timedate_main_page_title; diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/TimeDateCommandsProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/TimeDateCommandsProvider.cs index d29356fa77..26bd4d8453 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/TimeDateCommandsProvider.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/TimeDateCommandsProvider.cs @@ -15,7 +15,7 @@ namespace Microsoft.CmdPal.Ext.TimeDate; public partial class TimeDateCommandsProvider : CommandProvider { private readonly CommandItem _command; - private static readonly SettingsManager _settingsManager = new(); + private static readonly SettingsManager _settingsManager = new SettingsManager(); private static readonly CompositeFormat MicrosoftPluginTimedatePluginDescription = System.Text.CompositeFormat.Parse(Resources.Microsoft_plugin_timedate_plugin_description); private static readonly TimeDateExtensionPage _timeDateExtensionPage = new(_settingsManager); private readonly FallbackTimeDateItem _fallbackTimeDateItem = new(_settingsManager); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/ISettingsInterface.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/ISettingsInterface.cs new file mode 100644 index 0000000000..e77acb56cf --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/ISettingsInterface.cs @@ -0,0 +1,26 @@ +// 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. + +namespace Microsoft.CmdPal.Ext.WindowWalker.Helpers; + +public interface ISettingsInterface +{ + public bool ResultsFromVisibleDesktopOnly { get; } + + public bool SubtitleShowPid { get; } + + public bool SubtitleShowDesktopName { get; } + + public bool ConfirmKillProcess { get; } + + public bool KillProcessTree { get; } + + public bool OpenAfterKillAndClose { get; } + + public bool HideKillProcessOnElevatedProcesses { get; } + + public bool HideExplorerSettingInfo { get; } + + public bool InMruOrder { get; } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/SettingsManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/SettingsManager.cs index 6f541d28df..b2a248beca 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/SettingsManager.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/SettingsManager.cs @@ -8,7 +8,7 @@ using Microsoft.CommandPalette.Extensions.Toolkit; namespace Microsoft.CmdPal.Ext.WindowWalker.Helpers; -public class SettingsManager : JsonSettingsManager +public class SettingsManager : JsonSettingsManager, ISettingsInterface { private static readonly string _namespace = "windowWalker"; From c690cb1bb814ddc618504548e09d03e2f1ee881f Mon Sep 17 00:00:00 2001 From: Gordon Lam <73506701+yeelam-gordon@users.noreply.github.com> Date: Wed, 13 Aug 2025 08:19:06 -0700 Subject: [PATCH 22/99] Initial draft for 0.93 release note (#41036) ## Summary of the Pull Request ## AI Summary This pull request updates the `README.md` to document the 0.93 (August 2025) release of Microsoft PowerToys. It introduces a new, modern settings dashboard, details major improvements and new features across multiple modules, and updates installation links and documentation. The release focuses on enhanced user experience, accessibility, performance, stability, and test coverage. Most important changes: **Release and Installation Updates** - Updated all installer links and release references from version 0.92.1 to 0.93.0, and milestone tracking for the next release to 0.94. - Updated the release highlights and version number to reflect the 0.93 (August 2025) release, with a summary of new features and improvements. **Settings and User Experience** - Introduced a completely redesigned, card-based settings dashboard with clearer descriptions, faster navigation, and improved release notes formatting for a better user experience. - Rewrote setting descriptions for clarity and consistency, added deep link support to specific settings pages, and fixed various UI/UX issues in the settings module. **Command Palette and Extensions** - Resolved over 99 issues in Command Palette, including accessibility improvements, context menu enhancements, new navigation shortcuts, AOT compilation mode (reducing install size and memory usage), and re-enabled Clipboard History. - Added new settings and features to Command Palette extensions, such as command history in Run, improved Apps extension handling, and new context menu options. **Module Improvements and New Features** - Mouse Utilities: Added a new spotlight highlighting mode for presentations. - Peek: Added instant previews and embedded thumbnail support for Binary G-code (.bgcode) 3D printing files. - Quick Accent: Added Vietnamese language support. **Development, Testing, and Documentation** - Upgraded .NET libraries and spell check system, improved CI pipelines, reduced test timeouts, and added over 600 new unit tests (mainly for Command Palette), doubling UI automation coverage. - Added detailed developer documentation, fixed broken SDK links, and documented new community plugins. Other minor changes: - Standardized naming, improved spelling, and cleaned up configuration files for smoother development. - Minor capitalization fix for "Mouse Utilities" in the utilities table. --- README.md | 202 ++++++++++++++++++++++++------------------------------ 1 file changed, 91 insertions(+), 111 deletions(-) diff --git a/README.md b/README.md index 493878bbde..27c98d07ff 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Microsoft PowerToys is a set of utilities for power users to tune and streamline | [Color Picker](https://aka.ms/PowerToysOverview_ColorPicker) | [Command Not Found](https://aka.ms/PowerToysOverview_CmdNotFound) | [Command Palette](https://aka.ms/PowerToysOverview_CmdPal) | | [Crop And Lock](https://aka.ms/PowerToysOverview_CropAndLock) | [Environment Variables](https://aka.ms/PowerToysOverview_EnvironmentVariables) | [FancyZones](https://aka.ms/PowerToysOverview_FancyZones) | | [File Explorer Add-ons](https://aka.ms/PowerToysOverview_FileExplorerAddOns) | [File Locksmith](https://aka.ms/PowerToysOverview_FileLocksmith) | [Hosts File Editor](https://aka.ms/PowerToysOverview_HostsFileEditor) | -| [Image Resizer](https://aka.ms/PowerToysOverview_ImageResizer) | [Keyboard Manager](https://aka.ms/PowerToysOverview_KeyboardManager) | [Mouse utilities](https://aka.ms/PowerToysOverview_MouseUtilities) | +| [Image Resizer](https://aka.ms/PowerToysOverview_ImageResizer) | [Keyboard Manager](https://aka.ms/PowerToysOverview_KeyboardManager) | [Mouse Utilities](https://aka.ms/PowerToysOverview_MouseUtilities) | | [Mouse Without Borders](https://aka.ms/PowerToysOverview_MouseWithoutBorders) | [New+](https://aka.ms/PowerToysOverview_NewPlus) | [Paste as Plain Text](https://aka.ms/PowerToysOverview_PastePlain) | | [Peek](https://aka.ms/PowerToysOverview_Peek) | [PowerRename](https://aka.ms/PowerToysOverview_PowerRename) | [PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) | | [Quick Accent](https://aka.ms/PowerToysOverview_QuickAccent) | [Registry Preview](https://aka.ms/PowerToysOverview_RegistryPreview) | [Screen Ruler](https://aka.ms/PowerToysOverview_ScreenRuler) | @@ -35,19 +35,19 @@ Microsoft PowerToys is a set of utilities for power users to tune and streamline Go to the [Microsoft PowerToys GitHub releases page][github-release-link] and click on `Assets` at the bottom to show the files available in the release. Please use the appropriate PowerToys installer that matches your machine's architecture and install scope. For most, it is `x64` and per-user. -[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.93%22 -[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.92%22 -[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.92.1/PowerToysUserSetup-0.92.1-x64.exe -[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.92.1/PowerToysUserSetup-0.92.1-arm64.exe -[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.92.1/PowerToysSetup-0.92.1-x64.exe -[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.92.1/PowerToysSetup-0.92.1-arm64.exe +[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.94%22 +[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.93%22 +[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.93.0/PowerToysUserSetup-0.93.0-x64.exe +[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.93.0/PowerToysUserSetup-0.93.0-arm64.exe +[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.93.0/PowerToysSetup-0.93.0-x64.exe +[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.93.0/PowerToysSetup-0.93.0-arm64.exe | Description | Filename | |----------------|----------| -| Per user - x64 | [PowerToysUserSetup-0.92.1-x64.exe][ptUserX64] | -| Per user - ARM64 | [PowerToysUserSetup-0.92.1-arm64.exe][ptUserArm64] | -| Machine wide - x64 | [PowerToysSetup-0.92.1-x64.exe][ptMachineX64] | -| Machine wide - ARM64 | [PowerToysSetup-0.92.1-arm64.exe][ptMachineArm64] | +| Per user - x64 | [PowerToysUserSetup-0.93.0-x64.exe][ptUserX64] | +| Per user - ARM64 | [PowerToysUserSetup-0.93.0-arm64.exe][ptUserArm64] | +| Machine wide - x64 | [PowerToysSetup-0.93.0-x64.exe][ptMachineX64] | +| Machine wide - ARM64 | [PowerToysSetup-0.93.0-arm64.exe][ptMachineArm64] | This is our preferred method. @@ -93,139 +93,119 @@ For guidance on developing for PowerToys, please read the [developer docs](./doc Our [prioritized roadmap][roadmap] of features and utilities that the core team is focusing on. -### 0.92 - June 2025 Update +### 0.93 - Aug 2025 Update In this release, we focused on new features, stability, optimization improvements, and automation. **✨Highlights** - - PowerToys settings now has a toggle for the system tray icon, giving users control over its visibility based on personal preference. Thanks [@BLM16](https://github.com/BLM16)! - - Command Palette now has Ahead-of-Time ([AOT](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot)) compatibility for all first-party extensions, improved extensibility, and core UX fixes, resulting in better performance and stability across commands. - - Color Picker now has customizable mouse button actions, enabling more personalized workflows by assigning functions to left, right, and middle clicks. Thanks [@PesBandi](https://github.com/PesBandi)! - - Bug Report Tool now has a faster and clearer reporting process, with progress indicators, improved compression, auto-cleanup of old trace logs, and inclusion of MSIX installer logs for more efficient diagnostics. - - File Explorer add-ons now have improved rendering stability, resolving issues with PDF previews, blank thumbnails, and text file crashes during file browsing. - -### Color Picker - - - Added mouse button actions so you can choose what left, right, or middle click does. Thanks [@PesBandi](https://github.com/PesBandi)! - -### Crop & Lock - - - Aligned window styling with current Windows theme for a cleaner look. Thanks [@sadirano](https://github.com/sadirano)! + - PowerToys settings debuts a modern, card-based dashboard with clearer descriptions and faster navigation for a streamlined user experience. + - Command Palette had over 99 issues resolved, including bringing back Clipboard History, adding context menu shortcuts, pinning favorite apps, and supporting history in Run. + - Command Palette reduced its startup memory usage by ~15%, load time by ~40%, built-in extensions loading time by ~70%, and installation size by ~55%—all due to using the full Ahead-of-Time (AOT) compilation mode in Windows App SDK. + - Peek now supports instant previews and embedded thumbnails for Binary G-code (.bgcode) 3D printing files, making it easy to inspect models at a glance. Thanks [@pedrolamas](https://github.com/pedrolamas)! + - Mouse Utilities introduces a new spotlight highlighting mode that dims the screen and draws attention to your cursor, perfect for presentations. + - Test coverage improvements for multiple PowerToys modules including Command Palette, Advanced Paste, Peek, Text Extractor, and PowerRename — ensuring better reliability and quality, with over 600 new unit tests (mostly for Command Palette) and doubled UI automation coverage. ### Command Palette - - Enhanced performance by resolving a regression in page loading. - - Applied consistent hotkey handling across all Command Palette commands for a smoother user experience. - - Improved graceful closing of Command Palette. Thanks [@davidegiacometti](https://github.com/davidegiacometti)! - - Fixed consistency issue for extensions' alias with "Direct" setting and enabled localization for "Direct" and "Indirect" for better user understanding. Thanks [@davidegiacometti](https://github.com/davidegiacometti)! - - Improved visual clarity by styling critical context items correctly. - - Automatically focused the field when only one is present on the content page. - - Improved stability and efficiency when loading file icons in SDK ThumbnailHelper.cs by removing unnecessary operations. Thanks [@OldUser101](https://github.com/OldUser101)! - - Enhanced details view with commands implementation. (See [Extension sample](./src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleListPageWithDetails.cs)) + - Ensured screen readers are notified when the selected item in the list changes for better accessibility. + - Fixed command title changes not being properly notified to screen readers. Thanks [@jiripolasek](https://github.com/jiripolasek)! + - Made icon controls excluded from keyboard navigation by default for better accessibility. Thanks [@jiripolasek](https://github.com/jiripolasek)! + - Improved UI design with better text sizing and alignment. + - Fixed keyboard shortcuts to work better in text boxes and context menus. + - Added right-click context menus with critical command styling and separators. + - Improved various context menu issues, improving item selection, handling of long titles, search bar text scaling, initial item behavior, and primary button functionality. + - Fixed context menu crashes with better type handling. + - Fixed "Reload" command to work with both uppercase and lowercase letters. + - Added mouse back button support for easier navigation. Thanks [@jiripolasek](https://github.com/jiripolasek)! + - Fixed Alt+Left Arrow navigation not working when search box contains text. Thanks [@jiripolasek](https://github.com/jiripolasek)! + - Updated back button tooltip to show keyboard shortcut information. Thanks [@jiripolasek](https://github.com/jiripolasek)! + - Fixed Command Palette window not appearing properly when activated. Thanks [@jiripolasek](https://github.com/jiripolasek)! + - Fixed Command Palette window staying hidden from taskbar after File Explorer restarts. Thanks [@jiripolasek](https://github.com/jiripolasek)! + - Fixed window focus not returning to previous app properly. + - Fixed Command Palette window to always appear on top when shown and move to bottom when hidden. Thanks [@jiripolasek](https://github.com/jiripolasek)! + - Fixed window hiding to properly work on UI thread. Thanks [@jiripolasek](https://github.com/jiripolasek)! + - Fixed crashes and improved stability with better synchronization of Command list updates. Thanks [@jiripolasek](https://github.com/jiripolasek)! + - Improved extension disposal with better error handling to prevent crashes. Thanks [@jiripolasek](https://github.com/jiripolasek)! + - Improved stability by fixing a UI threading issue when loading more results, preventing possible crashes and ensuring the loading state resets if loading fails. Thanks [@jiripolasek](https://github.com/jiripolasek)! + - Enhanced icon loading stability with better exception handling. Thanks [@jiripolasek](https://github.com/jiripolasek)! + - Added thread safety to recent commands to prevent crashes. Thanks [@MaoShengelia](https://github.com/MaoShengelia)! + - Fixed acrylic (frosted glass) system backdrop display issues by ensuring proper UI thread handling. Thanks [@jiripolasek](https://github.com/jiripolasek)! ### Command Palette extensions - - Added "Copy Path" command to *App* search results for convenience. Thanks [@PesBandi](https://github.com/PesBandi)! - - Improved *Calculator* input experience by ignoring leading equal signs. Thanks [@PesBandi](https://github.com/PesBandi)! - - Corrected input handling in the *Calculator* extension to avoid showing errors for input with only leading whitespace. - - Improved *New Extension* wizard by validating names to prevent namespace errors. - - Ensured consistent context items display for the *Run* extension between fallback and top-level results. - - Fixed missing *Time & Date* commands in fallback results. Thanks [@htcfreek](https://github.com/htcfreek)! - - Fixed outdated results in the *Time & Date* extension. Thanks [@htcfreek](https://github.com/htcfreek)! - - Fixed an issue where *Web Search* always opened Microsoft Edge instead of the user's default browser on Windows 11 24H2 and later. Thanks [@RuggMatt](https://github.com/RuggMatt)! - - Improved ordering of *Windows Settings* extension search results from alphabetical to relevance-based for quicker access. - - Added "Restart Windows Explorer" command to the *Windows System Commands* provider for gracefully terminate and relaunch explorer.exe. Thanks [@jiripolasek](https://github.com/jiripolasek)! + - Added settings to each provider to control which fallback commands are enabled. Thanks [@jiripolasek](https://github.com/jiripolasek)! for fixing a regression in this feature. + - Added sample code showing how Command Palette extensions can track when their pages are loaded or unloaded. [Check it out here](./src/modules/cmdpal/ext/SamplePagesExtension/OnLoadPage.cs). + - Fixed *Calculator* to accept regular spaces in numbers that use space separators. Thanks [@PesBandi](https://github.com/PesBandi)! + - Added a new setting to *Calculator* to make "Copy" the primary button (replacing “Save”) and enable "Close on Enter", streamlining the workflow. Thanks [@PesBandi](https://github.com/PesBandi)! + - Improved *Apps* indexing error handling and removed obsolete code. Thanks [@davidegiacometti](https://github.com/davidegiacometti)! + - Prevented apps from showing in search when the *Apps* extension is disabled. Thanks [@jiripolasek](https://github.com/jiripolasek)! + - Added ability to pin/unpin *Apps* using Ctrl+P shortcut. + - Added keyboard shortcuts to the *Apps* context menu items for faster access. + - Added all file context menu options to the *Apps* items context menu, making all file actions available there for better functionality. + - Streamlined All *Apps* extension settings by removing redundant descriptions, making the UI clearer. + - Added command history to the *Run* page for easier access to previous commands. + - Fixed directory path handling in *Run* fallback for better file navigation. + - Fixed URL fallback item hiding properly in *Web Search* extension when search query becomes invalid. Thanks [@jiripolasek](https://github.com/jiripolasek)! + - Added proper empty state message for *Web Search* extension when no results found. Thanks [@jiripolasek](https://github.com/jiripolasek)! + - Added fallback command to *Windows Settings* extension for better search results. + - Re-enabled *Clipboard History* feature with proper window handling. + - Improved *Add Bookmark* extension to automatically detect file, folder, or URL types without manual input. + - Updated terminology from "Kill process" to "End task" in *Window Walker* for consistency with Windows. + - Fixed minor grammar error in SamplePagesExtension code comments. Thanks [@purofle](https://github.com/purofle)! -### Command Palette Ahead-of-Time (AOT) readiness +### Mouse Utilities - - We’ve made foundational changes to prepare the Command Palette for future Ahead-of-Time (AOT) publishing. This includes replacing the calculator library with ExprTk, improving COM object handling, refining Win32 interop, and correcting trimming behavior—all to ensure compatibility, performance, and reliability under AOT constraints. All first-party extensions are now AOT-compatible. These improvements lay the groundwork for publishing Command Palette as an AOT application in the next release. - - Special thanks to [@Sergio0694](https://github.com/Sergio0694) for guidance on making COM APIs AOT-compatible, [@jtschuster](https://github.com/jtschuster) for fixing COM object handling, [@ArashPartow](https://github.com/ArashPartow) from ExprTk for integration suggestions, and [@tian-lt](https://github.com/tian-lt) from the Windows Calculator team for valuable suggestion throughout the migration journey and review. - - As part of the upcoming release, we’re also enabling AOT compatibility for key dependencies, including markdown rendering, Adaptive Cards, internal logging and telemetry library, and the core Command Palette UX. - -### FancyZones - - - Fixed DPI-scaling issues to ensure FancyZones Editor displays crisply on high-resolution monitors. Thanks [@HO-COOH](https://github.com/HO-COOH)! This inspired us a broader review across other PowerToys modules, leading to DPI display optimizations in Awake, Color Picker, PowerAccent, and more. - -### File Explorer add-ons - - - Fixed potential failures in PDF previewer and thumbnail generation, improving reliability when browsing PDF files. Thanks [@mohiuddin-khan-shiam](https://github.com/mohiuddin-khan-shiam)! - - Prevented Monaco Preview Handler crash when opening UTF-8-BOM text files. - -### Hosts File Editor - - - Added an in-app *“Learn more”* link to warning dialogs for quick guidance. Thanks [@PesBandi](https://github.com/PesBandi)! - -### Mouse Without Borders - - - Fixed firewall rule so MWB now accepts connections from IPs outside your local subnet. - - Cleaned legacy logs to reduce disk usage and noise. + - Added a new spotlight highlighting mode that creates a large transparent circle around your cursor with a backdrop effect, providing an alternative to the traditional circle highlight. Perfect for presentations where you want to focus attention on a specific area while dimming the rest of the screen. ### Peek - - Updated QOI reader so 3-channel QOI images preview correctly in Peek and File Explorer. Thanks [@mbartlett21](https://github.com/mbartlett21)! - - Added codec detection with a clear warning when a video can’t be previewed, along with a link to the Microsoft Store to download the required codec. + - Added preview and thumbnail support for Binary G-code (.bgcode) files used in 3D printing. You can now see embedded thumbnails and preview these compressed 3D printing files directly in Peek and File Explorer. Thanks [@pedrolamas](https://github.com/pedrolamas)! -### PowerRename +### Quick Accent - - Added support for $YY-$MM-$DD in ModificationTime and AccessTime to enable flexible date-based renaming. - -### PowerToys Run - - - Suppressed error UI for known WPF-related crashes to reduce user confusion, while retaining diagnostic logging for analysis. This targets COMException 0xD0000701 and 0x80263001 caused by temporary DWM unavailability. - -### Registry Preview - - - Added "Extended data preview" via magnifier icon and context menu in the Data Grid, enabled easier inspection of complex registry types like REG_BINARY, REG_EXPAND_SZ, and REG_MULTI_SZ, etc. Thanks [@htcfreek](https://github.com/htcfreek)! - - Improved file-saving experience in Registry Preview by aligning with Notepad-like behavior, enhancing user prompts, error handling, and preventing crashes during unsaved or interrupted actions. Thanks [@htcfreek](https://github.com/htcfreek)! + - Added Vietnamese language support to Quick Accent, mappings for Vietnamese vowels (a, e, i, o, u, y) and the letter d. Thanks [@octastylos-pseudodipteros](https://github.com/octastylos-pseudodipteros)! ### Settings - - Added an option to hide or show the PowerToys system tray icon. Thanks [@BLM16](https://github.com/BLM16)! - - Improved settings to show progress while a bug report package is being generated. - -### Workspaces - - - Stored Workspaces icons in user AppData to ensure profile portability and prevent loss during temporary folder cleanup. - - Enabled capture and launch of PWAs on non-default Edge or Chrome profiles, ensuring consistent behavior during creation and execution. + - Completely redesigned the Settings dashboard with a modern card-based layout featuring organized sections for quick actions and shortcuts overview, replacing the old module list. + - Rewrote setting descriptions to be more concise and follow Windows writing style guidelines, making them easier to understand. + - Improved formatting and readability of release notes in the "What's New" section with better typography and spacing. + - Added missing deep link support for various settings pages (Peek, Quick Accent, PowerToys Run, etc.) so you can jump directly to specific settings. + - Resolved an issue where the settings page header would drift away from its position when resizing the settings window. + - Resolved a settings crash related to incompatible property names in ZoomIt configuration. ### Documentation - - Added SpeedTest and Dictionary Definition to the third-party plugins documentation for PowerToys Run. Thanks [@ruslanlap](https://github.com/ruslanlap)! - - Corrected sample links and typo in Command Palette documentation. Thanks [@daverayment](https://github.com/daverayment) and [@roycewilliams](https://github.com/roycewilliams)! + - Added detailed step-by-step instructions for first-time developers building the Command Palette module, including prerequisites and Visual Studio setup guidance. Thanks [@chatasweetie](https://github.com/chatasweetie)! + - **Fixed Broken SDK Link**: Corrected a broken markdown link in the Command Palette SDK README that was pointing to an incorrect directory path. Thanks [@ChrisGuzak](https://github.com/ChrisGuzak)! + - Added documentation for the "Open With Cursor" plugin that enables opening Visual Studio and VS Code recent files using Cursor AI. Thanks [@VictorNoxx](https://github.com/VictorNoxx)! + - Added documentation for two new community plugins - Hotkeys plugin for creating custom keyboard shortcuts, and RandomGen plugin for generating random data like passwords, colors, and placeholder text. Thanks [@ruslanlap](https://github.com/ruslanlap)! ### Development - - Updated .NET libraries to 9.0.6 for performance and security. Thanks [@snickler](https://github.com/snickler)! - - Updated WinAppSDK to 1.7.2 for better stability and Windows support. - - Introduced a one-step local build script that generates a signed installer, enhancing developer productivity. - - Generated portable PDBs so cross-platform debuggers can read symbol files, improving debugging experience in VSCode and other tools. - - Simplified WinGet configuration files by using the [Microsoft.Windows.Settings](https://www.powershellgallery.com/packages/Microsoft.Windows.Settings) module to enable Developer Mode. Thanks [@mdanish-kh](https://github.com/mdanish-kh)! - - Adjusted build scripts for the latest Az.Accounts module to keep CI green. - - Streamlined release pipeline by removing hard-coded telemetry version numbers, and unified Command Palette versioning with Windows Terminal's versioning method for consistent updates. - - Enhanced the build validation step to show detailed differences between NOTICE.md and actual package dependencies and versions. - - Improved spell-checking accuracy across the repo. Thanks [@rovercoder](https://github.com/rovercoder)! - - Upgraded CI to TouchdownBuild v5 for faster pipelines. - - Added context comments to *Resources.resw* to help translators. - - Expanded fuzz testing coverage to include FancyZones. - - Integrated all unit tests into the CI pipeline, increasing from ~3,000 to ~5,000 tests. - - Enabled daily UI test automation on the main branch, now covering over 370 UI tests for end-to-end validation. - - Newly added unit tests for WorkspacesLib to improve reliability and maintainability. + - Updated .NET libraries to 9.0.8 for performance and security. Thanks [@snickler](https://github.com/snickler)! + - Updated the spell check system to version 0.0.25 with better GitHub integration and SARIF reporting, plus fixed numerous spelling errors throughout the codebase including property names and documentation. Thanks [@jsoref](https://github.com/jsoref)! + - Cleaned up spelling check configuration to eliminate false positives and excessive noise that was appearing in every pull request, making the development process smoother. + - Replaced NuGet feed with Azure Artifacts for better package management. + - Implemented configurable UI test pipeline that can use pre-built official releases instead of building everything from scratch, reducing test execution time from 2+ hours. + - Replaced brittle pixel-by-pixel image comparison with perceptual hash (pHash) technology that's more robust to minor rendering differences - no more test failures due to anti-aliasing or compression artifacts. + - Reduced CI/fuzzing/UI test timeouts from 4 hours to 90 minutes, dramatically improving developer feedback loops and preventing long waits when builds get stuck. + - Standardized test project naming across the entire codebase and improved pipeline result identification by adding platform/install mode context to test run titles. Thanks [@khmyznikov](https://github.com/khmyznikov)! + - Added comprehensive UI test suites for multiple PowerToys modules including Command Palette, Advanced Paste, Peek, Text Extractor, and PowerRename - ensuring better reliability and quality. + - Enhanced UI test automation with command-line argument support, better session management, and improved element location methods using pattern matching to avoid failures from minor differences in exact matches. -### General +### What is being planned over the next few releases -- Updated bug report compression library (cziplib 0.3.3) for faster and more reliable package creation. Thanks [@Chubercik](https://github.com/Chubercik)! -- Included App Installer (“AppX Deployment Server”) event logs in bug reports for more thorough diagnostics. - -### What is being planned for version 0.93 - -For [v0.93][github-next-release-work], we'll work on the items below: +For [v0.94][github-next-release-work], we'll work on the items below: - Continued Command Palette polish - - New UI automation tests - - Working on installer upgrades + - Working on Shortcut Guide v2 (Thanks [@noraa-junker](https://github.com/noraa-junker)!) + - Working on upgrading the installer to WiX 5 - Working on shortcut conflict detection + - Working on setting search - Upgrading Keyboard Manager's editor UI + - New UI automation tests - Stability, bug fixes ## PowerToys Community From 911989bac1cc1a6cebae0c209fbb43e71a7beba3 Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Wed, 13 Aug 2025 11:01:25 -0500 Subject: [PATCH 23/99] store: update package catalog before running install (#41121) It's actually failing because we're bad at... Linux? --- .github/workflows/msstore-submissions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/msstore-submissions.yml b/.github/workflows/msstore-submissions.yml index 8878780987..a44dafb199 100644 --- a/.github/workflows/msstore-submissions.yml +++ b/.github/workflows/msstore-submissions.yml @@ -17,7 +17,7 @@ jobs: steps: - name: BODGY - Set up Gnome Keyring for future Cert Auth run: |- - sudo apt-get install -y gnome-keyring + sudo apt-get update && sudo apt-get install -y gnome-keyring export $(dbus-launch --sh-syntax) export $(echo 'anypass_just_to_unlock' | gnome-keyring-daemon --unlock) export $(echo 'anypass_just_to_unlock' | gnome-keyring-daemon --start --components=gpg,pkcs11,secrets,ssh) From ab76dd1255281f06a3a513fe31c84344c31e81a2 Mon Sep 17 00:00:00 2001 From: Davide Giacometti <25966642+davidegiacometti@users.noreply.github.com> Date: Wed, 13 Aug 2025 20:42:40 +0200 Subject: [PATCH 24/99] [CmdPal] Search PATH starting with ~ / \ (#40887) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary of the Pull Request Love that we have now environment variables expanding! 🚀 Porting also few small features I implemented in Run Folder plugin a long time ago and I love: - https://github.com/microsoft/PowerToys/pull/7711 - https://github.com/microsoft/PowerToys/pull/9579 Threat `/` and `\` as root of system drive (typically `C:\`) Threat `~` as user home directory `%USERPROFILE%` ## 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 image image image ## Validation Steps Performed - Tested search starting with `~` `/` `\` - Tested UNC network path starting with `\\...` and `//...` --- .../FallbackExecuteItem.cs | 64 +++++++++++++++++-- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/FallbackExecuteItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/FallbackExecuteItem.cs index 167956c166..79be63cd65 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/FallbackExecuteItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/FallbackExecuteItem.cs @@ -4,6 +4,7 @@ using System; using System.IO; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CmdPal.Ext.Shell.Helpers; @@ -15,6 +16,8 @@ namespace Microsoft.CmdPal.Ext.Shell; internal sealed partial class FallbackExecuteItem : FallbackCommandItem, IDisposable { + private static readonly char[] _systemDirectoryRoots = ['\\', '/']; + private readonly Action? _addToHistory; private CancellationTokenSource? _cancellationTokenSource; private Task? _currentUpdateTask; @@ -80,8 +83,8 @@ internal sealed partial class FallbackExecuteItem : FallbackCommandItem, IDispos cancellationToken.ThrowIfCancellationRequested(); var searchText = query.Trim(); - var expanded = Environment.ExpandEnvironmentVariables(searchText); - searchText = expanded; + Expand(ref searchText); + if (string.IsNullOrEmpty(searchText) || string.IsNullOrWhiteSpace(searchText)) { Command = null; @@ -184,8 +187,8 @@ internal sealed partial class FallbackExecuteItem : FallbackCommandItem, IDispos internal static bool SuppressFileFallbackIf(string query) { var searchText = query.Trim(); - var expanded = Environment.ExpandEnvironmentVariables(searchText); - searchText = expanded; + Expand(ref searchText); + if (string.IsNullOrEmpty(searchText) || string.IsNullOrWhiteSpace(searchText)) { return false; @@ -197,4 +200,57 @@ internal sealed partial class FallbackExecuteItem : FallbackCommandItem, IDispos return exeExists || pathIsDir; } + + private static void Expand(ref string searchText) + { + if (searchText.Length == 0) + { + return; + } + + var singleCharQuery = searchText.Length == 1; + + searchText = Environment.ExpandEnvironmentVariables(searchText); + + if (!TryExpandHome(ref searchText)) + { + TryExpandRoot(ref searchText); + } + } + + private static bool TryExpandHome(ref string searchText) + { + if (searchText[0] == '~') + { + var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + + if (searchText.Length == 1) + { + searchText = home; + } + else if (_systemDirectoryRoots.Contains(searchText[1])) + { + searchText = Path.Combine(home, searchText[2..]); + } + + return true; + } + + return false; + } + + private static bool TryExpandRoot(ref string searchText) + { + if (_systemDirectoryRoots.Contains(searchText[0]) && (searchText.Length == 1 || !_systemDirectoryRoots.Contains(searchText[1]))) + { + var root = Path.GetPathRoot(Environment.SystemDirectory); + if (root != null) + { + searchText = searchText.Length == 1 ? root : Path.Combine(root, searchText[1..]); + return true; + } + } + + return false; + } } From 7f4a97cac560c80bbc0918a689d98eae3825dc47 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 13 Aug 2025 13:42:52 -0500 Subject: [PATCH 25/99] CmdPal: extension nuget should target a lower windows SDK version (#40902) related to some #40113 work The extension SDK shouldn't rely on a preview version of the Windows SDK. It should use the stable one. Also moves some messages around that we didn't need --- .../Microsoft.CmdPal.UI.ViewModels/Commands/MainListPage.cs | 1 + .../Commands/OpenSettingsCommand.cs | 2 +- .../Microsoft.CmdPal.UI.ViewModels/Commands/QuitAction.cs | 2 +- .../Commands/ReloadExtensionsCommand.cs | 1 + .../Messages/OpenSettingsMessage.cs | 2 +- .../Messages/QuitMessage.cs | 2 +- .../Messages/ReloadCommandsMessage.cs | 2 +- .../Messages/UpdateFallbackItemsMessage.cs | 2 +- .../ProviderSettingsViewModel.cs | 2 +- .../Microsoft.CmdPal.UI.ViewModels/TopLevelCommandManager.cs | 4 ++-- .../Microsoft.CmdPal.UI.ViewModels/TopLevelViewModel.cs | 1 + .../cmdpal/Microsoft.CmdPal.UI/Helpers/TrayIconService.cs | 3 ++- src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs | 3 ++- .../Messages/HotkeySummonMessage.cs | 2 +- .../Messages/SettingsWindowClosedMessage.cs | 2 +- .../cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs | 2 +- .../Microsoft.CmdPal.UI/Settings/SettingsWindow.xaml.cs | 3 ++- src/modules/cmdpal/Microsoft.CmdPal.UI/ToastWindow.xaml.cs | 2 +- .../Microsoft.CommandPalette.Extensions.Toolkit.csproj | 3 +++ 19 files changed, 25 insertions(+), 16 deletions(-) rename src/modules/cmdpal/{Microsoft.CmdPal.Core.ViewModels => Microsoft.CmdPal.UI.ViewModels}/Messages/OpenSettingsMessage.cs (80%) rename src/modules/cmdpal/{Microsoft.CmdPal.Core.ViewModels => Microsoft.CmdPal.UI.ViewModels}/Messages/QuitMessage.cs (87%) rename src/modules/cmdpal/{Microsoft.CmdPal.Core.ViewModels => Microsoft.CmdPal.UI.ViewModels}/Messages/ReloadCommandsMessage.cs (81%) rename src/modules/cmdpal/{Microsoft.CmdPal.Core.ViewModels => Microsoft.CmdPal.UI.ViewModels}/Messages/UpdateFallbackItemsMessage.cs (81%) rename src/modules/cmdpal/{Microsoft.CmdPal.Core.ViewModels => Microsoft.CmdPal.UI}/Messages/HotkeySummonMessage.cs (82%) rename src/modules/cmdpal/{Microsoft.CmdPal.Core.ViewModels => Microsoft.CmdPal.UI}/Messages/SettingsWindowClosedMessage.cs (81%) 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 f877afa9c5..9c4750b0e9 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/MainListPage.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/MainListPage.cs @@ -9,6 +9,7 @@ using ManagedCommon; using Microsoft.CmdPal.Common.Helpers; using Microsoft.CmdPal.Core.ViewModels.Messages; using Microsoft.CmdPal.Ext.Apps; +using Microsoft.CmdPal.UI.ViewModels.Messages; using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions.Toolkit; using Microsoft.Extensions.DependencyInjection; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/OpenSettingsCommand.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/OpenSettingsCommand.cs index a5af351fd4..ac7fe624e5 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/OpenSettingsCommand.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/OpenSettingsCommand.cs @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. using CommunityToolkit.Mvvm.Messaging; -using Microsoft.CmdPal.Core.ViewModels.Messages; +using Microsoft.CmdPal.UI.Messages; using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions.Toolkit; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/QuitAction.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/QuitAction.cs index 313685f6f2..bd3cee3159 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/QuitAction.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/QuitAction.cs @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. using CommunityToolkit.Mvvm.Messaging; -using Microsoft.CmdPal.Core.ViewModels.Messages; +using Microsoft.CmdPal.UI.ViewModels.Messages; using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions.Toolkit; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/ReloadExtensionsCommand.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/ReloadExtensionsCommand.cs index 77efb05a73..88024efe2f 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/ReloadExtensionsCommand.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/ReloadExtensionsCommand.cs @@ -4,6 +4,7 @@ using CommunityToolkit.Mvvm.Messaging; using Microsoft.CmdPal.Core.ViewModels.Messages; +using Microsoft.CmdPal.UI.ViewModels.Messages; using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions.Toolkit; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/Messages/OpenSettingsMessage.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/OpenSettingsMessage.cs similarity index 80% rename from src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/Messages/OpenSettingsMessage.cs rename to src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/OpenSettingsMessage.cs index e4b02b5c0c..c699ab427a 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/Messages/OpenSettingsMessage.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/OpenSettingsMessage.cs @@ -2,7 +2,7 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace Microsoft.CmdPal.Core.ViewModels.Messages; +namespace Microsoft.CmdPal.UI.Messages; public record OpenSettingsMessage() { diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/Messages/QuitMessage.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/QuitMessage.cs similarity index 87% rename from src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/Messages/QuitMessage.cs rename to src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/QuitMessage.cs index 12b9cec827..ae65782336 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/Messages/QuitMessage.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/QuitMessage.cs @@ -2,7 +2,7 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace Microsoft.CmdPal.Core.ViewModels.Messages; +namespace Microsoft.CmdPal.UI.ViewModels.Messages; /// /// Message which closes the application. Used by via . diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/Messages/ReloadCommandsMessage.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/ReloadCommandsMessage.cs similarity index 81% rename from src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/Messages/ReloadCommandsMessage.cs rename to src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/ReloadCommandsMessage.cs index a553568f50..cba0fa3f56 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/Messages/ReloadCommandsMessage.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/ReloadCommandsMessage.cs @@ -2,7 +2,7 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace Microsoft.CmdPal.Core.ViewModels.Messages; +namespace Microsoft.CmdPal.UI.ViewModels.Messages; public record ReloadCommandsMessage() { diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/Messages/UpdateFallbackItemsMessage.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/UpdateFallbackItemsMessage.cs similarity index 81% rename from src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/Messages/UpdateFallbackItemsMessage.cs rename to src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/UpdateFallbackItemsMessage.cs index 8a913f7a3f..08e65c2213 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/Messages/UpdateFallbackItemsMessage.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/UpdateFallbackItemsMessage.cs @@ -2,7 +2,7 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace Microsoft.CmdPal.Core.ViewModels.Messages; +namespace Microsoft.CmdPal.UI.ViewModels.Messages; public record UpdateFallbackItemsMessage() { diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ProviderSettingsViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ProviderSettingsViewModel.cs index 3c8e402364..838e77cb62 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ProviderSettingsViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ProviderSettingsViewModel.cs @@ -7,7 +7,7 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Messaging; using Microsoft.CmdPal.Common.Services; using Microsoft.CmdPal.Core.ViewModels; -using Microsoft.CmdPal.Core.ViewModels.Messages; +using Microsoft.CmdPal.UI.ViewModels.Messages; using Microsoft.CmdPal.UI.ViewModels.Properties; using Microsoft.Extensions.DependencyInjection; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelCommandManager.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelCommandManager.cs index a783a2458a..eefba9cc0d 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelCommandManager.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelCommandManager.cs @@ -12,7 +12,7 @@ using ManagedCommon; using Microsoft.CmdPal.Common.Helpers; using Microsoft.CmdPal.Common.Services; using Microsoft.CmdPal.Core.ViewModels; -using Microsoft.CmdPal.Core.ViewModels.Messages; +using Microsoft.CmdPal.UI.ViewModels.Messages; using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions.Toolkit; using Microsoft.Extensions.DependencyInjection; @@ -151,7 +151,7 @@ public partial class TopLevelCommandManager : ObservableObject, WeakReference weakSelf = new(this); await sender.LoadTopLevelCommands(_serviceProvider, weakSelf); - List newItems = [..sender.TopLevelItems]; + List newItems = [.. sender.TopLevelItems]; foreach (var i in sender.FallbackItems) { if (i.IsEnabled) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelViewModel.cs index f439f0fb84..7bdb0ed904 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelViewModel.cs @@ -8,6 +8,7 @@ using CommunityToolkit.Mvvm.Messaging; using ManagedCommon; using Microsoft.CmdPal.Core.ViewModels; using Microsoft.CmdPal.Core.ViewModels.Messages; +using Microsoft.CmdPal.UI.ViewModels.Messages; using Microsoft.CmdPal.UI.ViewModels.Settings; using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions.Toolkit; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/TrayIconService.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/TrayIconService.cs index 496c7cf9b7..60bc67eb3d 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/TrayIconService.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/TrayIconService.cs @@ -5,8 +5,9 @@ using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using CommunityToolkit.Mvvm.Messaging; -using Microsoft.CmdPal.Core.ViewModels.Messages; +using Microsoft.CmdPal.UI.Messages; using Microsoft.CmdPal.UI.ViewModels; +using Microsoft.CmdPal.UI.ViewModels.Messages; using Microsoft.UI.Xaml; using Windows.Win32; using Windows.Win32.Foundation; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs index d42c46abec..49a8eacceb 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs @@ -10,11 +10,12 @@ using ManagedCommon; using Microsoft.CmdPal.Common.Helpers; using Microsoft.CmdPal.Common.Messages; using Microsoft.CmdPal.Common.Services; -using Microsoft.CmdPal.Core.ViewModels; using Microsoft.CmdPal.Core.ViewModels.Messages; using Microsoft.CmdPal.UI.Events; using Microsoft.CmdPal.UI.Helpers; +using Microsoft.CmdPal.UI.Messages; using Microsoft.CmdPal.UI.ViewModels; +using Microsoft.CmdPal.UI.ViewModels.Messages; using Microsoft.Extensions.DependencyInjection; using Microsoft.PowerToys.Telemetry; using Microsoft.UI.Composition; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/Messages/HotkeySummonMessage.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Messages/HotkeySummonMessage.cs similarity index 82% rename from src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/Messages/HotkeySummonMessage.cs rename to src/modules/cmdpal/Microsoft.CmdPal.UI/Messages/HotkeySummonMessage.cs index 4dcef111a3..65f6b27adb 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/Messages/HotkeySummonMessage.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Messages/HotkeySummonMessage.cs @@ -2,7 +2,7 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace Microsoft.CmdPal.Core.ViewModels.Messages; +namespace Microsoft.CmdPal.UI.Messages; public record HotkeySummonMessage(string CommandId, IntPtr Hwnd) { diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/Messages/SettingsWindowClosedMessage.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Messages/SettingsWindowClosedMessage.cs similarity index 81% rename from src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/Messages/SettingsWindowClosedMessage.cs rename to src/modules/cmdpal/Microsoft.CmdPal.UI/Messages/SettingsWindowClosedMessage.cs index f58637e8a5..57ea5b8c1d 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/Messages/SettingsWindowClosedMessage.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Messages/SettingsWindowClosedMessage.cs @@ -2,7 +2,7 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace Microsoft.CmdPal.Core.ViewModels.Messages; +namespace Microsoft.CmdPal.UI.Messages; public record SettingsWindowClosedMessage { diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs index 63c51d4eb3..6ba4163096 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs @@ -9,6 +9,7 @@ using ManagedCommon; using Microsoft.CmdPal.Core.ViewModels; using Microsoft.CmdPal.Core.ViewModels.Messages; using Microsoft.CmdPal.UI.Events; +using Microsoft.CmdPal.UI.Messages; using Microsoft.CmdPal.UI.Settings; using Microsoft.CmdPal.UI.ViewModels; using Microsoft.CommandPalette.Extensions; @@ -17,7 +18,6 @@ using Microsoft.PowerToys.Telemetry; using Microsoft.UI.Dispatching; using Microsoft.UI.Input; using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Controls.Primitives; using Microsoft.UI.Xaml.Input; using Microsoft.UI.Xaml.Media.Animation; using DispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/SettingsWindow.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/SettingsWindow.xaml.cs index a13782478a..9fbdb11102 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/SettingsWindow.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/SettingsWindow.xaml.cs @@ -4,9 +4,10 @@ using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.Messaging; -using Microsoft.CmdPal.Core.ViewModels.Messages; using Microsoft.CmdPal.UI.Helpers; +using Microsoft.CmdPal.UI.Messages; using Microsoft.CmdPal.UI.ViewModels; +using Microsoft.CmdPal.UI.ViewModels.Messages; using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/ToastWindow.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/ToastWindow.xaml.cs index 6b38020e22..87e04dfdcf 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/ToastWindow.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/ToastWindow.xaml.cs @@ -6,8 +6,8 @@ using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.WinUI; using ManagedCommon; using Microsoft.CmdPal.Core.ViewModels; -using Microsoft.CmdPal.Core.ViewModels.Messages; using Microsoft.CmdPal.UI.Helpers; +using Microsoft.CmdPal.UI.ViewModels.Messages; using Microsoft.UI.Dispatching; using Microsoft.UI.Windowing; using Windows.Win32; diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/Microsoft.CommandPalette.Extensions.Toolkit.csproj b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/Microsoft.CommandPalette.Extensions.Toolkit.csproj index 3a01a9d232..6217cd25b6 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/Microsoft.CommandPalette.Extensions.Toolkit.csproj +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/Microsoft.CommandPalette.Extensions.Toolkit.csproj @@ -3,6 +3,9 @@ + + 10.0.26100.57 + $(SolutionDir)$(Platform)\$(Configuration)\Microsoft.CommandPalette.Extensions.Toolkit false false From e260c01553a44bf7d6222dd9a3ff11e8d8d7dbe7 Mon Sep 17 00:00:00 2001 From: Jessica Dene Earley-Cha <12740421+chatasweetie@users.noreply.github.com> Date: Wed, 13 Aug 2025 11:43:54 -0700 Subject: [PATCH 26/99] CmdPal: Setting Activation Shortcut now auto focuses on window & delivers dialog (#40968) ## Summary of the Pull Request Screen readers now will focus on the activation shortcut windows and read out the text ## PR Checklist - [x] Closes: #40967 - [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 https://github.com/user-attachments/assets/d72a9aea-28b8-49d1-b51f-7a7d2a8ff42f --- .../Controls/ShortcutControl/ShortcutDialogContentControl.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ShortcutControl/ShortcutDialogContentControl.xaml b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ShortcutControl/ShortcutDialogContentControl.xaml index 56ae0bfca6..8ab0fb7586 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ShortcutControl/ShortcutDialogContentControl.xaml +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ShortcutControl/ShortcutDialogContentControl.xaml @@ -15,7 +15,7 @@ - + Date: Wed, 13 Aug 2025 20:44:31 +0200 Subject: [PATCH 27/99] CmdPal: Fix race condition in SupersedingAsyncGate cancellation handling [MSH] (#40983) ## Summary of the Pull Request Change SetCanceled to TrySetCanceled in OperationCanceledException handler to prevent InvalidOperationException when external and internal cancellation tokens complete the TaskCompletionSource simultaneously. ## PR Checklist - [x] Closes: #40982 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** none - [ ] **Localization:** nope - [ ] **Dev docs:** none - [ ] **New binaries:** none - [ ] **Documentation updated:** none ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed --- .../Microsoft.CmdPal.Common/Helpers/SupersedingAsyncGate.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/SupersedingAsyncGate.cs b/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/SupersedingAsyncGate.cs index d4618b5c3b..9313ba6755 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/SupersedingAsyncGate.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/SupersedingAsyncGate.cs @@ -89,7 +89,7 @@ public class SupersedingAsyncGate : IDisposable } catch (OperationCanceledException) { - CompleteIfCurrent(currentTcs, currentCallId, tcs => tcs.SetCanceled(currentCts.Token)); + CompleteIfCurrent(currentTcs, currentCallId, tcs => tcs.TrySetCanceled(currentCts.Token)); } catch (Exception ex) { From 7a3616e996fd63dd042c38c3908831a12446f9a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pol=C3=A1=C5=A1ek?= Date: Wed, 13 Aug 2025 20:45:47 +0200 Subject: [PATCH 28/99] CmdPal: Replace Clipboard History extension outline icon with colorful icon (#41012) ## Summary of the Pull Request Replace Clipboard History extension icon with an icon derived from Fluent UI System Color set (https://github.com/microsoft/fluentui-system-icons/). Icon is under MIT license. image ## PR Checklist - [x] Closes: #41018 - [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 I looked at the icon in the top-level list. Looks nice. I looked at the icon in the settings page. Also looks nice. --- .../Assets/ClipboardHistory.png | Bin 0 -> 5088 bytes .../Assets/ClipboardHistory.svg | 1 + .../Icons.cs | 2 +- .../Microsoft.CmdPal.Ext.ClipboardHistory.csproj | 9 +++++++++ 4 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Assets/ClipboardHistory.png create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Assets/ClipboardHistory.svg diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Assets/ClipboardHistory.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Assets/ClipboardHistory.png new file mode 100644 index 0000000000000000000000000000000000000000..2dbdeb30ac209c28020d8ba5157ffa6b23e0eeda GIT binary patch literal 5088 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 l8hROKcfOIAzSV8;nnv|5q~!=sZU1A=K-W~K \ No newline at end of file diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Icons.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Icons.cs index 38fbc06d07..be7533d569 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Icons.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Icons.cs @@ -14,5 +14,5 @@ internal sealed class Icons internal static IconInfo PasteIcon { get; } = new("\uE77F"); - internal static IconInfo ClipboardListIcon { get; } = new("\uF0E3"); + internal static IconInfo ClipboardListIcon { get; } = IconHelpers.FromRelativePath("Assets\\ClipboardHistory.svg"); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Microsoft.CmdPal.Ext.ClipboardHistory.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Microsoft.CmdPal.Ext.ClipboardHistory.csproj index 7bc3bd65af..dc2ee202df 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Microsoft.CmdPal.Ext.ClipboardHistory.csproj +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Microsoft.CmdPal.Ext.ClipboardHistory.csproj @@ -30,4 +30,13 @@ PublicResXFileCodeGenerator + + + + PreserveNewest + + + PreserveNewest + + From a5b9a38517d984c8f7e8fb02001025c14a354c4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pol=C3=A1=C5=A1ek?= Date: Wed, 13 Aug 2025 20:48:07 +0200 Subject: [PATCH 29/99] CmdPal: Bring existing Settings window to the foreground when opened (#41087) ## Summary of the Pull Request Adds extra BringToFront after Activate. Don't ask. ## PR Checklist - [x] Closes: #41086 - [ ] **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/Pages/ShellPage.xaml.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs index 6ba4163096..1bc0fefb5a 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs @@ -242,6 +242,7 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page, } _settingsWindow.Activate(); + _settingsWindow.BringToFront(); } public void Receive(ShowDetailsMessage message) From 051c07885e9fa35131fd765e808a2f6e8c68a46f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pol=C3=A1=C5=A1ek?= Date: Thu, 14 Aug 2025 17:52:37 +0200 Subject: [PATCH 30/99] CmdPal: Replace the brush used for the menu item separator (#41130) ## Summary of the Pull Request Replace the brush used for the menu item separator in SeparatorContextMenuViewModelTemplate with the brush used by WinUI 3 for flyout menus. The brush previously used is a legacy brush and a WinUI trap. After screenshot: image ## PR Checklist - [x] Closes: #41128 - [ ] **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/Controls/ContextMenu.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContextMenu.xaml b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContextMenu.xaml index aa8689656e..f3c4e5413e 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContextMenu.xaml +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContextMenu.xaml @@ -112,7 +112,7 @@ + Fill="{ThemeResource MenuFlyoutSeparatorBackground}" /> From 67cd0f055ce7ff41399b048a63a97103b519f7ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pol=C3=A1=C5=A1ek?= Date: Fri, 15 Aug 2025 13:48:54 +0200 Subject: [PATCH 31/99] CmdPal: Check icon parent before adding in ContentIcon (Closes: #40928) (#40931) ## Summary of the Pull Request This pull request introduces a minor but important update to the `ContentIcon` control in the `Microsoft.CmdPal.UI` module. The changes improve robustness by adding checks to prevent duplicate parenting of the `Content` element and include a debug assertion for better diagnostics during development. ## PR Checklist - [x] Closes: #40928 - [ ] **Communication:** not yet - [ ] **Tests:** nope - [ ] **Localization:** none - [ ] **Dev docs:** nay - [ ] **New binaries:** no nothing - [ ] **Documentation updated:** too lazy for that ## Detailed Description of the Pull Request / Additional comments ### Key changes: #### Diagnostics and robustness improvements: * Added a `Debug.Assert` statement to verify that the `Content` element is not already parented to another element, helping to catch potential issues during development. (`[src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContentIcon.csR39-R49](diffhunk://#diff-330aad69f925cf7a9e07bb7147af8e6cd09776a4c745455ac8a91a24b482d076R39-R49)`) * Introduced checks to ensure the `Content` element is not added to the `Grid`'s `Children` collection if it already exists there, preventing redundant operations. (`[src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContentIcon.csR39-R49](diffhunk://#diff-330aad69f925cf7a9e07bb7147af8e6cd09776a4c745455ac8a91a24b482d076R39-R49)`) #### Code maintenance: * Added a `using System.Diagnostics` directive to enable the use of the `Debug` class for assertions. (`[src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContentIcon.csR5](diffhunk://#diff-330aad69f925cf7a9e07bb7147af8e6cd09776a4c745455ac8a91a24b482d076R5)`) ## Validation Steps Performed Turned extensions off and on and off and on and off and on and off and on and off and on and off and on and off and on and off and on and off and on and off and on and off and on and off and on and off and on and off and on and off and on. And then off and on again, just to be sure. --------- Co-authored-by: Mike Griese --- .../Microsoft.CmdPal.UI/Controls/ContentIcon.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContentIcon.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContentIcon.cs index 1c4945d131..211d28b410 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContentIcon.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContentIcon.cs @@ -2,6 +2,7 @@ // 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.Diagnostics; using CommunityToolkit.WinUI; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; @@ -35,6 +36,17 @@ public partial class ContentIcon : FontIcon { if (this.FindDescendants().OfType().FirstOrDefault() is Grid grid && Content is not null) { + if (grid.Children.Contains(Content)) + { + return; + } + + if (Content is FrameworkElement element && element.Parent is not null) + { + Debug.Assert(false, $"IconBoxElement Content is already parented to {element.Parent.GetType().Name}"); + return; + } + grid.Children.Add(Content); } } From c4c9277f3f12fe5ae3ab27dd44549429facf70bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pol=C3=A1=C5=A1ek?= Date: Fri, 15 Aug 2025 16:17:57 +0200 Subject: [PATCH 32/99] CmdPal: Fix regression when updating a command provider without commands (#40984) Improves item insertion logic in TopLevelCommandManager. Updated the insertion logic to handle invalid startIndex values. If startIndex is -1, new items will be appended to the end of the collection, enhancing robustness. Fixes regression introduced in #40752 ## Summary of the Pull Request ## 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 --- .../TopLevelCommandManager.cs | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelCommandManager.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelCommandManager.cs index eefba9cc0d..75c327385d 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelCommandManager.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelCommandManager.cs @@ -170,20 +170,29 @@ public partial class TopLevelCommandManager : ObservableObject, // TODO: just added a lock around all of this anyway, but keeping the clone // while looking on some other ways to improve this; can be removed later. List clone = [.. TopLevelCommands]; - var startIndex = -1; + var startIndex = FindIndexForFirstProviderItem(clone, sender.ProviderId); + clone.RemoveAll(item => item.CommandProviderId == sender.ProviderId); + clone.InsertRange(startIndex, newItems); + + ListHelpers.InPlaceUpdateList(TopLevelCommands, clone); + } + + return; + + static int FindIndexForFirstProviderItem(List topLevelItems, string providerId) + { // Tricky: all Commands from a single provider get added to the // top-level list all together, in a row. So if we find just the first // one, we can slice it out and insert the new ones there. - for (var i = 0; i < clone.Count; i++) + for (var i = 0; i < topLevelItems.Count; i++) { - var wrapper = clone[i]; + var wrapper = topLevelItems[i]; try { - if (sender.ProviderId == wrapper.CommandProviderId) + if (providerId == wrapper.CommandProviderId) { - startIndex = i; - break; + return i; } } catch @@ -191,9 +200,8 @@ public partial class TopLevelCommandManager : ObservableObject, } } - clone.RemoveAll(item => item.CommandProviderId == sender.ProviderId); - clone.InsertRange(startIndex, newItems); - ListHelpers.InPlaceUpdateList(TopLevelCommands, clone); + // If we didn't find any, then we just append the new commands to the end of the list. + return topLevelItems.Count; } } From e8754e4cd6499312270e7540d39839393224a028 Mon Sep 17 00:00:00 2001 From: leileizhang Date: Mon, 18 Aug 2025 10:18:47 +0800 Subject: [PATCH 33/99] Fix: Move ImageResizer satellite resource dlls under WinUI3Apps (#41152) ## Summary of the Pull Request ### Root cause: Problem Previously the installer installed ImageResizer satellite assemblies into [INSTALLFOLDER]*.dll. The runtime probes WinUI3Apps\ for WinUI3 app resource assemblies, so localization failed. ### Fix: Updated Resources.wxs: ImageResizer_$(var.IdSafeLanguage)_Component now targets Directory="Resource$(var.IdSafeLanguage)WinUI3AppsInstallFolder". ## PR Checklist - [x] Closes: #41142 - [ ] **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 updates the installer configuration in `Resources.wxs` to support resource management for WinUI 3 apps. The main changes ensure that resource directories and uninstall logic properly handle the new `WinUI3AppsInstallFolder`, and update the component registration for localized resources. **Installer resource management updates:** * Added `WinUI3AppsInstallFolder` to the list of parent directories for resource file generation, ensuring resources for WinUI 3 apps are included during installer builds. **Component and uninstall logic updates:** * Updated the `ImageResizer` component to register its resources under `Resource$(var.IdSafeLanguage)WinUI3AppsInstallFolder` instead of the default install folder, aligning with the new directory structure for WinUI 3 apps. * Added uninstall logic to remove the localized resource folder for `WinUI3AppsInstallFolder`, ensuring cleanup of WinUI 3 app resources during uninstall. --- installer/PowerToysSetup/Resources.wxs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/installer/PowerToysSetup/Resources.wxs b/installer/PowerToysSetup/Resources.wxs index 5da4db1390..b238799dd1 100644 --- a/installer/PowerToysSetup/Resources.wxs +++ b/installer/PowerToysSetup/Resources.wxs @@ -11,7 +11,7 @@ - + @@ -181,7 +181,7 @@ @@ -553,6 +553,7 @@ + From efb48aa1634658b31db3ad980b135d3f0427c07b Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Mon, 18 Aug 2025 06:00:13 -0500 Subject: [PATCH 34/99] build: remove *tests* and all coverage/DIA DLLs from binskim (#41108) This thing files about 900 bugs a month on us. Before: ``` Done. 11,036 files scanned. ``` After: ``` Done. 4,753 files scanned. ``` --- .github/actions/spell-check/expect.txt | 3 +++ .pipelines/v2/release.yml | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index 9c9ed952df..bc5ba04289 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -115,6 +115,7 @@ bigbar bigobj binlog binres +binskim BITMAPFILEHEADER bitmapimage BITMAPINFO @@ -255,6 +256,7 @@ Corpor cotaskmem COULDNOT countof +covrun cpcontrols cph cplusplus @@ -969,6 +971,7 @@ msc mscorlib msctls msdata +msdia MSDL MSGFLT MSHCTX diff --git a/.pipelines/v2/release.yml b/.pipelines/v2/release.yml index 18163e899a..d6c2177720 100644 --- a/.pipelines/v2/release.yml +++ b/.pipelines/v2/release.yml @@ -64,6 +64,10 @@ extends: tsa: enabled: true configFile: '$(Build.SourcesDirectory)\.pipelines\tsa.json' + binskim: + enabled: true + # Exclude every dll/exe in tests/*, as well as all msdia*, covrun* and vcruntime* + analyzeTargetGlob: +:file|$(Build.ArtifactStagingDirectory)/**/*.dll;+:file|$(Build.ArtifactStagingDirectory)/**/*.exe;-:file:regex|tests.*\.(dll|exe)$;-:file:regex|(covrun.*)\.dll$;-:file:regex|(msdia.*)\.dll$;-:file:regex|(vcruntime.*)\.dll$ stages: - stage: Build From 6acb79318449850fa0af6b3111c1b598635872dc Mon Sep 17 00:00:00 2001 From: Michael Jolley Date: Mon, 18 Aug 2025 06:07:28 -0500 Subject: [PATCH 35/99] CmdPal: Null pattern matching based on `is` expression rather than overridable operators (#40972) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What the title says. 😄 Rather than relying on the potentially overloaded `!=` or `==` operators when checking for null, now we'll use the `is` expression (possibly combined with the `not` operator) to ensure correct checking. Probably overkill for many of these classes, but decided to err on the side of consistency. Would matter more on classes that may be inherited or extended. Using `is` and `is not` will provide us a guarantee that no user-overloaded equality operators (`==`/`!=`) is invoked when a `expression is null` is evaluated. In code form, changed all instances of: ```c# something != null something == null ``` to: ```c# something is not null something is null ``` The one exception was checking null on a `KeyChord`. `KeyChord` is a struct which is never null so VS will raise an error when trying this versus just providing a warning when using `keyChord != null`. In reality, we shouldn't do this check because it can't ever be null. In the case of a `KeyChord` it **would** be a `KeyChord` equivalent to: ```c# KeyChord keyChord = new () { Modifiers = 0, Vkey = 0, ScanCode = 0 }; ``` --- .../Helpers/ExtensionHostInstance.cs | 6 ++--- .../AppExtensionHost.cs | 10 +++---- .../CommandBarViewModel.cs | 17 ++++++------ .../CommandContextItemViewModel.cs | 4 +-- .../CommandItemViewModel.cs | 22 ++++++++-------- .../CommandViewModel.cs | 10 +++---- .../ConfirmResultViewModel.cs | 2 +- .../ContentPageViewModel.cs | 20 +++++++------- .../ContextMenuViewModel.cs | 15 +++++------ .../DetailsCommandsViewModel.cs | 2 +- .../DetailsElementViewModel.cs | 2 +- .../DetailsLinkViewModel.cs | 6 ++--- .../DetailsTagsViewModel.cs | 2 +- .../DetailsViewModel.cs | 6 ++--- .../IconDataViewModel.cs | 4 +-- .../IconInfoViewModel.cs | 4 +-- .../ListItemViewModel.cs | 12 ++++----- .../ListViewModel.cs | 26 +++++++++---------- .../LogMessageViewModel.cs | 2 +- .../PageViewModel.cs | 8 +++--- .../ProgressViewModel.cs | 4 +-- .../ShellViewModel.cs | 10 +++---- .../StatusMessageViewModel.cs | 10 +++---- .../TagViewModel.cs | 2 +- .../AliasManager.cs | 6 ++--- .../AppStateModel.cs | 2 +- .../CommandProviderWrapper.cs | 6 ++--- .../CommandSettingsViewModel.cs | 8 +++--- .../Commands/CreatedExtensionForm.cs | 2 +- .../Commands/LogMessagesPage.cs | 2 +- .../Commands/MainListPage.cs | 2 +- .../Commands/NewExtensionForm.cs | 2 +- .../Commands/NewExtensionPage.cs | 6 ++--- .../ContentMarkdownViewModel.cs | 6 ++--- .../ContentTreeViewModel.cs | 12 ++++----- .../HotkeyManager.cs | 2 +- .../Models/ExtensionService.cs | 14 +++++----- .../ProviderSettings.cs | 2 +- .../ProviderSettingsViewModel.cs | 12 ++++----- .../RecentCommandsManager.cs | 4 +-- .../SettingsModel.cs | 2 +- .../TopLevelCommandManager.cs | 6 ++--- .../TopLevelViewModel.cs | 8 +++--- .../Controls/CommandBar.xaml.cs | 3 +-- .../Controls/ContentFormControl.xaml.cs | 16 ++++++------ .../Controls/ContextMenu.xaml.cs | 2 +- .../Microsoft.CmdPal.UI/Controls/IconBox.cs | 6 ++--- .../Controls/KeyVisual/KeyVisual.cs | 5 ++-- .../Controls/SearchBar.xaml.cs | 12 ++++----- .../ShortcutControl/ShortcutControl.xaml.cs | 14 +++++----- .../Microsoft.CmdPal.UI/Controls/Tag.xaml.cs | 4 +-- .../ExtViews/ListPage.xaml.cs | 18 ++++++------- .../Helpers/GpoValueChecker.cs | 9 +------ .../Helpers/IconCacheProvider.cs | 3 +-- .../Helpers/IconCacheService.cs | 4 +-- .../Helpers/TrayIconService.cs | 18 ++++++------- .../Helpers/TypedEventHandlerExtensions.cs | 2 +- .../Helpers/WindowHelper.cs | 2 +- .../Microsoft.CmdPal.UI/MainWindow.xaml.cs | 10 +++---- .../Pages/LoadingPage.xaml.cs | 2 +- .../Pages/ShellPage.xaml.cs | 6 ++--- .../PowerToysRootPageService.cs | 2 +- .../NumberTranslatorTests.cs | 4 +-- .../TimeAndDateHelperTests.cs | 4 +-- .../Microsoft.CmdPal.Ext.Apps/AllAppsPage.cs | 6 +---- .../ext/Microsoft.CmdPal.Ext.Apps/AppCache.cs | 3 +-- .../Microsoft.CmdPal.Ext.Apps/AppListItem.cs | 4 +-- .../Programs/AppxPackageHelper.cs | 6 ++--- .../Programs/PackageManagerWrapper.cs | 4 +-- .../Microsoft.CmdPal.Ext.Apps/Programs/UWP.cs | 4 +-- .../Programs/UWPApplication.cs | 6 ++--- .../Programs/Win32Program.cs | 18 ++++++------- .../Storage/FileSystemWatcherWrapper.cs | 2 +- .../Storage/Win32ProgramRepository.cs | 13 +++++----- .../Utils/ComFreeHelper.cs | 3 +-- .../Utils/ShellLinkHelper.cs | 4 +-- .../Utils/ShellLocalization.cs | 2 +- .../Utils/ThemeHelper.cs | 2 +- .../AddBookmarkForm.cs | 2 +- .../BookmarkPlaceholderForm.cs | 2 +- .../BookmarksCommandProvider.cs | 10 +++---- .../UrlCommand.cs | 10 +++---- .../Helper/NumberTranslator.cs | 2 +- .../Helper/ResultHelper.cs | 4 +-- .../Pages/CalculatorListPage.cs | 2 +- .../Pages/FallbackCalculatorItem.cs | 2 +- .../Helpers/ClipboardHelper.cs | 8 +++--- .../Models/ClipboardItem.cs | 2 +- .../Pages/ClipboardHistoryListPage.cs | 6 ++--- .../FallbackOpenFileItem.cs | 6 ++--- .../Indexer/DataSourceManager.cs | 2 +- .../Indexer/SearchQuery.cs | 25 +++++++++--------- .../Indexer/SearchResult.cs | 2 +- .../Indexer/Utils/QueryStringBuilder.cs | 8 +++--- .../Pages/ActionsListContextItem.cs | 10 +++---- .../Pages/DirectoryExplorePage.cs | 12 ++++----- .../Pages/DirectoryPage.cs | 4 +-- .../SearchEngine.cs | 4 +-- .../Helpers/RegistryHelper.cs | 7 +++-- .../Helpers/ResultHelper.cs | 2 +- .../Helpers/ValueHelper.cs | 2 +- .../Commands/ExecuteItem.cs | 2 +- .../Helpers/ShellListPageHelpers.cs | 2 +- .../Pages/RunExeItem.cs | 2 +- .../Pages/ShellListPage.cs | 10 +++---- .../PathListItem.cs | 2 +- .../FallbackSystemCommandItem.cs | 2 +- .../Helpers/NetworkConnectionProperties.cs | 8 +++--- .../FallbackTimeDateItem.cs | 6 ++--- .../Helpers/AvailableResultsList.cs | 2 +- .../Helpers/SettingsManager.cs | 4 +-- .../Helpers/DefaultBrowserInfo.cs | 3 +-- .../Helpers/SettingsManager.cs | 2 +- .../Pages/WebSearchListPage.cs | 6 ++--- .../Pages/InstallPackageCommand.cs | 5 ++-- .../Pages/InstallPackageListItem.cs | 14 +++++----- .../Pages/WinGetExtensionPage.cs | 8 +++--- .../Commands/SwitchToWindowCommand.cs | 4 +-- .../Components/ResultHelper.cs | 2 +- .../Helpers/VirtualDesktopHelper.cs | 20 +++++++------- .../Helpers/ServiceHelper.cs | 4 +-- .../Helpers/UnsupportedSettingsHelper.cs | 4 +-- .../Pages/SampleContentPage.cs | 2 +- .../SampleUpdatingItemsPage.cs | 2 +- .../AnonymousCommand.cs | 2 +- .../ChoiceSetSetting.cs | 2 +- .../ClipboardHelper.cs | 5 +--- .../CommandContextItem.cs | 2 +- .../CommandItem.cs | 6 ++--- .../ExtensionHost.cs | 6 ++--- .../ExtensionInstanceManager`1.cs | 2 +- .../JsonSettingsManager.cs | 2 +- .../Settings.cs | 6 ++--- .../SettingsForm.cs | 2 +- .../ShellHelpers.cs | 2 +- .../StringMatcher.cs | 2 +- .../TextSetting.cs | 2 +- .../ToggleSetting.cs | 2 +- 138 files changed, 395 insertions(+), 431 deletions(-) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/ExtensionHostInstance.cs b/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/ExtensionHostInstance.cs index 25ff815a69..76de2729d0 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/ExtensionHostInstance.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/ExtensionHostInstance.cs @@ -24,7 +24,7 @@ public partial class ExtensionHostInstance /// The log message to send public void LogMessage(ILogMessage message) { - if (Host != null) + if (Host is not null) { _ = Task.Run(async () => { @@ -47,7 +47,7 @@ public partial class ExtensionHostInstance public void ShowStatus(IStatusMessage message, StatusContext context) { - if (Host != null) + if (Host is not null) { _ = Task.Run(async () => { @@ -64,7 +64,7 @@ public partial class ExtensionHostInstance public void HideStatus(IStatusMessage message) { - if (Host != null) + if (Host is not null) { _ = Task.Run(async () => { diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/AppExtensionHost.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/AppExtensionHost.cs index 3a828a3e5d..8a93aee51d 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/AppExtensionHost.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/AppExtensionHost.cs @@ -36,7 +36,7 @@ public abstract partial class AppExtensionHost : IExtensionHost public IAsyncAction HideStatus(IStatusMessage? message) { - if (message == null) + if (message is null) { return Task.CompletedTask.AsAsyncAction(); } @@ -55,7 +55,7 @@ public abstract partial class AppExtensionHost : IExtensionHost public IAsyncAction LogMessage(ILogMessage? message) { - if (message == null) + if (message is null) { return Task.CompletedTask.AsAsyncAction(); } @@ -80,7 +80,7 @@ public abstract partial class AppExtensionHost : IExtensionHost try { var vm = StatusMessages.Where(messageVM => messageVM.Model.Unsafe == message).FirstOrDefault(); - if (vm != null) + if (vm is not null) { StatusMessages.Remove(vm); } @@ -113,7 +113,7 @@ public abstract partial class AppExtensionHost : IExtensionHost { // If this message is already in the list of messages, just bring it to the top var oldVm = StatusMessages.Where(messageVM => messageVM.Model.Unsafe == message).FirstOrDefault(); - if (oldVm != null) + if (oldVm is not null) { Task.Factory.StartNew( () => @@ -142,7 +142,7 @@ public abstract partial class AppExtensionHost : IExtensionHost public IAsyncAction ShowStatus(IStatusMessage? message, StatusContext context) { - if (message == null) + if (message is null) { return Task.CompletedTask.AsAsyncAction(); } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/CommandBarViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/CommandBarViewModel.cs index f506c127f2..c01cb13730 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/CommandBarViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/CommandBarViewModel.cs @@ -2,7 +2,6 @@ // 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.Collections.ObjectModel; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Messaging; using Microsoft.CmdPal.Core.ViewModels.Messages; @@ -35,13 +34,13 @@ public partial class CommandBarViewModel : ObservableObject, [NotifyPropertyChangedFor(nameof(HasPrimaryCommand))] public partial CommandItemViewModel? PrimaryCommand { get; set; } - public bool HasPrimaryCommand => PrimaryCommand != null && PrimaryCommand.ShouldBeVisible; + public bool HasPrimaryCommand => PrimaryCommand is not null && PrimaryCommand.ShouldBeVisible; [ObservableProperty] [NotifyPropertyChangedFor(nameof(HasSecondaryCommand))] public partial CommandItemViewModel? SecondaryCommand { get; set; } - public bool HasSecondaryCommand => SecondaryCommand != null; + public bool HasSecondaryCommand => SecondaryCommand is not null; [ObservableProperty] public partial bool ShouldShowContextMenu { get; set; } = false; @@ -58,14 +57,14 @@ public partial class CommandBarViewModel : ObservableObject, private void SetSelectedItem(ICommandBarContext? value) { - if (value != null) + if (value is not null) { PrimaryCommand = value.PrimaryCommand; value.PropertyChanged += SelectedItemPropertyChanged; } else { - if (SelectedItem != null) + if (SelectedItem is not null) { SelectedItem.PropertyChanged -= SelectedItemPropertyChanged; } @@ -88,7 +87,7 @@ public partial class CommandBarViewModel : ObservableObject, private void UpdateContextItems() { - if (SelectedItem == null) + if (SelectedItem is null) { SecondaryCommand = null; ShouldShowContextMenu = false; @@ -127,13 +126,13 @@ public partial class CommandBarViewModel : ObservableObject, public ContextKeybindingResult CheckKeybinding(bool ctrl, bool alt, bool shift, bool win, VirtualKey key) { var keybindings = SelectedItem?.Keybindings(); - if (keybindings != null) + if (keybindings is not null) { // Does the pressed key match any of the keybindings? var pressedKeyChord = KeyChordHelpers.FromModifiers(ctrl, alt, shift, win, key, 0); if (keybindings.TryGetValue(pressedKeyChord, out var matchedItem)) { - return matchedItem != null ? PerformCommand(matchedItem) : ContextKeybindingResult.Unhandled; + return matchedItem is not null ? PerformCommand(matchedItem) : ContextKeybindingResult.Unhandled; } } @@ -142,7 +141,7 @@ public partial class CommandBarViewModel : ObservableObject, private ContextKeybindingResult PerformCommand(CommandItemViewModel? command) { - if (command == null) + if (command is null) { return ContextKeybindingResult.Unhandled; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/CommandContextItemViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/CommandContextItemViewModel.cs index f2060efe88..4b25f68e0a 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/CommandContextItemViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/CommandContextItemViewModel.cs @@ -20,7 +20,7 @@ public partial class CommandContextItemViewModel(ICommandContextItem contextItem public KeyChord? RequestedShortcut { get; private set; } - public bool HasRequestedShortcut => RequestedShortcut != null && (RequestedShortcut.Value != nullKeyChord); + public bool HasRequestedShortcut => RequestedShortcut is not null && (RequestedShortcut.Value != nullKeyChord); public override void InitializeProperties() { @@ -32,7 +32,7 @@ public partial class CommandContextItemViewModel(ICommandContextItem contextItem base.InitializeProperties(); var contextItem = Model.Unsafe; - if (contextItem == null) + if (contextItem is null) { return; // throw? } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/CommandItemViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/CommandItemViewModel.cs index 1b9dcf211a..4f589a4e2f 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/CommandItemViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/CommandItemViewModel.cs @@ -68,7 +68,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa { get { - List l = _defaultCommandContextItem == null ? + List l = _defaultCommandContextItem is null ? new() : [_defaultCommandContextItem]; @@ -100,7 +100,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa } var model = _commandItemModel.Unsafe; - if (model == null) + if (model is null) { return; } @@ -128,7 +128,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa } var model = _commandItemModel.Unsafe; - if (model == null) + if (model is null) { return; } @@ -136,7 +136,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa Command.InitializeProperties(); var listIcon = model.Icon; - if (listIcon != null) + if (listIcon is not null) { _listItemIcon = new(listIcon); _listItemIcon.InitializeProperties(); @@ -172,13 +172,13 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa } var model = _commandItemModel.Unsafe; - if (model == null) + if (model is null) { return; } var more = model.MoreCommands; - if (more != null) + if (more is not null) { MoreCommands = more .Select(item => @@ -300,7 +300,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa protected virtual void FetchProperty(string propertyName) { var model = this._commandItemModel.Unsafe; - if (model == null) + if (model is null) { return; // throw? } @@ -308,7 +308,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa switch (propertyName) { case nameof(Command): - if (Command != null) + if (Command is not null) { Command.PropertyChanged -= Command_PropertyChanged; } @@ -339,7 +339,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa case nameof(model.MoreCommands): var more = model.MoreCommands; - if (more != null) + if (more is not null) { var newContextMenu = more .Select(item => @@ -394,7 +394,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa // Extensions based on Command Palette SDK < 0.3 CommandItem class won't notify when Title changes because Command // or Command.Name change. This is a workaround to ensure that the Title is always up-to-date for extensions with old SDK. var model = _commandItemModel.Unsafe; - if (model != null) + if (model is not null) { _itemTitle = model.Title; } @@ -430,7 +430,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa Command.SafeCleanup(); var model = _commandItemModel.Unsafe; - if (model != null) + if (model is not null) { model.PropChanged -= Model_PropChanged; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/CommandViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/CommandViewModel.cs index 6e48cef382..30a85045d3 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/CommandViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/CommandViewModel.cs @@ -44,7 +44,7 @@ public partial class CommandViewModel : ExtensionObjectViewModel } var model = Model.Unsafe; - if (model == null) + if (model is null) { return; } @@ -67,13 +67,13 @@ public partial class CommandViewModel : ExtensionObjectViewModel } var model = Model.Unsafe; - if (model == null) + if (model is null) { return; } var ico = model.Icon; - if (ico != null) + if (ico is not null) { Icon = new(ico); Icon.InitializeProperties(); @@ -98,7 +98,7 @@ public partial class CommandViewModel : ExtensionObjectViewModel protected void FetchProperty(string propertyName) { var model = Model.Unsafe; - if (model == null) + if (model is null) { return; // throw? } @@ -125,7 +125,7 @@ public partial class CommandViewModel : ExtensionObjectViewModel Icon = new(null); // necessary? var model = Model.Unsafe; - if (model != null) + if (model is not null) { model.PropChanged -= Model_PropChanged; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ConfirmResultViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ConfirmResultViewModel.cs index 45cd18f4dd..c653357ccd 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ConfirmResultViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ConfirmResultViewModel.cs @@ -25,7 +25,7 @@ public partial class ConfirmResultViewModel(IConfirmationArgs _args, WeakReferen public override void InitializeProperties() { var model = Model.Unsafe; - if (model == null) + if (model is null) { return; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ContentPageViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ContentPageViewModel.cs index 7787916de5..0c0f7c7c12 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ContentPageViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ContentPageViewModel.cs @@ -28,7 +28,7 @@ public abstract partial class ContentPageViewModel : PageViewModel, ICommandBarC public DetailsViewModel? Details { get; private set; } [MemberNotNullWhen(true, nameof(Details))] - public bool HasDetails => Details != null; + public bool HasDetails => Details is not null; /////// ICommandBarContext /////// public IEnumerable MoreCommands => Commands.Skip(1); @@ -67,7 +67,7 @@ public abstract partial class ContentPageViewModel : PageViewModel, ICommandBarC foreach (var item in newItems) { var viewModel = ViewModelFromContent(item, PageContext); - if (viewModel != null) + if (viewModel is not null) { viewModel.InitializeProperties(); newContent.Add(viewModel); @@ -104,7 +104,7 @@ public abstract partial class ContentPageViewModel : PageViewModel, ICommandBarC base.InitializeProperties(); var model = _model.Unsafe; - if (model == null) + if (model is null) { return; // throw? } @@ -133,7 +133,7 @@ public abstract partial class ContentPageViewModel : PageViewModel, ICommandBarC }); var extensionDetails = model.Details; - if (extensionDetails != null) + if (extensionDetails is not null) { Details = new(extensionDetails, PageContext); Details.InitializeProperties(); @@ -156,7 +156,7 @@ public abstract partial class ContentPageViewModel : PageViewModel, ICommandBarC base.FetchProperty(propertyName); var model = this._model.Unsafe; - if (model == null) + if (model is null) { return; // throw? } @@ -166,7 +166,7 @@ public abstract partial class ContentPageViewModel : PageViewModel, ICommandBarC case nameof(Commands): var more = model.Commands; - if (more != null) + if (more is not null) { var newContextMenu = more .ToList() @@ -216,7 +216,7 @@ public abstract partial class ContentPageViewModel : PageViewModel, ICommandBarC break; case nameof(Details): var extensionDetails = model.Details; - Details = extensionDetails != null ? new(extensionDetails, PageContext) : null; + Details = extensionDetails is not null ? new(extensionDetails, PageContext) : null; UpdateDetails(); break; } @@ -248,7 +248,7 @@ public abstract partial class ContentPageViewModel : PageViewModel, ICommandBarC [RelayCommand] private void InvokePrimaryCommand(ContentPageViewModel page) { - if (PrimaryCommand != null) + if (PrimaryCommand is not null) { WeakReferenceMessenger.Default.Send(new(PrimaryCommand.Command.Model, PrimaryCommand.Model)); } @@ -258,7 +258,7 @@ public abstract partial class ContentPageViewModel : PageViewModel, ICommandBarC [RelayCommand] private void InvokeSecondaryCommand(ContentPageViewModel page) { - if (SecondaryCommand != null) + if (SecondaryCommand is not null) { WeakReferenceMessenger.Default.Send(new(SecondaryCommand.Command.Model, SecondaryCommand.Model)); } @@ -285,7 +285,7 @@ public abstract partial class ContentPageViewModel : PageViewModel, ICommandBarC Content.Clear(); var model = _model.Unsafe; - if (model != null) + if (model is not null) { model.ItemsChanged -= Model_ItemsChanged; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ContextMenuViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ContextMenuViewModel.cs index c13d4dbb96..02af0aa67e 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ContextMenuViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ContextMenuViewModel.cs @@ -8,7 +8,6 @@ using CommunityToolkit.Mvvm.Messaging; using Microsoft.CmdPal.Core.ViewModels.Messages; using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions.Toolkit; -using Microsoft.Diagnostics.Utilities; using Windows.System; namespace Microsoft.CmdPal.Core.ViewModels; @@ -51,7 +50,7 @@ public partial class ContextMenuViewModel : ObservableObject, public void UpdateContextItems() { - if (SelectedItem != null) + if (SelectedItem is not null) { if (SelectedItem.MoreCommands.Count() > 1) { @@ -68,14 +67,14 @@ public partial class ContextMenuViewModel : ObservableObject, return; } - if (SelectedItem == null) + if (SelectedItem is null) { return; } _lastSearchText = searchText; - if (CurrentContextMenu == null) + if (CurrentContextMenu is null) { ListHelpers.InPlaceUpdateList(FilteredItems, []); return; @@ -124,7 +123,7 @@ public partial class ContextMenuViewModel : ObservableObject, /// that have a shortcut key set. public Dictionary Keybindings() { - if (CurrentContextMenu == null) + if (CurrentContextMenu is null) { return []; } @@ -140,7 +139,7 @@ public partial class ContextMenuViewModel : ObservableObject, public ContextKeybindingResult? CheckKeybinding(bool ctrl, bool alt, bool shift, bool win, VirtualKey key) { var keybindings = Keybindings(); - if (keybindings != null) + if (keybindings is not null) { // Does the pressed key match any of the keybindings? var pressedKeyChord = KeyChordHelpers.FromModifiers(ctrl, alt, shift, win, key, 0); @@ -190,7 +189,7 @@ public partial class ContextMenuViewModel : ObservableObject, OnPropertyChanging(nameof(CurrentContextMenu)); OnPropertyChanged(nameof(CurrentContextMenu)); - if (CurrentContextMenu != null) + if (CurrentContextMenu is not null) { ListHelpers.InPlaceUpdateList(FilteredItems, [.. CurrentContextMenu!]); } @@ -198,7 +197,7 @@ public partial class ContextMenuViewModel : ObservableObject, public ContextKeybindingResult InvokeCommand(CommandItemViewModel? command) { - if (command == null) + if (command is null) { return ContextKeybindingResult.Unhandled; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsCommandsViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsCommandsViewModel.cs index b85aeaba81..11a67603e9 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsCommandsViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsCommandsViewModel.cs @@ -22,7 +22,7 @@ public partial class DetailsCommandsViewModel( { base.InitializeProperties(); var model = _dataModel.Unsafe; - if (model == null) + if (model is null) { return; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsElementViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsElementViewModel.cs index 390459f26c..9739220b65 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsElementViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsElementViewModel.cs @@ -16,7 +16,7 @@ public abstract partial class DetailsElementViewModel(IDetailsElement _detailsEl public override void InitializeProperties() { var model = _model.Unsafe; - if (model == null) + if (model is null) { return; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsLinkViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsLinkViewModel.cs index e7aa9b67af..427fcd170e 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsLinkViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsLinkViewModel.cs @@ -18,7 +18,7 @@ public partial class DetailsLinkViewModel( public Uri? Link { get; private set; } - public bool IsLink => Link != null; + public bool IsLink => Link is not null; public bool IsText => !IsLink; @@ -26,14 +26,14 @@ public partial class DetailsLinkViewModel( { base.InitializeProperties(); var model = _dataModel.Unsafe; - if (model == null) + if (model is null) { return; } Text = model.Text ?? string.Empty; Link = model.Link; - if (string.IsNullOrEmpty(Text) && Link != null) + if (string.IsNullOrEmpty(Text) && Link is not null) { Text = Link.ToString(); } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsTagsViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsTagsViewModel.cs index 803585c1ce..747a0a74c9 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsTagsViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsTagsViewModel.cs @@ -22,7 +22,7 @@ public partial class DetailsTagsViewModel( { base.InitializeProperties(); var model = _dataModel.Unsafe; - if (model == null) + if (model is null) { return; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsViewModel.cs index 034e247519..a381cfda6b 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/DetailsViewModel.cs @@ -26,7 +26,7 @@ public partial class DetailsViewModel(IDetails _details, WeakReference new DetailsTagsViewModel(element, this.PageContext), _ => null, }; - if (vm != null) + if (vm is not null) { vm.InitializeProperties(); Metadata.Add(vm); diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/IconDataViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/IconDataViewModel.cs index 70b143864c..5f4b4436f2 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/IconDataViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/IconDataViewModel.cs @@ -16,7 +16,7 @@ public partial class IconDataViewModel : ObservableObject, IIconData // If the extension previously gave us a Data, then died, the data will // throw if we actually try to read it, but the pointer itself won't be // null, so this is relatively safe. - public bool HasIcon => !string.IsNullOrEmpty(Icon) || Data.Unsafe != null; + public bool HasIcon => !string.IsNullOrEmpty(Icon) || Data.Unsafe is not null; // Locally cached properties from IIconData. public string Icon { get; private set; } = string.Empty; @@ -36,7 +36,7 @@ public partial class IconDataViewModel : ObservableObject, IIconData public void InitializeProperties() { var model = _model.Unsafe; - if (model == null) + if (model is null) { return; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/IconInfoViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/IconInfoViewModel.cs index 21ddbe99d9..aebe9b03aa 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/IconInfoViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/IconInfoViewModel.cs @@ -26,7 +26,7 @@ public partial class IconInfoViewModel : ObservableObject, IIconInfo public bool HasIcon(bool light) => IconForTheme(light).HasIcon; - public bool IsSet => _model.Unsafe != null; + public bool IsSet => _model.Unsafe is not null; IIconData? IIconInfo.Dark => Dark; @@ -43,7 +43,7 @@ public partial class IconInfoViewModel : ObservableObject, IIconInfo public void InitializeProperties() { var model = _model.Unsafe; - if (model == null) + if (model is null) { return; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ListItemViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ListItemViewModel.cs index 682bf4daea..ad1aebe2d1 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ListItemViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ListItemViewModel.cs @@ -27,7 +27,7 @@ public partial class ListItemViewModel(IListItem model, WeakReference Details != null; + public bool HasDetails => Details is not null; public override void InitializeProperties() { @@ -40,7 +40,7 @@ public partial class ListItemViewModel(IListItem model, WeakReference(new(item.Command.Model, item.Model)); } - else if (ShowEmptyContent && EmptyContent.PrimaryCommand?.Model.Unsafe != null) + else if (ShowEmptyContent && EmptyContent.PrimaryCommand?.Model.Unsafe is not null) { WeakReferenceMessenger.Default.Send(new( EmptyContent.PrimaryCommand.Command.Model, @@ -314,14 +314,14 @@ public partial class ListViewModel : PageViewModel, IDisposable [RelayCommand] private void InvokeSecondaryCommand(ListItemViewModel? item) { - if (item != null) + if (item is not null) { - if (item.SecondaryCommand != null) + if (item.SecondaryCommand is not null) { WeakReferenceMessenger.Default.Send(new(item.SecondaryCommand.Command.Model, item.Model)); } } - else if (ShowEmptyContent && EmptyContent.SecondaryCommand?.Model.Unsafe != null) + else if (ShowEmptyContent && EmptyContent.SecondaryCommand?.Model.Unsafe is not null) { WeakReferenceMessenger.Default.Send(new( EmptyContent.SecondaryCommand.Command.Model, @@ -332,12 +332,12 @@ public partial class ListViewModel : PageViewModel, IDisposable [RelayCommand] private void UpdateSelectedItem(ListItemViewModel? item) { - if (_lastSelectedItem != null) + if (_lastSelectedItem is not null) { _lastSelectedItem.PropertyChanged -= SelectedItemPropertyChanged; } - if (item != null) + if (item is not null) { SetSelectedItem(item); } @@ -383,7 +383,7 @@ public partial class ListViewModel : PageViewModel, IDisposable private void SelectedItemPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e) { var item = _lastSelectedItem; - if (item == null) + if (item is null) { return; } @@ -438,7 +438,7 @@ public partial class ListViewModel : PageViewModel, IDisposable base.InitializeProperties(); var model = _model.Unsafe; - if (model == null) + if (model is null) { return; // throw? } @@ -465,7 +465,7 @@ public partial class ListViewModel : PageViewModel, IDisposable public void LoadMoreIfNeeded() { var model = this._model.Unsafe; - if (model == null) + if (model is null) { return; } @@ -509,7 +509,7 @@ public partial class ListViewModel : PageViewModel, IDisposable base.FetchProperty(propertyName); var model = this._model.Unsafe; - if (model == null) + if (model is null) { return; // throw? } @@ -540,7 +540,7 @@ public partial class ListViewModel : PageViewModel, IDisposable private void UpdateEmptyContent() { UpdateProperty(nameof(ShowEmptyContent)); - if (!ShowEmptyContent || EmptyContent.Model.Unsafe == null) + if (!ShowEmptyContent || EmptyContent.Model.Unsafe is null) { return; } @@ -588,7 +588,7 @@ public partial class ListViewModel : PageViewModel, IDisposable } var model = _model.Unsafe; - if (model != null) + if (model is not null) { model.ItemsChanged -= Model_ItemsChanged; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/LogMessageViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/LogMessageViewModel.cs index 9ebff20304..969bf60aea 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/LogMessageViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/LogMessageViewModel.cs @@ -22,7 +22,7 @@ public partial class LogMessageViewModel : ExtensionObjectViewModel public override void InitializeProperties() { var model = _model.Unsafe; - if (model == null) + if (model is null) { return; // throw? } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/PageViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/PageViewModel.cs index 552971b96c..7a301c89b0 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/PageViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/PageViewModel.cs @@ -45,7 +45,7 @@ public partial class PageViewModel : ExtensionObjectViewModel, IPageContext [ObservableProperty] public partial AppExtensionHost ExtensionHost { get; private set; } - public bool HasStatusMessage => MostRecentStatusMessage != null; + public bool HasStatusMessage => MostRecentStatusMessage is not null; [ObservableProperty] [NotifyPropertyChangedFor(nameof(HasStatusMessage))] @@ -132,7 +132,7 @@ public partial class PageViewModel : ExtensionObjectViewModel, IPageContext public override void InitializeProperties() { var page = _pageModel.Unsafe; - if (page == null) + if (page is null) { return; // throw? } @@ -177,7 +177,7 @@ public partial class PageViewModel : ExtensionObjectViewModel, IPageContext protected virtual void FetchProperty(string propertyName) { var model = this._pageModel.Unsafe; - if (model == null) + if (model is null) { return; // throw? } @@ -240,7 +240,7 @@ public partial class PageViewModel : ExtensionObjectViewModel, IPageContext ExtensionHost.StatusMessages.CollectionChanged -= StatusMessages_CollectionChanged; var model = _pageModel.Unsafe; - if (model != null) + if (model is not null) { model.PropChanged -= Model_PropChanged; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ProgressViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ProgressViewModel.cs index 40ea290dd4..4ddcfb22e7 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ProgressViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ProgressViewModel.cs @@ -24,7 +24,7 @@ public partial class ProgressViewModel : ExtensionObjectViewModel public override void InitializeProperties() { var model = Model.Unsafe; - if (model == null) + if (model is null) { return; // throw? } @@ -50,7 +50,7 @@ public partial class ProgressViewModel : ExtensionObjectViewModel protected virtual void FetchProperty(string propertyName) { var model = this.Model.Unsafe; - if (model == null) + if (model is null) { return; // throw? } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ShellViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ShellViewModel.cs index 3663190f11..6c660d52f2 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ShellViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/ShellViewModel.cs @@ -120,7 +120,7 @@ public partial class ShellViewModel : ObservableObject, ////LoadedState = ViewModelLoadedState.Loading; if (!viewModel.IsInitialized - && viewModel.InitializeCommand != null) + && viewModel.InitializeCommand is not null) { _ = Task.Run(async () => { @@ -185,7 +185,7 @@ public partial class ShellViewModel : ObservableObject, private void PerformCommand(PerformCommandMessage message) { var command = message.Command.Unsafe; - if (command == null) + if (command is null) { return; } @@ -205,7 +205,7 @@ public partial class ShellViewModel : ObservableObject, // Construct our ViewModel of the appropriate type and pass it the UI Thread context. var pageViewModel = _pageViewModelFactory.TryCreatePageViewModel(page, _isNested, host); - if (pageViewModel == null) + if (pageViewModel is null) { Logger.LogError($"Failed to create ViewModel for page {page.GetType().Name}"); throw new NotSupportedException(); @@ -240,7 +240,7 @@ public partial class ShellViewModel : ObservableObject, // TODO GH #525 This needs more better locking. lock (_invokeLock) { - if (_handleInvokeTask != null) + if (_handleInvokeTask is not null) { // do nothing - a command is already doing a thing } @@ -280,7 +280,7 @@ public partial class ShellViewModel : ObservableObject, private void UnsafeHandleCommandResult(ICommandResult? result) { - if (result == null) + if (result is null) { // No result, nothing to do. return; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/StatusMessageViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/StatusMessageViewModel.cs index fb8b333637..2c78ff407e 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/StatusMessageViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/StatusMessageViewModel.cs @@ -17,7 +17,7 @@ public partial class StatusMessageViewModel : ExtensionObjectViewModel public ProgressViewModel? Progress { get; private set; } - public bool HasProgress => Progress != null; + public bool HasProgress => Progress is not null; public StatusMessageViewModel(IStatusMessage message, WeakReference context) : base(context) @@ -28,7 +28,7 @@ public partial class StatusMessageViewModel : ExtensionObjectViewModel public override void InitializeProperties() { var model = Model.Unsafe; - if (model == null) + if (model is null) { return; // throw? } @@ -36,7 +36,7 @@ public partial class StatusMessageViewModel : ExtensionObjectViewModel Message = model.Message; State = model.State; var modelProgress = model.Progress; - if (modelProgress != null) + if (modelProgress is not null) { Progress = new(modelProgress, this.PageContext); Progress.InitializeProperties(); @@ -61,7 +61,7 @@ public partial class StatusMessageViewModel : ExtensionObjectViewModel protected virtual void FetchProperty(string propertyName) { var model = this.Model.Unsafe; - if (model == null) + if (model is null) { return; // throw? } @@ -76,7 +76,7 @@ public partial class StatusMessageViewModel : ExtensionObjectViewModel break; case nameof(Progress): var modelProgress = model.Progress; - if (modelProgress != null) + if (modelProgress is not null) { Progress = new(modelProgress, this.PageContext); Progress.InitializeProperties(); diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/TagViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/TagViewModel.cs index 98ea66f4e8..5287cf441c 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/TagViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/TagViewModel.cs @@ -28,7 +28,7 @@ public partial class TagViewModel(ITag _tag, WeakReference context public override void InitializeProperties() { var model = _tagModel.Unsafe; - if (model == null) + if (model is null) { return; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/AliasManager.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/AliasManager.cs index 131d633940..642e5ad4a9 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/AliasManager.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/AliasManager.cs @@ -35,7 +35,7 @@ public partial class AliasManager : ObservableObject try { var topLevelCommand = _topLevelCommandManager.LookupCommand(alias.CommandId); - if (topLevelCommand != null) + if (topLevelCommand is not null) { WeakReferenceMessenger.Default.Send(); @@ -88,7 +88,7 @@ public partial class AliasManager : ObservableObject } // If we already have _this exact alias_, do nothing - if (newAlias != null && + if (newAlias is not null && _aliases.TryGetValue(newAlias.SearchPrefix, out var existingAlias)) { if (existingAlias.CommandId == commandId) @@ -113,7 +113,7 @@ public partial class AliasManager : ObservableObject _aliases.Remove(alias.SearchPrefix); } - if (newAlias != null) + if (newAlias is not null) { AddAlias(newAlias); } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/AppStateModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/AppStateModel.cs index dd0cfa817d..3a11c50a59 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/AppStateModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/AppStateModel.cs @@ -55,7 +55,7 @@ public partial class AppStateModel : ObservableObject var loaded = JsonSerializer.Deserialize(jsonContent, JsonSerializationContext.Default.AppStateModel); - Debug.WriteLine(loaded != null ? "Loaded settings file" : "Failed to parse"); + Debug.WriteLine(loaded is not null ? "Loaded settings file" : "Failed to parse"); return loaded ?? new(); } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandProviderWrapper.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandProviderWrapper.cs index 852babe4b7..59903d7ed8 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandProviderWrapper.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandProviderWrapper.cs @@ -15,7 +15,7 @@ namespace Microsoft.CmdPal.UI.ViewModels; public sealed class CommandProviderWrapper { - public bool IsExtension => Extension != null; + public bool IsExtension => Extension is not null; private readonly bool isValid; @@ -188,14 +188,14 @@ public sealed class CommandProviderWrapper return topLevelViewModel; }; - if (commands != null) + if (commands is not null) { TopLevelItems = commands .Select(c => makeAndAdd(c, false)) .ToArray(); } - if (fallbacks != null) + if (fallbacks is not null) { FallbackItems = fallbacks .Select(c => makeAndAdd(c, true)) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandSettingsViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandSettingsViewModel.cs index 5709a643cb..2c2eafc44c 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandSettingsViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandSettingsViewModel.cs @@ -18,18 +18,18 @@ public partial class CommandSettingsViewModel(ICommandSettings? _unsafeSettings, public bool Initialized { get; private set; } public bool HasSettings => - _model.Unsafe != null && // We have a settings model AND - (!Initialized || SettingsPage != null); // we weren't initialized, OR we were, and we do have a settings page + _model.Unsafe is not null && // We have a settings model AND + (!Initialized || SettingsPage is not null); // we weren't initialized, OR we were, and we do have a settings page private void UnsafeInitializeProperties() { var model = _model.Unsafe; - if (model == null) + if (model is null) { return; } - if (model.SettingsPage != null) + if (model.SettingsPage is not null) { SettingsPage = new CommandPaletteContentPageViewModel(model.SettingsPage, mainThread, provider.ExtensionHost); SettingsPage.InitializeProperties(); diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/CreatedExtensionForm.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/CreatedExtensionForm.cs index 44bcb49cb3..4ab993d84a 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/CreatedExtensionForm.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/CreatedExtensionForm.cs @@ -30,7 +30,7 @@ internal sealed partial class CreatedExtensionForm : NewExtensionFormBase public override ICommandResult SubmitForm(string inputs, string data) { var dataInput = JsonNode.Parse(data)?.AsObject(); - if (dataInput == null) + if (dataInput is null) { return CommandResult.KeepOpen(); } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/LogMessagesPage.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/LogMessagesPage.cs index acb04889fb..90dea58e5c 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/LogMessagesPage.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/LogMessagesPage.cs @@ -23,7 +23,7 @@ public partial class LogMessagesPage : ListPage private void LogMessages_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { - if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems != null) + if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems is not null) { foreach (var item in e.NewItems) { 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 9c4750b0e9..781371a866 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/MainListPage.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/MainListPage.cs @@ -203,7 +203,7 @@ public partial class MainListPage : DynamicListPage, // If we don't have any previous filter results to work with, start // with a list of all our commands & apps. - if (_filteredItems == null) + if (_filteredItems is null) { _filteredItems = commands; _filteredItemsIncludesApps = _includeApps; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionForm.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionForm.cs index c1f3f64612..62301714e9 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionForm.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionForm.cs @@ -98,7 +98,7 @@ internal sealed partial class NewExtensionForm : NewExtensionFormBase public override CommandResult SubmitForm(string payload) { var formInput = JsonNode.Parse(payload)?.AsObject(); - if (formInput == null) + if (formInput is null) { return CommandResult.KeepOpen(); } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionPage.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionPage.cs index 8cfa9658d4..6bdb8a7330 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionPage.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionPage.cs @@ -14,7 +14,7 @@ public partial class NewExtensionPage : ContentPage public override IContent[] GetContent() { - return _resultForm != null ? [_resultForm] : [_inputForm]; + return _resultForm is not null ? [_resultForm] : [_inputForm]; } public NewExtensionPage() @@ -28,13 +28,13 @@ public partial class NewExtensionPage : ContentPage private void FormSubmitted(NewExtensionFormBase sender, NewExtensionFormBase? args) { - if (_resultForm != null) + if (_resultForm is not null) { _resultForm.FormSubmitted -= FormSubmitted; } _resultForm = args; - if (_resultForm != null) + if (_resultForm is not null) { _resultForm.FormSubmitted += FormSubmitted; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentMarkdownViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentMarkdownViewModel.cs index 8ae0935f12..c747bfc231 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentMarkdownViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentMarkdownViewModel.cs @@ -20,7 +20,7 @@ public partial class ContentMarkdownViewModel(IMarkdownContent _markdown, WeakRe public override void InitializeProperties() { var model = Model.Unsafe; - if (model == null) + if (model is null) { return; } @@ -47,7 +47,7 @@ public partial class ContentMarkdownViewModel(IMarkdownContent _markdown, WeakRe protected void FetchProperty(string propertyName) { var model = Model.Unsafe; - if (model == null) + if (model is null) { return; // throw? } @@ -66,7 +66,7 @@ public partial class ContentMarkdownViewModel(IMarkdownContent _markdown, WeakRe { base.UnsafeCleanup(); var model = Model.Unsafe; - if (model != null) + if (model is not null) { model.PropChanged -= Model_PropChanged; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentTreeViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentTreeViewModel.cs index 6368f86ac6..6b6a579207 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentTreeViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentTreeViewModel.cs @@ -30,13 +30,13 @@ public partial class ContentTreeViewModel(ITreeContent _tree, WeakReference item.Hotkey == null); + _commandHotkeys.RemoveAll(item => item.Hotkey is null); foreach (var item in _commandHotkeys) { diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Models/ExtensionService.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Models/ExtensionService.cs index 364d234f5e..f0a14ab7db 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Models/ExtensionService.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Models/ExtensionService.cs @@ -90,7 +90,7 @@ public partial class ExtensionService : IExtensionService, IDisposable }).Result; var isExtension = isCmdPalExtensionResult.IsExtension; var extension = isCmdPalExtensionResult.Extension; - if (isExtension && extension != null) + if (isExtension && extension is not null) { CommandPaletteHost.Instance.DebugLog($"Installed new extension app {extension.DisplayName}"); @@ -152,7 +152,7 @@ public partial class ExtensionService : IExtensionService, IDisposable { var (cmdPalProvider, classId) = await GetCmdPalExtensionPropertiesAsync(extension); - return new(cmdPalProvider != null && classId.Count != 0, extension); + return new(cmdPalProvider is not null && classId.Count != 0, extension); } } @@ -237,7 +237,7 @@ public partial class ExtensionService : IExtensionService, IDisposable { var (cmdPalProvider, classIds) = await GetCmdPalExtensionPropertiesAsync(extension); - if (cmdPalProvider == null || classIds.Count == 0) + if (cmdPalProvider is null || classIds.Count == 0) { return []; } @@ -352,12 +352,12 @@ public partial class ExtensionService : IExtensionService, IDisposable { var propSetList = new List(); var singlePropertySet = GetSubPropertySet(activationPropSet, CreateInstanceProperty); - if (singlePropertySet != null) + if (singlePropertySet is not null) { var classId = GetProperty(singlePropertySet, ClassIdProperty); // If the instance has a classId as a single string, then it's only supporting a single instance. - if (classId != null) + if (classId is not null) { propSetList.Add(classId); } @@ -365,7 +365,7 @@ public partial class ExtensionService : IExtensionService, IDisposable else { var propertySetArray = GetSubPropertySetArray(activationPropSet, CreateInstanceProperty); - if (propertySetArray != null) + if (propertySetArray is not null) { foreach (var prop in propertySetArray) { @@ -375,7 +375,7 @@ public partial class ExtensionService : IExtensionService, IDisposable } var classId = GetProperty(propertySet, ClassIdProperty); - if (classId != null) + if (classId is not null) { propSetList.Add(classId); } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ProviderSettings.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ProviderSettings.cs index ec33bf4216..1e20040d57 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ProviderSettings.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ProviderSettings.cs @@ -35,7 +35,7 @@ public class ProviderSettings public void Connect(CommandProviderWrapper wrapper) { ProviderId = wrapper.ProviderId; - IsBuiltin = wrapper.Extension == null; + IsBuiltin = wrapper.Extension is null; ProviderDisplayName = wrapper.DisplayName; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ProviderSettingsViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ProviderSettingsViewModel.cs index 838e77cb62..714b3ca805 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ProviderSettingsViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ProviderSettingsViewModel.cs @@ -33,7 +33,7 @@ public partial class ProviderSettingsViewModel( Resources.builtin_disabled_extension; [MemberNotNullWhen(true, nameof(Extension))] - public bool IsFromExtension => _provider.Extension != null; + public bool IsFromExtension => _provider.Extension is not null; public IExtensionWrapper? Extension => _provider.Extension; @@ -76,7 +76,7 @@ public partial class ProviderSettingsViewModel( { get { - if (_provider.Settings == null) + if (_provider.Settings is null) { return false; } @@ -100,7 +100,7 @@ public partial class ProviderSettingsViewModel( { get { - if (_provider.Settings == null) + if (_provider.Settings is null) { return null; } @@ -126,7 +126,7 @@ public partial class ProviderSettingsViewModel( { get { - if (field == null) + if (field is null) { field = BuildTopLevelViewModels(); } @@ -149,7 +149,7 @@ public partial class ProviderSettingsViewModel( { get { - if (field == null) + if (field is null) { field = BuildFallbackViewModels(); } @@ -173,7 +173,7 @@ public partial class ProviderSettingsViewModel( private void InitializeSettingsPage() { - if (_provider.Settings == null) + if (_provider.Settings is null) { return; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/RecentCommandsManager.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/RecentCommandsManager.cs index 8551b5f964..9135c9588a 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/RecentCommandsManager.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/RecentCommandsManager.cs @@ -30,7 +30,7 @@ public partial class RecentCommandsManager : ObservableObject // These numbers are vaguely scaled so that "VS" will make "Visual Studio" the // match after one use. // Usually it has a weight of 84, compared to 109 for the VS cmd prompt - if (entry.Item != null) + if (entry.Item is not null) { var index = entry.Index; @@ -61,7 +61,7 @@ public partial class RecentCommandsManager : ObservableObject var entry = History .Where(item => item.CommandId == commandId) .FirstOrDefault(); - if (entry == null) + if (entry is null) { var newitem = new HistoryItem() { CommandId = commandId, Uses = 1 }; History.Insert(0, newitem); diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs index 587a8e4f62..b0d10a5285 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs @@ -95,7 +95,7 @@ public partial class SettingsModel : ObservableObject var loaded = JsonSerializer.Deserialize(jsonContent, JsonSerializationContext.Default.SettingsModel); - Debug.WriteLine(loaded != null ? "Loaded settings file" : "Failed to parse"); + Debug.WriteLine(loaded is not null ? "Loaded settings file" : "Failed to parse"); return loaded ?? new(); } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelCommandManager.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelCommandManager.cs index 75c327385d..3bd2d8cedf 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelCommandManager.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelCommandManager.cs @@ -249,7 +249,7 @@ public partial class TopLevelCommandManager : ObservableObject, _extensionCommandProviders.Clear(); } - if (extensions != null) + if (extensions is not null) { await StartExtensionsAndGetCommands(extensions); } @@ -283,7 +283,7 @@ public partial class TopLevelCommandManager : ObservableObject, var startTasks = extensions.Select(StartExtensionWithTimeoutAsync); // Wait for all extensions to start - var wrappers = (await Task.WhenAll(startTasks)).Where(wrapper => wrapper != null).Select(w => w!).ToList(); + var wrappers = (await Task.WhenAll(startTasks)).Where(wrapper => wrapper is not null).Select(w => w!).ToList(); lock (_commandProvidersLock) { @@ -293,7 +293,7 @@ public partial class TopLevelCommandManager : ObservableObject, // Load the commands from the providers in parallel var loadTasks = wrappers.Select(LoadCommandsWithTimeoutAsync); - var commandSets = (await Task.WhenAll(loadTasks)).Where(results => results != null).Select(r => r!).ToList(); + var commandSets = (await Task.WhenAll(loadTasks)).Where(results => results is not null).Select(r => r!).ToList(); lock (TopLevelCommands) { diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelViewModel.cs index 7bdb0ed904..e73f5b09ba 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelViewModel.cs @@ -240,7 +240,7 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem private void FetchAliasFromAliasManager() { var am = _serviceProvider.GetService(); - if (am != null) + if (am is not null) { var commandAlias = am.AliasFromId(Id); if (commandAlias is not null) @@ -254,7 +254,7 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem private void UpdateHotkey() { var hotkey = _settings.CommandHotkeys.Where(hk => hk.CommandId == Id).FirstOrDefault(); - if (hotkey != null) + if (hotkey is not null) { _hotkey = hotkey.Hotkey; } @@ -264,12 +264,12 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem { List tags = []; - if (Hotkey != null) + if (Hotkey is not null) { tags.Add(new Tag() { Text = Hotkey.ToString() }); } - if (Alias != null) + if (Alias is not null) { tags.Add(new Tag() { Text = Alias.SearchPrefix }); } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml.cs index 4dec691009..f4a0dc3d43 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml.cs @@ -10,7 +10,6 @@ using Microsoft.CmdPal.UI.Views; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls.Primitives; -using Microsoft.UI.Xaml.Input; using Windows.System; namespace Microsoft.CmdPal.UI.Controls; @@ -50,7 +49,7 @@ public sealed partial class CommandBar : UserControl, return; } - if (message.Element == null) + if (message.Element is null) { _ = DispatcherQueue.TryEnqueue( () => diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContentFormControl.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContentFormControl.xaml.cs index 78805f00b2..3301326883 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContentFormControl.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContentFormControl.xaml.cs @@ -44,7 +44,7 @@ public sealed partial class ContentFormControl : UserControl // 5% BODGY: if we set this multiple times over the lifetime of the app, // then the second call will explode, because "CardOverrideStyles is already the child of another element". // SO only set this once. - if (_renderer.OverrideStyles == null) + if (_renderer.OverrideStyles is null) { _renderer.OverrideStyles = CardOverrideStyles; } @@ -55,19 +55,19 @@ public sealed partial class ContentFormControl : UserControl private void AttachViewModel(ContentFormViewModel? vm) { - if (_viewModel != null) + if (_viewModel is not null) { _viewModel.PropertyChanged -= ViewModel_PropertyChanged; } _viewModel = vm; - if (_viewModel != null) + if (_viewModel is not null) { _viewModel.PropertyChanged += ViewModel_PropertyChanged; var c = _viewModel.Card; - if (c != null) + if (c is not null) { DisplayCard(c); } @@ -76,7 +76,7 @@ public sealed partial class ContentFormControl : UserControl private void ViewModel_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e) { - if (ViewModel == null) + if (ViewModel is null) { return; } @@ -84,7 +84,7 @@ public sealed partial class ContentFormControl : UserControl if (e.PropertyName == nameof(ViewModel.Card)) { var c = ViewModel.Card; - if (c != null) + if (c is not null) { DisplayCard(c); } @@ -95,7 +95,7 @@ public sealed partial class ContentFormControl : UserControl { _renderedCard = _renderer.RenderAdaptiveCard(result.AdaptiveCard); ContentGrid.Children.Clear(); - if (_renderedCard.FrameworkElement != null) + if (_renderedCard.FrameworkElement is not null) { ContentGrid.Children.Add(_renderedCard.FrameworkElement); @@ -148,7 +148,7 @@ public sealed partial class ContentFormControl : UserControl // Recursively check children var result = FindFirstFocusableElement(child); - if (result != null) + if (result is not null) { return result; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContextMenu.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContextMenu.xaml.cs index ac1e06aa36..bde733eea8 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContextMenu.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContextMenu.xaml.cs @@ -31,7 +31,7 @@ public sealed partial class ContextMenu : UserControl, WeakReferenceMessenger.Default.Register(this); WeakReferenceMessenger.Default.Register(this); - if (ViewModel != null) + if (ViewModel is not null) { ViewModel.PropertyChanged += ViewModel_PropertyChanged; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/IconBox.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/IconBox.cs index ba4c9d8c17..dd6d5fd4ff 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/IconBox.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/IconBox.cs @@ -91,7 +91,7 @@ public partial class IconBox : ContentControl { if (d is IconBox @this) { - if (e.NewValue == null) + if (e.NewValue is null) { @this.Source = null; } @@ -104,7 +104,7 @@ public partial class IconBox : ContentControl var requestedTheme = @this.ActualTheme; var eventArgs = new SourceRequestedEventArgs(e.NewValue, requestedTheme); - if (@this.SourceRequested != null) + if (@this.SourceRequested is not null) { await @this.SourceRequested.InvokeAsync(@this, eventArgs); @@ -142,7 +142,7 @@ public partial class IconBox : ContentControl iconData = requestedTheme == ElementTheme.Light ? info.Light : info.Dark; } - if (iconData != null && + if (iconData is not null && @this.Source is FontIconSource) { if (!string.IsNullOrEmpty(iconData.Icon) && iconData.Icon.Length <= 2) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/KeyVisual/KeyVisual.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/KeyVisual/KeyVisual.cs index 609bcec62e..ed7022fce9 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/KeyVisual/KeyVisual.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/KeyVisual/KeyVisual.cs @@ -2,7 +2,6 @@ // 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.CmdPal.UI; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Markup; @@ -80,12 +79,12 @@ public sealed partial class KeyVisual : Control private void Update() { - if (_keyVisual == null) + if (_keyVisual is null) { return; } - if (_keyVisual.Content != null) + if (_keyVisual.Content is not null) { if (_keyVisual.Content.GetType() == typeof(string)) { diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/SearchBar.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/SearchBar.xaml.cs index d048a2ab04..7b34594b46 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/SearchBar.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/SearchBar.xaml.cs @@ -51,13 +51,13 @@ public sealed partial class SearchBar : UserControl, //// TODO: If the Debounce timer hasn't fired, we may want to store the current Filter in the OldValue/prior VM, but we don't want that to go actually do work... var @this = (SearchBar)d; - if (@this != null + if (@this is not null && e.OldValue is PageViewModel old) { old.PropertyChanged -= @this.Page_PropertyChanged; } - if (@this != null + if (@this is not null && e.NewValue is PageViewModel page) { // TODO: In some cases we probably want commands to clear a filter @@ -85,7 +85,7 @@ public sealed partial class SearchBar : UserControl, { this.FilterBox.Text = string.Empty; - if (CurrentPageViewModel != null) + if (CurrentPageViewModel is not null) { CurrentPageViewModel.Filter = string.Empty; } @@ -143,7 +143,7 @@ public sealed partial class SearchBar : UserControl, FilterBox.Text = string.Empty; // hack TODO GH #245 - if (CurrentPageViewModel != null) + if (CurrentPageViewModel is not null) { CurrentPageViewModel.Filter = FilterBox.Text; } @@ -154,7 +154,7 @@ public sealed partial class SearchBar : UserControl, else if (e.Key == VirtualKey.Back) { // hack TODO GH #245 - if (CurrentPageViewModel != null) + if (CurrentPageViewModel is not null) { CurrentPageViewModel.Filter = FilterBox.Text; } @@ -318,7 +318,7 @@ public sealed partial class SearchBar : UserControl, } // Actually plumb Filtering to the view model - if (CurrentPageViewModel != null) + if (CurrentPageViewModel is not null) { CurrentPageViewModel.Filter = FilterBox.Text; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ShortcutControl/ShortcutControl.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ShortcutControl/ShortcutControl.xaml.cs index b89a627d70..e7fa721277 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ShortcutControl/ShortcutControl.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ShortcutControl/ShortcutControl.xaml.cs @@ -39,13 +39,13 @@ public sealed partial class ShortcutControl : UserControl, IDisposable, IRecipie private static void OnAllowDisableChanged(DependencyObject d, DependencyPropertyChangedEventArgs? e) { var me = d as ShortcutControl; - if (me == null) + if (me is null) { return; } var description = me.c?.FindDescendant(); - if (description == null) + if (description is null) { return; } @@ -431,7 +431,7 @@ public sealed partial class ShortcutControl : UserControl, IDisposable, IRecipie private void ShortcutDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) { - if (lastValidSettings != null && ComboIsValid(lastValidSettings)) + if (lastValidSettings is not null && ComboIsValid(lastValidSettings)) { HotkeySettings = lastValidSettings with { }; } @@ -458,7 +458,7 @@ public sealed partial class ShortcutControl : UserControl, IDisposable, IRecipie private static bool ComboIsValid(HotkeySettings? settings) { - return settings != null && (settings.IsValid() || settings.IsEmpty()); + return settings is not null && (settings.IsValid() || settings.IsEmpty()); } public void Receive(WindowActivatedEventArgs message) => DoWindowActivated(message); @@ -466,12 +466,12 @@ public sealed partial class ShortcutControl : UserControl, IDisposable, IRecipie private void DoWindowActivated(WindowActivatedEventArgs args) { args.Handled = true; - if (args.WindowActivationState != WindowActivationState.Deactivated && (hook == null || hook.GetDisposedState() == true)) + if (args.WindowActivationState != WindowActivationState.Deactivated && (hook is null || hook.GetDisposedState() == true)) { // If the PT settings window gets focussed/activated again, we enable the keyboard hook to catch the keyboard input. hook = new HotkeySettingsControlHook(Hotkey_KeyDown, Hotkey_KeyUp, Hotkey_IsActive, FilterAccessibleKeyboardEvents); } - else if (args.WindowActivationState == WindowActivationState.Deactivated && hook != null && hook.GetDisposedState() == false) + else if (args.WindowActivationState == WindowActivationState.Deactivated && hook is not null && hook.GetDisposedState() == false) { // If the PT settings window lost focus/activation, we disable the keyboard hook to allow keyboard input on other windows. hook.Dispose(); @@ -490,7 +490,7 @@ public sealed partial class ShortcutControl : UserControl, IDisposable, IRecipie { if (disposing) { - if (hook != null) + if (hook is not null) { hook.Dispose(); } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/Tag.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/Tag.xaml.cs index 9f96eebd1d..b74cc54687 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/Tag.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/Tag.xaml.cs @@ -84,7 +84,7 @@ public partial class Tag : Control return; } - if (tag.ForegroundColor != null && + if (tag.ForegroundColor is not null && OptionalColorBrushCacheProvider.Convert(tag.ForegroundColor.Value) is SolidColorBrush brush) { tag.Foreground = brush; @@ -114,7 +114,7 @@ public partial class Tag : Control return; } - if (tag.BackgroundColor != null && + if (tag.BackgroundColor is not null && OptionalColorBrushCacheProvider.Convert(tag.BackgroundColor.Value) is SolidColorBrush brush) { tag.Background = brush; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/ExtViews/ListPage.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/ExtViews/ListPage.xaml.cs index 48ad679c4e..475e2b964e 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/ExtViews/ListPage.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/ExtViews/ListPage.xaml.cs @@ -74,7 +74,7 @@ public sealed partial class ListPage : Page, WeakReferenceMessenger.Default.Unregister(this); WeakReferenceMessenger.Default.Unregister(this); - if (ViewModel != null) + if (ViewModel is not null) { ViewModel.PropertyChanged -= ViewModel_PropertyChanged; ViewModel.ItemsUpdated -= Page_ItemsUpdated; @@ -142,13 +142,13 @@ public sealed partial class ListPage : Page, // here, then in Page_ItemsUpdated trying to select that cached item if // it's in the list (otherwise, clear the cache), but that seems // aggressively BODGY for something that mostly just works today. - if (ItemsList.SelectedItem != null) + if (ItemsList.SelectedItem is not null) { ItemsList.ScrollIntoView(ItemsList.SelectedItem); // Automation notification for screen readers var listViewPeer = Microsoft.UI.Xaml.Automation.Peers.ListViewAutomationPeer.CreatePeerForElement(ItemsList); - if (listViewPeer != null && li != null) + if (listViewPeer is not null && li is not null) { var notificationText = li.Title; listViewPeer.RaiseNotificationEvent( @@ -165,7 +165,7 @@ public sealed partial class ListPage : Page, // Find the ScrollViewer in the ListView var listViewScrollViewer = FindScrollViewer(this.ItemsList); - if (listViewScrollViewer != null) + if (listViewScrollViewer is not null) { listViewScrollViewer.ViewChanged += ListViewScrollViewer_ViewChanged; } @@ -174,7 +174,7 @@ public sealed partial class ListPage : Page, private void ListViewScrollViewer_ViewChanged(object? sender, ScrollViewerViewChangedEventArgs e) { var scrollView = sender as ScrollViewer; - if (scrollView == null) + if (scrollView is null) { return; } @@ -256,7 +256,7 @@ public sealed partial class ListPage : Page, page.PropertyChanged += @this.ViewModel_PropertyChanged; page.ItemsUpdated += @this.Page_ItemsUpdated; } - else if (e.NewValue == null) + else if (e.NewValue is null) { Logger.LogDebug("cleared view model"); } @@ -274,7 +274,7 @@ public sealed partial class ListPage : Page, // ItemsList_SelectionChanged again to give us another chance to change // the selection from null -> something. Better to just update the // selection once, at the end of all the updating. - if (ItemsList.SelectedItem == null) + if (ItemsList.SelectedItem is null) { ItemsList.SelectedIndex = 0; } @@ -307,7 +307,7 @@ public sealed partial class ListPage : Page, { var child = VisualTreeHelper.GetChild(parent, i); var result = FindScrollViewer(child); - if (result != null) + if (result is not null) { return result; } @@ -329,7 +329,7 @@ public sealed partial class ListPage : Page, _ => (null, null), }; - if (item == null || element == null) + if (item is null || element is null) { return; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/GpoValueChecker.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/GpoValueChecker.cs index fcd8ba1590..1c713c17c6 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/GpoValueChecker.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/GpoValueChecker.cs @@ -2,13 +2,6 @@ // 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.Text; -using System.Threading.Tasks; -using Microsoft.CmdPal.Ext.Bookmarks; -using Microsoft.UI.Xaml.Documents; using Microsoft.Win32; namespace Microsoft.CmdPal.UI.Helpers; @@ -63,7 +56,7 @@ internal static class GpoValueChecker { using (RegistryKey? key = rootKey.OpenSubKey(subKeyPath, false)) { - if (key == null) + if (key is null) { return null; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/IconCacheProvider.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/IconCacheProvider.cs index b8860fa53d..2687909cfa 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/IconCacheProvider.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/IconCacheProvider.cs @@ -4,7 +4,6 @@ using Microsoft.CmdPal.Core.ViewModels; using Microsoft.CmdPal.UI.Controls; -using Microsoft.CmdPal.UI.Helpers; namespace Microsoft.CmdPal.UI.Helpers; @@ -19,7 +18,7 @@ public static partial class IconCacheProvider public static async void SourceRequested(IconBox sender, SourceRequestedEventArgs args) #pragma warning restore IDE0060 // Remove unused parameter { - if (args.Key == null) + if (args.Key is null) { return; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/IconCacheService.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/IconCacheService.cs index 59a6d04ca4..5d058166ff 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/IconCacheService.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/IconCacheService.cs @@ -28,7 +28,7 @@ public sealed class IconCacheService(DispatcherQueue dispatcherQueue) var source = IconPathConverter.IconSourceMUX(icon.Icon, false); return source; } - else if (icon.Data != null) + else if (icon.Data is not null) { try { @@ -49,7 +49,7 @@ public sealed class IconCacheService(DispatcherQueue dispatcherQueue) private async Task StreamToIconSource(IRandomAccessStreamReference iconStreamRef) { - if (iconStreamRef == null) + if (iconStreamRef is null) { return null; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/TrayIconService.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/TrayIconService.cs index 60bc67eb3d..224c851ff1 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/TrayIconService.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/TrayIconService.cs @@ -50,7 +50,7 @@ internal sealed partial class TrayIconService { if (showSystemTrayIcon ?? _settingsModel.ShowSystemTrayIcon) { - if (_window == null) + if (_window is null) { _window = new Window(); _hwnd = new HWND(WindowNative.GetWindowHandle(_window)); @@ -64,7 +64,7 @@ internal sealed partial class TrayIconService _originalWndProc = Marshal.GetDelegateForFunctionPointer(PInvoke.SetWindowLongPtr(_hwnd, WINDOW_LONG_PTR_INDEX.GWL_WNDPROC, hotKeyPrcPointer)); } - if (_trayIconData == null) + if (_trayIconData is null) { // We need to stash this handle, so it doesn't clean itself up. If // explorer restarts, we'll come back through here, and we don't @@ -88,7 +88,7 @@ internal sealed partial class TrayIconService // Add the notification icon PInvoke.Shell_NotifyIcon(NOTIFY_ICON_MESSAGE.NIM_ADD, in d); - if (_popupMenu == null) + if (_popupMenu is null) { _popupMenu = PInvoke.CreatePopupMenu_SafeHandle(); PInvoke.InsertMenu(_popupMenu, 0, MENU_ITEM_FLAGS.MF_BYPOSITION | MENU_ITEM_FLAGS.MF_STRING, PInvoke.WM_USER + 1, RS_.GetString("TrayMenu_Settings")); @@ -103,7 +103,7 @@ internal sealed partial class TrayIconService public void Destroy() { - if (_trayIconData != null) + if (_trayIconData is not null) { var d = (NOTIFYICONDATAW)_trayIconData; if (PInvoke.Shell_NotifyIcon(NOTIFY_ICON_MESSAGE.NIM_DELETE, in d)) @@ -112,19 +112,19 @@ internal sealed partial class TrayIconService } } - if (_popupMenu != null) + if (_popupMenu is not null) { _popupMenu.Close(); _popupMenu = null; } - if (_largeIcon != null) + if (_largeIcon is not null) { _largeIcon.Close(); _largeIcon = null; } - if (_window != null) + if (_window is not null) { _window.Close(); _window = null; @@ -167,7 +167,7 @@ internal sealed partial class TrayIconService // WM_WINDOWPOSCHANGING which is always received on explorer startup sequence. case PInvoke.WM_WINDOWPOSCHANGING: { - if (_trayIconData == null) + if (_trayIconData is null) { SetupTrayIcon(); } @@ -189,7 +189,7 @@ internal sealed partial class TrayIconService { case PInvoke.WM_RBUTTONUP: { - if (_popupMenu != null) + if (_popupMenu is not null) { PInvoke.GetCursorPos(out var cursorPos); PInvoke.SetForegroundWindow(_hwnd); diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/TypedEventHandlerExtensions.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/TypedEventHandlerExtensions.cs index 561ad4592d..8671f90f81 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/TypedEventHandlerExtensions.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/TypedEventHandlerExtensions.cs @@ -46,7 +46,7 @@ public static class TypedEventHandlerExtensions #pragma warning restore CA1715 // Identifiers should have correct prefix where R : DeferredEventArgs { - if (eventHandler == null) + if (eventHandler is null) { return Task.CompletedTask; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/WindowHelper.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/WindowHelper.cs index c0d257088e..deddf13d5d 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/WindowHelper.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/WindowHelper.cs @@ -13,7 +13,7 @@ internal sealed partial class WindowHelper UserNotificationState state; // https://learn.microsoft.com/en-us/windows/win32/api/shellapi/ne-shellapi-query_user_notification_state - if (Marshal.GetExceptionForHR(NativeMethods.SHQueryUserNotificationState(out state)) == null) + if (Marshal.GetExceptionForHR(NativeMethods.SHQueryUserNotificationState(out state)) is null) { if (state == UserNotificationState.QUNS_RUNNING_D3D_FULL_SCREEN || state == UserNotificationState.QUNS_BUSY || diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs index 49a8eacceb..012ec3ccf6 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs @@ -384,7 +384,7 @@ public sealed partial class MainWindow : WindowEx, private void DisposeAcrylic() { - if (_acrylicController != null) + if (_acrylicController is not null) { _acrylicController.Dispose(); _acrylicController = null!; @@ -459,7 +459,7 @@ public sealed partial class MainWindow : WindowEx, PowerToysTelemetry.Log.WriteEvent(new CmdPalDismissedOnLostFocus()); } - if (_configurationSource != null) + if (_configurationSource is not null) { _configurationSource.IsInputActive = args.WindowActivationState != WindowActivationState.Deactivated; } @@ -467,7 +467,7 @@ public sealed partial class MainWindow : WindowEx, public void HandleLaunch(AppActivationArguments? activatedEventArgs) { - if (activatedEventArgs == null) + if (activatedEventArgs is null) { Summon(string.Empty); return; @@ -535,7 +535,7 @@ public sealed partial class MainWindow : WindowEx, UnregisterHotkeys(); var globalHotkey = settings.Hotkey; - if (globalHotkey != null) + if (globalHotkey is not null) { if (settings.UseLowLevelGlobalHotkey) { @@ -565,7 +565,7 @@ public sealed partial class MainWindow : WindowEx, { var key = commandHotkey.Hotkey; - if (key != null) + if (key is not null) { if (settings.UseLowLevelGlobalHotkey) { diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/LoadingPage.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/LoadingPage.xaml.cs index ed234c4d54..2883321236 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/LoadingPage.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/LoadingPage.xaml.cs @@ -24,7 +24,7 @@ public sealed partial class LoadingPage : Page protected override void OnNavigatedTo(NavigationEventArgs e) { if (e.Parameter is ShellViewModel shellVM - && shellVM.LoadCommand != null) + && shellVM.LoadCommand is not null) { // This will load the built-in commands, then navigate to the main page. // Once the mainpage loads, we'll start loading extensions. diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs index 1bc0fefb5a..2c8788faa8 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs @@ -171,7 +171,7 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page, // This gets called from the UI thread private async Task HandleConfirmArgsOnUiThread(IConfirmationArgs? args) { - if (args == null) + if (args is null) { return; } @@ -236,7 +236,7 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page, public void OpenSettings() { - if (_settingsWindow == null) + if (_settingsWindow is null) { _settingsWindow = new SettingsWindow(); } @@ -324,7 +324,7 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page, // command from our list of toplevel commands. var tlcManager = App.Current.Services.GetService()!; var topLevelCommand = tlcManager.LookupCommand(commandId); - if (topLevelCommand != null) + if (topLevelCommand is not null) { var command = topLevelCommand.CommandViewModel.Model.Unsafe; var isPage = command is not IInvokableCommand; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/PowerToysRootPageService.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/PowerToysRootPageService.cs index 60bd5e9360..e7ba073a9b 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/PowerToysRootPageService.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/PowerToysRootPageService.cs @@ -100,7 +100,7 @@ internal sealed class PowerToysRootPageService : IRootPageService _activeExtension = extension; var extensionWinRtObject = _activeExtension?.GetExtensionObject(); - if (extensionWinRtObject != null) + if (extensionWinRtObject is not null) { try { diff --git a/src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.Calc.UnitTests/NumberTranslatorTests.cs b/src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.Calc.UnitTests/NumberTranslatorTests.cs index f85e252df2..d6dbfc0f02 100644 --- a/src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.Calc.UnitTests/NumberTranslatorTests.cs +++ b/src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.Calc.UnitTests/NumberTranslatorTests.cs @@ -18,8 +18,8 @@ public class NumberTranslatorTests public void Create_ThrowError_WhenCalledNullOrEmpty(string sourceCultureName, string targetCultureName) { // Arrange - CultureInfo sourceCulture = sourceCultureName != null ? new CultureInfo(sourceCultureName) : null; - CultureInfo targetCulture = targetCultureName != null ? new CultureInfo(targetCultureName) : null; + CultureInfo sourceCulture = sourceCultureName is not null ? new CultureInfo(sourceCultureName) : null; + CultureInfo targetCulture = targetCultureName is not null ? new CultureInfo(targetCultureName) : null; // Act Assert.ThrowsException(() => NumberTranslator.Create(sourceCulture, targetCulture)); diff --git a/src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.TimeDate.UnitTests/TimeAndDateHelperTests.cs b/src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.TimeDate.UnitTests/TimeAndDateHelperTests.cs index 681e2be2f9..90ec826a95 100644 --- a/src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.TimeDate.UnitTests/TimeAndDateHelperTests.cs +++ b/src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.TimeDate.UnitTests/TimeAndDateHelperTests.cs @@ -45,7 +45,7 @@ public class TimeAndDateHelperTests var result = TimeAndDateHelper.GetCalendarWeekRule(setting); // Assert - if (valueExpected == null) + if (valueExpected is null) { // falls back to system setting. Assert.AreEqual(DateTimeFormatInfo.CurrentInfo.CalendarWeekRule, result); @@ -72,7 +72,7 @@ public class TimeAndDateHelperTests var result = TimeAndDateHelper.GetFirstDayOfWeek(setting); // Assert - if (valueExpected == null) + if (valueExpected is null) { // falls back to system setting. Assert.AreEqual(DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek, result); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AllAppsPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AllAppsPage.cs index 4c8b5baedc..35cac8b01c 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AllAppsPage.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AllAppsPage.cs @@ -2,16 +2,12 @@ // 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.Diagnostics; using System.Linq; -using System.Numerics; -using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using ManagedCommon; -using Microsoft.CmdPal.Ext.Apps.Commands; using Microsoft.CmdPal.Ext.Apps.Programs; using Microsoft.CmdPal.Ext.Apps.Properties; using Microsoft.CmdPal.Ext.Apps.State; @@ -145,7 +141,7 @@ public sealed partial class AllAppsPage : ListPage */ var existingAppItem = allApps.FirstOrDefault(f => f.AppIdentifier == e.AppIdentifier); - if (existingAppItem != null) + if (existingAppItem is not null) { var appListItem = new AppListItem(existingAppItem, true, e.IsPinned); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppCache.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppCache.cs index a0c3f7c363..746bfdfe9d 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppCache.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppCache.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Threading.Tasks; using Microsoft.CmdPal.Ext.Apps.Programs; @@ -66,7 +65,7 @@ public sealed partial class AppCache : IDisposable private void UpdateUWPIconPath(Theme theme) { - if (_packageRepository != null) + if (_packageRepository is not null) { foreach (UWPApplication app in _packageRepository) { diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppListItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppListItem.cs index 4ac8f79aea..1a3efacd97 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppListItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppListItem.cs @@ -72,7 +72,7 @@ internal sealed partial class AppListItem : ListItem try { var stream = await ThumbnailHelper.GetThumbnail(_app.ExePath, true); - if (stream != null) + if (stream is not null) { heroImage = IconInfo.FromStream(stream); } @@ -106,7 +106,7 @@ internal sealed partial class AppListItem : ListItem try { var stream = await ThumbnailHelper.GetThumbnail(_app.ExePath); - if (stream != null) + if (stream is not null) { var data = new IconData(RandomAccessStreamReference.CreateFromStream(stream)); icon = new IconInfo(data, data); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/AppxPackageHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/AppxPackageHelper.cs index ef81410898..61f581d2dd 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/AppxPackageHelper.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/AppxPackageHelper.cs @@ -6,9 +6,7 @@ using System; using System.Collections.Generic; using ManagedCommon; using Microsoft.CmdPal.Ext.Apps.Utils; -using Microsoft.UI.Xaml.Controls; using Windows.Win32; -using Windows.Win32.Foundation; using Windows.Win32.Storage.Packaging.Appx; using Windows.Win32.System.Com; @@ -51,14 +49,14 @@ public static class AppxPackageHelper { result.Add((IntPtr)manifestApp); } - else if (manifestApp != null) + else if (manifestApp is not null) { manifestApp->Release(); } } catch (Exception ex) { - if (manifestApp != null) + if (manifestApp is not null) { manifestApp->Release(); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/PackageManagerWrapper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/PackageManagerWrapper.cs index be70a0ba95..38337c4462 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/PackageManagerWrapper.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/PackageManagerWrapper.cs @@ -22,11 +22,11 @@ public class PackageManagerWrapper : IPackageManager { var user = WindowsIdentity.GetCurrent().User; - if (user != null) + if (user is not null) { var pkgs = _packageManager.FindPackagesForUser(user.Value); - return pkgs.Select(PackageWrapper.GetWrapperFromPackage).Where(package => package != null); + return pkgs.Select(PackageWrapper.GetWrapperFromPackage).Where(package => package is not null); } return Enumerable.Empty(); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWP.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWP.cs index 9be6cc9eb2..01a518f057 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWP.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWP.cs @@ -11,9 +11,7 @@ using System.Threading.Tasks; using System.Xml.Linq; using ManagedCommon; using Microsoft.CmdPal.Ext.Apps.Utils; -using Microsoft.CommandPalette.Extensions.Toolkit; using Windows.Win32; -using Windows.Win32.Foundation; using Windows.Win32.Storage.Packaging.Appx; using Windows.Win32.System.Com; @@ -99,7 +97,7 @@ public partial class UWP private static string[] XmlNamespaces(string path) { var z = XDocument.Load(path); - if (z.Root != null) + if (z.Root is not null) { var namespaces = z.Root.Attributes(). Where(a => a.IsNamespaceDeclaration). diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWPApplication.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWPApplication.cs index 5c689545bd..484dc162ee 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWPApplication.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWPApplication.cs @@ -308,7 +308,7 @@ public class UWPApplication : IProgram private bool SetScaleIcons(string path, string colorscheme, bool highContrast = false) { var extension = Path.GetExtension(path); - if (extension != null) + if (extension is not null) { var end = path.Length - extension.Length; var prefix = path.Substring(0, end); @@ -363,7 +363,7 @@ public class UWPApplication : IProgram private bool SetTargetSizeIcon(string path, string colorscheme, bool highContrast = false) { var extension = Path.GetExtension(path); - if (extension != null) + if (extension is not null) { var end = path.Length - extension.Length; var prefix = path.Substring(0, end); @@ -576,7 +576,7 @@ public class UWPApplication : IProgram var group = new DrawingGroup(); var converted = ColorConverter.ConvertFromString(currentBackgroundColor); - if (converted != null) + if (converted is not null) { var color = (Color)converted; var brush = new SolidColorBrush(color); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/Win32Program.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/Win32Program.cs index 74819d87c7..bf9e5f7334 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/Win32Program.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/Win32Program.cs @@ -170,7 +170,7 @@ public class Win32Program : IProgram public bool QueryEqualsNameForRunCommands(string query) { - if (query != null && AppType == ApplicationType.RunCommand) + if (query is not null && AppType == ApplicationType.RunCommand) { // Using OrdinalIgnoreCase since this is used internally if (!query.Equals(Name, StringComparison.OrdinalIgnoreCase) && !query.Equals(ExecutableName, StringComparison.OrdinalIgnoreCase)) @@ -667,7 +667,7 @@ public class Win32Program : IProgram var paths = new List(); using (var root = Registry.LocalMachine.OpenSubKey(appPaths)) { - if (root != null) + if (root is not null) { paths.AddRange(GetPathsFromRegistry(root)); } @@ -675,7 +675,7 @@ public class Win32Program : IProgram using (var root = Registry.CurrentUser.OpenSubKey(appPaths)) { - if (root != null) + if (root is not null) { paths.AddRange(GetPathsFromRegistry(root)); } @@ -700,7 +700,7 @@ public class Win32Program : IProgram { using (var key = root.OpenSubKey(subkey)) { - if (key == null) + if (key is null) { return string.Empty; } @@ -742,13 +742,13 @@ public class Win32Program : IProgram public bool Equals(Win32Program? app1, Win32Program? app2) { - if (app1 == null && app2 == null) + if (app1 is null && app2 is null) { return true; } - return app1 != null - && app2 != null + return app1 is not null + && app2 is not null && (app1.Name?.ToUpperInvariant(), app1.ExecutableName?.ToUpperInvariant(), app1.FullPath?.ToUpperInvariant()) .Equals((app2.Name?.ToUpperInvariant(), app2.ExecutableName?.ToUpperInvariant(), app2.FullPath?.ToUpperInvariant())); } @@ -908,7 +908,7 @@ public class Win32Program : IProgram Parallel.ForEach(paths, source => { var program = GetProgramFromPath(source); - if (program != null) + if (program is not null) { programsList.Add(program); } @@ -918,7 +918,7 @@ public class Win32Program : IProgram Parallel.ForEach(runCommandPaths, source => { var program = GetRunCommandProgramFromPath(source); - if (program != null) + if (program is not null) { runCommandProgramsList.Add(program); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/FileSystemWatcherWrapper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/FileSystemWatcherWrapper.cs index 436e7e44c1..f7fac6e12d 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/FileSystemWatcherWrapper.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/FileSystemWatcherWrapper.cs @@ -19,7 +19,7 @@ public sealed partial class FileSystemWatcherWrapper : FileSystemWatcher, IFileS get => this.Filters; set { - if (value != null) + if (value is not null) { foreach (var filter in value) { diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/Win32ProgramRepository.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/Win32ProgramRepository.cs index 6fdb5e49f6..98da723743 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/Win32ProgramRepository.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/Win32ProgramRepository.cs @@ -10,7 +10,6 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Threading.Tasks; using ManagedCommon; -using Microsoft.CmdPal.Ext.Apps.Programs; using Win32Program = Microsoft.CmdPal.Ext.Apps.Programs.Win32Program; namespace Microsoft.CmdPal.Ext.Apps.Storage; @@ -53,7 +52,7 @@ internal sealed partial class Win32ProgramRepository : ListRepository(T* comPtr) where T : unmanaged { - if (comPtr != null) + if (comPtr is not null) { ((IUnknown*)comPtr)->Release(); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ShellLinkHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ShellLinkHelper.cs index 543abf5dcf..11652c7524 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ShellLinkHelper.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ShellLinkHelper.cs @@ -3,8 +3,6 @@ // See the LICENSE file in the project root for more information. using System; -using System.Text; -using ManagedCommon; using Windows.Win32; using Windows.Win32.Foundation; using Windows.Win32.System.Com; @@ -37,7 +35,7 @@ public class ShellLinkHelper : IShellLinkHelper IPersistFile* persistFile = null; Guid iid = typeof(IPersistFile).GUID; ((IUnknown*)link)->QueryInterface(&iid, (void**)&persistFile); - if (persistFile != null) + if (persistFile is not null) { using var persistFileHandle = new SafeComHandle((IntPtr)persistFile); try diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ShellLocalization.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ShellLocalization.cs index 87e152b7e0..c157847861 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ShellLocalization.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ShellLocalization.cs @@ -45,7 +45,7 @@ public class ShellLocalization var filename = ComFreeHelper.GetStringAndFree(hr, filenamePtr); - if (filename == null) + if (filename is null) { return string.Empty; } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ThemeHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ThemeHelper.cs index 8175667d0a..005f1962f6 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ThemeHelper.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ThemeHelper.cs @@ -32,7 +32,7 @@ public static class ThemeHelper // Retrieve the registry value, which is a DWORD (0 or 1) var registryValueObj = Registry.GetValue(registryKey, registryValue, null); - if (registryValueObj != null) + if (registryValueObj is not null) { // 0 = Dark mode, 1 = Light mode var isLightMode = Convert.ToBoolean((int)registryValueObj, CultureInfo.InvariantCulture); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/AddBookmarkForm.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/AddBookmarkForm.cs index c5f0b4ea3e..93fc6d8d01 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/AddBookmarkForm.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/AddBookmarkForm.cs @@ -63,7 +63,7 @@ internal sealed partial class AddBookmarkForm : FormContent public override CommandResult SubmitForm(string payload) { var formInput = JsonNode.Parse(payload); - if (formInput == null) + if (formInput is null) { return CommandResult.GoHome(); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarkPlaceholderForm.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarkPlaceholderForm.cs index 4aac3e600e..965f42d1b0 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarkPlaceholderForm.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarkPlaceholderForm.cs @@ -73,7 +73,7 @@ internal sealed partial class BookmarkPlaceholderForm : FormContent // parse the submitted JSON and then open the link var formInput = JsonNode.Parse(payload); var formObject = formInput?.AsObject(); - if (formObject == null) + if (formObject is null) { return CommandResult.GoHome(); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarksCommandProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarksCommandProvider.cs index 91d9f902cb..081fb2bccb 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarksCommandProvider.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarksCommandProvider.cs @@ -49,7 +49,7 @@ public partial class BookmarksCommandProvider : CommandProvider private void SaveAndUpdateCommands() { - if (_bookmarks != null) + if (_bookmarks is not null) { var jsonPath = BookmarksCommandProvider.StateJsonPath(); Bookmarks.WriteToFile(jsonPath, _bookmarks); @@ -64,12 +64,12 @@ public partial class BookmarksCommandProvider : CommandProvider List collected = []; collected.Add(new CommandItem(_addNewCommand)); - if (_bookmarks == null) + if (_bookmarks is null) { LoadBookmarksFromFile(); } - if (_bookmarks != null) + if (_bookmarks is not null) { collected.AddRange(_bookmarks.Data.Select(BookmarkToCommandItem)); } @@ -93,7 +93,7 @@ public partial class BookmarksCommandProvider : CommandProvider Logger.LogError(ex.Message); } - if (_bookmarks == null) + if (_bookmarks is null) { _bookmarks = new(); } @@ -134,7 +134,7 @@ public partial class BookmarksCommandProvider : CommandProvider name: Resources.bookmarks_delete_name, action: () => { - if (_bookmarks != null) + if (_bookmarks is not null) { ExtensionHost.LogMessage($"Deleting bookmark ({bookmark.Name},{bookmark.Bookmark})"); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/UrlCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/UrlCommand.cs index d94f4619f1..db60a31940 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/UrlCommand.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/UrlCommand.cs @@ -73,7 +73,7 @@ public partial class UrlCommand : InvokableCommand if (string.IsNullOrEmpty(args)) { var uri = GetUri(exe); - if (uri != null) + if (uri is not null) { _ = Launcher.LaunchUriAsync(uri); } @@ -109,7 +109,7 @@ public partial class UrlCommand : InvokableCommand // First, try to get the icon from the thumbnail helper // This works for local files and folders icon = await MaybeGetIconForPath(target); - if (icon != null) + if (icon is not null) { return icon; } @@ -142,7 +142,7 @@ public partial class UrlCommand : InvokableCommand { // If the executable exists, try to get the icon from the file icon = await MaybeGetIconForPath(fullExePath); - if (icon != null) + if (icon is not null) { return icon; } @@ -154,7 +154,7 @@ public partial class UrlCommand : InvokableCommand try { var uri = GetUri(baseString); - if (uri != null) + if (uri is not null) { var hostname = uri.Host; var faviconUrl = $"{uri.Scheme}://{hostname}/favicon.ico"; @@ -176,7 +176,7 @@ public partial class UrlCommand : InvokableCommand try { var stream = await ThumbnailHelper.GetThumbnail(target); - if (stream != null) + if (stream is not null) { var data = new IconData(RandomAccessStreamReference.CreateFromStream(stream)); return new IconInfo(data, data); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/NumberTranslator.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/NumberTranslator.cs index 7331c44b40..34da2872cf 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/NumberTranslator.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/NumberTranslator.cs @@ -107,7 +107,7 @@ public class NumberTranslator // Currently, we only convert base literals (hexadecimal, binary, octal) to decimal. var converted = ConvertBaseLiteral(token, cultureTo); - if (converted != null) + if (converted is not null) { outputBuilder.Append(converted); continue; diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/ResultHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/ResultHelper.cs index f53fadaa52..cd2b811567 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/ResultHelper.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/ResultHelper.cs @@ -16,7 +16,7 @@ public static class ResultHelper public static ListItem CreateResult(decimal? roundedResult, CultureInfo inputCulture, CultureInfo outputCulture, string query, ISettingsInterface settings, TypedEventHandler handleSave) { // Return null when the expression is not a valid calculator query. - if (roundedResult == null) + if (roundedResult is null) { return null; } @@ -48,7 +48,7 @@ public static class ResultHelper public static ListItem CreateResult(decimal? roundedResult, CultureInfo inputCulture, CultureInfo outputCulture, string query) { // Return null when the expression is not a valid calculator query. - if (roundedResult == null) + if (roundedResult is null) { return null; } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/CalculatorListPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/CalculatorListPage.cs index d4b7f6d135..72e5f3db30 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/CalculatorListPage.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/CalculatorListPage.cs @@ -82,7 +82,7 @@ public sealed partial class CalculatorListPage : DynamicListPage { this._items.Clear(); - if (result != null) + if (result is not null) { this._items.Add(result); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/FallbackCalculatorItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/FallbackCalculatorItem.cs index 5dc85ae51f..4367c67810 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/FallbackCalculatorItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/FallbackCalculatorItem.cs @@ -28,7 +28,7 @@ public sealed partial class FallbackCalculatorItem : FallbackCommandItem { var result = QueryHelper.Query(query, _settings, true, null); - if (result == null) + if (result is null) { _copyCommand.Text = string.Empty; _copyCommand.Name = string.Empty; diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Helpers/ClipboardHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Helpers/ClipboardHelper.cs index 066d8822f3..87937c8100 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Helpers/ClipboardHelper.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Helpers/ClipboardHelper.cs @@ -139,7 +139,7 @@ internal static class ClipboardHelper switch (clipboardFormat) { case ClipboardFormat.Text: - if (clipboardItem.Content == null) + if (clipboardItem.Content is null) { ExtensionHost.LogMessage(new LogMessage() { Message = "No valid clipboard content" }); return; @@ -152,7 +152,7 @@ internal static class ClipboardHelper break; case ClipboardFormat.Image: - if (clipboardItem.ImageData == null) + if (clipboardItem.ImageData is null) { ExtensionHost.LogMessage(new LogMessage() { Message = "No valid clipboard content" }); return; @@ -240,7 +240,7 @@ internal static class ClipboardHelper internal static async Task GetClipboardImageContentAsync(DataPackageView clipboardData) { using var stream = await GetClipboardImageStreamAsync(clipboardData); - if (stream != null) + if (stream is not null) { var decoder = await BitmapDecoder.CreateAsync(stream); return await decoder.GetSoftwareBitmapAsync(); @@ -255,7 +255,7 @@ internal static class ClipboardHelper { var storageItems = await clipboardData.GetStorageItemsAsync(); var file = storageItems.Count == 1 ? storageItems[0] as StorageFile : null; - if (file != null) + if (file is not null) { return await file.OpenReadAsync(); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Models/ClipboardItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Models/ClipboardItem.cs index 94c5a86dc3..ec01883b87 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Models/ClipboardItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Models/ClipboardItem.cs @@ -37,7 +37,7 @@ public class ClipboardItem } [MemberNotNullWhen(true, nameof(ImageData))] - private bool IsImage => ImageData != null; + private bool IsImage => ImageData is not null; [MemberNotNullWhen(true, nameof(Content))] private bool IsText => !string.IsNullOrEmpty(Content); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Pages/ClipboardHistoryListPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Pages/ClipboardHistoryListPage.cs index b8cccb987b..b6b72afba3 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Pages/ClipboardHistoryListPage.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Pages/ClipboardHistoryListPage.cs @@ -54,7 +54,7 @@ internal sealed partial class ClipboardHistoryListPage : ListPage try { var allowClipboardHistory = Registry.GetValue(registryKey, "AllowClipboardHistory", null); - return allowClipboardHistory != null ? (int)allowClipboardHistory == 0 : false; + return allowClipboardHistory is not null ? (int)allowClipboardHistory == 0 : false; } catch (Exception) { @@ -100,7 +100,7 @@ internal sealed partial class ClipboardHistoryListPage : ListPage { var imageReceived = await item.Item.Content.GetBitmapAsync(); - if (imageReceived != null) + if (imageReceived is not null) { item.ImageData = imageReceived; } @@ -141,7 +141,7 @@ internal sealed partial class ClipboardHistoryListPage : ListPage for (var i = 0; i < clipboardHistory.Count; i++) { var item = clipboardHistory[i]; - if (item != null) + if (item is not null) { listItems.Add(item.ToListItem()); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/FallbackOpenFileItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/FallbackOpenFileItem.cs index 7da8702f1e..2b408f24dc 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/FallbackOpenFileItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/FallbackOpenFileItem.cs @@ -46,7 +46,7 @@ internal sealed partial class FallbackOpenFileItem : FallbackCommandItem, System return; } - if (_suppressCallback != null && _suppressCallback(query)) + if (_suppressCallback is not null && _suppressCallback(query)) { Command = new NoOpCommand(); Title = string.Empty; @@ -71,7 +71,7 @@ internal sealed partial class FallbackOpenFileItem : FallbackCommandItem, System try { var stream = ThumbnailHelper.GetThumbnail(item.FullPath).Result; - if (stream != null) + if (stream is not null) { var data = new IconData(RandomAccessStreamReference.CreateFromStream(stream)); Icon = new IconInfo(data, data); @@ -92,7 +92,7 @@ internal sealed partial class FallbackOpenFileItem : FallbackCommandItem, System _searchEngine.Query(query, _queryCookie); var results = _searchEngine.FetchItems(0, 20, _queryCookie, out var _); - if (results.Count == 0 || ((results[0] as IndexerListItem) == null)) + if (results.Count == 0 || ((results[0] as IndexerListItem) is null)) { // Exit 2: We searched for the file, and found nothing. Oh well. // Hide ourselves. diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/DataSourceManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/DataSourceManager.cs index 7b9f9bd45b..1e2119f0ab 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/DataSourceManager.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/DataSourceManager.cs @@ -16,7 +16,7 @@ internal static class DataSourceManager public static IDBInitialize GetDataSource() { - if (_dataSource == null) + if (_dataSource is null) { InitializeDataSource(); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SearchQuery.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SearchQuery.cs index 8fa972f302..6b85834bb8 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SearchQuery.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SearchQuery.cs @@ -12,7 +12,6 @@ using ManagedCsWin32; using Microsoft.CmdPal.Ext.Indexer.Indexer.OleDB; using Microsoft.CmdPal.Ext.Indexer.Indexer.SystemSearch; using Microsoft.CmdPal.Ext.Indexer.Indexer.Utils; -using static Microsoft.CmdPal.Ext.Indexer.Indexer.Utils.NativeHelpers; namespace Microsoft.CmdPal.Ext.Indexer.Indexer; @@ -54,14 +53,14 @@ internal sealed partial class SearchQuery : IDisposable try { queryTpTimer = new Timer(QueryTimerCallback, this, Timeout.Infinite, Timeout.Infinite); - if (queryTpTimer == null) + if (queryTpTimer is null) { Logger.LogError("Failed to create query timer"); return; } queryCompletedEvent = new EventWaitHandle(false, EventResetMode.ManualReset); - if (queryCompletedEvent == null) + if (queryCompletedEvent is null) { Logger.LogError("Failed to create query completed event"); return; @@ -85,7 +84,7 @@ internal sealed partial class SearchQuery : IDisposable // Are we currently doing work? If so, let's cancel lock (_lockObject) { - if (queryTpTimer != null) + if (queryTpTimer is not null) { queryTpTimer.Change(Timeout.Infinite, Timeout.Infinite); queryTpTimer.Dispose(); @@ -117,7 +116,7 @@ internal sealed partial class SearchQuery : IDisposable try { // We need to generate a search query string with the search text the user entered above - if (currentRowset != null) + if (currentRowset is not null) { // We have a previous rowset, this means the user is typing and we should store this // recapture the where ID from this so the next ExecuteSync call will be faster @@ -146,14 +145,14 @@ internal sealed partial class SearchQuery : IDisposable { getRow.GetRowFromHROW(null, rowHandle, ref Unsafe.AsRef(in IID.IPropertyStore), out var propertyStore); - if (propertyStore == null) + if (propertyStore is null) { Logger.LogError("Failed to get IPropertyStore interface"); return false; } var searchResult = SearchResult.Create(propertyStore); - if (searchResult == null) + if (searchResult is null) { Logger.LogError("Failed to create search result"); return false; @@ -171,7 +170,7 @@ internal sealed partial class SearchQuery : IDisposable public bool FetchRows(int offset, int limit) { - if (currentRowset == null) + if (currentRowset is null) { Logger.LogError("No rowset to fetch rows from"); return false; @@ -241,7 +240,7 @@ internal sealed partial class SearchQuery : IDisposable { var queryStr = QueryStringBuilder.GeneratePrimingQuery(); var rowset = ExecuteCommand(queryStr); - if (rowset != null) + if (rowset is not null) { reuseRowset = rowset; reuseWhereID = GetReuseWhereId(reuseRowset); @@ -261,7 +260,7 @@ internal sealed partial class SearchQuery : IDisposable var guid = typeof(IDBCreateCommand).GUID; session.CreateSession(IntPtr.Zero, ref guid, out var ppDBSession); - if (ppDBSession == null) + if (ppDBSession is null) { Logger.LogError("CreateSession failed"); return null; @@ -271,7 +270,7 @@ internal sealed partial class SearchQuery : IDisposable guid = typeof(ICommandText).GUID; createCommand.CreateCommand(IntPtr.Zero, ref guid, out ICommandText commandText); - if (commandText == null) + if (commandText is null) { Logger.LogError("Failed to get ICommandText interface"); return null; @@ -342,13 +341,13 @@ internal sealed partial class SearchQuery : IDisposable { var rowsetInfo = (IRowsetInfo)rowset; - if (rowsetInfo == null) + if (rowsetInfo is null) { return 0; } var prop = GetPropset(rowsetInfo); - if (prop == null) + if (prop is null) { return 0; } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SearchResult.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SearchResult.cs index b44e9ab11b..fa2cf31704 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SearchResult.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SearchResult.cs @@ -26,7 +26,7 @@ internal sealed class SearchResult ItemUrl = url; IsFolder = isFolder; - if (LaunchUri == null || LaunchUri.Length == 0) + if (LaunchUri is null || LaunchUri.Length == 0) { // Launch the file with the default app, so use the file path LaunchUri = filePath; diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/Utils/QueryStringBuilder.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/Utils/QueryStringBuilder.cs index 997d364b4d..068ea08750 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/Utils/QueryStringBuilder.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/Utils/QueryStringBuilder.cs @@ -5,8 +5,6 @@ using System; using System.Globalization; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.Marshalling; using ManagedCommon; using ManagedCsWin32; using Microsoft.CmdPal.Ext.Indexer.Indexer.SystemSearch; @@ -28,7 +26,7 @@ internal sealed partial class QueryStringBuilder public static string GenerateQuery(string searchText, uint whereId) { - if (queryHelper == null) + if (queryHelper is null) { ISearchManager searchManager; @@ -43,13 +41,13 @@ internal sealed partial class QueryStringBuilder } ISearchCatalogManager catalogManager = searchManager.GetCatalog(SystemIndex); - if (catalogManager == null) + if (catalogManager is null) { throw new ArgumentException($"Failed to get catalog manager for {SystemIndex}"); } queryHelper = catalogManager.GetQueryHelper(); - if (queryHelper == null) + if (queryHelper is null) { throw new ArgumentException("Failed to get query helper from catalog manager"); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/ActionsListContextItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/ActionsListContextItem.cs index 0c2823fed5..9f37f94c1b 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/ActionsListContextItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/ActionsListContextItem.cs @@ -44,12 +44,12 @@ internal sealed partial class ActionsListContextItem : CommandContextItem, IDisp { lock (UpdateMoreCommandsLock) { - if (actionRuntime == null) + if (actionRuntime is null) { actionRuntime = ActionRuntimeManager.InstanceAsync.GetAwaiter().GetResult(); } - if (actionRuntime == null) + if (actionRuntime is null) { return; } @@ -62,7 +62,7 @@ internal sealed partial class ActionsListContextItem : CommandContextItem, IDisp { var extension = System.IO.Path.GetExtension(fullPath).ToLower(CultureInfo.InvariantCulture); ActionEntity entity = null; - if (extension != null) + if (extension is not null) { if (extension == ".jpg" || extension == ".jpeg" || extension == ".png") { @@ -74,7 +74,7 @@ internal sealed partial class ActionsListContextItem : CommandContextItem, IDisp } } - if (entity == null) + if (entity is null) { entity = actionRuntime.EntityFactory.CreateFileEntity(fullPath); } @@ -100,7 +100,7 @@ internal sealed partial class ActionsListContextItem : CommandContextItem, IDisp { lock (UpdateMoreCommandsLock) { - if (actionRuntime != null) + if (actionRuntime is not null) { actionRuntime.ActionCatalog.Changed -= ActionCatalog_Changed; } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/DirectoryExplorePage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/DirectoryExplorePage.cs index 9bb7820a07..3bdbe1b0ce 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/DirectoryExplorePage.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/DirectoryExplorePage.cs @@ -35,14 +35,14 @@ public sealed partial class DirectoryExplorePage : DynamicListPage public override void UpdateSearchText(string oldSearch, string newSearch) { - if (_directoryContents == null) + if (_directoryContents is null) { return; } if (string.IsNullOrEmpty(newSearch)) { - if (_filteredContents != null) + if (_filteredContents is not null) { _filteredContents = null; RaiseItemsChanged(-1); @@ -58,7 +58,7 @@ public sealed partial class DirectoryExplorePage : DynamicListPage newSearch, (s, i) => ListHelpers.ScoreListItem(s, i)); - if (_filteredContents != null) + if (_filteredContents is not null) { lock (_filteredContents) { @@ -75,12 +75,12 @@ public sealed partial class DirectoryExplorePage : DynamicListPage public override IListItem[] GetItems() { - if (_filteredContents != null) + if (_filteredContents is not null) { return _filteredContents.ToArray(); } - if (_directoryContents != null) + if (_directoryContents is not null) { return _directoryContents.ToArray(); } @@ -120,7 +120,7 @@ public sealed partial class DirectoryExplorePage : DynamicListPage try { var stream = ThumbnailHelper.GetThumbnail(item.FilePath).Result; - if (stream != null) + if (stream is not null) { var data = new IconData(RandomAccessStreamReference.CreateFromStream(stream)); icon = new IconInfo(data, data); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/DirectoryPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/DirectoryPage.cs index a6f989c41e..91e78d87fd 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/DirectoryPage.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/DirectoryPage.cs @@ -31,7 +31,7 @@ public sealed partial class DirectoryPage : ListPage public override IListItem[] GetItems() { - if (_directoryContents != null) + if (_directoryContents is not null) { return _directoryContents.ToArray(); } @@ -86,7 +86,7 @@ public sealed partial class DirectoryPage : ListPage try { var stream = ThumbnailHelper.GetThumbnail(item.FilePath).Result; - if (stream != null) + if (stream is not null) { var data = new IconData(RandomAccessStreamReference.CreateFromStream(stream)); icon = new IconInfo(data, data); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/SearchEngine.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/SearchEngine.cs index 4d77de679a..eb1ca563b4 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/SearchEngine.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/SearchEngine.cs @@ -42,7 +42,7 @@ public sealed partial class SearchEngine : IDisposable { hasMore = false; var results = new List(); - if (_searchQuery != null) + if (_searchQuery is not null) { var cookie = _searchQuery.Cookie; if (cookie == queryCookie) @@ -59,7 +59,7 @@ public sealed partial class SearchEngine : IDisposable try { var stream = ThumbnailHelper.GetThumbnail(result.LaunchUri).Result; - if (stream != null) + if (stream is not null) { var data = new IconData(RandomAccessStreamReference.CreateFromStream(stream)); icon = new IconInfo(data, data); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/RegistryHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/RegistryHelper.cs index 9cd30b2bea..b64894baaf 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/RegistryHelper.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/RegistryHelper.cs @@ -7,7 +7,6 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; -using ManagedCommon; using Microsoft.CmdPal.Ext.Registry.Classes; using Microsoft.CmdPal.Ext.Registry.Constants; using Microsoft.CmdPal.Ext.Registry.Properties; @@ -118,7 +117,7 @@ internal static class RegistryHelper subKey = result.First().Key; } - if (result.Count > 1 || subKey == null) + if (result.Count > 1 || subKey is null) { break; } @@ -183,7 +182,7 @@ internal static class RegistryHelper if (string.Equals(subKey, searchSubKey, StringComparison.OrdinalIgnoreCase)) { var key = parentKey.OpenSubKey(subKey, RegistryKeyPermissionCheck.ReadSubTree); - if (key != null) + if (key is not null) { list.Add(new RegistryEntry(key)); } @@ -194,7 +193,7 @@ internal static class RegistryHelper try { var key = parentKey.OpenSubKey(subKey, RegistryKeyPermissionCheck.ReadSubTree); - if (key != null) + if (key is not null) { list.Add(new RegistryEntry(key)); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/ResultHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/ResultHelper.cs index c05af5f594..0ac3159531 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/ResultHelper.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/ResultHelper.cs @@ -88,7 +88,7 @@ internal static class ResultHelper foreach (var valueName in valueNames) { var value = key.GetValue(valueName); - if (value != null) + if (value is not null) { valueList.Add(KeyValuePair.Create(valueName, value)); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/ValueHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/ValueHelper.cs index e0e6eaf951..f25bc56064 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/ValueHelper.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/ValueHelper.cs @@ -26,7 +26,7 @@ internal static class ValueHelper { var unformattedValue = key.GetValue(valueName); - if (unformattedValue == null) + if (unformattedValue is null) { throw new InvalidOperationException($"Cannot proceed when {nameof(unformattedValue)} is null."); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Commands/ExecuteItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Commands/ExecuteItem.cs index 5058b386b3..4ca772dc1e 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Commands/ExecuteItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Commands/ExecuteItem.cs @@ -46,7 +46,7 @@ internal sealed partial class ExecuteItem : InvokableCommand private void Execute(Func startProcess, ProcessStartInfo info) { - if (startProcess == null) + if (startProcess is null) { return; } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Helpers/ShellListPageHelpers.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Helpers/ShellListPageHelpers.cs index acf739cdbf..6a545c7225 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Helpers/ShellListPageHelpers.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Helpers/ShellListPageHelpers.cs @@ -126,7 +126,7 @@ public class ShellListPageHelpers return null; } - if (li != null) + if (li is not null) { li.TextToSuggest = searchText; } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Pages/RunExeItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Pages/RunExeItem.cs index ea98f2fe47..a8d578939e 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Pages/RunExeItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Pages/RunExeItem.cs @@ -78,7 +78,7 @@ internal sealed partial class RunExeItem : ListItem try { var stream = await ThumbnailHelper.GetThumbnail(FullExePath); - if (stream != null) + if (stream is not null) { var data = new IconData(RandomAccessStreamReference.CreateFromStream(stream)); icon = new IconInfo(data, data); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Pages/ShellListPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Pages/ShellListPage.cs index 8ecfe091c1..4b99477d2a 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Pages/ShellListPage.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Pages/ShellListPage.cs @@ -245,14 +245,14 @@ internal sealed partial class ShellListPage : DynamicListPage, IDisposable var histItemsNotInSearch = _historyItems .Where(kv => !kv.Key.Equals(newSearch, StringComparison.OrdinalIgnoreCase)); - if (_exeItem != null) + if (_exeItem is not null) { // If we have an exe item, we want to remove it from the history items histItemsNotInSearch = histItemsNotInSearch .Where(kv => !kv.Value.Title.Equals(_exeItem.Title, StringComparison.OrdinalIgnoreCase)); } - if (_uriItem != null) + if (_uriItem is not null) { // If we have an uri item, we want to remove it from the history items histItemsNotInSearch = histItemsNotInSearch @@ -307,8 +307,8 @@ internal sealed partial class ShellListPage : DynamicListPage, IDisposable } var filteredTopLevel = ListHelpers.FilterList(_topLevelItems, SearchText); - List uriItems = _uriItem != null ? [_uriItem] : []; - List exeItems = _exeItem != null ? [_exeItem] : []; + List uriItems = _uriItem is not null ? [_uriItem] : []; + List exeItems = _exeItem is not null ? [_exeItem] : []; return exeItems @@ -459,7 +459,7 @@ internal sealed partial class ShellListPage : DynamicListPage, IDisposable var hist = _historyService.GetRunHistory(); var histItems = hist .Select(h => (h, ShellListPageHelpers.ListItemForCommandString(h, AddToHistory))) - .Where(tuple => tuple.Item2 != null) + .Where(tuple => tuple.Item2 is not null) .Select(tuple => (tuple.h, tuple.Item2!)) .ToList(); _historyItems.Clear(); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/PathListItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/PathListItem.cs index 2e1dd38349..18f37818e6 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/PathListItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/PathListItem.cs @@ -72,7 +72,7 @@ internal sealed partial class PathListItem : ListItem _icon = new Lazy(() => { var iconStream = ThumbnailHelper.GetThumbnail(path).Result; - var icon = iconStream != null ? IconInfo.FromStream(iconStream) : + var icon = iconStream is not null ? IconInfo.FromStream(iconStream) : _isDirectory ? Icons.FolderIcon : Icons.RunV2Icon; return icon; }); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/FallbackSystemCommandItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/FallbackSystemCommandItem.cs index 6cb6e7a3ec..6914c00626 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/FallbackSystemCommandItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/FallbackSystemCommandItem.cs @@ -57,7 +57,7 @@ internal sealed partial class FallbackSystemCommandItem : FallbackCommandItem } } - if (result == null) + if (result is null) { Command = null; Title = string.Empty; diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/NetworkConnectionProperties.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/NetworkConnectionProperties.cs index 486eeaa8b5..69e5c2ac78 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/NetworkConnectionProperties.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/NetworkConnectionProperties.cs @@ -155,7 +155,7 @@ internal sealed class NetworkConnectionProperties internal static List GetList() { var interfaces = NetworkInterface.GetAllNetworkInterfaces() - .Where(x => x.NetworkInterfaceType != NetworkInterfaceType.Loopback && x.GetPhysicalAddress() != null) + .Where(x => x.NetworkInterfaceType != NetworkInterfaceType.Loopback && x.GetPhysicalAddress() is not null) .Select(i => new NetworkConnectionProperties(i)) .OrderByDescending(i => i.IPv4) // list IPv4 first .ThenBy(i => i.IPv6Primary) // then IPv6 @@ -195,9 +195,9 @@ internal sealed class NetworkConnectionProperties CreateIpInfoForDetailsText($"**{Resources.Microsoft_plugin_sys_Ip6Site}:**\n\n* ", IPv6SiteLocal) + CreateIpInfoForDetailsText($"**{Resources.Microsoft_plugin_sys_Ip6Unique}:**\n\n* ", IPv6UniqueLocal) + CreateIpInfoForDetailsText($"**{Resources.Microsoft_plugin_sys_Gateways}:**\n\n* ", Gateways) + - CreateIpInfoForDetailsText($"**{Resources.Microsoft_plugin_sys_Dhcp}:**\n\n* ", DhcpServers == null ? string.Empty : DhcpServers) + - CreateIpInfoForDetailsText($"**{Resources.Microsoft_plugin_sys_Dns}:**\n\n* ", DnsServers == null ? string.Empty : DnsServers) + - CreateIpInfoForDetailsText($"**{Resources.Microsoft_plugin_sys_Wins}:**\n\n* ", WinsServers == null ? string.Empty : WinsServers) + + CreateIpInfoForDetailsText($"**{Resources.Microsoft_plugin_sys_Dhcp}:**\n\n* ", DhcpServers is null ? string.Empty : DhcpServers) + + CreateIpInfoForDetailsText($"**{Resources.Microsoft_plugin_sys_Dns}:**\n\n* ", DnsServers is null ? string.Empty : DnsServers) + + CreateIpInfoForDetailsText($"**{Resources.Microsoft_plugin_sys_Wins}:**\n\n* ", WinsServers is null ? string.Empty : WinsServers) + $"\n\n**{Resources.Microsoft_plugin_sys_AdapterName}:** {Adapter}" + $"\n\n**{Resources.Microsoft_plugin_sys_PhysicalAddress}:** {PhysicalAddress}" + $"\n\n**{Resources.Microsoft_plugin_sys_Speed}:** {GetFormattedSpeedValue(Speed)}"; diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/FallbackTimeDateItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/FallbackTimeDateItem.cs index cc757bcd88..57749d3b8d 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/FallbackTimeDateItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/FallbackTimeDateItem.cs @@ -4,11 +4,9 @@ using System; using System.Collections.Generic; -using System.Drawing; using System.Globalization; using System.Linq; using Microsoft.CmdPal.Ext.TimeDate.Helpers; -using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions.Toolkit; namespace Microsoft.CmdPal.Ext.TimeDate; @@ -66,7 +64,7 @@ internal sealed partial class FallbackTimeDateItem : FallbackCommandItem } } - if (result != null) + if (result is not null) { Title = result.Title; Subtitle = result.Subtitle; @@ -90,7 +88,7 @@ internal sealed partial class FallbackTimeDateItem : FallbackCommandItem foreach (var option in _validOptions) { - if (option == null) + if (option is null) { continue; } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/AvailableResultsList.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/AvailableResultsList.cs index 0966c0d3df..5666ff6fa3 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/AvailableResultsList.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/AvailableResultsList.cs @@ -29,7 +29,7 @@ internal static class AvailableResultsList var timeExtended = timeLongFormat ?? settings.TimeWithSecond; var dateExtended = dateLongFormat ?? settings.DateWithWeekday; - var isSystemDateTime = timestamp == null; + var isSystemDateTime = timestamp is null; var dateTimeNow = timestamp ?? DateTime.Now; var dateTimeNowUtc = dateTimeNow.ToUniversalTime(); var firstWeekRule = firstWeekOfYear ?? TimeAndDateHelper.GetCalendarWeekRule(settings.FirstWeekOfYear); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/SettingsManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/SettingsManager.cs index 727c5258aa..4bd8bf4d7c 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/SettingsManager.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/SettingsManager.cs @@ -103,7 +103,7 @@ public class SettingsManager : JsonSettingsManager, ISettingsInterface { get { - if (_firstWeekOfYear.Value == null || string.IsNullOrEmpty(_firstWeekOfYear.Value)) + if (_firstWeekOfYear.Value is null || string.IsNullOrEmpty(_firstWeekOfYear.Value)) { return -1; } @@ -123,7 +123,7 @@ public class SettingsManager : JsonSettingsManager, ISettingsInterface { get { - if (_firstDayOfWeek.Value == null || string.IsNullOrEmpty(_firstDayOfWeek.Value)) + if (_firstDayOfWeek.Value is null || string.IsNullOrEmpty(_firstDayOfWeek.Value)) { return -1; } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/DefaultBrowserInfo.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/DefaultBrowserInfo.cs index 87b87c7ff5..f6b82ecfbb 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/DefaultBrowserInfo.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/DefaultBrowserInfo.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System; -using System.Runtime.InteropServices; using System.Text; using System.Threading; using ManagedCommon; @@ -87,7 +86,7 @@ public static class DefaultBrowserInfo var appName = GetRegistryValue($@"HKEY_CLASSES_ROOT\{progId}\Application", "ApplicationName") ?? GetRegistryValue($@"HKEY_CLASSES_ROOT\{progId}", "FriendlyTypeName"); - if (appName != null) + if (appName is not null) { // Handle indirect strings: if (appName.StartsWith('@')) diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/SettingsManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/SettingsManager.cs index 8a39bca35b..300cb105fb 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/SettingsManager.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/SettingsManager.cs @@ -67,7 +67,7 @@ public class SettingsManager : JsonSettingsManager public void SaveHistory(HistoryItem historyItem) { - if (historyItem == null) + if (historyItem is null) { return; } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Pages/WebSearchListPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Pages/WebSearchListPage.cs index c96efe24c7..faf65cd973 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Pages/WebSearchListPage.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Pages/WebSearchListPage.cs @@ -34,7 +34,7 @@ internal sealed partial class WebSearchListPage : DynamicListPage Id = "com.microsoft.cmdpal.websearch"; _settingsManager = settingsManager; _historyItems = _settingsManager.ShowHistory != Resources.history_none ? _settingsManager.LoadHistory() : null; - if (_historyItems != null) + if (_historyItems is not null) { _allItems.AddRange(_historyItems); } @@ -55,7 +55,7 @@ internal sealed partial class WebSearchListPage : DynamicListPage ArgumentNullException.ThrowIfNull(query); IEnumerable? filteredHistoryItems = null; - if (_historyItems != null) + if (_historyItems is not null) { filteredHistoryItems = _settingsManager.ShowHistory != Resources.history_none ? ListHelpers.FilterList(_historyItems, query).OfType() : null; } @@ -74,7 +74,7 @@ internal sealed partial class WebSearchListPage : DynamicListPage results.Add(result); } - if (filteredHistoryItems != null) + if (filteredHistoryItems is not null) { results.AddRange(filteredHistoryItems); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageCommand.cs index c4fd7b7a4c..d2c1ea7283 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageCommand.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageCommand.cs @@ -5,7 +5,6 @@ using System; using System.Globalization; using System.Text; -using System.Threading; using System.Threading.Tasks; using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions.Toolkit; @@ -79,7 +78,7 @@ public partial class InstallPackageCommand : InvokableCommand { // TODO: LOCK in here, so this can only be invoked once until the // install / uninstall is done. Just use like, an atomic - if (_installTask != null) + if (_installTask is not null) { return CommandResult.KeepOpen(); } @@ -143,7 +142,7 @@ public partial class InstallPackageCommand : InvokableCommand { await Task.Delay(2500).ConfigureAwait(false); - if (_installTask == null) + if (_installTask is null) { WinGetExtensionHost.Instance.HideStatus(_installBanner); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageListItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageListItem.cs index dd51e297a9..e2a3d2e4b4 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageListItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageListItem.cs @@ -34,7 +34,7 @@ public partial class InstallPackageListItem : ListItem var version = _package.DefaultInstallVersion ?? _package.InstalledVersion; var versionTagText = "Unknown"; - if (version != null) + if (version is not null) { versionTagText = version.Version == "Unknown" && version.PackageCatalog.Info.Id == "StoreEdgeFD" ? "msstore" : version.Version; } @@ -60,11 +60,11 @@ public partial class InstallPackageListItem : ListItem Logger.LogWarning($"{ex.ErrorCode}"); } - if (metadata != null) + if (metadata is not null) { if (metadata.Tags.Where(t => t.Equals(WinGetExtensionPage.ExtensionsTag, StringComparison.OrdinalIgnoreCase)).Any()) { - if (_installCommand != null) + if (_installCommand is not null) { _installCommand.SkipDependencies = true; } @@ -172,7 +172,7 @@ public partial class InstallPackageListItem : ListItem return; } - var isInstalled = _package.InstalledVersion != null; + var isInstalled = _package.InstalledVersion is not null; var installedState = isInstalled ? (_package.IsUpdateAvailable ? @@ -193,11 +193,11 @@ public partial class InstallPackageListItem : ListItem Icon = Icons.DeleteIcon, }; - if (WinGetStatics.AppSearchCallback != null) + if (WinGetStatics.AppSearchCallback is not null) { var callback = WinGetStatics.AppSearchCallback; - var installedApp = callback(_package.DefaultInstallVersion == null ? _package.Name : _package.DefaultInstallVersion.DisplayName); - if (installedApp != null) + var installedApp = callback(_package.DefaultInstallVersion is null ? _package.Name : _package.DefaultInstallVersion.DisplayName); + if (installedApp is not null) { this.Command = installedApp.Command; contextMenu = [.. installedApp.MoreCommands]; diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/WinGetExtensionPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/WinGetExtensionPage.cs index 1ca113d55c..c348d209d4 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/WinGetExtensionPage.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/WinGetExtensionPage.cs @@ -53,7 +53,7 @@ internal sealed partial class WinGetExtensionPage : DynamicListPage, IDisposable { // emptySearchForTag === // we don't have results yet, we haven't typed anything, and we're searching for a tag - var emptySearchForTag = _results == null && + var emptySearchForTag = _results is null && string.IsNullOrEmpty(SearchText) && HasTag; @@ -64,7 +64,7 @@ internal sealed partial class WinGetExtensionPage : DynamicListPage, IDisposable return items; } - if (_results != null && _results.Any()) + if (_results is not null && _results.Any()) { ListItem[] results = _results.Select(PackageToListItem).ToArray(); IsLoading = false; @@ -100,7 +100,7 @@ internal sealed partial class WinGetExtensionPage : DynamicListPage, IDisposable private void DoUpdateSearchText(string newSearch) { // Cancel any ongoing search - if (_cancellationTokenSource != null) + if (_cancellationTokenSource is not null) { Logger.LogDebug("Cancelling old search", memberName: nameof(DoUpdateSearchText)); _cancellationTokenSource.Cancel(); @@ -221,7 +221,7 @@ internal sealed partial class WinGetExtensionPage : DynamicListPage, IDisposable // WinGetStatics static ctor when we were created. PackageCatalog catalog = await catalogTask.Value; - if (catalog == null) + if (catalog is null) { // This error should have already been displayed by WinGetStatics return []; diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Commands/SwitchToWindowCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Commands/SwitchToWindowCommand.cs index 0bfc1e0396..695eaa2c83 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Commands/SwitchToWindowCommand.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Commands/SwitchToWindowCommand.cs @@ -18,10 +18,10 @@ internal sealed partial class SwitchToWindowCommand : InvokableCommand { Name = Resources.switch_to_command_title; _window = window; - if (_window != null) + if (_window is not null) { var p = Process.GetProcessById((int)_window.Process.ProcessID); - if (p != null) + if (p is not null) { try { diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/ResultHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/ResultHelper.cs index fd7cf9149c..8739d88a2f 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/ResultHelper.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/ResultHelper.cs @@ -23,7 +23,7 @@ internal static class ResultHelper /// List of results internal static List GetResultList(List searchControllerResults, bool isKeywordSearch) { - if (searchControllerResults == null || searchControllerResults.Count == 0) + if (searchControllerResults is null || searchControllerResults.Count == 0) { return []; } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/VirtualDesktopHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/VirtualDesktopHelper.cs index 41e6f1fc7f..131ec7ae82 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/VirtualDesktopHelper.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/VirtualDesktopHelper.cs @@ -83,7 +83,7 @@ public class VirtualDesktopHelper /// /// Gets a value indicating whether the Virtual Desktop Manager is initialized successfully /// - public bool VirtualDesktopManagerInitialized => _virtualDesktopManager != null; + public bool VirtualDesktopManagerInitialized => _virtualDesktopManager is not null; /// /// Method to update the list of Virtual Desktops from Registry @@ -98,10 +98,10 @@ public class VirtualDesktopHelper // List of all desktops using RegistryKey? virtualDesktopKey = Registry.CurrentUser.OpenSubKey(registryExplorerVirtualDesktops, false); - if (virtualDesktopKey != null) + if (virtualDesktopKey is not null) { var allDeskValue = (byte[]?)virtualDesktopKey.GetValue("VirtualDesktopIDs", null) ?? Array.Empty(); - if (allDeskValue != null) + if (allDeskValue is not null) { // We clear only, if we can read from registry. Otherwise, we keep the existing values. _availableDesktops.Clear(); @@ -124,10 +124,10 @@ public class VirtualDesktopHelper // Guid for current desktop var virtualDesktopsKeyName = _isWindowsEleven ? registryExplorerVirtualDesktops : registrySessionVirtualDesktops; using RegistryKey? virtualDesktopsKey = Registry.CurrentUser.OpenSubKey(virtualDesktopsKeyName, false); - if (virtualDesktopsKey != null) + if (virtualDesktopsKey is not null) { var currentVirtualDesktopValue = virtualDesktopsKey.GetValue("CurrentVirtualDesktop", null); - if (currentVirtualDesktopValue != null) + if (currentVirtualDesktopValue is not null) { _currentDesktop = new Guid((byte[])currentVirtualDesktopValue); } @@ -268,7 +268,7 @@ public class VirtualDesktopHelper using RegistryKey? deskSubKey = Registry.CurrentUser.OpenSubKey(registryPath, false); var desktopName = deskSubKey?.GetValue("Name"); - return (desktopName != null) ? (string)desktopName : defaultName; + return (desktopName is not null) ? (string)desktopName : defaultName; } /// @@ -313,7 +313,7 @@ public class VirtualDesktopHelper /// HResult of the called method as integer. public int GetWindowDesktopId(IntPtr hWindow, out Guid desktopId) { - if (_virtualDesktopManager == null) + if (_virtualDesktopManager is null) { ExtensionHost.LogMessage(new LogMessage() { Message = "VirtualDesktopHelper.GetWindowDesktopId() failed: The instance of isn't available." }); desktopId = Guid.Empty; @@ -330,7 +330,7 @@ public class VirtualDesktopHelper /// An instance of for the desktop where the window is assigned to, or an empty instance of on failure. public VDesktop GetWindowDesktop(IntPtr hWindow) { - if (_virtualDesktopManager == null) + if (_virtualDesktopManager is null) { ExtensionHost.LogMessage(new LogMessage() { Message = "VirtualDesktopHelper.GetWindowDesktop() failed: The instance of isn't available." }); return CreateVDesktopInstance(Guid.Empty); @@ -348,7 +348,7 @@ public class VirtualDesktopHelper /// Type of . public VirtualDesktopAssignmentType GetWindowDesktopAssignmentType(IntPtr hWindow, Guid? desktop = null) { - if (_virtualDesktopManager == null) + if (_virtualDesktopManager is null) { ExtensionHost.LogMessage(new LogMessage() { Message = "VirtualDesktopHelper.GetWindowDesktopAssignmentType() failed: The instance of isn't available." }); return VirtualDesktopAssignmentType.Unknown; @@ -415,7 +415,7 @@ public class VirtualDesktopHelper /// on success and on failure. public bool MoveWindowToDesktop(IntPtr hWindow, ref Guid desktopId) { - if (_virtualDesktopManager == null) + if (_virtualDesktopManager is null) { ExtensionHost.LogMessage(new LogMessage() { Message = "VirtualDesktopHelper.MoveWindowToDesktop() failed: The instance of isn't available." }); return false; diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Helpers/ServiceHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Helpers/ServiceHelper.cs index ed67163ca5..6e874b1581 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Helpers/ServiceHelper.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Helpers/ServiceHelper.cs @@ -47,7 +47,7 @@ public static class ServiceHelper var result = serviceList.Select(s => { var serviceResult = ServiceResult.CreateServiceController(s); - if (serviceResult == null) + if (serviceResult is null) { return null; } @@ -98,7 +98,7 @@ public static class ServiceHelper // ToolTipData = new ToolTipData(serviceResult.DisplayName, serviceResult.ServiceName), // IcoPath = icoPath, }; - }).Where(s => s != null); + }).Where(s => s is not null); return result; } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/UnsupportedSettingsHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/UnsupportedSettingsHelper.cs index 9ad75ad561..c53844a005 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/UnsupportedSettingsHelper.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/UnsupportedSettingsHelper.cs @@ -49,8 +49,8 @@ internal static class UnsupportedSettingsHelper : currentBuildNumber; var filteredSettingsList = windowsSettings.Settings.Where(found - => (found.DeprecatedInBuild == null || currentWindowsBuild < found.DeprecatedInBuild) - && (found.IntroducedInBuild == null || currentWindowsBuild >= found.IntroducedInBuild)); + => (found.DeprecatedInBuild is null || currentWindowsBuild < found.DeprecatedInBuild) + && (found.IntroducedInBuild is null || currentWindowsBuild >= found.IntroducedInBuild)); filteredSettingsList = filteredSettingsList.OrderBy(found => found.Name); diff --git a/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleContentPage.cs b/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleContentPage.cs index 1e5d3f6c5f..3d5b49f61d 100644 --- a/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleContentPage.cs +++ b/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleContentPage.cs @@ -309,7 +309,7 @@ internal sealed partial class SampleContentForm : FormContent public override CommandResult SubmitForm(string payload) { var formInput = JsonNode.Parse(payload)?.AsObject(); - if (formInput == null) + if (formInput is null) { return CommandResult.GoHome(); } diff --git a/src/modules/cmdpal/ext/SamplePagesExtension/SampleUpdatingItemsPage.cs b/src/modules/cmdpal/ext/SamplePagesExtension/SampleUpdatingItemsPage.cs index 4b94a22ead..63bf2a5a6f 100644 --- a/src/modules/cmdpal/ext/SamplePagesExtension/SampleUpdatingItemsPage.cs +++ b/src/modules/cmdpal/ext/SamplePagesExtension/SampleUpdatingItemsPage.cs @@ -24,7 +24,7 @@ public partial class SampleUpdatingItemsPage : ListPage public override IListItem[] GetItems() { - if (timer == null) + if (timer is null) { timer = new Timer(500); timer.Elapsed += (object source, ElapsedEventArgs e) => diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/AnonymousCommand.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/AnonymousCommand.cs index c47fe5334b..4c6450706f 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/AnonymousCommand.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/AnonymousCommand.cs @@ -18,7 +18,7 @@ public sealed partial class AnonymousCommand : InvokableCommand public override ICommandResult Invoke() { - if (_action != null) + if (_action is not null) { _action(); } diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ChoiceSetSetting.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ChoiceSetSetting.cs index b38a1f305d..51beb0b5e7 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ChoiceSetSetting.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ChoiceSetSetting.cs @@ -65,7 +65,7 @@ public sealed class ChoiceSetSetting : Setting public override void Update(JsonObject payload) { // If the key doesn't exist in the payload, don't do anything - if (payload[Key] != null) + if (payload[Key] is not null) { Value = payload[Key]?.GetValue(); } diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ClipboardHelper.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ClipboardHelper.cs index ca9e397f45..b2a8e65bc6 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ClipboardHelper.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ClipboardHelper.cs @@ -2,10 +2,7 @@ // 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.Diagnostics; using System.Runtime.InteropServices; -using System.Threading; namespace Microsoft.CommandPalette.Extensions.Toolkit; @@ -293,7 +290,7 @@ public static partial class ClipboardHelper thread.Start(); thread.Join(); - if (exception != null) + if (exception is not null) { throw exception; } diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/CommandContextItem.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/CommandContextItem.cs index 92dfc714bf..467953381d 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/CommandContextItem.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/CommandContextItem.cs @@ -28,7 +28,7 @@ public partial class CommandContextItem : CommandItem, ICommandContextItem c.Name = name; } - if (result != null) + if (result is not null) { c.Result = result; } diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/CommandItem.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/CommandItem.cs index 153c4cda4f..b1a0917260 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/CommandItem.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/CommandItem.cs @@ -48,7 +48,7 @@ public partial class CommandItem : BaseObservable, ICommandItem get => _command; set { - if (_commandListener != null) + if (_commandListener is not null) { _commandListener.Detach(); _commandListener = null; @@ -56,7 +56,7 @@ public partial class CommandItem : BaseObservable, ICommandItem _command = value; - if (value != null) + if (value is not null) { _commandListener = new(this, OnCommandPropertyChanged, listener => value.PropChanged -= listener.OnEvent); value.PropChanged += _commandListener.OnEvent; @@ -123,7 +123,7 @@ public partial class CommandItem : BaseObservable, ICommandItem c.Name = name; } - if (result != null) + if (result is not null) { c.Result = result; } diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ExtensionHost.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ExtensionHost.cs index ed8ecb9566..cc9e2af15f 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ExtensionHost.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ExtensionHost.cs @@ -19,7 +19,7 @@ public partial class ExtensionHost /// The log message to send public static void LogMessage(ILogMessage message) { - if (Host != null) + if (Host is not null) { _ = Task.Run(async () => { @@ -42,7 +42,7 @@ public partial class ExtensionHost public static void ShowStatus(IStatusMessage message, StatusContext context) { - if (Host != null) + if (Host is not null) { _ = Task.Run(async () => { @@ -59,7 +59,7 @@ public partial class ExtensionHost public static void HideStatus(IStatusMessage message) { - if (Host != null) + if (Host is not null) { _ = Task.Run(async () => { diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ExtensionInstanceManager`1.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ExtensionInstanceManager`1.cs index 019b4dc398..b80742f8f7 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ExtensionInstanceManager`1.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ExtensionInstanceManager`1.cs @@ -55,7 +55,7 @@ internal sealed partial class ExtensionInstanceManager : IClassFactory ppvObject = IntPtr.Zero; - if (pUnkOuter != null) + if (pUnkOuter is not null) { Marshal.ThrowExceptionForHR(CLASS_E_NOAGGREGATION); } diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/JsonSettingsManager.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/JsonSettingsManager.cs index 8cf8d49db5..09c1eebdbe 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/JsonSettingsManager.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/JsonSettingsManager.cs @@ -76,7 +76,7 @@ public abstract class JsonSettingsManager { foreach (var item in newSettings) { - savedSettings[item.Key] = item.Value != null ? item.Value.DeepClone() : null; + savedSettings[item.Key] = item.Value is not null ? item.Value.DeepClone() : null; } var serialized = savedSettings.ToJsonString(_serializerOptions); diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/Settings.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/Settings.cs index 0d163ec3fb..fbd74ce694 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/Settings.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/Settings.cs @@ -41,7 +41,7 @@ public sealed partial class Settings : ICommandSettings .Values .Where(s => s is ISettingsForm) .Select(s => s as ISettingsForm) - .Where(s => s != null) + .Where(s => s is not null) .Select(s => s!); var bodies = string.Join(",", settings @@ -77,7 +77,7 @@ public sealed partial class Settings : ICommandSettings .Values .Where(s => s is ISettingsForm) .Select(s => s as ISettingsForm) - .Where(s => s != null) + .Where(s => s is not null) .Select(s => s!); var content = string.Join(",\n", settings.Select(s => s.ToState())); return $"{{\n{content}\n}}"; @@ -86,7 +86,7 @@ public sealed partial class Settings : ICommandSettings public void Update(string data) { var formInput = JsonNode.Parse(data)?.AsObject(); - if (formInput == null) + if (formInput is null) { return; } diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/SettingsForm.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/SettingsForm.cs index 79f548bf56..2bab5e78dc 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/SettingsForm.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/SettingsForm.cs @@ -19,7 +19,7 @@ public partial class SettingsForm : FormContent public override ICommandResult SubmitForm(string inputs, string data) { var formInput = JsonNode.Parse(inputs)?.AsObject(); - if (formInput == null) + if (formInput is null) { return CommandResult.KeepOpen(); } diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ShellHelpers.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ShellHelpers.cs index 4ab7cfb02f..6c761edcf2 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ShellHelpers.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ShellHelpers.cs @@ -125,7 +125,7 @@ public static class ShellHelpers else { var values = Environment.GetEnvironmentVariable("PATH"); - if (values != null) + if (values is not null) { foreach (var path in values.Split(';')) { diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/StringMatcher.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/StringMatcher.cs index 798bce3b9f..6d9009661a 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/StringMatcher.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/StringMatcher.cs @@ -93,7 +93,7 @@ public partial class StringMatcher query = query.Trim(); - // if (_alphabet != null) + // if (_alphabet is not null) // { // query = _alphabet.Translate(query); // stringToCompare = _alphabet.Translate(stringToCompare); diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/TextSetting.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/TextSetting.cs index aaa8c2fbee..7cf9147159 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/TextSetting.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/TextSetting.cs @@ -50,7 +50,7 @@ public partial class TextSetting : Setting public override void Update(JsonObject payload) { // If the key doesn't exist in the payload, don't do anything - if (payload[Key] != null) + if (payload[Key] is not null) { Value = payload[Key]?.GetValue(); } diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ToggleSetting.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ToggleSetting.cs index c5e1838608..cdb7b72b25 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ToggleSetting.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ToggleSetting.cs @@ -43,7 +43,7 @@ public sealed class ToggleSetting : Setting public override void Update(JsonObject payload) { // If the key doesn't exist in the payload, don't do anything - if (payload[Key] != null) + if (payload[Key] is not null) { // Adaptive cards returns boolean values as a string "true"/"false", cause of course. var strFromJson = payload[Key]?.GetValue() ?? string.Empty; From 65b752b3ff118f94a8e0f9a419547cb61f3a927b Mon Sep 17 00:00:00 2001 From: Heiko <61519853+htcfreek@users.noreply.github.com> Date: Mon, 18 Aug 2025 18:22:26 +0200 Subject: [PATCH 36/99] [CmdPal > Ext] Use empty content for WindowWalker, Windows Settings and Windows Search (#40722) ## Summary of the Pull Request This PR improves the behavior of CmdPal on empty or wrong search query for the following exts: - Window Walker - Windows Settings - Windows Search (indexer) ### Window Walker image ### Windows Settings - Empty query image ### Windows Settings - No search match image ### Windows search (indexer) image ## PR Checklist - [x] **Closes:** #40614 , #38293 , #40565 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **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 --------- Co-authored-by: Niels Laute Co-authored-by: Mike Griese --- .../Pages/IndexerPage.cs | 18 +++++++++- .../Properties/Resources.Designer.cs | 20 ++++++++++- .../Properties/Resources.resx | 6 ++++ .../Pages/WindowWalkerListPage.cs | 8 +++++ .../Properties/Resources.Designer.cs | 11 +++++- .../Properties/Resources.resx | 3 ++ .../Classes/WindowsSetting.cs | 6 ++-- .../Pages/WindowsSettingsListPage.cs | 27 +++++++++++--- .../Properties/Resources.Designer.cs | 35 ++++++++++++++++--- .../Properties/Resources.resx | 18 +++++++--- .../WindowsSettings.json | 8 ++--- .../WindowsSettings.schema.json | 7 ++-- 12 files changed, 141 insertions(+), 26 deletions(-) diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/IndexerPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/IndexerPage.cs index a62f03295a..f03452effb 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/IndexerPage.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/IndexerPage.cs @@ -21,6 +21,8 @@ internal sealed partial class IndexerPage : DynamicListPage, IDisposable private string initialQuery = string.Empty; + private bool _isEmptyQuery = true; + public IndexerPage() { Id = "com.microsoft.indexer.fileSearch"; @@ -43,15 +45,19 @@ internal sealed partial class IndexerPage : DynamicListPage, IDisposable disposeSearchEngine = false; } + public override ICommandItem EmptyContent => GetEmptyContent(); + public override void UpdateSearchText(string oldSearch, string newSearch) { if (oldSearch != newSearch && newSearch != initialQuery) { _ = Task.Run(() => { + _isEmptyQuery = string.IsNullOrWhiteSpace(newSearch); Query(newSearch); LoadMore(); - initialQuery = string.Empty; + OnPropertyChanged(nameof(EmptyContent)); + initialQuery = null; }); } } @@ -68,6 +74,16 @@ internal sealed partial class IndexerPage : DynamicListPage, IDisposable RaiseItemsChanged(_indexerListItems.Count); } + private CommandItem GetEmptyContent() + { + return new CommandItem(new NoOpCommand()) + { + Icon = Icon, + Title = _isEmptyQuery ? Resources.Indexer_Subtitle : Resources.Indexer_NoResultsMessage, + Subtitle = Resources.Indexer_NoResultsMessageTip, + }; + } + private void Query(string query) { ++_queryCookie; diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.Designer.cs index f5d1ba2d61..a78488a7f1 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.Designer.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.Designer.cs @@ -61,7 +61,7 @@ namespace Microsoft.CmdPal.Ext.Indexer.Properties { } /// - /// Looks up a localized string similar to Actions. + /// Looks up a localized string similar to Actions.... /// internal static string Indexer_Command_Actions { get { @@ -177,6 +177,24 @@ namespace Microsoft.CmdPal.Ext.Indexer.Properties { } } + /// + /// Looks up a localized string similar to No items found. + /// + internal static string Indexer_NoResultsMessage { + get { + return ResourceManager.GetString("Indexer_NoResultsMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tip: Improve your search result using filters like in Windows Explorer. (For example: type:directory). + /// + internal static string Indexer_NoResultsMessageTip { + get { + return ResourceManager.GetString("Indexer_NoResultsMessageTip", resourceCulture); + } + } + /// /// Looks up a localized string similar to Search for files and folders.... /// diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.resx index 61d51998b2..bbe8f0bd31 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.resx +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.resx @@ -180,4 +180,10 @@ Search for "{0}" in files + + No items found + + + Tip: Refine your search using filters, just like in File Explorer (e.g., type:directory). + \ No newline at end of file diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Pages/WindowWalkerListPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Pages/WindowWalkerListPage.cs index ff7217498a..f0cbc01995 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Pages/WindowWalkerListPage.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Pages/WindowWalkerListPage.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using Microsoft.CmdPal.Ext.WindowWalker.Components; using Microsoft.CmdPal.Ext.WindowWalker.Properties; using Microsoft.CommandPalette.Extensions; @@ -23,6 +24,13 @@ internal sealed partial class WindowWalkerListPage : DynamicListPage, IDisposabl Name = Resources.windowwalker_name; Id = "com.microsoft.cmdpal.windowwalker"; PlaceholderText = Resources.windowwalker_PlaceholderText; + + EmptyContent = new CommandItem(new NoOpCommand()) + { + Icon = Icon, + Title = Resources.window_walker_top_level_command_title, + Subtitle = Resources.windowwalker_NoResultsMessage, + }; } public override void UpdateSearchText(string oldSearch, string newSearch) => diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Properties/Resources.Designer.cs index 1884f3b3e5..ecb09c8c38 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Properties/Resources.Designer.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Properties/Resources.Designer.cs @@ -142,7 +142,7 @@ namespace Microsoft.CmdPal.Ext.WindowWalker.Properties { } /// - /// Looks up a localized string similar to You are going to end the following process:. + /// Looks up a localized string similar to The following process will be ended:. /// public static string windowwalker_KillMessage { get { @@ -186,6 +186,15 @@ namespace Microsoft.CmdPal.Ext.WindowWalker.Properties { } } + /// + /// Looks up a localized string similar to No open windows found. + /// + public static string windowwalker_NoResultsMessage { + get { + return ResourceManager.GetString("windowwalker_NoResultsMessage", resourceCulture); + } + } + /// /// Looks up a localized string similar to Not Responding. /// diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Properties/Resources.resx index 1c4191bfee..c610b7b09c 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Properties/Resources.resx +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Properties/Resources.resx @@ -232,4 +232,7 @@ Search open windows... + + No open windows found + \ No newline at end of file diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Classes/WindowsSetting.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Classes/WindowsSetting.cs index fa6485d138..b276d3a876 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Classes/WindowsSetting.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Classes/WindowsSetting.cs @@ -19,7 +19,7 @@ internal sealed class WindowsSetting Name = string.Empty; Command = string.Empty; Type = string.Empty; - ShowAsFirstResult = false; + AppHomepageScore = 0; } /// @@ -65,9 +65,9 @@ internal sealed class WindowsSetting public uint? DeprecatedInBuild { get; set; } /// - /// Gets or sets a value indicating whether to use a higher score as normal for this setting to show it as one of the first results. + /// Gets or sets the score for entries if they are a settings app (homepage). If the score is higher 0 they are shown on empty query. /// - public bool ShowAsFirstResult { get; set; } + public int AppHomepageScore { get; set; } /// /// Gets or sets the value with the generated area path as string. diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Pages/WindowsSettingsListPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Pages/WindowsSettingsListPage.cs index 3c27d28537..1196de0b31 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Pages/WindowsSettingsListPage.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Pages/WindowsSettingsListPage.cs @@ -23,6 +23,13 @@ internal sealed partial class WindowsSettingsListPage : DynamicListPage Name = Resources.settings_title; Id = "com.microsoft.cmdpal.windowsSettings"; _windowsSettings = windowsSettings; + + EmptyContent = new CommandItem(new NoOpCommand()) + { + Icon = Icon, + Title = Resources.settings_subtitle, + Subtitle = Resources.PluginNoResultsMessage + "\n\n" + Resources.PluginNoResultsMessageHelp, + }; } public WindowsSettingsListPage(Classes.WindowsSettings windowsSettings, string query) @@ -38,11 +45,21 @@ internal sealed partial class WindowsSettingsListPage : DynamicListPage return new List(0); } - var filteredList = _windowsSettings.Settings - .Select(setting => ScoringHelper.SearchScoringPredicate(query, setting)) - .Where(scoredSetting => scoredSetting.Score > 0) - .OrderByDescending(scoredSetting => scoredSetting.Score) - .Select(scoredSetting => scoredSetting.Setting); + var filteredList = _windowsSettings.Settings; + if (!string.IsNullOrEmpty(query)) + { + filteredList = filteredList + .Select(setting => ScoringHelper.SearchScoringPredicate(query, setting)) + .Where(scoredSetting => scoredSetting.Score > 0) + .OrderByDescending(scoredSetting => scoredSetting.Score) + .Select(scoredSetting => scoredSetting.Setting); + } + else + { + filteredList = filteredList + .Where(s => s.AppHomepageScore > 0) + .OrderByDescending(s => s.AppHomepageScore); + } var newList = ResultHelper.GetResultList(filteredList); return newList; diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Properties/Resources.Designer.cs index 0d5ce2cede..114ff4912a 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Properties/Resources.Designer.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Properties/Resources.Designer.cs @@ -322,7 +322,7 @@ namespace Microsoft.CmdPal.Ext.WindowsSettings.Properties { } /// - /// Looks up a localized string similar to System settings. + /// Looks up a localized string similar to Settings app. /// internal static string AppSettingsApp { get { @@ -3049,7 +3049,7 @@ namespace Microsoft.CmdPal.Ext.WindowsSettings.Properties { } /// - /// Looks up a localized string similar to Control Panel (Application homepage). + /// Looks up a localized string similar to Open Control Panel. /// internal static string OpenControlPanel { get { @@ -3058,7 +3058,16 @@ namespace Microsoft.CmdPal.Ext.WindowsSettings.Properties { } /// - /// Looks up a localized string similar to Open Settings. + /// Looks up a localized string similar to Open Microsoft Management Console. + /// + internal static string OpenMMC { + get { + return ResourceManager.GetString("OpenMMC", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Open. /// internal static string OpenSettings { get { @@ -3067,7 +3076,7 @@ namespace Microsoft.CmdPal.Ext.WindowsSettings.Properties { } /// - /// Looks up a localized string similar to Settings (Application homepage). + /// Looks up a localized string similar to Open Settings app. /// internal static string OpenSettingsApp { get { @@ -3345,6 +3354,24 @@ namespace Microsoft.CmdPal.Ext.WindowsSettings.Properties { } } + /// + /// Looks up a localized string similar to No settings found. + /// + internal static string PluginNoResultsMessage { + get { + return ResourceManager.GetString("PluginNoResultsMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tip: Use ':' to search for setting categories (e.g., Update:), and > to search by setting path (e.g., Settings app>Apps).. + /// + internal static string PluginNoResultsMessageHelp { + get { + return ResourceManager.GetString("PluginNoResultsMessageHelp", resourceCulture); + } + } + /// /// Looks up a localized string similar to Windows settings. /// diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Properties/Resources.resx index 467defe1e8..95b4b5a174 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Properties/Resources.resx +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Properties/Resources.resx @@ -228,7 +228,7 @@ Area Apps - System settings + Settings app Type of the setting is a "Modern Windows settings". We use the same term as used in start menu search at the moment. @@ -1319,11 +1319,11 @@ On-Screen - Control Panel (Application homepage) + Open Control Panel 'Control Panel' is here the name of the legacy settings app. - Settings (Application homepage) + Open Settings app 'Settings' is here the name of the modern settings app. @@ -2080,7 +2080,8 @@ Mean zooming of things via a magnifier - Open Settings + Open + Open 'the setting' in Settings app, Control Panel or MMC. Windows Settings @@ -2097,4 +2098,13 @@ Search Windows settings for this device + + Tip: Use ':' to search for setting categories (e.g., Update:), and > to search by setting path (e.g., Settings app>Apps). + + + No settings found + + + Open Microsoft Management Console + \ No newline at end of file diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettings.json b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettings.json index 97c4d3f65c..794dbcc280 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettings.json +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettings.json @@ -6,13 +6,13 @@ "Type": "AppSettingsApp", "AltNames": [ "SettingsApp", "AppSettingsApp" ], "Command": "ms-settings:", - "ShowAsFirstResult": true + "AppHomepageScore": 30 }, { "Name": "OpenControlPanel", "Type": "AppControlPanel", "Command": "control.exe", - "ShowAsFirstResult": true + "AppHomepageScore": 20 }, { "Name": "AccessWorkOrSchool", @@ -1834,11 +1834,11 @@ "Command": "ms-settings-connectabledevices:devicediscovery" }, { - "Name": "AppMMC", + "Name": "OpenMMC", "Type": "AppMMC", "AltNames": [ "MMC_mmcexe" ], "Command": "mmc.exe", - "ShowAsFirstResult" : true + "AppHomepageScore" : 10 }, { "Name": "AuthorizationManager", diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettings.schema.json b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettings.schema.json index a60e5c5ffd..ad7f84b4bd 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettings.schema.json +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettings.schema.json @@ -62,9 +62,10 @@ "minimum": 0, "maximum": 4294967295 }, - "ShowAsFirstResult": { - "description": "Use a higher score as normal for this setting to show it as one of the first results.", - "type": "boolean" + "AppHomepageScore": { + "description": "Order score for the result if it is a settings app (homepage). Use a score > 0.", + "type": "integer", + "minimum": 1 } } } From 409ae3d73a0b4089afe61b7f61f3ce9608e5b12f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pol=C3=A1=C5=A1ek?= Date: Mon, 18 Aug 2025 18:31:41 +0200 Subject: [PATCH 37/99] CmdPal: Improve page exception details for users (#41035) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary of the Pull Request Show timestamp, HRESULT (hex/decimal), and full Exception.ToString() in the error message. Centralize message generation in a helper class for consistency. Example: ``` ============================================================ 😢 An unexpected error occurred in the 'Open' extension. Summary: Message: Operation is not valid due to the current state of the object. (inferred from HRESULT 0x80131509) Type: System.Runtime.InteropServices.COMException Source: WinRT.Runtime Time: 2025-08-07 15:54:20.4189499 HRESULT: 0x80131509 (-2146233079) Stack Trace: at WinRT.ExceptionHelpers.g__Throw|38_0(Int32 hr) at ABI.Microsoft.CommandPalette.Extensions.IListPageMethods.GetItems(IObjectReference _obj) at Microsoft.CmdPal.Core.ViewModels.ListViewModel.FetchItems() at Microsoft.CmdPal.Core.ViewModels.ListViewModel.InitializeProperties() at Microsoft.CmdPal.Core.ViewModels.PageViewModel.InitializeAsync() ------------------ Full Exception Details ------------------ System.Runtime.InteropServices.COMException (0x80131509) at WinRT.ExceptionHelpers.g__Throw|38_0(Int32 hr) at ABI.Microsoft.CommandPalette.Extensions.IListPageMethods.GetItems(IObjectReference _obj) at Microsoft.CmdPal.Core.ViewModels.ListViewModel.FetchItems() at Microsoft.CmdPal.Core.ViewModels.ListViewModel.InitializeProperties() at Microsoft.CmdPal.Core.ViewModels.PageViewModel.InitializeAsync() ℹ️ If you need further assistance, please include this information in your support request. ℹ️ Before sending, take a quick look to make sure it doesn't contain any personal or sensitive information. ============================================================ ``` ## PR Checklist - [x] Closes: #41034 - [ ] **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 I crashed an extension on purpose and read the message. --- .../Helpers/DiagnosticsHelper.cs | 66 +++++++++++++++++++ .../PageViewModel.cs | 8 ++- .../TopLevelCommandManager.cs | 4 +- 3 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/DiagnosticsHelper.cs diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/DiagnosticsHelper.cs b/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/DiagnosticsHelper.cs new file mode 100644 index 0000000000..d2e9ddbcb3 --- /dev/null +++ b/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/DiagnosticsHelper.cs @@ -0,0 +1,66 @@ +// 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.Runtime.InteropServices; + +namespace Microsoft.CmdPal.Common.Helpers; + +/// +/// Provides utility methods for building diagnostic and error messages. +/// +public static class DiagnosticsHelper +{ + /// + /// Builds a comprehensive exception message with timestamp and detailed diagnostic information. + /// + /// The exception that occurred. + /// A hint about which extension caused the exception to help with debugging. + /// A string containing the exception details, timestamp, and source information for diagnostic purposes. + public static string BuildExceptionMessage(Exception exception, string? extensionHint) + { + var locationHint = string.IsNullOrWhiteSpace(extensionHint) ? "application" : $"'{extensionHint}' extension"; + + // let's try to get a message from the exception or inferred it from the HRESULT + // to show at least something + var message = exception.Message; + if (string.IsNullOrWhiteSpace(message)) + { + var temp = Marshal.GetExceptionForHR(exception.HResult)?.Message; + if (!string.IsNullOrWhiteSpace(temp)) + { + message = temp + $" (inferred from HRESULT 0x{exception.HResult:X8})"; + } + } + + if (string.IsNullOrWhiteSpace(message)) + { + message = "[No message available]"; + } + + // note: keep date time kind and format consistent with the log + return $""" + ============================================================ + 😢 An unexpected error occurred in the {locationHint}. + + Summary: + Message: {message} + Type: {exception.GetType().FullName} + Source: {exception.Source ?? "N/A"} + Time: {DateTimeOffset.Now:yyyy-MM-dd HH:mm:ss.fffffff} + HRESULT: 0x{exception.HResult:X8} ({exception.HResult}) + + Stack Trace: + {exception.StackTrace ?? "[No stack trace available]"} + + ------------------ Full Exception Details ------------------ + {exception} + + ℹ️ If you need further assistance, please include this information in your support request. + ℹ️ Before sending, take a quick look to make sure it doesn't contain any personal or sensitive information. + ============================================================ + + """; + } +} diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/PageViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/PageViewModel.cs index 7a301c89b0..046c9fae93 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/PageViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Core.ViewModels/PageViewModel.cs @@ -5,6 +5,7 @@ using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; +using Microsoft.CmdPal.Common.Helpers; using Microsoft.CmdPal.Core.ViewModels.Models; using Microsoft.CommandPalette.Extensions; @@ -223,9 +224,10 @@ public partial class PageViewModel : ExtensionObjectViewModel, IPageContext extensionHint ??= ExtensionHost.GetExtensionDisplayName() ?? Title; Task.Factory.StartNew( () => - { - ErrorMessage += $"A bug occurred in {$"the \"{extensionHint}\"" ?? "an unknown's"} extension's code:\n{ex.Message}\n{ex.Source}\n{ex.StackTrace}\n\n"; - }, + { + var message = DiagnosticsHelper.BuildExceptionMessage(ex, extensionHint); + ErrorMessage += message; + }, CancellationToken.None, TaskCreationOptions.None, Scheduler); diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelCommandManager.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelCommandManager.cs index 3bd2d8cedf..f55a322792 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelCommandManager.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelCommandManager.cs @@ -410,8 +410,8 @@ public partial class TopLevelCommandManager : ObservableObject, void IPageContext.ShowException(Exception ex, string? extensionHint) { - var errorMessage = $"A bug occurred in {$"the \"{extensionHint}\"" ?? "an unknown's"} extension's code:\n{ex.Message}\n{ex.Source}\n{ex.StackTrace}\n\n"; - CommandPaletteHost.Instance.Log(errorMessage); + var message = DiagnosticsHelper.BuildExceptionMessage(ex, extensionHint ?? "TopLevelCommandManager"); + CommandPaletteHost.Instance.Log(message); } internal bool IsProviderActive(string id) From d2a4c96e12fea28b7ff5ce3f67385a6f4c478db9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pol=C3=A1=C5=A1ek?= Date: Mon, 18 Aug 2025 18:45:25 +0200 Subject: [PATCH 38/99] CmdPal: Prevent disposed ContentPage from handling messages (#41083) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary of the Pull Request Changes the timing of when `ContentPage` registers to messages from the Toolkit Messenger so it happens only when navigated to, mirroring the unregister on navigation from. Also unregisters from all messages when unloaded. Proactively unregisters the Settings window from all messages on close instead of relying on the GC’s nondeterministic cleanup. Since the Settings window is newly created each time, old instances can still react to messages even after their time is over, merely waiting for GC to collect them. Co-authored-by: zadjii-msft ## PR Checklist - [x] Closes: #40846 - [ ] **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 --- .../ExtViews/ContentPage.xaml.cs | 20 +++++++++++++++++-- .../Settings/SettingsWindow.xaml.cs | 2 ++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/ExtViews/ContentPage.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/ExtViews/ContentPage.xaml.cs index 55887f155d..2bc8c2a4b0 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/ExtViews/ContentPage.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/ExtViews/ContentPage.xaml.cs @@ -34,8 +34,14 @@ public sealed partial class ContentPage : Page, public ContentPage() { this.InitializeComponent(); - WeakReferenceMessenger.Default.Register(this); - WeakReferenceMessenger.Default.Register(this); + this.Unloaded += OnUnloaded; + } + + private void OnUnloaded(object sender, RoutedEventArgs e) + { + // Unhook from everything to ensure nothing can reach us + // between this point and our complete and utter destruction. + WeakReferenceMessenger.Default.UnregisterAll(this); } protected override void OnNavigatedTo(NavigationEventArgs e) @@ -45,6 +51,16 @@ public sealed partial class ContentPage : Page, ViewModel = vm; } + if (!WeakReferenceMessenger.Default.IsRegistered(this)) + { + WeakReferenceMessenger.Default.Register(this); + } + + if (!WeakReferenceMessenger.Default.IsRegistered(this)) + { + WeakReferenceMessenger.Default.Register(this); + } + base.OnNavigatedTo(e); } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/SettingsWindow.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/SettingsWindow.xaml.cs index 9fbdb11102..9a2ca373ca 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/SettingsWindow.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/SettingsWindow.xaml.cs @@ -105,6 +105,8 @@ public sealed partial class SettingsWindow : WindowEx, private void Window_Closed(object sender, WindowEventArgs args) { WeakReferenceMessenger.Default.Send(); + + WeakReferenceMessenger.Default.UnregisterAll(this); } private void PaneToggleBtn_Click(object sender, RoutedEventArgs e) From 8f93d0269fb7f9c244a2c383d60faee31feeb6a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pol=C3=A1=C5=A1ek?= Date: Mon, 18 Aug 2025 23:46:08 +0200 Subject: [PATCH 39/99] CmdPal: Honor "Single-click activation" only for pointer clicks and not for keyboard (#41119) ## Summary of the Pull Request Changes the behavior of keyboard item activation when the item list view has focus. Previously, the list view handled item activation according to the "Single-click activation" setting regardless of the input source (mouse, pen, touch, or keyboard). Now, when handling a ListView item click, the input source is detected, and the "Single-click activation" setting is applied only for pointer-raised clicks. For keyboard-triggered clicks, items are always activated immediately. Since the event `ListView.ItemClick` doesn't provide information about what caused the item activation, this PR work around that by observing last user input on the list immediately before `ItemClick` event is invoked. ## PR Checklist - [x] Closes: #41101 - [ ] **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 --- .../ExtViews/ListPage.xaml.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/ExtViews/ListPage.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/ExtViews/ListPage.xaml.cs index 475e2b964e..0ef1052db7 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/ExtViews/ListPage.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/ExtViews/ListPage.xaml.cs @@ -15,6 +15,7 @@ using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Input; using Microsoft.UI.Xaml.Media; using Microsoft.UI.Xaml.Navigation; +using Windows.System; namespace Microsoft.CmdPal.UI; @@ -24,6 +25,8 @@ public sealed partial class ListPage : Page, IRecipient, IRecipient { + private InputSource _lastInputSource; + private ListViewModel? ViewModel { get => (ListViewModel?)GetValue(ViewModelProperty); @@ -39,6 +42,8 @@ public sealed partial class ListPage : Page, this.InitializeComponent(); this.NavigationCacheMode = NavigationCacheMode.Disabled; this.ItemsList.Loaded += ItemsList_Loaded; + this.ItemsList.PreviewKeyDown += ItemsList_PreviewKeyDown; + this.ItemsList.PointerPressed += ItemsList_PointerPressed; } protected override void OnNavigatedTo(NavigationEventArgs e) @@ -98,6 +103,12 @@ public sealed partial class ListPage : Page, { if (e.ClickedItem is ListItemViewModel item) { + if (_lastInputSource == InputSource.Keyboard) + { + ViewModel?.InvokeItemCommand.Execute(item); + return; + } + var settings = App.Current.Services.GetService()!; if (settings.SingleClickActivates) { @@ -363,4 +374,21 @@ public sealed partial class ListPage : Page, { _ = DispatcherQueue.TryEnqueue(() => WeakReferenceMessenger.Default.Send()); } + + private void ItemsList_PointerPressed(object sender, PointerRoutedEventArgs e) => _lastInputSource = InputSource.Pointer; + + private void ItemsList_PreviewKeyDown(object sender, KeyRoutedEventArgs e) + { + if (e.Key is VirtualKey.Enter or VirtualKey.Space) + { + _lastInputSource = InputSource.Keyboard; + } + } + + private enum InputSource + { + None, + Keyboard, + Pointer, + } } From 2f6876b85fb0f4fff8cac52fda5093cd1473fbc4 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 18 Aug 2025 16:46:36 -0500 Subject: [PATCH 40/99] CmdPal: Add a couple evil samples for testing (#41158) This doesn't fix any bugs, it just makes them easier to repro RE: #38190 RE: #41149 also accidentally a great example for RE: #39837 --- .../SamplePagesExtension/EvilSamplesPage.cs | 204 +++++++++++++++--- 1 file changed, 179 insertions(+), 25 deletions(-) diff --git a/src/modules/cmdpal/ext/SamplePagesExtension/EvilSamplesPage.cs b/src/modules/cmdpal/ext/SamplePagesExtension/EvilSamplesPage.cs index 2fc1218bd7..21e033f8da 100644 --- a/src/modules/cmdpal/ext/SamplePagesExtension/EvilSamplesPage.cs +++ b/src/modules/cmdpal/ext/SamplePagesExtension/EvilSamplesPage.cs @@ -2,6 +2,7 @@ // 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.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CommandPalette.Extensions; @@ -13,31 +14,43 @@ namespace SamplePagesExtension; public partial class EvilSamplesPage : ListPage { private readonly IListItem[] _commands = [ - new ListItem(new EvilSampleListPage()) - { - Title = "List Page without items", - Subtitle = "Throws exception on GetItems", - }, - new ListItem(new ExplodeInFiveSeconds(false)) - { - Title = "Page that will throw an exception after loading it", - Subtitle = "Throws exception on GetItems _after_ a ItemsChanged", - }, - new ListItem(new ExplodeInFiveSeconds(true)) - { - Title = "Page that keeps throwing exceptions", - Subtitle = "Will throw every 5 seconds once you open it", - }, - new ListItem(new ExplodeOnPropChange()) - { - Title = "Throw in the middle of a PropChanged", - Subtitle = "Will throw every 5 seconds once you open it", - }, - new ListItem(new SelfImmolateCommand()) - { - Title = "Terminate this extension", - Subtitle = "Will exit this extension (while it's loaded!)", - }, + new ListItem(new EvilSampleListPage()) + { + Title = "List Page without items", + Subtitle = "Throws exception on GetItems", + }, + new ListItem(new ExplodeInFiveSeconds(false)) + { + Title = "Page that will throw an exception after loading it", + Subtitle = "Throws exception on GetItems _after_ a ItemsChanged", + }, + new ListItem(new ExplodeInFiveSeconds(true)) + { + Title = "Page that keeps throwing exceptions", + Subtitle = "Will throw every 5 seconds once you open it", + }, + new ListItem(new ExplodeOnPropChange()) + { + Title = "Throw in the middle of a PropChanged", + Subtitle = "Will throw every 5 seconds once you open it", + }, + new ListItem(new SelfImmolateCommand()) + { + Title = "Terminate this extension", + Subtitle = "Will exit this extension (while it's loaded!)", + }, + new ListItem(new EvilSlowDynamicPage()) + { + Title = "Slow loading Dynamic Page", + Subtitle = "Takes 5 seconds to load each time you type", + Tags = [new Tag("GH #38190")], + }, + new ListItem(new EvilFastUpdatesPage()) + { + Title = "Fast updating Dynamic Page", + Subtitle = "Updates in the middle of a GetItems call", + Tags = [new Tag("GH #41149")], + }, new ListItem(new NoOpCommand()) { Title = "I have lots of nulls", @@ -260,3 +273,144 @@ internal sealed partial class ExplodeOnPropChange : ListPage return Commands; } } + +/// +/// This sample simulates a long delay in handling UpdateSearchText. I've found +/// that if I type "124356781234", then somewhere around the second "1234", +/// we'll get into a state where the character is typed, but then CmdPal snaps +/// back to a previous query. +/// +/// We can use this to validate that we're always sticking with the last +/// SearchText. My guess is that it's a bug in +/// Toolkit.DynamicListPage.SearchText.set +/// +/// see GH #38190 +/// +[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Sample code")] +internal sealed partial class EvilSlowDynamicPage : DynamicListPage +{ + private IListItem[] _items = []; + + public EvilSlowDynamicPage() + { + Icon = new IconInfo(string.Empty); + Name = "Open"; + Title = "Evil Slow Dynamic Page"; + PlaceholderText = "Type to see items appear after a delay"; + } + + public override void UpdateSearchText(string oldSearch, string newSearch) + { + DoQuery(newSearch); + RaiseItemsChanged(newSearch.Length); + } + + public override IListItem[] GetItems() + { + return _items.Length > 0 ? _items : DoQuery(SearchText); + } + + private IListItem[] DoQuery(string newSearch) + { + IsLoading = true; + + // Sleep for longer for shorter search terms + var delay = 10000 - (newSearch.Length * 2000); + delay = delay < 0 ? 0 : delay; + if (newSearch.Length == 0) + { + delay = 0; + } + + delay += 50; + + Thread.Sleep(delay); // Simulate a long load time + + var items = newSearch.ToCharArray().Select(ch => new ListItem(new NoOpCommand()) { Title = ch.ToString() }).ToArray(); + if (items.Length == 0) + { + items = [new ListItem(new NoOpCommand()) { Title = "Start typing in the search box" }]; + } + + if (items.Length > 0) + { + items[0].Subtitle = "Notice how the number of items changes for this page when you type in the filter box"; + } + + IsLoading = false; + + return items; + } +} + +/// +/// A sample for a page that updates its items in the middle of a GetItems call. +/// In this sample, we're returning 10000 items, which genuinely marshal slowly +/// (even before we start retrieving properties from them). +/// +/// While we're in the middle of the marshalling of that GetItems call, the +/// background thread we started will kick off another GetItems (via the +/// RaiseItemsChanged). +/// +/// That second GetItems will return a single item, which marshals quickly. +/// CmdPal _should_ only display that single green item. However, as of v0.4, +/// we'll display that green item, then "snap back" to the red items, when they +/// finish marshalling. +/// +/// See GH #41149 +/// +[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Sample code")] +internal sealed partial class EvilFastUpdatesPage : DynamicListPage +{ + private static readonly IconInfo _red = new("🔴"); // "Red" icon + private static readonly IconInfo _green = new("🟢"); // "Green" icon + + private IListItem[] _redItems = []; + private IListItem[] _greenItems = []; + private bool _sentRed; + + public EvilFastUpdatesPage() + { + Icon = new IconInfo(string.Empty); + Name = "Open"; + Title = "Evil Fast Updates Page"; + PlaceholderText = "Type to trigger an update"; + + _redItems = Enumerable.Range(0, 10000).Select(i => new ListItem(new NoOpCommand()) + { + Icon = _red, + Title = $"Item {i + 1}", + Subtitle = "CmdPal is doing it wrong", + }).ToArray(); + _greenItems = [new ListItem(new NoOpCommand()) { Icon = _green, Title = "It works" }]; + } + + public override void UpdateSearchText(string oldSearch, string newSearch) + { + _sentRed = false; + RaiseItemsChanged(); + } + + public override IListItem[] GetItems() + { + if (!_sentRed) + { + IsLoading = true; + _sentRed = true; + + // kick off a task to update the items after a delay + _ = Task.Run(() => + { + Thread.Sleep(5); + RaiseItemsChanged(); + }); + + return _redItems; + } + else + { + IsLoading = false; + return _greenItems; + } + } +} From 8737de29afa6d98a9af438c9fa8699a119e59fba Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 18 Aug 2025 16:52:49 -0500 Subject: [PATCH 41/99] CmdPal: mark CommandProvider.Dispose as virtual (#41184) If your provider wants to implement this, they should be able to --- .../CommandProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/CommandProvider.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/CommandProvider.cs index 1efc9475a7..308265f7c0 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/CommandProvider.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/CommandProvider.cs @@ -31,7 +31,7 @@ public abstract partial class CommandProvider : ICommandProvider public virtual void InitializeWithHost(IExtensionHost host) => ExtensionHost.Initialize(host); #pragma warning disable CA1816 // Dispose methods should call SuppressFinalize - public void Dispose() + public virtual void Dispose() { } #pragma warning restore CA1816 // Dispose methods should call SuppressFinalize From 69c6475e15a84e6072606cdf8e371685a61fccc7 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Mon, 14 Oct 2024 19:02:22 +0200 Subject: [PATCH 42/99] [WIP] Shortcut Guide V2 --- Directory.Packages.props | 1 + PowerToys.sln | 47 +++++-- .../Assets/Hosts/AppList.scale-100.png | Bin 0 -> 567 bytes .../Assets/Hosts/AppList.scale-125.png | Bin 0 -> 768 bytes .../Assets/Hosts/AppList.scale-150.png | Bin 0 -> 1001 bytes .../Assets/Hosts/AppList.scale-200.png | Bin 0 -> 1542 bytes .../Assets/Hosts/AppList.scale-400.png | Bin 0 -> 4283 bytes .../ShortcutGuide.Ui/Assets/Hosts/Hosts.ico | Bin 0 -> 178017 bytes .../Assets/ShortcutGuide/CopilotKey.png | Bin 0 -> 412 bytes .../Assets/ShortcutGuide/OfficeKey.png | Bin 0 -> 31310 bytes .../ShortcutGuide.Ui/DisplayHelper.cs | 96 ++++++++++++++ .../ShortcutGuide.Ui/DpiHelper.cs | 56 ++++++++ .../Exceptions/InvalidYamlFileException.cs | 10 ++ .../ShortcutGuide.Ui/Models/IndexFile.cs | 20 +++ .../ShortcutGuide.Ui/Models/Shortcut.cs | 81 ++++++++++++ .../Models/ShortcutCategory.cs | 13 ++ .../ShortcutGuide.Ui/Models/ShortcutList.cs | 13 ++ .../ShortcutGuide.Ui/NativeMethods.cs | 27 ++++ .../ShortcutGuide.Ui/Package.appxmanifest | 51 ++++++++ .../ShortcutGuide.Ui/Program.cs | 46 +++++++ .../Properties/Resource.Designer.cs | 72 ++++++++++ .../ShortcutGuide.Ui/Properties/Resource.resx | 123 ++++++++++++++++++ .../ShortcutGuide.Ui/ShortcutGuide.Ui.csproj | 121 +++++++++++++++++ .../ShortcutGuideXAML/App.xaml | 16 +++ .../ShortcutGuideXAML/App.xaml.cs | 24 ++++ .../ShortcutGuideXAML/MainWindow.xaml | 45 +++++++ .../ShortcutGuideXAML/MainWindow.xaml.cs | 113 ++++++++++++++++ .../ShortcutTemplateDataObject.cs | 38 ++++++ .../ShortcutGuideXAML/ShortcutView.xaml | 48 +++++++ .../ShortcutGuideXAML/ShortcutView.xaml.cs | 48 +++++++ .../StringToVisibilityConverter.cs | 24 ++++ .../ShortcutGuide.Ui/YmlInterpreter.cs | 46 +++++++ .../ShortcutGuide.Ui/app.manifest | 22 ++++ 33 files changed, 1189 insertions(+), 12 deletions(-) create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-100.png create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-125.png create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-150.png create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-200.png create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-400.png create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/Hosts.ico create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/CopilotKey.png create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/OfficeKey.png create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DisplayHelper.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DpiHelper.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Exceptions/InvalidYamlFileException.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/IndexFile.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/Shortcut.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutCategory.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutList.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Package.appxmanifest create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.Designer.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.resx create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutTemplateDataObject.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/StringToVisibilityConverter.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/YmlInterpreter.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/app.manifest diff --git a/Directory.Packages.props b/Directory.Packages.props index 71bbda5042..e951a1d451 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -107,6 +107,7 @@ + diff --git a/PowerToys.sln b/PowerToys.sln index 00986aae29..3f3c245ef4 100644 --- a/PowerToys.sln +++ b/PowerToys.sln @@ -328,12 +328,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Community.PowerToys.Run.Plu EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Community.PowerToys.Run.Plugin.UnitConverter.UnitTest", "src\modules\launcher\Plugins\Community.PowerToys.Run.Plugin.UnitConverter.UnitTest\Community.PowerToys.Run.Plugin.UnitConverter.UnitTest.csproj", "{3E424AD2-19E5-4AE6-B833-F53963EB5FC1}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shortcutguide", "shortcutguide", "{106CBECA-0701-4FC3-838C-9DF816A19AE2}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ShortcutGuide", "ShortcutGuide", "{106CBECA-0701-4FC3-838C-9DF816A19AE2}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShortcutGuideModuleInterface", "src\modules\ShortcutGuide\ShortcutGuideModuleInterface\ShortcutGuideModuleInterface.vcxproj", "{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShortcutGuide", "src\modules\ShortcutGuide\ShortcutGuide\ShortcutGuide.vcxproj", "{2EDB3EB4-FA92-4BFF-B2D8-566584837231}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FancyZonesModuleInterface", "src\modules\fancyzones\FancyZonesModuleInterface\FancyZonesModuleInterface.vcxproj", "{48804216-2A0E-4168-A6D8-9CD068D14227}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FancyZones", "src\modules\fancyzones\FancyZones\FancyZones.vcxproj", "{FF1D7936-842A-4BBB-8BEA-E9FE796DE700}" @@ -788,6 +786,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.Window EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.UnitTestBase", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.UnitTestsBase\Microsoft.CmdPal.Ext.UnitTestBase.csproj", "{00D8659C-2068-40B6-8B86-759CD6284BBB}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShortcutGuide.CPPProject", "src\modules\ShortcutGuide\ShortcutGuide.CPPProject\ShortcutGuide.CPPProject.vcxproj", "{C992FD2C-83B8-4941-9FC1-09730068D8EC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShortcutGuide.IndexYmlGenerator", "src\modules\ShortcutGuide\ShortcutGuide.IndexYmlGenerator\ShortcutGuide.IndexYmlGenerator.csproj", "{30F57201-9B54-5253-8033-8A28ECD3F1CE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShortcutGuide.Ui", "src\modules\ShortcutGuide\ShortcutGuide.Ui\ShortcutGuide.Ui.csproj", "{D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM64 = Debug|ARM64 @@ -1428,14 +1432,6 @@ Global {2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Release|ARM64.Build.0 = Release|ARM64 {2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Release|x64.ActiveCfg = Release|x64 {2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Release|x64.Build.0 = Release|x64 - {2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Debug|ARM64.Build.0 = Debug|ARM64 - {2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Debug|x64.ActiveCfg = Debug|x64 - {2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Debug|x64.Build.0 = Debug|x64 - {2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Release|ARM64.ActiveCfg = Release|ARM64 - {2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Release|ARM64.Build.0 = Release|ARM64 - {2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Release|x64.ActiveCfg = Release|x64 - {2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Release|x64.Build.0 = Release|x64 {48804216-2A0E-4168-A6D8-9CD068D14227}.Debug|ARM64.ActiveCfg = Debug|ARM64 {48804216-2A0E-4168-A6D8-9CD068D14227}.Debug|ARM64.Build.0 = Debug|ARM64 {48804216-2A0E-4168-A6D8-9CD068D14227}.Debug|x64.ActiveCfg = Debug|x64 @@ -2850,6 +2846,30 @@ Global {00D8659C-2068-40B6-8B86-759CD6284BBB}.Release|ARM64.Build.0 = Release|ARM64 {00D8659C-2068-40B6-8B86-759CD6284BBB}.Release|x64.ActiveCfg = Release|x64 {00D8659C-2068-40B6-8B86-759CD6284BBB}.Release|x64.Build.0 = Release|x64 + {C992FD2C-83B8-4941-9FC1-09730068D8EC}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C992FD2C-83B8-4941-9FC1-09730068D8EC}.Debug|ARM64.Build.0 = Debug|ARM64 + {C992FD2C-83B8-4941-9FC1-09730068D8EC}.Debug|x64.ActiveCfg = Debug|x64 + {C992FD2C-83B8-4941-9FC1-09730068D8EC}.Debug|x64.Build.0 = Debug|x64 + {C992FD2C-83B8-4941-9FC1-09730068D8EC}.Release|ARM64.ActiveCfg = Release|ARM64 + {C992FD2C-83B8-4941-9FC1-09730068D8EC}.Release|ARM64.Build.0 = Release|ARM64 + {C992FD2C-83B8-4941-9FC1-09730068D8EC}.Release|x64.ActiveCfg = Release|x64 + {C992FD2C-83B8-4941-9FC1-09730068D8EC}.Release|x64.Build.0 = Release|x64 + {30F57201-9B54-5253-8033-8A28ECD3F1CE}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {30F57201-9B54-5253-8033-8A28ECD3F1CE}.Debug|ARM64.Build.0 = Debug|ARM64 + {30F57201-9B54-5253-8033-8A28ECD3F1CE}.Debug|x64.ActiveCfg = Debug|x64 + {30F57201-9B54-5253-8033-8A28ECD3F1CE}.Debug|x64.Build.0 = Debug|x64 + {30F57201-9B54-5253-8033-8A28ECD3F1CE}.Release|ARM64.ActiveCfg = Release|ARM64 + {30F57201-9B54-5253-8033-8A28ECD3F1CE}.Release|ARM64.Build.0 = Release|ARM64 + {30F57201-9B54-5253-8033-8A28ECD3F1CE}.Release|x64.ActiveCfg = Release|x64 + {30F57201-9B54-5253-8033-8A28ECD3F1CE}.Release|x64.Build.0 = Release|x64 + {D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D}.Debug|ARM64.Build.0 = Debug|ARM64 + {D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D}.Debug|x64.ActiveCfg = Debug|x64 + {D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D}.Debug|x64.Build.0 = Debug|x64 + {D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D}.Release|ARM64.ActiveCfg = Release|ARM64 + {D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D}.Release|ARM64.Build.0 = Release|ARM64 + {D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D}.Release|x64.ActiveCfg = Release|x64 + {D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -3161,8 +3181,11 @@ Global {E816D7AF-4688-4ECB-97CC-3D8E798F3828} = {8EF25507-2575-4ADE-BF7E-D23376903AB8} {E816D7B0-4688-4ECB-97CC-3D8E798F3829} = {8EF25507-2575-4ADE-BF7E-D23376903AB8} {00D8659C-2068-40B6-8B86-759CD6284BBB} = {8EF25507-2575-4ADE-BF7E-D23376903AB8} + {C992FD2C-83B8-4941-9FC1-09730068D8EC} = {106CBECA-0701-4FC3-838C-9DF816A19AE2} + {30F57201-9B54-5253-8033-8A28ECD3F1CE} = {106CBECA-0701-4FC3-838C-9DF816A19AE2} + {D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D} = {106CBECA-0701-4FC3-838C-9DF816A19AE2} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0} EndGlobalSection -EndGlobal +EndGlobal \ No newline at end of file diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-100.png b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-100.png new file mode 100644 index 0000000000000000000000000000000000000000..adcd8d708a6c94e27261b5833fe2b4fec72f5d30 GIT binary patch literal 567 zcmV-70?7S|P)T6ps7Uw|u7PB|fEVXhgs-n#hsi}$ZT%LvstE%eIB3^IuGfvn{GLuTFQc83DnR}l5?B1Oa zJmthp&4kRTj`k=i)hW-7ZC>-*UC)1a7pK+Ww9F*TKs>t%#*qVkzW?w`>Ww<7Aalx_ zz#@=m8(?Bll~5ZESYDlFFqq=dzQYdo_rgR>z&RiuMijlCSHQTsn;k9&gf$YEU`7I2i}qhd@UhF%@NDb%x&I z0j-H<%+60TvouL#q6x_S`aD>IOhz6N#gy&eyC=3_`?oHbQL6{-pSM}PZcQ@-VFW^g zLK;`xy5+>|xEnXF6Ux-`j8U&stJlJk2F9fg%oC37-#RW`z7R+MI%4P74mqq`ziBgu zgUbDXbR-2vBb>0kgGcH9T3ow%lPhn(Dtd?e)SGqp{?U%X;hrd(BM~A@0Q-lI#%~}0 zcw%J(qYNs{6h#Fc`Nm(7E7h~fS*k$93=~sCkle><9Rv2cd?N!^gFFBL002ovPDHLk FV1jzu2EhOT literal 0 HcmV?d00001 diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-125.png b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-125.png new file mode 100644 index 0000000000000000000000000000000000000000..4ff1604ac8d710dc132d6bba7fa2260d45f58c7c GIT binary patch literal 768 zcmV+b1ONPqP)bLVtfH3X`H)Fm!5y`eFlA6%{6AA253UnK-R?BSPy@8`You}DowH4J_ zp06=8vEcb5LsZwUj#cFdlu#&oC@f_H5N52~IAC>czgOM1kLo}lm)*Qqfxfo&tM0qP z<=Lg!cIh^U4h@0=(6eQNP#sv?AHRKl!c9BYQ8Zf2O)QWm>$a@1uUcX9>;!wR+Z(2$ zB>oqeBqWj|h=S72kjw$b0FW@t(hQ~-Pa%Uy+IXD4m6t)BhmY}DF?oc``aoc;bpw3>ydzBx*((Q;vA zCa{QTADO)~GypT&xpDs2^ImrM6*L=7s_Uw>AyHj7z^)ti#puCv?dEF+fQHfo2%sz1 zw#~8653y%VHcjU;wt#O%lQMXa!jHr=DDo^0000X1^@s6D=Y3@000B9Nkl`2Y3EbTw1$2!hfJXvh;I=0a+`YfzoEhM`wR`oo zVlN5^LTQlzAZQvJHm|$$@bKF6fGm*)GbY785-O>RR9cw`r~!rcoAHpdC!fE&4b+MN zCYF|<3X}k9KT3)g5@0YqeeCJdkQsn7rP@i*b-@G_RqV&VYy&0oDA|cGEa{c^_668wi?hdHe7?K0Fy=&}w6PWRZt1?4{*qwQ-$-#!8UnKz%@h z>Wl*?cHq;iNjjdz*@{V?K!#^v=HGHH_+v}bZg%Le`qF8(V8{WQQndX*+Km>r z9^6XxujUkiAb~}uQ9`2E?b9o|3}KhbW{czSl zPN7iGBb`oT{@WZ0qP(+$teeH^)C%@qJ|xSd^I*g;s?C+O4!#EXZbPr#lYIl@6HmUx&kZ();hKz5t(w@z$kXrGc4Rx8qKEz056huDC*hPl zaR>J!_dcNA2na(MaJUXsgEckPH9$e9*~aM8ZvrAzt*T(R**3V*bX6bfm=tl79Yn+= zqlOFP4F?^qDdn%_f%r21H%Jm1Fvd;pGlmVf;;m*P1&v-}jGN%hpmQ|%xq03XVP*mV XqGl$9@}BWF00000NkvXXu0mjfQmfq% literal 0 HcmV?d00001 diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-200.png b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..a585ff9ad6cd56a1565e5ba7ccbeceacb15c806a GIT binary patch literal 1542 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") as PathIcon)!; + Viewbox winIconContainer = new Viewbox(); + winIconContainer.Child = winIcon; + winIconContainer.HorizontalAlignment = HorizontalAlignment.Center; + winIconContainer.VerticalAlignment = VerticalAlignment.Center; + winIconContainer.Height = 24; + winIconContainer.Width = 24; + winIconContainer.Margin = new Thickness(3); + shortcutStackPanel.Children.Add(winIconContainer); + } + + if (shortcut.Ctrl) + { + AddNewTextToStackPanel("Ctrl"); + } + + if (shortcut.Alt) + { + AddNewTextToStackPanel("Alt"); + } + + if (shortcut.Shift) + { + AddNewTextToStackPanel("Shift"); + } + + foreach (string key in shortcut.Keys) + { + switch (key) + { + case "": + shortcutStackPanel.Children.Add(new BitmapIcon() { UriSource = new("ms-appx:///Assets/ShortcutGuide/CopilotKey.png") }); + break; + case "": + shortcutStackPanel.Children.Add(new BitmapIcon() { UriSource = new("ms-appx:///Assets/ShortcutGuide/OfficeKey.png"), Height = 20, Width = 20 }); + break; + default: + AddNewTextToStackPanel(key); + break; + } + } + + return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, shortcutStackPanel); + } + } +} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutCategory.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutCategory.cs new file mode 100644 index 0000000000..553c4b5846 --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutCategory.cs @@ -0,0 +1,13 @@ +// 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. + +namespace ShortcutGuide.Models +{ + public struct ShortcutCategory + { + public string SectionName { get; set; } + + public Shortcut[] Properties { get; set; } + } +} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutList.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutList.cs new file mode 100644 index 0000000000..a8535bd17d --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutList.cs @@ -0,0 +1,13 @@ +// 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. + +namespace ShortcutGuide.Models +{ + public struct ShortcutList + { + public string PackageName { get; set; } + + public ShortcutCategory[] Shortcuts { get; set; } + } +} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs new file mode 100644 index 0000000000..92c061a6cc --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs @@ -0,0 +1,27 @@ +// 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.Runtime.InteropServices; + +internal static class NativeMethods +{ + [DllImport("user32.dll")] + internal static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); + + internal static readonly IntPtr HWND_TOPMOST = new System.IntPtr(-1); + internal const uint SWP_NOSIZE = 0x0001; + internal const uint SWP_NOMOVE = 0x0002; + internal const uint SWP_NOACTIVATE = 0x0010; + internal const uint SWP_SHOWWINDOW = 0x0040; + + [DllImport("user32.dll", SetLastError = true)] + internal static extern int GetWindowLong(IntPtr hWnd, int nIndex); + + [DllImport("user32.dll")] + internal static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); + + internal const int GWL_STYLE = -16; + internal const int WS_CAPTION = 0x00C00000; +} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Package.appxmanifest b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Package.appxmanifest new file mode 100644 index 0000000000..5d8b7d8069 --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Package.appxmanifest @@ -0,0 +1,51 @@ + + + + + + + + + + ShortcutGuide.Ui + aaron + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs new file mode 100644 index 0000000000..8c74d28c13 --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs @@ -0,0 +1,46 @@ +// 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.Threading; +using ManagedCommon; +using Microsoft.UI.Dispatching; +using Microsoft.Windows.AppLifecycle; + +namespace ShortcutGuide +{ + public sealed class Program + { + [STAThread] + public static void Main(string[] args) + { + Logger.InitializeLogger("\\ShortcutGuide\\Logs"); + WinRT.ComWrappersSupport.InitializeComWrappers(); + + if (PowerToys.GPOWrapper.GPOWrapper.GetConfiguredShortcutGuideEnabledValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled) + { + Logger.LogWarning("Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator."); + return; + } + + var instanceKey = AppInstance.FindOrRegisterForKey("PowerToys_ShortcutGuide_Instance"); + + if (instanceKey.IsCurrent) + { + Microsoft.UI.Xaml.Application.Start((p) => + { + var context = new DispatcherQueueSynchronizationContext(DispatcherQueue.GetForCurrentThread()); + SynchronizationContext.SetSynchronizationContext(context); + _ = new App(); + }); + } + else + { + Logger.LogWarning("Another instance of ShortcutGuide is running. Exiting ShortcutGuide"); + } + + return; + } + } +} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.Designer.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.Designer.cs new file mode 100644 index 0000000000..46507ec7b3 --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ShortcutGuide.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resource { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resource() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ShortcutGuide.Properties.Resource", typeof(Resource).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Shortcut Guide. + /// + internal static string Title { + get { + return ResourceManager.GetString("Title", resourceCulture); + } + } + } +} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.resx b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.resx new file mode 100644 index 0000000000..dcbe0da53c --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Shortcut Guide + + \ No newline at end of file diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj new file mode 100644 index 0000000000..bbdc4832a1 --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj @@ -0,0 +1,121 @@ + + + + + + + WinExe + ShortcutGuide + app.manifest + true + true + None + enable + false + false + true + ..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps + PowerToys.Hosts + DISABLE_XAML_GENERATED_MAIN,TRACE + Assets/Hosts/Hosts.ico + + PowerToys.ShortcutGuide.pri + + + + + + + + + + + + + + + + PreserveNewest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PowerToys.GPOWrapper + $(OutDir) + false + + + + + + + + + + + + + + + + + + + + + + + + True + True + Resource.resx + + + + + ResXFileCodeGenerator + Resource.Designer.cs + + + + + MSBuild:Compile + + + + + true + + diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml new file mode 100644 index 0000000000..96acc70087 --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs new file mode 100644 index 0000000000..01c7e3417a --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs @@ -0,0 +1,24 @@ +// 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; + +namespace ShortcutGuide +{ + public partial class App : Application + { + public App() + { + InitializeComponent(); + } + + protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) + { + _window = new MainWindow(); + _window.Activate(); + } + + private Window? _window; + } +} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml new file mode 100644 index 0000000000..16545dbb35 --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs new file mode 100644 index 0000000000..7969ac25d0 --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs @@ -0,0 +1,113 @@ +// 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.Globalization; +using System.Runtime.InteropServices; +using Microsoft.UI; +using Microsoft.UI.Input; +using Microsoft.UI.Windowing; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using ShortcutGuide.Models; +using ShortcutGuide.Properties; +using Windows.ApplicationModel.Chat; +using Windows.Devices.Display; +using Windows.Foundation; +using Windows.Graphics; +using Windows.System.UserProfile; +using WinUIEx; + +using static NativeMethods; + +namespace ShortcutGuide +{ + /// + /// An empty window that can be used on its own or navigated to within a Frame. + /// + public sealed partial class MainWindow : WindowEx + { + private AppWindow _appWindow; + + public MainWindow() + { + InitializeComponent(); + Title = Resource.ResourceManager.GetString("Title", CultureInfo.InvariantCulture)!; + + var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this); + WindowId windowId = Win32Interop.GetWindowIdFromWindow(hwnd); + _appWindow = AppWindow.GetFromWindowId(windowId); +#if DEBUG +#else + this.SetIsAlwaysOnTop(true); + this.SetIsShownInSwitchers(false); +#endif + this.SetIsResizable(false); + this.SetIsMinimizable(false); + this.SetIsMaximizable(false); + IsTitleBarVisible = false; + + // Remove the caption style from the window style. Windows App SDK 1.6 added it, which made the title bar and borders appear for Measure Tool. This code removes it. + var windowStyle = GetWindowLong(hwnd, GWL_STYLE); + windowStyle = windowStyle & (~WS_CAPTION); + _ = SetWindowLong(hwnd, GWL_STYLE, windowStyle); +#if DEBUG +#else + SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); +#endif + + this.Activated += OnLauched; + } + + private void OnLauched(object sender, WindowActivatedEventArgs e) + { + if (!_setPosition) + { + var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this); + WindowId windowId = Win32Interop.GetWindowIdFromWindow(hwnd); + + _appWindow = AppWindow.GetFromWindowId(windowId); + + GetCursorPos(out POINT lpPoint); + _appWindow.Move(lpPoint); + + float dpiScale = DpiHelper.GetDPIScaleForWindow((int)hwnd); + + Rect monitorRect = DisplayHelper.GetWorkAreaForDisplayWithWindow(hwnd); + this.SetWindowSize(monitorRect.Width / dpiScale, monitorRect.Height / dpiScale / 2); + + // Move top of the window to the center of the monitor + _appWindow.Move(new PointInt32((int)monitorRect.X, (int)(monitorRect.Y + (int)(monitorRect.Height / 2)))); + _setPosition = true; + } + } + + public void WindowSelectionChanged(object sender, SelectorBarSelectionChangedEventArgs e) + { + ContentFrame.Navigate(typeof(ShortcutView)); + } + + private bool _setPosition; + + [LibraryImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool GetCursorPos(out POINT lpPoint); + + public struct POINT + { + public int X; + public int Y; + + public static implicit operator PointInt32(POINT point) + { + return new PointInt32(point.X, point.Y); + } + } + + public void CloseButton_Clicked(object sender, RoutedEventArgs e) + { + Environment.Exit(0); + } + } +} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutTemplateDataObject.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutTemplateDataObject.cs new file mode 100644 index 0000000000..3c3e5c256e --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutTemplateDataObject.cs @@ -0,0 +1,38 @@ +// 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; + +namespace ShortcutGuide +{ + public sealed class ShortcutTemplateDataObject + { + public string Name { get; set; } + + public string Description { get; set; } + + public StackPanel Shortcut { get; set; } + + public Visibility DescriptionVisible { get; set; } + + public ShortcutTemplateDataObject(string name, string description, StackPanel shortcut) + { + Name = name; + Description = description; + + if (string.IsNullOrWhiteSpace(description)) + { + DescriptionVisible = Visibility.Collapsed; + } + else + { + DescriptionVisible = Visibility.Visible; + } + + shortcut.Orientation = Orientation.Horizontal; + Shortcut = shortcut; + } + } +} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml new file mode 100644 index 0000000000..be12acb31e --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs new file mode 100644 index 0000000000..a803c7c0a7 --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs @@ -0,0 +1,48 @@ +// 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.Globalization; +using Microsoft.UI.Xaml.Controls; +using ShortcutGuide.Models; + +namespace ShortcutGuide +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class ShortcutView : Page + { + private ShortcutList shortcutList = YmlInterpreter.GetShortcutsOfDefaultShell(); + + public ShortcutView() + { + InitializeComponent(); + + int i = 0; + foreach (var category in shortcutList.Shortcuts) + { + CategorySelector.Items.Add(new SelectorBarItem() { Text = category.SectionName, Name = i.ToString(CultureInfo.InvariantCulture) }); + i++; + } + + CategorySelector.SelectedItem = CategorySelector.Items[0]; + CategorySelector.SelectionChanged += CategorySelector_SelectionChanged; + + foreach (var shortcut in shortcutList.Shortcuts[0].Properties) + { + ShortcutListElement.Items.Add((ShortcutTemplateDataObject)shortcut); + } + } + + public void CategorySelector_SelectionChanged(SelectorBar sender, SelectorBarSelectionChangedEventArgs e) + { + ShortcutListElement.Items.Clear(); + + foreach (var shortcut in shortcutList.Shortcuts[int.Parse(sender.SelectedItem.Name, CultureInfo.InvariantCulture)].Properties) + { + ShortcutListElement.Items.Add((ShortcutTemplateDataObject)shortcut); + } + } + } +} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/StringToVisibilityConverter.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/StringToVisibilityConverter.cs new file mode 100644 index 0000000000..0de9e139ca --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/StringToVisibilityConverter.cs @@ -0,0 +1,24 @@ +// 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 Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Data; + +namespace ShortcutGuide +{ + public partial class StringToVisibilityConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + return string.IsNullOrWhiteSpace((string)value) ? Visibility.Collapsed : Visibility.Visible; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + var visiblity = (Visibility)value; + return visiblity == Visibility.Visible; + } + } +} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/YmlInterpreter.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/YmlInterpreter.cs new file mode 100644 index 0000000000..eb9bff704c --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/YmlInterpreter.cs @@ -0,0 +1,46 @@ +// 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.IO; +using ShortcutGuide.Exceptions; +using ShortcutGuide.Models; +using YamlDotNet.Serialization; + +namespace ShortcutGuide +{ + public class YmlInterpreter + { + public static ShortcutList GetShortcutsOfApplication(string applicationName) + { + string path = GetPathOfIntepretations(); + string content = File.ReadAllText(Path.Combine(path, applicationName + ".yml")); + return YamlToShortcutList(content); + } + + public static ShortcutList YamlToShortcutList(string content) + { + Deserializer deserializer = new(); + return deserializer.Deserialize(content); + } + + private static string GetPathOfIntepretations() + { + return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "Windows", "KeyboardShortcuts"); + } + + private static IndexFile GetIndexYamlFile() + { + string path = GetPathOfIntepretations(); + string content = File.ReadAllText(Path.Combine(path, "index.yml")); + Deserializer deserializer = new(); + return deserializer.Deserialize(content); + } + + public static ShortcutList GetShortcutsOfDefaultShell() + { + return GetShortcutsOfApplication(GetIndexYamlFile().DefaultShellName); + } + } +} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/app.manifest b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/app.manifest new file mode 100644 index 0000000000..a5aa870b41 --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/app.manifest @@ -0,0 +1,22 @@ + + + + + + + + true/PM + PerMonitorV2, PerMonitor + + + + + + + + + From 55b3e15f1081aa0d757086e3fcf703022d91a997 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Mon, 14 Oct 2024 20:37:55 +0200 Subject: [PATCH 43/99] Changed style a little bit --- .../ShortcutGuideXAML/ShortcutView.xaml | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml index be12acb31e..87595f68ec 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml @@ -11,21 +11,21 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + @@ -39,8 +39,7 @@ + Orientation="Horizontal"/> From 6558260c5385e1ac9cf6ca0a29bac68f30c28ef1 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Sat, 2 Nov 2024 15:10:33 +0100 Subject: [PATCH 44/99] Push --- .../Helpers/TaskListPositions.cs | 27 ++++++++++++ .../ShortcutGuide.Ui/Models/Shortcut.cs | 22 ++++++++++ .../Models/ShortcutPageParameters.cs | 23 +++++++++++ .../ShortcutGuide.Ui/NativeMethods.cs | 6 +++ .../ShortcutGuideXAML/MainWindow.xaml | 2 +- .../ShortcutGuideXAML/MainWindow.xaml.cs | 11 ++--- .../ShortcutGuideXAML/ShortcutView.xaml | 4 +- .../ShortcutGuideXAML/ShortcutView.xaml.cs | 41 ++++++++++++++++++- 8 files changed, 127 insertions(+), 9 deletions(-) create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/TaskListPositions.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/TaskListPositions.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/TaskListPositions.cs new file mode 100644 index 0000000000..b408d8e3e2 --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/TaskListPositions.cs @@ -0,0 +1,27 @@ +// 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.Runtime.InteropServices; + +namespace ShortcutGuide.Helpers +{ + internal sealed class TaskListPositions + { + public static List GetTaskbarIconPositions() + { + throw new NotImplementedException(); + } + + [StructLayout(LayoutKind.Sequential)] + public struct RECT + { + public int Left; + public int Top; + public int Right; + public int Bottom; + } + } +} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/Shortcut.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/Shortcut.cs index 8f320b5f57..a675bcdff9 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/Shortcut.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/Shortcut.cs @@ -5,6 +5,8 @@ using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Markup; +using Windows.Security.Cryptography.Certificates; +using YamlDotNet.Core.Tokens; namespace ShortcutGuide.Models { @@ -26,6 +28,11 @@ namespace ShortcutGuide.Models shortcutStackPanel.Orientation = Orientation.Horizontal; + if (shortcut.Ctrl == false && shortcut.Alt == false && shortcut.Shift == false && shortcut.Win == false && shortcut.Keys.Length == 0) + { + return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, shortcutStackPanel); + } + void AddNewTextToStackPanel(string text) { shortcutStackPanel.Children.Add(new TextBlock { Text = text, Margin = new Thickness(3), VerticalAlignment = VerticalAlignment.Center }); @@ -69,6 +76,21 @@ namespace ShortcutGuide.Models case "": shortcutStackPanel.Children.Add(new BitmapIcon() { UriSource = new("ms-appx:///Assets/ShortcutGuide/OfficeKey.png"), Height = 20, Width = 20 }); break; + case "": + AddNewTextToStackPanel("←"); + break; + case "": + AddNewTextToStackPanel("→"); + break; + case "": + AddNewTextToStackPanel("↑"); + break; + case "": + AddNewTextToStackPanel("↓"); + break; + case string name when name.StartsWith('<'): + AddNewTextToStackPanel(key.Replace("<", string.Empty).Replace(">", string.Empty)); + break; default: AddNewTextToStackPanel(key); break; diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs new file mode 100644 index 0000000000..54e72ab1b3 --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs @@ -0,0 +1,23 @@ +// 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; + +namespace ShortcutGuide.Models +{ + internal struct ShortcutPageParameters + { + public static SeachFilterObservable SearchFilter = new(); + } + + internal sealed class SeachFilterObservable + { + public event EventHandler? FilterChanged; + + public void OnFilterChanged(string filter) + { + FilterChanged?.Invoke(this, filter); + } + } +} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs index 92c061a6cc..856f6a9501 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs @@ -22,6 +22,12 @@ internal static class NativeMethods [DllImport("user32.dll")] internal static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); + [DllImport("user32.dll", CharSet = CharSet.Unicode)] + internal static extern int FindWindowA(in string lpClassName, in string? lpWindowName); + + [DllImport("user32.dll", CharSet = CharSet.Unicode)] + internal static extern int FindWindowExA(int hwndParent, int hwndChildAfter, in string lpClassName, in string? lpWindowName); + internal const int GWL_STYLE = -16; internal const int WS_CAPTION = 0x00C00000; } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml index 16545dbb35..a728cb99ff 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml @@ -33,7 +33,7 @@ - + diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs index 7969ac25d0..1693eeb7f2 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs @@ -6,19 +6,14 @@ using System; using System.Globalization; using System.Runtime.InteropServices; using Microsoft.UI; -using Microsoft.UI.Input; using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using ShortcutGuide.Models; using ShortcutGuide.Properties; -using Windows.ApplicationModel.Chat; -using Windows.Devices.Display; using Windows.Foundation; using Windows.Graphics; -using Windows.System.UserProfile; using WinUIEx; - using static NativeMethods; namespace ShortcutGuide @@ -33,6 +28,7 @@ namespace ShortcutGuide public MainWindow() { InitializeComponent(); + Title = Resource.ResourceManager.GetString("Title", CultureInfo.InvariantCulture)!; var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this); @@ -109,5 +105,10 @@ namespace ShortcutGuide { Environment.Exit(0); } + + private void SearchBox_TextChanged(object sender, TextChangedEventArgs e) + { + ShortcutPageParameters.SearchFilter.OnFilterChanged(SearchBox.Text); + } } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml index 87595f68ec..6dc978ae04 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml @@ -20,7 +20,7 @@ - + @@ -39,7 +39,7 @@ + Orientation="Vertical"/> diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs index a803c7c0a7..0196f8b401 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs @@ -2,9 +2,13 @@ // 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.Globalization; using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Navigation; using ShortcutGuide.Models; +using Windows.ApplicationModel.ConversationalAgent; +using Windows.Storage; namespace ShortcutGuide { @@ -22,7 +26,18 @@ namespace ShortcutGuide int i = 0; foreach (var category in shortcutList.Shortcuts) { - CategorySelector.Items.Add(new SelectorBarItem() { Text = category.SectionName, Name = i.ToString(CultureInfo.InvariantCulture) }); + switch (category.SectionName) + { + case string name when name.StartsWith("", System.StringComparison.Ordinal): + // Todo: Implement GetTaskbarIconPositions + break; + case string name when name.StartsWith('<'): + break; + default: + CategorySelector.Items.Add(new SelectorBarItem() { Text = category.SectionName, Name = i.ToString(CultureInfo.InvariantCulture) }); + break; + } + i++; } @@ -33,6 +48,30 @@ namespace ShortcutGuide { ShortcutListElement.Items.Add((ShortcutTemplateDataObject)shortcut); } + + ShortcutPageParameters.SearchFilter.FilterChanged += SearchFilter_FilterChanged; + } + + private void SearchFilter_FilterChanged(object? sender, string e) + { + FilterBy(e); + } + + public void FilterBy(string filter) + { + ShortcutListElement.Items.Clear(); + foreach (var shortcut in shortcutList.Shortcuts[int.Parse(CategorySelector.SelectedItem.Name, CultureInfo.InvariantCulture)].Properties) + { + if (shortcut.Name.Contains(filter, System.StringComparison.OrdinalIgnoreCase)) + { + ShortcutListElement.Items.Add((ShortcutTemplateDataObject)shortcut); + } + } + + if (ShortcutListElement.Items.Count == 0) + { + ShortcutListElement.Items.Add(new ShortcutTemplateDataObject("No search results found", string.Empty, new StackPanel() { Visibility = Microsoft.UI.Xaml.Visibility.Collapsed })); + } } public void CategorySelector_SelectionChanged(SelectorBar sender, SelectorBarSelectionChangedEventArgs e) From 2f4766df19c3b16a7f69506a56ec718f5c1971ad Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Sun, 3 Nov 2024 22:06:38 +0100 Subject: [PATCH 45/99] Push --- .../ShortcutGuide.Ui/Models/Shortcut.cs | 134 +++++++++-- .../ShortcutGuide.Ui/Models/ShortcutList.cs | 2 + .../Models/ShortcutPageParameters.cs | 29 ++- .../PowerToysShortcutsPopulator.cs | 78 +++++++ .../ShortcutGuide.Ui/Program.cs | 2 + .../ShortcutGuide.Ui/ShortcutGuide.Ui.csproj | 1 + .../ShortcutGuideXAML/MainWindow.xaml | 6 +- .../ShortcutGuideXAML/MainWindow.xaml.cs | 24 +- .../ShortcutTemplateDataObject.cs | 6 +- .../ShortcutGuideXAML/ShortcutView.xaml | 60 ++++- .../ShortcutGuideXAML/ShortcutView.xaml.cs | 209 ++++++++++++++++-- .../ShortcutGuide.Ui/YmlInterpreter.cs | 4 +- 12 files changed, 497 insertions(+), 58 deletions(-) create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/PowerToysShortcutsPopulator.cs diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/Shortcut.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/Shortcut.cs index a675bcdff9..b70d6054cf 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/Shortcut.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/Shortcut.cs @@ -2,25 +2,45 @@ // 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.Text.Json.Serialization; +using System.Threading.Tasks; +using Microsoft.PowerToys.Settings.UI.Library.Utilities; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Markup; -using Windows.Security.Cryptography.Certificates; -using YamlDotNet.Core.Tokens; namespace ShortcutGuide.Models { - public struct Shortcut(string name, string? description, bool recommended, bool ctrl, bool shift, bool alt, bool win, string[] keys) + public class Shortcut(string name, string? description, bool recommended, bool ctrl, bool shift, bool alt, bool win, string[] keys) { - public string Name = name; - public string? Description = description; - public bool Recommended = recommended; + public Shortcut() + : this(string.Empty, string.Empty, false, false, false, false, false, []) + { + } - public bool Ctrl = ctrl; - public bool Shift = shift; - public bool Alt = alt; - public bool Win = win; - public string[] Keys = keys; + [JsonPropertyName(nameof(Name))] + public string Name { get; set; } = name; + + [JsonPropertyName(nameof(Description))] + public string? Description { get; set; } = description; + + [JsonPropertyName(nameof(Recommended))] + public bool Recommended { get; set; } = recommended; + + [JsonPropertyName(nameof(Ctrl))] + public bool Ctrl { get; set; } = ctrl; + + [JsonPropertyName(nameof(Shift))] + public bool Shift { get; set; } = shift; + + [JsonPropertyName(nameof(Alt))] + public bool Alt { get; set; } = alt; + + [JsonPropertyName(nameof(Win))] + public bool Win { get; set; } = win; + + [JsonPropertyName(nameof(Keys))] + public string[] Keys { get; set; } = keys; public static implicit operator ShortcutTemplateDataObject(Shortcut shortcut) { @@ -30,7 +50,7 @@ namespace ShortcutGuide.Models if (shortcut.Ctrl == false && shortcut.Alt == false && shortcut.Shift == false && shortcut.Win == false && shortcut.Keys.Length == 0) { - return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, shortcutStackPanel); + return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, shortcutStackPanel, shortcut); } void AddNewTextToStackPanel(string text) @@ -38,10 +58,22 @@ namespace ShortcutGuide.Models shortcutStackPanel.Children.Add(new TextBlock { Text = text, Margin = new Thickness(3), VerticalAlignment = VerticalAlignment.Center }); } + async void AnimateTextBlock(TextBlock animatedTextBlock, string text, int delay = 500) + { + int index = 0; + + while (true) + { + animatedTextBlock.Text = text[index].ToString(); + index = (index + 1) % text.Length; + await Task.Delay(delay); + } + } + if (shortcut.Win) { PathIcon winIcon = (XamlReader.Load(@"") as PathIcon)!; - Viewbox winIconContainer = new Viewbox(); + Viewbox winIconContainer = new(); winIconContainer.Child = winIcon; winIconContainer.HorizontalAlignment = HorizontalAlignment.Center; winIconContainer.VerticalAlignment = VerticalAlignment.Center; @@ -66,7 +98,7 @@ namespace ShortcutGuide.Models AddNewTextToStackPanel("Shift"); } - foreach (string key in shortcut.Keys) + foreach (object key in shortcut.Keys) { switch (key) { @@ -88,16 +120,82 @@ namespace ShortcutGuide.Models case "": AddNewTextToStackPanel("↓"); break; - case string name when name.StartsWith('<'): - AddNewTextToStackPanel(key.Replace("<", string.Empty).Replace(">", string.Empty)); + case "": + TextBlock animatedTextBlock = new() + { + Text = "A", + Margin = new Thickness(3), + VerticalAlignment = VerticalAlignment.Center, + + // Use monospaced font to ensure the text doesn't move + FontFamily = new("Courier New"), + TextDecorations = Windows.UI.Text.TextDecorations.Underline, + }; + + shortcutStackPanel.Children.Add(animatedTextBlock); + + AnimateTextBlock(animatedTextBlock, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + break; + case "": + TextBlock arrowTextBlock = new() + { + Text = "→", + Margin = new Thickness(3), + VerticalAlignment = VerticalAlignment.Center, + }; + + shortcutStackPanel.Children.Add(arrowTextBlock); + + AnimateTextBlock(arrowTextBlock, "→↓←↑", 1000); + break; + case "": + TextBlock arrowLRTextBlock = new() + { + Text = "→", + Margin = new Thickness(3), + FontFamily = new("Courier New"), + VerticalAlignment = VerticalAlignment.Center, + }; + shortcutStackPanel.Children.Add(arrowLRTextBlock); + AnimateTextBlock(arrowLRTextBlock, "→←", 1000); + break; + case "": + TextBlock arrowUDTextBlock = new() + { + Text = "↑", + Margin = new Thickness(3), + FontFamily = new("Courier New"), + VerticalAlignment = VerticalAlignment.Center, + }; + shortcutStackPanel.Children.Add(arrowUDTextBlock); + AnimateTextBlock(arrowUDTextBlock, "↑↓", 1000); + break; + case string name when name.StartsWith('<') && name.EndsWith('>'): + AddNewTextToStackPanel(name[1..^1]); + break; + case int num: + if (num == 0) + { + break; + } + + AddNewTextToStackPanel(Helper.GetKeyName((uint)num)); + break; + case string num when int.TryParse(num, out int parsedNum): + if (parsedNum == 0) + { + break; + } + + AddNewTextToStackPanel(Helper.GetKeyName((uint)parsedNum)); break; default: - AddNewTextToStackPanel(key); + AddNewTextToStackPanel((string)key); break; } } - return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, shortcutStackPanel); + return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, shortcutStackPanel, shortcut); } } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutList.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutList.cs index a8535bd17d..b4023a6445 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutList.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutList.cs @@ -9,5 +9,7 @@ namespace ShortcutGuide.Models public string PackageName { get; set; } public ShortcutCategory[] Shortcuts { get; set; } + + public string WindowFilter { get; set; } } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs index 54e72ab1b3..a5a1ba409c 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs @@ -3,21 +3,38 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; namespace ShortcutGuide.Models { internal struct ShortcutPageParameters { public static SeachFilterObservable SearchFilter = new(); - } - internal sealed class SeachFilterObservable - { - public event EventHandler? FilterChanged; + public static Dictionary> PinnedShortcuts = []; - public void OnFilterChanged(string filter) + public static string CurrentPageName = string.Empty; + + public static FrameHeightObservable FrameHeight = new(); + + internal sealed class SeachFilterObservable { - FilterChanged?.Invoke(this, filter); + public event EventHandler? FilterChanged; + + public void OnFilterChanged(string filter) + { + FilterChanged?.Invoke(this, filter); + } + } + + internal sealed class FrameHeightObservable + { + public event EventHandler? FrameHeightChanged; + + public void OnFrameHeightChanged(double height) + { + FrameHeightChanged?.Invoke(this, height); + } } } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/PowerToysShortcutsPopulator.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/PowerToysShortcutsPopulator.cs new file mode 100644 index 0000000000..e0ca43540f --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/PowerToysShortcutsPopulator.cs @@ -0,0 +1,78 @@ +// 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.Globalization; +using System.IO; +using System.Text.RegularExpressions; +using Microsoft.PowerToys.Settings.UI.Library; + +namespace ShortcutGuide +{ + internal sealed class PowerToysShortcutsPopulator + { + public static void Populate() + { + string path = Path.Combine(YmlInterpreter.GetPathOfIntepretations(), "Microsoft.PowerToys.yml"); + + string content = File.ReadAllText(path); + + const string populateStartString = "# "; + const string populateEndString = "# "; + + content = Regex.Replace(content, populateStartString + "[\\s\\S\\n\\r]*" + populateEndString, populateStartString + Environment.NewLine); + + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.AdvancedPasteUIShortcut, "Advanced Paste", content, "Open Advanced Paste window"); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.PasteAsPlainTextShortcut, "Advanced Paste", content, "Paste as plain text directly"); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.PasteAsMarkdownShortcut, "Advanced Paste", content, "Paste as markdown directly"); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.PasteAsJsonShortcut, "Advanced Paste", content, "Paste as JSON directly"); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.Hotkey, "Always On Top", content, "Pin a window"); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut, "Color Picker", content, "Pick a color"); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ThumbnailHotkey, "Crop And Lock", content, "Thumbnail"); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ReparentHotkey, "Crop And Lock", content, "Reparent"); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.FancyzonesEditorHotkey, "FancyZones", content, "Open editor"); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut, "Mouse Highlight", content, "Highlight clicks"); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut, "Mouse Jump", content, "Quickly move the mouse pointer"); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut, "Mouse Pointer Crosshairs", content, "Show crosshairs"); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut, "Peek", content); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.OpenPowerLauncher, "PowerToys Run", content); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut, "Screen Ruler", content); + { + ShortcutGuideProperties settingsProperties = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties; + content = settingsProperties.UseLegacyPressWinKeyBehavior.Value + ? HotkeySettingsToYaml(new HotkeySettings(true, false, false, false, 0), "Shortcut Guide", content) + : HotkeySettingsToYaml(settingsProperties.DefaultOpenShortcutGuide, "Shortcut Guide", content); + } + + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut, "Text Extractor", content); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.Hotkey, "Workspaces", content); + + content += populateEndString; + + File.WriteAllText(path, content); + } + + public static string HotkeySettingsToYaml(HotkeySettings hotkeySettings, string moduleName, string content, string? description = null) + { + content += " - Name: " + moduleName + Environment.NewLine; + content += " Win: " + hotkeySettings.Win.ToString() + Environment.NewLine; + content += " Ctrl: " + hotkeySettings.Ctrl.ToString() + Environment.NewLine; + content += " Alt: " + hotkeySettings.Alt.ToString() + Environment.NewLine; + content += " Shift: " + hotkeySettings.Shift.ToString() + Environment.NewLine; + if (description != null) + { + content += " Description: " + description + Environment.NewLine; + } + + content += " Keys:" + Environment.NewLine; + content += " - " + hotkeySettings.Code.ToString(CultureInfo.InvariantCulture) + Environment.NewLine; + return content; + } + + public static string HotkeySettingsToYaml(KeyboardKeysProperty keyboardKeys, string moduleName, string content, string? description = null) + { + return HotkeySettingsToYaml(keyboardKeys.Value, moduleName, content, description); + } + } +} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs index 8c74d28c13..09c8b20369 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs @@ -15,6 +15,8 @@ namespace ShortcutGuide [STAThread] public static void Main(string[] args) { + PowerToysShortcutsPopulator.Populate(); + Logger.InitializeLogger("\\ShortcutGuide\\Logs"); WinRT.ComWrappersSupport.InitializeComWrappers(); diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj index bbdc4832a1..5ee417e94e 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj @@ -91,6 +91,7 @@ + diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml index a728cb99ff..28785d4f00 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml @@ -21,13 +21,13 @@ - + - - + + diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs index 1693eeb7f2..fb3f6eea2e 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs @@ -3,8 +3,12 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Runtime.InteropServices; +using System.Text.Json; +using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.UI; using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; @@ -53,7 +57,15 @@ namespace ShortcutGuide SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); #endif - this.Activated += OnLauched; + Activated += OnLauched; + + SettingsUtils settingsUtils = new(); + + if (settingsUtils.SettingsExists(ShortcutGuideSettings.ModuleName, "Pinned.json")) + { + string pinnedPath = settingsUtils.GetSettingsFilePath(ShortcutGuideSettings.ModuleName, "Pinned.json"); + ShortcutPageParameters.PinnedShortcuts = JsonSerializer.Deserialize>>(File.ReadAllText(pinnedPath))!; + } } private void OnLauched(object sender, WindowActivatedEventArgs e) @@ -77,10 +89,20 @@ namespace ShortcutGuide _appWindow.Move(new PointInt32((int)monitorRect.X, (int)(monitorRect.Y + (int)(monitorRect.Height / 2)))); _setPosition = true; } + + WindowSelector.SelectedItem = WindowsSelectorBarItem; } public void WindowSelectionChanged(object sender, SelectorBarSelectionChangedEventArgs e) { + ShortcutPageParameters.CurrentPageName = ((SelectorBar)sender).SelectedItem.Name switch { + "WindowsSelectorBarItem" => YmlInterpreter.GetIndexYamlFile().DefaultShellName, + "PowerToysSelectorBarItem" => "Microsoft.PowerToys", + _ => throw new NotImplementedException(), + }; + + ContentFrame.Loaded += (s, e) => ShortcutPageParameters.FrameHeight.OnFrameHeightChanged(ContentFrame.ActualHeight); + ContentFrame.Navigate(typeof(ShortcutView)); } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutTemplateDataObject.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutTemplateDataObject.cs index 3c3e5c256e..fac8a121cd 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutTemplateDataObject.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutTemplateDataObject.cs @@ -4,6 +4,7 @@ using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; +using ShortcutGuide.Models; namespace ShortcutGuide { @@ -15,12 +16,15 @@ namespace ShortcutGuide public StackPanel Shortcut { get; set; } + public Shortcut OriginalShortcutObject { get; set; } + public Visibility DescriptionVisible { get; set; } - public ShortcutTemplateDataObject(string name, string description, StackPanel shortcut) + public ShortcutTemplateDataObject(string name, string description, StackPanel shortcut, Shortcut originalShortcutObject) { Name = name; Description = description; + OriginalShortcutObject = originalShortcutObject; if (string.IsNullOrWhiteSpace(description)) { diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml index 6dc978ae04..e0059e06aa 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml @@ -7,24 +7,31 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" + DataContext="{Binding RelativeSource={RelativeSource Self}}" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> + + + + + + - - + + - + @@ -34,14 +41,43 @@ - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs index 0196f8b401..67f19e34bd 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs @@ -3,35 +3,42 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; +using System.ComponentModel; using System.Globalization; +using System.IO; +using System.Runtime.CompilerServices; +using System.Text.Json; +using Microsoft.PowerToys.Settings.UI.Library; +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Navigation; using ShortcutGuide.Models; -using Windows.ApplicationModel.ConversationalAgent; -using Windows.Storage; namespace ShortcutGuide { - /// - /// An empty page that can be used on its own or navigated to within a Frame. - /// - public sealed partial class ShortcutView : Page + public sealed partial class ShortcutView : Page, INotifyPropertyChanged { - private ShortcutList shortcutList = YmlInterpreter.GetShortcutsOfDefaultShell(); + private ShortcutList shortcutList = YmlInterpreter.GetShortcutsOfApplication(ShortcutPageParameters.CurrentPageName); public ShortcutView() { InitializeComponent(); + DataContext = this; + + int i = -1; + + CategorySelector.Items.Add(new SelectorBarItem() { Text = "Overview", Name = i.ToString(CultureInfo.InvariantCulture) }); + + i++; - int i = 0; foreach (var category in shortcutList.Shortcuts) { switch (category.SectionName) { - case string name when name.StartsWith("", System.StringComparison.Ordinal): + case string name when name.StartsWith("", StringComparison.Ordinal): // Todo: Implement GetTaskbarIconPositions break; - case string name when name.StartsWith('<'): + case string name when name.StartsWith('<') && name.EndsWith('>'): break; default: CategorySelector.Items.Add(new SelectorBarItem() { Text = category.SectionName, Name = i.ToString(CultureInfo.InvariantCulture) }); @@ -49,7 +56,91 @@ namespace ShortcutGuide ShortcutListElement.Items.Add((ShortcutTemplateDataObject)shortcut); } + ShortcutPageParameters.FrameHeight.FrameHeightChanged += ContentHeightChanged; ShortcutPageParameters.SearchFilter.FilterChanged += SearchFilter_FilterChanged; + + if (!ShortcutPageParameters.PinnedShortcuts.TryGetValue(ShortcutPageParameters.CurrentPageName, out var _)) + { + ShortcutPageParameters.PinnedShortcuts.Add(ShortcutPageParameters.CurrentPageName, new List()); + } + + OpenOverview(); + } + + private void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + private double _contentHeight; + + public event PropertyChangedEventHandler? PropertyChanged; + + public double ContentHeight + { + get => _contentHeight - CategorySelector.ActualHeight; + set + { + _contentHeight = value; + OnPropertyChanged(nameof(ContentHeight)); + } + } + + public void ContentHeightChanged(object? sender, double e) + { + ContentHeight = e; + } + + private void OpenOverview() + { + RecommendedListElement.Items.Clear(); + PinnedListElement.Items.Clear(); + OverviewStackPanel.Visibility = Visibility.Visible; + RecommendedListElement.Visibility = Visibility.Visible; + PinnedListElement.Visibility = Visibility.Visible; + RecommendedListTitle.Visibility = Visibility.Visible; + PinnedListTitle.Visibility = Visibility.Visible; + ShortcutListElement.Visibility = Visibility.Collapsed; + + foreach (var list in shortcutList.Shortcuts) + { + if (list.Properties == null) + { + continue; + } + + foreach (var shortcut in list.Properties) + { + if (shortcut.Recommended) + { + RecommendedListElement.Items.Add((ShortcutTemplateDataObject)shortcut); + } + } + } + + if (RecommendedListElement.Items.Count == 0) + { + RecommendedListTitle.Visibility = Visibility.Collapsed; + RecommendedListElement.Visibility = Visibility.Collapsed; + } + + foreach (var shortcut in ShortcutPageParameters.PinnedShortcuts[ShortcutPageParameters.CurrentPageName]) + { + PinnedListElement.Items.Add((ShortcutTemplateDataObject)shortcut); + } + + if (PinnedListElement.Items.Count == 0) + { + PinnedListTitle.Visibility = Visibility.Collapsed; + PinnedListElement.Visibility = Visibility.Collapsed; + } + + if (RecommendedListElement.Items.Count == 0 && PinnedListElement.Items.Count == 0) + { + OverviewStackPanel.Visibility = Visibility.Collapsed; + ErrorMessage.Visibility = Visibility.Visible; + ErrorMessage.Text = "No shortcuts pinned or recommended"; + } } private void SearchFilter_FilterChanged(object? sender, string e) @@ -60,28 +151,116 @@ namespace ShortcutGuide public void FilterBy(string filter) { ShortcutListElement.Items.Clear(); - foreach (var shortcut in shortcutList.Shortcuts[int.Parse(CategorySelector.SelectedItem.Name, CultureInfo.InvariantCulture)].Properties) + ShortcutListElement.Visibility = Visibility.Visible; + ErrorMessage.Visibility = Visibility.Collapsed; + + if (int.Parse(CategorySelector.SelectedItem.Name, CultureInfo.InvariantCulture) == -1) { - if (shortcut.Name.Contains(filter, System.StringComparison.OrdinalIgnoreCase)) + if (string.IsNullOrWhiteSpace(filter)) { - ShortcutListElement.Items.Add((ShortcutTemplateDataObject)shortcut); + OpenOverview(); + return; + } + + OverviewStackPanel.Visibility = Visibility.Collapsed; + + foreach (var list in shortcutList.Shortcuts) + { + if (list.Properties == null) + { + continue; + } + + foreach (var shortcut in list.Properties) + { + if (shortcut.Name.Contains(filter, StringComparison.InvariantCultureIgnoreCase)) + { + ShortcutListElement.Items.Add((ShortcutTemplateDataObject)shortcut); + } + } + } + } + else + { + foreach (var shortcut in shortcutList.Shortcuts[int.Parse(CategorySelector.SelectedItem.Name, CultureInfo.InvariantCulture)].Properties) + { + if (shortcut.Name.Contains(filter, StringComparison.InvariantCultureIgnoreCase)) + { + ShortcutListElement.Items.Add((ShortcutTemplateDataObject)shortcut); + } } } if (ShortcutListElement.Items.Count == 0) { - ShortcutListElement.Items.Add(new ShortcutTemplateDataObject("No search results found", string.Empty, new StackPanel() { Visibility = Microsoft.UI.Xaml.Visibility.Collapsed })); + ShortcutListElement.Visibility = Visibility.Collapsed; + ErrorMessage.Visibility = Visibility.Visible; + ErrorMessage.Text = "No results found"; } } public void CategorySelector_SelectionChanged(SelectorBar sender, SelectorBarSelectionChangedEventArgs e) { ShortcutListElement.Items.Clear(); + RecommendedListElement.Items.Clear(); + PinnedListElement.Items.Clear(); + ErrorMessage.Visibility = Visibility.Collapsed; + RecommendedListElement.Visibility = Visibility.Collapsed; + PinnedListElement.Visibility = Visibility.Collapsed; + OverviewStackPanel.Visibility = Visibility.Collapsed; + ShortcutListElement.Visibility = Visibility.Visible; + + if (int.Parse(sender.SelectedItem.Name, CultureInfo.InvariantCulture) == -1) + { + OpenOverview(); + return; + } foreach (var shortcut in shortcutList.Shortcuts[int.Parse(sender.SelectedItem.Name, CultureInfo.InvariantCulture)].Properties) { ShortcutListElement.Items.Add((ShortcutTemplateDataObject)shortcut); } } + + private void PinShortcut(object sender, RoutedEventArgs e) + { + if (ShortcutPageParameters.PinnedShortcuts[ShortcutPageParameters.CurrentPageName].Contains(((ShortcutTemplateDataObject)((MenuFlyoutItem)sender).DataContext).OriginalShortcutObject)) + { + ShortcutPageParameters.PinnedShortcuts[ShortcutPageParameters.CurrentPageName].Remove(((ShortcutTemplateDataObject)((MenuFlyoutItem)sender).DataContext).OriginalShortcutObject); + } + else + { + ShortcutPageParameters.PinnedShortcuts[ShortcutPageParameters.CurrentPageName].Add(((ShortcutTemplateDataObject)((MenuFlyoutItem)sender).DataContext).OriginalShortcutObject); + } + + if (int.Parse(CategorySelector.SelectedItem.Name, CultureInfo.InvariantCulture) == -1) + { + OpenOverview(); + } + + string serialized = JsonSerializer.Serialize(ShortcutPageParameters.PinnedShortcuts); + + SettingsUtils settingsUtils = new(); + string pinnedPath = settingsUtils.GetSettingsFilePath(ShortcutGuideSettings.ModuleName, "Pinned.json"); + File.WriteAllText(pinnedPath, serialized); + } + + private void MenuFlyout_Opening(object sender, object e) + { + if (sender is not MenuFlyout menu || + menu.Target is not Grid parentGrid || + parentGrid.DataContext is not ShortcutTemplateDataObject dataObject || + menu.Items[0] is not MenuFlyoutItem pinItem) + { + return; + } + + Shortcut originalObject = dataObject.OriginalShortcutObject; + + bool isItemPinned = ShortcutPageParameters.PinnedShortcuts[ShortcutPageParameters.CurrentPageName].Contains(originalObject); + + pinItem.Text = isItemPinned ? "Unpin" : "Pin"; + pinItem.Icon = new SymbolIcon(isItemPinned ? Symbol.UnPin : Symbol.Pin); + } } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/YmlInterpreter.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/YmlInterpreter.cs index eb9bff704c..a244eac652 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/YmlInterpreter.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/YmlInterpreter.cs @@ -25,12 +25,12 @@ namespace ShortcutGuide return deserializer.Deserialize(content); } - private static string GetPathOfIntepretations() + public static string GetPathOfIntepretations() { return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "Windows", "KeyboardShortcuts"); } - private static IndexFile GetIndexYamlFile() + public static IndexFile GetIndexYamlFile() { string path = GetPathOfIntepretations(); string content = File.ReadAllText(Path.Combine(path, "index.yml")); From ddd090cc81074c534a76224a81dd0d6defc152f3 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Mon, 4 Nov 2024 00:11:16 +0100 Subject: [PATCH 46/99] Code cleanup --- .../ShortcutGuide.Ui/DisplayHelper.cs | 27 +++++++------------ .../ShortcutGuide.Ui/DpiHelper.cs | 14 ++++------ .../ShortcutGuide.Ui/Models/ShortcutList.cs | 2 ++ .../ShortcutGuide.Ui/NativeMethods.cs | 23 ++++++++-------- .../PowerToysShortcutsPopulator.cs | 7 +++-- .../ShortcutGuide.Ui/Program.cs | 2 +- .../ShortcutGuideXAML/App.xaml.cs | 2 +- .../ShortcutGuideXAML/MainWindow.xaml.cs | 6 ++--- .../ShortcutTemplateDataObject.cs | 9 +------ .../ShortcutGuideXAML/ShortcutView.xaml | 1 - .../ShortcutGuideXAML/ShortcutView.xaml.cs | 3 +-- .../StringToVisibilityConverter.cs | 24 ----------------- .../ShortcutGuide.Ui/YmlInterpreter.cs | 1 - 13 files changed, 40 insertions(+), 81 deletions(-) delete mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/StringToVisibilityConverter.cs diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DisplayHelper.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DisplayHelper.cs index fc20efa118..5df8283b8f 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DisplayHelper.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DisplayHelper.cs @@ -3,17 +3,13 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; -using System.Linq; using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; using Windows.Foundation; using WinUIEx; namespace ShortcutGuide { - public static class DisplayHelper + public static partial class DisplayHelper { private enum MonitorFromWindowDwFlags : int { @@ -56,30 +52,25 @@ namespace ShortcutGuide private delegate bool MonitorEnumDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData); - [DllImport("User32.dll")] - private static extern IntPtr MonitorFromWindow(nint hwnd, int dwFlags); + [LibraryImport("User32.dll")] + private static partial IntPtr MonitorFromWindow(nint hwnd, int dwFlags); - [DllImport("User32.dll")] + [LibraryImport("User32.dll")] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData); + private static partial bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData); - public struct LPARAM + public struct LPARAM(IntPtr value) { - public IntPtr Value; - - public LPARAM(IntPtr value) - { - Value = value; - } + public IntPtr Value = value; public static implicit operator IntPtr(LPARAM lParam) { return lParam.Value; } - public static implicit operator LPARAM(IntPtr ptr) + public static implicit operator LPARAM(IntPtr value) { - return new LPARAM(ptr); + return new LPARAM(value); } public static implicit operator LPARAM(int value) diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DpiHelper.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DpiHelper.cs index e5ace7e3e9..78ee293599 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DpiHelper.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DpiHelper.cs @@ -3,16 +3,12 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; -using System.Linq; using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; namespace ShortcutGuide { // This class is rewritten from C++ to C# from the measure tool project - internal static class DpiHelper + internal static partial class DpiHelper { #pragma warning disable SA1310 // Field names should not contain underscore private const int DEFAULT_DPI = 96; @@ -47,10 +43,10 @@ namespace ShortcutGuide } } - [DllImport("User32.dll")] - private static extern IntPtr MonitorFromWindow(int hwnd, int dwFlags); + [LibraryImport("User32.dll")] + private static partial IntPtr MonitorFromWindow(int hwnd, int dwFlags); - [DllImport("Shcore.dll")] - private static extern long GetDpiForMonitor(int hmonitor, int dpiType, ref int dpiX, ref int dpiY); + [LibraryImport("Shcore.dll")] + private static partial long GetDpiForMonitor(int hmonitor, int dpiType, ref int dpiX, ref int dpiY); } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutList.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutList.cs index b4023a6445..dfd62ee54d 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutList.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutList.cs @@ -11,5 +11,7 @@ namespace ShortcutGuide.Models public ShortcutCategory[] Shortcuts { get; set; } public string WindowFilter { get; set; } + + public bool BackgroundProcess { get; set; } } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs index 856f6a9501..4a22026877 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs @@ -5,10 +5,11 @@ using System; using System.Runtime.InteropServices; -internal static class NativeMethods +internal static partial class NativeMethods { - [DllImport("user32.dll")] - internal static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); + [LibraryImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); internal static readonly IntPtr HWND_TOPMOST = new System.IntPtr(-1); internal const uint SWP_NOSIZE = 0x0001; @@ -16,17 +17,17 @@ internal static class NativeMethods internal const uint SWP_NOACTIVATE = 0x0010; internal const uint SWP_SHOWWINDOW = 0x0040; - [DllImport("user32.dll", SetLastError = true)] - internal static extern int GetWindowLong(IntPtr hWnd, int nIndex); + [LibraryImport("user32.dll", SetLastError = true)] + internal static partial int GetWindowLongW(IntPtr hWnd, int nIndex); - [DllImport("user32.dll")] - internal static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); + [LibraryImport("user32.dll")] + internal static partial int SetWindowLongW(IntPtr hWnd, int nIndex, int dwNewLong); - [DllImport("user32.dll", CharSet = CharSet.Unicode)] - internal static extern int FindWindowA(in string lpClassName, in string? lpWindowName); + [LibraryImport("user32.dll", StringMarshalling = StringMarshalling.Utf16)] + internal static partial int FindWindowA(in string lpClassName, in string? lpWindowName); - [DllImport("user32.dll", CharSet = CharSet.Unicode)] - internal static extern int FindWindowExA(int hwndParent, int hwndChildAfter, in string lpClassName, in string? lpWindowName); + [LibraryImport("user32.dll", StringMarshalling = StringMarshalling.Utf16)] + internal static partial int FindWindowExA(int hwndParent, int hwndChildAfter, in string lpClassName, in string? lpWindowName); internal const int GWL_STYLE = -16; internal const int WS_CAPTION = 0x00C00000; diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/PowerToysShortcutsPopulator.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/PowerToysShortcutsPopulator.cs index e0ca43540f..cc649eb7de 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/PowerToysShortcutsPopulator.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/PowerToysShortcutsPopulator.cs @@ -10,7 +10,7 @@ using Microsoft.PowerToys.Settings.UI.Library; namespace ShortcutGuide { - internal sealed class PowerToysShortcutsPopulator + internal sealed partial class PowerToysShortcutsPopulator { public static void Populate() { @@ -21,7 +21,7 @@ namespace ShortcutGuide const string populateStartString = "# "; const string populateEndString = "# "; - content = Regex.Replace(content, populateStartString + "[\\s\\S\\n\\r]*" + populateEndString, populateStartString + Environment.NewLine); + content = PoulateRegex().Replace(content, populateStartString + Environment.NewLine); content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.AdvancedPasteUIShortcut, "Advanced Paste", content, "Open Advanced Paste window"); content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.PasteAsPlainTextShortcut, "Advanced Paste", content, "Paste as plain text directly"); @@ -74,5 +74,8 @@ namespace ShortcutGuide { return HotkeySettingsToYaml(keyboardKeys.Value, moduleName, content, description); } + + [GeneratedRegex(@"# [\s\S\n\r]*# ")] + private static partial Regex PoulateRegex(); } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs index 09c8b20369..f50e668659 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs @@ -13,7 +13,7 @@ namespace ShortcutGuide public sealed class Program { [STAThread] - public static void Main(string[] args) + public static void Main() { PowerToysShortcutsPopulator.Populate(); diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs index 01c7e3417a..8813aa5b35 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs @@ -13,7 +13,7 @@ namespace ShortcutGuide InitializeComponent(); } - protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) + protected override void OnLaunched(LaunchActivatedEventArgs args) { _window = new MainWindow(); _window.Activate(); diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs index fb3f6eea2e..c553029977 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs @@ -49,9 +49,9 @@ namespace ShortcutGuide IsTitleBarVisible = false; // Remove the caption style from the window style. Windows App SDK 1.6 added it, which made the title bar and borders appear for Measure Tool. This code removes it. - var windowStyle = GetWindowLong(hwnd, GWL_STYLE); - windowStyle = windowStyle & (~WS_CAPTION); - _ = SetWindowLong(hwnd, GWL_STYLE, windowStyle); + var windowStyle = GetWindowLongW(hwnd, GWL_STYLE); + windowStyle &= ~WS_CAPTION; + _ = SetWindowLongW(hwnd, GWL_STYLE, windowStyle); #if DEBUG #else SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutTemplateDataObject.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutTemplateDataObject.cs index fac8a121cd..57a2f6f5db 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutTemplateDataObject.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutTemplateDataObject.cs @@ -26,14 +26,7 @@ namespace ShortcutGuide Description = description; OriginalShortcutObject = originalShortcutObject; - if (string.IsNullOrWhiteSpace(description)) - { - DescriptionVisible = Visibility.Collapsed; - } - else - { - DescriptionVisible = Visibility.Visible; - } + DescriptionVisible = string.IsNullOrWhiteSpace(description) ? Visibility.Collapsed : Visibility.Visible; shortcut.Orientation = Orientation.Horizontal; Shortcut = shortcut; diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml index e0059e06aa..2649f374e8 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml @@ -10,7 +10,6 @@ DataContext="{Binding RelativeSource={RelativeSource Self}}" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> - diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs index 67f19e34bd..154202e958 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.IO; @@ -61,7 +60,7 @@ namespace ShortcutGuide if (!ShortcutPageParameters.PinnedShortcuts.TryGetValue(ShortcutPageParameters.CurrentPageName, out var _)) { - ShortcutPageParameters.PinnedShortcuts.Add(ShortcutPageParameters.CurrentPageName, new List()); + ShortcutPageParameters.PinnedShortcuts.Add(ShortcutPageParameters.CurrentPageName, []); } OpenOverview(); diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/StringToVisibilityConverter.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/StringToVisibilityConverter.cs deleted file mode 100644 index 0de9e139ca..0000000000 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/StringToVisibilityConverter.cs +++ /dev/null @@ -1,24 +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 System; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Data; - -namespace ShortcutGuide -{ - public partial class StringToVisibilityConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, string language) - { - return string.IsNullOrWhiteSpace((string)value) ? Visibility.Collapsed : Visibility.Visible; - } - - public object ConvertBack(object value, Type targetType, object parameter, string language) - { - var visiblity = (Visibility)value; - return visiblity == Visibility.Visible; - } - } -} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/YmlInterpreter.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/YmlInterpreter.cs index a244eac652..737e5b06bc 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/YmlInterpreter.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/YmlInterpreter.cs @@ -4,7 +4,6 @@ using System; using System.IO; -using ShortcutGuide.Exceptions; using ShortcutGuide.Models; using YamlDotNet.Serialization; From acf510dff56b445c4509967dd0840c7b1410e7a7 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Mon, 4 Nov 2024 00:17:43 +0100 Subject: [PATCH 47/99] Fix display on monitor with mouse and move all NaticeMethods to NativeMethods.cs --- .../ShortcutGuide.Ui/DpiHelper.cs | 13 ++--------- .../ShortcutGuide.Ui/NativeMethods.cs | 22 +++++++++++++++++++ .../ShortcutGuideXAML/MainWindow.xaml.cs | 18 +-------------- 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DpiHelper.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DpiHelper.cs index 78ee293599..343998b68d 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DpiHelper.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DpiHelper.cs @@ -2,9 +2,6 @@ // 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.Runtime.InteropServices; - namespace ShortcutGuide { // This class is rewritten from C++ to C# from the measure tool project @@ -25,7 +22,7 @@ namespace ShortcutGuide public static long GetScreenDPIForWindow(int hwnd, ref int dpi) { - var targetMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); + var targetMonitor = NativeMethods.MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); return GetScreenDPIForMonitor(targetMonitor.ToInt32(), ref dpi); } @@ -34,7 +31,7 @@ namespace ShortcutGuide if (targetMonitor != 0) { int dummy = 0; - return GetDpiForMonitor(targetMonitor, MDT_EFFECTIVE_DPI, ref dpi, ref dummy); + return NativeMethods.GetDpiForMonitor(targetMonitor, MDT_EFFECTIVE_DPI, ref dpi, ref dummy); } else { @@ -42,11 +39,5 @@ namespace ShortcutGuide return 0x80004005L; } } - - [LibraryImport("User32.dll")] - private static partial IntPtr MonitorFromWindow(int hwnd, int dwFlags); - - [LibraryImport("Shcore.dll")] - private static partial long GetDpiForMonitor(int hmonitor, int dpiType, ref int dpiX, ref int dpiY); } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs index 4a22026877..26ab7e1e58 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs @@ -4,6 +4,7 @@ using System; using System.Runtime.InteropServices; +using Windows.Graphics; internal static partial class NativeMethods { @@ -29,6 +30,27 @@ internal static partial class NativeMethods [LibraryImport("user32.dll", StringMarshalling = StringMarshalling.Utf16)] internal static partial int FindWindowExA(int hwndParent, int hwndChildAfter, in string lpClassName, in string? lpWindowName); + [LibraryImport("User32.dll")] + internal static partial IntPtr MonitorFromWindow(int hwnd, int dwFlags); + + [LibraryImport("Shcore.dll")] + internal static partial long GetDpiForMonitor(int hmonitor, int dpiType, ref int dpiX, ref int dpiY); + + [LibraryImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool GetCursorPos(out POINT lpPoint); + + public struct POINT + { + public int X; + public int Y; + + public static implicit operator PointInt32(POINT point) + { + return new PointInt32(point.X, point.Y); + } + } + internal const int GWL_STYLE = -16; internal const int WS_CAPTION = 0x00C00000; } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs index c553029977..6a8a7fa507 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Runtime.InteropServices; using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.UI; @@ -78,7 +77,7 @@ namespace ShortcutGuide _appWindow = AppWindow.GetFromWindowId(windowId); GetCursorPos(out POINT lpPoint); - _appWindow.Move(lpPoint); + _appWindow.Move(lpPoint with { Y = lpPoint.Y - ((int)Height / 2), X = lpPoint.X - ((int)Width / 2) }); float dpiScale = DpiHelper.GetDPIScaleForWindow((int)hwnd); @@ -108,21 +107,6 @@ namespace ShortcutGuide private bool _setPosition; - [LibraryImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - public static partial bool GetCursorPos(out POINT lpPoint); - - public struct POINT - { - public int X; - public int Y; - - public static implicit operator PointInt32(POINT point) - { - return new PointInt32(point.X, point.Y); - } - } - public void CloseButton_Clicked(object sender, RoutedEventArgs e) { Environment.Exit(0); From 440e75184a2c69e1b9d5a7664b52bf3ba64718c2 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Sun, 10 Nov 2024 15:05:34 +0100 Subject: [PATCH 48/99] Fix error messages and read application titles out of index manifest --- .../ShortcutGuide.Ui/Models/IndexFile.cs | 4 +- .../ShortcutGuide.Ui/Models/ShortcutList.cs | 2 + .../Models/ShortcutPageParameters.cs | 5 ++ .../ShortcutGuide.Ui/NativeMethods.cs | 7 ++ .../ShortcutGuideXAML/MainWindow.xaml | 11 --- .../ShortcutGuideXAML/MainWindow.xaml.cs | 42 ++++++++--- .../ShortcutGuideXAML/ShortcutView.xaml | 2 +- .../ShortcutGuideXAML/ShortcutView.xaml.cs | 20 ++++-- .../ShortcutGuide.Ui/YmlInterpreter.cs | 72 +++++++++++++++++++ 9 files changed, 135 insertions(+), 30 deletions(-) diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/IndexFile.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/IndexFile.cs index 9b122c77a5..e8c64d813b 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/IndexFile.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/IndexFile.cs @@ -8,7 +8,9 @@ namespace ShortcutGuide.Models { public struct IndexItem { - public string Filter { get; set; } + public string WindowFilter { get; set; } + + public bool BackgroundProcess { get; set; } public string[] Apps { get; set; } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutList.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutList.cs index dfd62ee54d..dd80a4d218 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutList.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutList.cs @@ -13,5 +13,7 @@ namespace ShortcutGuide.Models public string WindowFilter { get; set; } public bool BackgroundProcess { get; set; } + + public string Name { get; set; } } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs index a5a1ba409c..ad687fefcb 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs @@ -33,6 +33,11 @@ namespace ShortcutGuide.Models public void OnFrameHeightChanged(double height) { + if (height <= 0) + { + return; + } + FrameHeightChanged?.Invoke(this, height); } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs index 26ab7e1e58..e16b8ffb71 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs @@ -4,6 +4,7 @@ using System; using System.Runtime.InteropServices; +using System.Text; using Windows.Graphics; internal static partial class NativeMethods @@ -40,6 +41,12 @@ internal static partial class NativeMethods [return: MarshalAs(UnmanagedType.Bool)] public static partial bool GetCursorPos(out POINT lpPoint); + [LibraryImport("user32.dll")] + public static partial IntPtr GetForegroundWindow(); + + [DllImport("user32.dll", SetLastError = true)] + public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId); + public struct POINT { public int X; diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml index 28785d4f00..75966a4384 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml @@ -21,17 +21,6 @@ - - - - - - - - - - - diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs index 4cc64752f1..f54d5601e5 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs @@ -12,6 +12,7 @@ using Microsoft.UI; using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; using ShortcutGuide.Models; using ShortcutGuide.Properties; using Windows.Foundation; @@ -138,5 +139,10 @@ namespace ShortcutGuide { ShortcutPageParameters.SearchFilter.OnFilterChanged(SearchBox.Text); } + + private void SearchBoy_KeyboardAcceleratorInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args) + { + SearchBox.Focus(FocusState.Programmatic); + } } } From 7acab452d509009bb3d9a27f8fa769375dd9af88 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Wed, 11 Jun 2025 15:41:39 +0200 Subject: [PATCH 54/99] Handle errors displaying app and close window automatically on focus change --- .../ShortcutGuideXAML/MainWindow.xaml.cs | 10 ++- .../ShortcutGuideXAML/ShortcutView.xaml.cs | 73 +++++++++++-------- 2 files changed, 49 insertions(+), 34 deletions(-) diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs index f54d5601e5..c0440cb735 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Text.Json; @@ -59,7 +60,7 @@ namespace ShortcutGuide SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); #endif - Activated += OnLauched; + Activated += Window_Activated; SettingsUtils settingsUtils = new(); @@ -70,8 +71,13 @@ namespace ShortcutGuide } } - private void OnLauched(object sender, WindowActivatedEventArgs e) + private void Window_Activated(object sender, WindowActivatedEventArgs e) { + if (e.WindowActivationState == WindowActivationState.Deactivated) + { + Environment.Exit(0); + } + if (!_setPosition) { var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this); diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs index a111ca97bd..ffbd507880 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs @@ -30,44 +30,53 @@ namespace ShortcutGuide int i = -1; - CategorySelector.Items.Add(new SelectorBarItem() { Text = "Overview", Name = i.ToString(CultureInfo.InvariantCulture) }); - - i++; - - foreach (var category in shortcutList.Shortcuts) + try { - switch (category.SectionName) - { - case string name when name.StartsWith("", StringComparison.Ordinal): - // Todo: Implement GetTaskbarIconPositions - break; - case string name when name.StartsWith('<') && name.EndsWith('>'): - break; - default: - CategorySelector.Items.Add(new SelectorBarItem() { Text = category.SectionName, Name = i.ToString(CultureInfo.InvariantCulture) }); - break; - } + CategorySelector.Items.Add(new SelectorBarItem() { Text = "Overview", Name = i.ToString(CultureInfo.InvariantCulture) }); i++; + + foreach (var category in shortcutList.Shortcuts) + { + switch (category.SectionName) + { + case string name when name.StartsWith("", StringComparison.Ordinal): + // Todo: Implement GetTaskbarIconPositions + break; + case string name when name.StartsWith('<') && name.EndsWith('>'): + break; + default: + CategorySelector.Items.Add(new SelectorBarItem() { Text = category.SectionName, Name = i.ToString(CultureInfo.InvariantCulture) }); + break; + } + + i++; + } + + CategorySelector.SelectedItem = CategorySelector.Items[0]; + CategorySelector.SelectionChanged += CategorySelector_SelectionChanged; + + foreach (var shortcut in shortcutList.Shortcuts[0].Properties) + { + ShortcutListElement.Items.Add((ShortcutTemplateDataObject)shortcut); + } + + ShortcutPageParameters.FrameHeight.FrameHeightChanged += ContentHeightChanged; + ShortcutPageParameters.SearchFilter.FilterChanged += SearchFilter_FilterChanged; + + if (!ShortcutPageParameters.PinnedShortcuts.TryGetValue(ShortcutPageParameters.CurrentPageName, out var _)) + { + ShortcutPageParameters.PinnedShortcuts.Add(ShortcutPageParameters.CurrentPageName, []); + } + + OpenOverview(); } - - CategorySelector.SelectedItem = CategorySelector.Items[0]; - CategorySelector.SelectionChanged += CategorySelector_SelectionChanged; - - foreach (var shortcut in shortcutList.Shortcuts[0].Properties) + catch (Exception) { - ShortcutListElement.Items.Add((ShortcutTemplateDataObject)shortcut); + OverviewStackPanel.Visibility = Visibility.Collapsed; + ErrorMessage.Visibility = Visibility.Visible; + ErrorMessage.Text = "Error displaying the applications shortcuts"; } - - ShortcutPageParameters.FrameHeight.FrameHeightChanged += ContentHeightChanged; - ShortcutPageParameters.SearchFilter.FilterChanged += SearchFilter_FilterChanged; - - if (!ShortcutPageParameters.PinnedShortcuts.TryGetValue(ShortcutPageParameters.CurrentPageName, out var _)) - { - ShortcutPageParameters.PinnedShortcuts.Add(ShortcutPageParameters.CurrentPageName, []); - } - - OpenOverview(); } private void OnPropertyChanged([CallerMemberName] string? propertyName = null) From e6edca93e7d0454997302f24b6ab61b557522aaf Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Fri, 13 Jun 2025 23:37:54 +0200 Subject: [PATCH 55/99] Add taskbar indicators --- .../ShortcutGuide/ShortcutGuide.vcxproj | 6 - .../ShortcutGuide.vcxproj.filters | 86 +++++- src/modules/ShortcutGuide/ShortcutGuide/pch.h | 3 +- .../ShortcutGuide/tasklist_positions.cpp | 267 +++++++++++------- .../ShortcutGuide/tasklist_positions.h | 25 +- .../ShortcutGuide.CPPProject.vcxproj | 149 ++++++++++ .../ShortcutGuide.CPPProject.vcxproj.filters | 33 +++ .../ShortcutGuide/+WindowsNT.Shell.en-US.yml | 21 +- .../ShortcutGuide.Ui/DisplayHelper.cs | 1 + .../Helpers/TaskListPositions.cs | 27 -- .../ShortcutGuide.Ui/NativeMethods.cs | 12 +- .../ShortcutGuide.Ui/ShortcutGuide.Ui.csproj | 12 + .../ShortcutGuideXAML/MainWindow.xaml.cs | 15 + .../ShortcutGuideXAML/ShortcutView.xaml | 43 +++ .../ShortcutGuideXAML/ShortcutView.xaml.cs | 71 ++++- .../ShortcutGuide.Ui/TasklistPositions.cs | 188 ++++++++++++ 16 files changed, 786 insertions(+), 173 deletions(-) create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj.filters delete mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/TaskListPositions.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/TasklistPositions.cs diff --git a/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj b/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj index 045be94f2b..4bb709f180 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj +++ b/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj @@ -65,14 +65,12 @@ - - @@ -83,13 +81,9 @@ - - Create - - diff --git a/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj.filters b/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj.filters index 006a6196ef..af14da58f3 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj.filters +++ b/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj.filters @@ -18,9 +18,6 @@ - - Header Files - Header Files @@ -51,9 +48,6 @@ Header Files - - Header Files - Header Files @@ -68,9 +62,6 @@ - - Source Files - Source Files @@ -101,9 +92,6 @@ Source Files - - Source Files - Source Files @@ -116,7 +104,79 @@ - + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + Resource Files diff --git a/src/modules/ShortcutGuide/ShortcutGuide/pch.h b/src/modules/ShortcutGuide/ShortcutGuide/pch.h index 9ec2bbcb41..9bff3b54c1 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide/pch.h +++ b/src/modules/ShortcutGuide/ShortcutGuide/pch.h @@ -25,5 +25,4 @@ #include #include #include -#include -#include \ No newline at end of file +#include \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.cpp b/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.cpp index 687fc86566..4572f412b3 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.cpp +++ b/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.cpp @@ -1,116 +1,193 @@ #include "pch.h" #include "tasklist_positions.h" +#include +#include +#include +#include -void Tasklist::update() +extern "C" { - // Get HWND of the tasklist - auto tasklist_hwnd = FindWindowA("Shell_TrayWnd", nullptr); - if (!tasklist_hwnd) - return; - tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "ReBarWindow32", nullptr); - if (!tasklist_hwnd) - return; - tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "MSTaskSwWClass", nullptr); - if (!tasklist_hwnd) - return; - tasklist_hwnd = FindWindowExA(tasklist_hwnd, 0, "MSTaskListWClass", nullptr); - if (!tasklist_hwnd) - return; - if (!automation) - { - winrt::check_hresult(CoCreateInstance(CLSID_CUIAutomation, - nullptr, - CLSCTX_INPROC_SERVER, - IID_IUIAutomation, - automation.put_void())); - winrt::check_hresult(automation->CreateTrueCondition(true_condition.put())); - } - element = nullptr; - winrt::check_hresult(automation->ElementFromHandle(tasklist_hwnd, element.put())); -} + winrt::com_ptr automation; + winrt::com_ptr element; + winrt::com_ptr true_condition; -bool Tasklist::update_buttons(std::vector& buttons) -{ - if (!automation || !element) + // Helper to get the taskbar HWND for the monitor under the cursor + HWND GetTaskbarHwndForCursorMonitor(HMONITOR monitor) { - return false; - } - winrt::com_ptr elements; - if (element->FindAll(TreeScope_Children, true_condition.get(), elements.put()) < 0) - return false; - if (!elements) - return false; - int count; - if (elements->get_Length(&count) < 0) - return false; - winrt::com_ptr child; - std::vector found_buttons; - found_buttons.reserve(count); - for (int i = 0; i < count; ++i) - { - child = nullptr; - if (elements->GetElement(i, child.put()) < 0) - return false; - TasklistButton button; - if (VARIANT var_rect; child->GetCurrentPropertyValue(UIA_BoundingRectanglePropertyId, &var_rect) >= 0) + POINT pt; + if (!GetCursorPos(&pt)) + return nullptr; + + // Find the primary taskbar + HWND primaryTaskbar = FindWindowW(L"Shell_TrayWnd", nullptr); + if (primaryTaskbar) { - if (var_rect.vt == (VT_R8 | VT_ARRAY)) + MONITORINFO mi = { sizeof(mi) }; + if (GetWindowRect(primaryTaskbar, &mi.rcMonitor)) { - LONG pos; - double value; - pos = 0; - SafeArrayGetElement(var_rect.parray, &pos, &value); - button.x = static_cast(value); - pos = 1; - SafeArrayGetElement(var_rect.parray, &pos, &value); - button.y = static_cast(value); - pos = 2; - SafeArrayGetElement(var_rect.parray, &pos, &value); - button.width = static_cast(value); - pos = 3; - SafeArrayGetElement(var_rect.parray, &pos, &value); - button.height = static_cast(value); + HMONITOR primaryMonitor = MonitorFromRect(&mi.rcMonitor, MONITOR_DEFAULTTONEAREST); + if (primaryMonitor == monitor) + return primaryTaskbar; } - VariantClear(&var_rect); + } + + // Find the secondary taskbar(s) + HWND secondaryTaskbar = nullptr; + while ((secondaryTaskbar = FindWindowExW(nullptr, secondaryTaskbar, L"Shell_SecondaryTrayWnd", nullptr)) != nullptr) + { + MONITORINFO mi = { sizeof(mi) }; + RECT rc; + if (GetWindowRect(secondaryTaskbar, &rc)) + { + HMONITOR monitor = MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST); + if (monitor == monitor) + return secondaryTaskbar; + } + } + + return nullptr; + } + + __declspec(dllexport) void update(HMONITOR monitor) + { + // Get HWND of the tasklist for the monitor under the cursor + auto taskbar_hwnd = GetTaskbarHwndForCursorMonitor(monitor); + if (!taskbar_hwnd) + return; + + wchar_t class_name[64] = {}; + GetClassNameW(taskbar_hwnd, class_name, 64); + + HWND tasklist_hwnd = nullptr; + + if (wcscmp(class_name, L"Shell_TrayWnd") == 0) + { + // Primary taskbar structure + tasklist_hwnd = FindWindowExW(taskbar_hwnd, 0, L"ReBarWindow32", nullptr); + if (!tasklist_hwnd) + return; + tasklist_hwnd = FindWindowExW(tasklist_hwnd, 0, L"MSTaskSwWClass", nullptr); + if (!tasklist_hwnd) + return; + tasklist_hwnd = FindWindowExW(tasklist_hwnd, 0, L"MSTaskListWClass", nullptr); + if (!tasklist_hwnd) + return; + } + else if (wcscmp(class_name, L"Shell_SecondaryTrayWnd") == 0) + { + // Secondary taskbar structure + HWND workerw = FindWindowExW(taskbar_hwnd, 0, L"WorkerW", nullptr); + if (!workerw) + return; + tasklist_hwnd = FindWindowExW(workerw, 0, L"MSTaskListWClass", nullptr); + if (!tasklist_hwnd) + return; } else + { + // Unknown taskbar type + return; + } + + if (!automation) + { + winrt::check_hresult(CoCreateInstance(CLSID_CUIAutomation, + nullptr, + CLSCTX_INPROC_SERVER, + IID_IUIAutomation, + automation.put_void())); + winrt::check_hresult(automation->CreateTrueCondition(true_condition.put())); + } + element = nullptr; + winrt::check_hresult(automation->ElementFromHandle(tasklist_hwnd, element.put())); + } + + __declspec(dllexport) bool update_buttons(std::vector& buttons) + { + if (!automation || !element) { return false; } - if (BSTR automation_id; child->get_CurrentAutomationId(&automation_id) >= 0) + winrt::com_ptr elements; + if (element->FindAll(TreeScope_Children, true_condition.get(), elements.put()) < 0) + return false; + if (!elements) + return false; + int count; + if (elements->get_Length(&count) < 0) + return false; + winrt::com_ptr child; + std::vector found_buttons; + found_buttons.reserve(count); + for (int i = 0; i < count; ++i) { - button.name = automation_id; - SysFreeString(automation_id); + child = nullptr; + if (elements->GetElement(i, child.put()) < 0) + return false; + TasklistButton button; + if (VARIANT var_rect; child->GetCurrentPropertyValue(UIA_BoundingRectanglePropertyId, &var_rect) >= 0) + { + if (var_rect.vt == (VT_R8 | VT_ARRAY)) + { + LONG pos; + double value; + pos = 0; + SafeArrayGetElement(var_rect.parray, &pos, &value); + button.x = static_cast(value); + pos = 1; + SafeArrayGetElement(var_rect.parray, &pos, &value); + button.y = static_cast(value); + pos = 2; + SafeArrayGetElement(var_rect.parray, &pos, &value); + button.width = static_cast(value); + pos = 3; + SafeArrayGetElement(var_rect.parray, &pos, &value); + button.height = static_cast(value); + } + VariantClear(&var_rect); + } + else + { + return false; + } + if (BSTR automation_id; child->get_CurrentAutomationId(&automation_id) >= 0) + { + wcsncpy_s(button.name, automation_id, _countof(button.name)); + SysFreeString(automation_id); + } + found_buttons.push_back(button); } - found_buttons.push_back(button); + // assign keynums + buttons.clear(); + for (auto& button : found_buttons) + { + if (buttons.empty()) + { + button.keynum = 1; + buttons.push_back(std::move(button)); + } + else + { + if (button.x < buttons.back().x || button.y < buttons.back().y) // skip 2nd row + break; + if (wcsncmp(button.name, buttons.back().name, _countof(button.name)) == 0) + continue; // skip buttons from the same app + button.keynum = buttons.back().keynum + 1; + buttons.push_back(std::move(button)); + if (buttons.back().keynum == 10) + break; // no more than 10 buttons + } + } + return true; } - // assign keynums - buttons.clear(); - for (auto& button : found_buttons) + + __declspec(dllexport) TasklistButton* get_buttons(HMONITOR monitor, int* size) { - if (buttons.empty()) - { - button.keynum = 1; - buttons.push_back(std::move(button)); - } - else - { - if (button.x < buttons.back().x || button.y < buttons.back().y) // skip 2nd row - break; - if (button.name == buttons.back().name) - continue; // skip buttons from the same app - button.keynum = buttons.back().keynum + 1; - buttons.push_back(std::move(button)); - if (buttons.back().keynum == 10) - break; // no more than 10 buttons - } + update(monitor); + static std::vector buttons; + update_buttons(buttons); + *size = static_cast(buttons.size()); + return buttons.data(); } - return true; } -std::vector Tasklist::get_buttons() -{ - std::vector buttons; - update_buttons(buttons); - return buttons; -} \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.h b/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.h index 4ac5bed8a9..cf71ee838f 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.h +++ b/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.h @@ -7,23 +7,10 @@ struct TasklistButton { - std::wstring name; - long x{}; - long y{}; - long width{}; - long height{}; - long keynum{}; -}; - -class Tasklist -{ -public: - void update(); - std::vector get_buttons(); - bool update_buttons(std::vector& buttons); - -private: - winrt::com_ptr automation; - winrt::com_ptr element; - winrt::com_ptr true_condition; + wchar_t name[256]; + int x; + int y; + int width; + int height; + int keynum; }; diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj b/src/modules/ShortcutGuideV2/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj new file mode 100644 index 0000000000..dcfe871e5b --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj @@ -0,0 +1,149 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {c992fd2c-83b8-4941-9fc1-09730068d8ec} + ShortcutGuideCPPProject + 10.0.22621.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + DynamicLibrary + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + ..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps\ + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Create + Create + Create + Create + + + + + + + + + + {d9b8fc84-322a-4f9f-bbb9-20915c47ddfd} + + + + + + \ No newline at end of file diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj.filters b/src/modules/ShortcutGuideV2/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj.filters new file mode 100644 index 0000000000..da95b2b982 --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Shell.en-US.yml b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Shell.en-US.yml index cf7aa4b240..0e3913b0c5 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Shell.en-US.yml +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Shell.en-US.yml @@ -12,6 +12,21 @@ Shortcuts: Alt: true Keys: - F4 + - Name: Test shortcut + Shortcut: + - Win: false + Ctrl: true + Shift: false + Alt: false + Keys: + - K + - Win: false + Ctrl: true + Shift: false + Alt: false + Keys: + - C + - Name: Open shutdown box Description: When no windows are open Shortcut: @@ -29,12 +44,6 @@ Shortcuts: Alt: true Keys: - Esc - - Win: false - Ctrl: false - Shift: false - Alt: true - Keys: - - Esc - Name: Reveal typed password Description: On sign-in screen Shortcut: diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DisplayHelper.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DisplayHelper.cs index 5df8283b8f..a41d0a9b1b 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DisplayHelper.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DisplayHelper.cs @@ -19,6 +19,7 @@ namespace ShortcutGuide public static Rect GetWorkAreaForDisplayWithWindow(IntPtr hwnd) { foundMonitorIndex = -1; + monitorIndex = 0; var monitor = MonitorFromWindow(hwnd, (int)MonitorFromWindowDwFlags.MONITOR_DEFAULTTONEAREST); EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, MonitorEnumProc, new LPARAM(monitor)); return MonitorInfo.GetDisplayMonitors()[foundMonitorIndex].RectWork; diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/TaskListPositions.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/TaskListPositions.cs deleted file mode 100644 index b408d8e3e2..0000000000 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/TaskListPositions.cs +++ /dev/null @@ -1,27 +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 System; -using System.Collections.Generic; -using System.Runtime.InteropServices; - -namespace ShortcutGuide.Helpers -{ - internal sealed class TaskListPositions - { - public static List GetTaskbarIconPositions() - { - throw new NotImplementedException(); - } - - [StructLayout(LayoutKind.Sequential)] - public struct RECT - { - public int Left; - public int Top; - public int Right; - public int Bottom; - } - } -} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs index e16b8ffb71..466551d453 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs @@ -26,10 +26,10 @@ internal static partial class NativeMethods internal static partial int SetWindowLongW(IntPtr hWnd, int nIndex, int dwNewLong); [LibraryImport("user32.dll", StringMarshalling = StringMarshalling.Utf16)] - internal static partial int FindWindowA(in string lpClassName, in string? lpWindowName); + internal static partial IntPtr FindWindowA(in string lpClassName, in string? lpWindowName); [LibraryImport("user32.dll", StringMarshalling = StringMarshalling.Utf16)] - internal static partial int FindWindowExA(int hwndParent, int hwndChildAfter, in string lpClassName, in string? lpWindowName); + public static partial IntPtr FindWindowExA(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [LibraryImport("User32.dll")] internal static partial IntPtr MonitorFromWindow(int hwnd, int dwFlags); @@ -47,6 +47,14 @@ internal static partial class NativeMethods [DllImport("user32.dll", SetLastError = true)] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId); + [DllImport("ole32.dll", SetLastError = true)] + public static extern uint CoCreateInstance( + in Guid rclsid, + IntPtr pUnkOuter, + uint dwClsContext, + in Guid riid, + out IntPtr ppv); + public struct POINT { public int X; diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj index cba7566b17..911ac0502f 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj @@ -60,6 +60,17 @@ + + + tlbimp + 0 + 1 + 944de083-8fb8-45cf-bcb7-c477acb2f897 + 0 + false + true + + @@ -95,6 +106,7 @@ + diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs index c0440cb735..a1561262a0 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs @@ -28,6 +28,8 @@ namespace ShortcutGuide /// public sealed partial class MainWindow : WindowEx { + public static nint WindowHwnd { get; set; } + private AppWindow _appWindow; private string[] _currentApplicationIds; @@ -41,6 +43,7 @@ namespace ShortcutGuide Title = Resource.ResourceManager.GetString("Title", CultureInfo.InvariantCulture)!; var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this); + WindowHwnd = hwnd; WindowId windowId = Win32Interop.GetWindowIdFromWindow(hwnd); _appWindow = AppWindow.GetFromWindowId(windowId); #if !DEBUG @@ -75,7 +78,9 @@ namespace ShortcutGuide { if (e.WindowActivationState == WindowActivationState.Deactivated) { +#if !DEBUG Environment.Exit(0); +#endif } if (!_setPosition) @@ -96,6 +101,16 @@ namespace ShortcutGuide // Move top of the window to the center of the monitor _appWindow.Move(new PointInt32((int)monitorRect.X, (int)(monitorRect.Y + (int)(monitorRect.Height / 2)))); _setPosition = true; + AppWindow.Changed += (_, a) => + { + if (a.DidPresenterChange) + { + Rect monitorRect = DisplayHelper.GetWorkAreaForDisplayWithWindow(hwnd); + float dpiScale = DpiHelper.GetDPIScaleForWindow((int)hwnd); + this.SetWindowSize(monitorRect.Width / dpiScale, monitorRect.Height / dpiScale / 2); + _appWindow.Move(new PointInt32((int)monitorRect.X, (int)(monitorRect.Y + (int)(monitorRect.Height / 2)))); + } + }; } if (WindowSelector.Items.Count == 0) diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml index 803178f318..971809d29b 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml @@ -38,6 +38,7 @@ + @@ -78,5 +79,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs index ffbd507880..7ad99dcc3f 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs @@ -7,13 +7,16 @@ using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.IO; +using System.Linq; using System.Runtime.CompilerServices; using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Library; +using Microsoft.UI; +using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Media; -using ShortcutGuide; +using Microsoft.UI.Xaml.Media.Animation; +using Microsoft.UI.Xaml.Shapes; using ShortcutGuide.Models; using Windows.Foundation; @@ -21,6 +24,8 @@ namespace ShortcutGuide { public sealed partial class ShortcutView : Page, INotifyPropertyChanged { + private readonly DispatcherTimer _taskbarUpdateTimer = new() { Interval = TimeSpan.FromMilliseconds(500) }; + private bool _showTaskbarShortcuts = true; private ShortcutFile shortcutList = ManifestInterpreter.GetShortcutsOfApplication(ShortcutPageParameters.CurrentPageName); public ShortcutView() @@ -41,7 +46,7 @@ namespace ShortcutGuide switch (category.SectionName) { case string name when name.StartsWith("", StringComparison.Ordinal): - // Todo: Implement GetTaskbarIconPositions + _showTaskbarShortcuts = true; break; case string name when name.StartsWith('<') && name.EndsWith('>'): break; @@ -69,6 +74,13 @@ namespace ShortcutGuide ShortcutPageParameters.PinnedShortcuts.Add(ShortcutPageParameters.CurrentPageName, []); } + if (_showTaskbarShortcuts) + { + TaskbarIndicators.Visibility = Visibility.Visible; + _taskbarUpdateTimer.Tick += UpdateTaskbarIndicators; + _taskbarUpdateTimer.Start(); + } + OpenOverview(); } catch (Exception) @@ -79,6 +91,59 @@ namespace ShortcutGuide } } + private void UpdateTaskbarIndicators(object? sender, object? e) + { + var buttons = TasklistPositions.GetButtons(); + Canvas[] canvases = [ + TaskbarIndicator1, + TaskbarIndicator2, + TaskbarIndicator3, + TaskbarIndicator4, + TaskbarIndicator5, + TaskbarIndicator6, + TaskbarIndicator7, + TaskbarIndicator8, + TaskbarIndicator9, + TaskbarIndicator10, + ]; + + for (int i = 0; i < canvases.Length; i++) + { + if (i < buttons.Length) + { + canvases[i].Visibility = Visibility.Visible; + Rect workArea = DisplayHelper.GetWorkAreaForDisplayWithWindow(MainWindow.WindowHwnd); + DoubleAnimation animation = new DoubleAnimation + { + To = (buttons[i].X - workArea.Left) / DpiHelper.GetDPIScaleForWindow(MainWindow.WindowHwnd.ToInt32()), + Duration = TimeSpan.FromMilliseconds(500), + }; + + // Create the storyboard + Storyboard storyboard = new Storyboard(); + storyboard.Children.Add(animation); + + // Set the target and property + Storyboard.SetTarget(animation, canvases[i]); + Storyboard.SetTargetProperty(animation, "(Canvas.Left)"); + + // Start the animation + storyboard.Begin(); + + canvases[i].Width = buttons[i].Width / DpiHelper.GetDPIScaleForWindow(MainWindow.WindowHwnd.ToInt32()); + canvases[i].Height = buttons[i].Height / DpiHelper.GetDPIScaleForWindow(MainWindow.WindowHwnd.ToInt32()); + ((Rectangle)canvases[i].Children[0]).Width = buttons[i].Width / DpiHelper.GetDPIScaleForWindow(MainWindow.WindowHwnd.ToInt32()); + ((Rectangle)canvases[i].Children[0]).Height = buttons[i].Height / DpiHelper.GetDPIScaleForWindow(MainWindow.WindowHwnd.ToInt32()); + ((TextBlock)canvases[i].Children[1]).Width = buttons[i].Width / DpiHelper.GetDPIScaleForWindow(MainWindow.WindowHwnd.ToInt32()); + ((TextBlock)canvases[i].Children[1]).Height = buttons[i].Height / DpiHelper.GetDPIScaleForWindow(MainWindow.WindowHwnd.ToInt32()); + } + else + { + canvases[i].Visibility = Visibility.Collapsed; + } + } + } + private void OnPropertyChanged([CallerMemberName] string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/TasklistPositions.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/TasklistPositions.cs new file mode 100644 index 0000000000..e924348802 --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/TasklistPositions.cs @@ -0,0 +1,188 @@ +// 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.Runtime.InteropServices; +using UIAutomationClient; + +namespace ShortcutGuide +{ + internal sealed partial class TasklistPositions + { + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct TasklistButton + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string Name; + + public int X; + + public int Y; + + public int Width; + + public int Height; + + public int Keynum; + } + + /* + private IUIAutomation? _automation; + private IUIAutomationElement? _element; + private IUIAutomationCondition? _trueCondition; + public void Update() + { + + // Get HWND of the tasklist + var tasklistHwnd = NativeMethods.FindWindowA("Shell_TrayWnd", null); + if (tasklistHwnd == IntPtr.Zero) + { + return; + } + + tasklistHwnd = NativeMethods.FindWindowExA(tasklistHwnd, IntPtr.Zero, "ReBarWindow32", string.Empty); + if (tasklistHwnd == IntPtr.Zero) + { + return; + } + + tasklistHwnd = NativeMethods.FindWindowExA(tasklistHwnd, IntPtr.Zero, "MSTaskSwWClass", string.Empty); + if (tasklistHwnd == IntPtr.Zero) + { + return; + } + + tasklistHwnd = NativeMethods.FindWindowExA(tasklistHwnd, IntPtr.Zero, "MSTaskListWClass", string.Empty); + if (tasklistHwnd == IntPtr.Zero) + { + return; + } + + if (_automation == null) + { + _automation = new CUIAutomation(); + _trueCondition = _automation.CreateTrueCondition(); + } + + _element = null; + _element = _automation.ElementFromHandle(tasklistHwnd); + } + + public bool UpdateButtons(List buttons) + { + if (_automation == null || _element == null) + { + return false; + } + + IUIAutomationElementArray elements = _element.FindAll(TreeScope.TreeScope_Children, _trueCondition); + if (elements == null) + { + return false; + } + + int count = elements.Length; + var foundButtons = new List(count); + + for (int i = 0; i < count; ++i) + { + var child = elements.GetElement(i); + var button = default(TasklistButton); + + object rectObj = child.GetCurrentPropertyValue(30001); + if (rectObj is double[] arr && arr.Length == 4) + { + button.X = (long)arr[0]; + button.Y = (long)arr[1]; + button.Width = (long)arr[2]; + button.Height = (long)arr[3]; + } + else if (rectObj is Windows.Foundation.Rect wrect) + { + button.X = (long)wrect.X; + button.Y = (long)wrect.Y; + button.Width = (long)wrect.Width; + button.Height = (long)wrect.Height; + } + else + { + System.Diagnostics.Debug.WriteLine($"rectObj type: {rectObj?.GetType()} value: {rectObj}"); + continue; // Don't return false, just skip + } + + object nameObj = child.GetCurrentPropertyValue(30011); + button.Name = nameObj as string ?? string.Empty; + + foundButtons.Add(button); + } + + // assign keynums + buttons.Clear(); + foreach (var button in foundButtons) + { + if (buttons.Count == 0) + { + var b = button; + b.KeyNumber = 1; + buttons.Add(b); + } + else + { + var last = buttons[^1]; + if (button.X < last.X || button.Y < last.Y) + { + break; + } + + if (button.Name == last.Name) + { + continue; + } + + var b = button; + b.KeyNumber = last.KeyNumber + 1; + buttons.Add(b); + if (b.KeyNumber == 10) + { + break; + } + } + } + + return true; + }*/ + + [DllImport("ShortcutGuide.CPPProject.dll", EntryPoint = "get_buttons")] + public static extern IntPtr GetTasklistButtons(nint monitor, out int size); + + [LibraryImport("User32.dll")] + private static partial IntPtr MonitorFromWindow(nint hwnd, int dwFlags); + + public static TasklistButton[] GetButtons() + { + var monitor = MonitorFromWindow(MainWindow.WindowHwnd, 0); + IntPtr ptr = GetTasklistButtons(monitor, out int size); + if (ptr == IntPtr.Zero) + { + return []; + } + + if (size <= 0) + { + return []; + } + + TasklistButton[] buttons = new TasklistButton[size]; + IntPtr currentPtr = ptr; + for (int i = 0; i < size; i++) + { + buttons[i] = Marshal.PtrToStructure(currentPtr); + currentPtr += Marshal.SizeOf(); + } + + return buttons; + } + } +} From 3302e61d729212212b0a5e522b994eeac6a8771b Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Sun, 15 Jun 2025 22:13:41 +0200 Subject: [PATCH 56/99] Refactoring and localisation --- src/modules/ShortcutGuide/ShortcutGuide/pch.h | 5 +- .../ShortcutGuide/tasklist_positions.cpp | 13 +- .../ShortcutGuide/tasklist_positions.h | 17 +- .../IndexYmlGenerator.cs | 1 + .../ShortcutGuide.Ui/DisplayHelper.cs | 88 -------- .../ShortcutGuide.Ui/Helpers/DisplayHelper.cs | 44 ++++ .../{ => Helpers}/DpiHelper.cs | 2 +- .../{ => Helpers}/ManifestInterpreter.cs | 20 +- .../PowerToysShortcutsPopulator.cs | 1 + .../Helpers/TasklistPositions.cs | 38 ++++ .../ShortcutGuide.Ui/Models/ShortcutEntry.cs | 6 +- .../ShortcutGuide.Ui/NativeMethods.cs | 100 +++++++--- .../ShortcutGuide.Ui/Program.cs | 1 + .../Properties/Resource.Designer.cs | 63 ++++++ .../ShortcutGuide.Ui/Properties/Resource.resx | 28 +++ .../ShortcutGuideXAML/MainWindow.xaml.cs | 6 +- .../ShortcutGuideXAML/ShortcutView.xaml.cs | 28 +-- .../ShortcutGuide.Ui/TasklistPositions.cs | 188 ------------------ 18 files changed, 296 insertions(+), 353 deletions(-) delete mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DisplayHelper.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/DisplayHelper.cs rename src/modules/ShortcutGuideV2/ShortcutGuide.Ui/{ => Helpers}/DpiHelper.cs (97%) rename src/modules/ShortcutGuideV2/ShortcutGuide.Ui/{ => Helpers}/ManifestInterpreter.cs (84%) rename src/modules/ShortcutGuideV2/ShortcutGuide.Ui/{ => Helpers}/PowerToysShortcutsPopulator.cs (99%) create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/TasklistPositions.cs delete mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/TasklistPositions.cs diff --git a/src/modules/ShortcutGuide/ShortcutGuide/pch.h b/src/modules/ShortcutGuide/ShortcutGuide/pch.h index 9bff3b54c1..0dfbbb9ec9 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide/pch.h +++ b/src/modules/ShortcutGuide/ShortcutGuide/pch.h @@ -1,9 +1,11 @@ #pragma once #define NOMINMAX +#include #include +#include +#include #include #include -#include #include #include #include @@ -24,5 +26,4 @@ #include #include #include -#include #include \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.cpp b/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.cpp index 4572f412b3..0368eecb6c 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.cpp +++ b/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.cpp @@ -1,17 +1,10 @@ #include "pch.h" #include "tasklist_positions.h" -#include -#include -#include -#include + +// Tried my hardest adapting this to C#, but FindWindowW didn't work properly in C#. ~Noraa Junker extern "C" { - winrt::com_ptr automation; - winrt::com_ptr element; - winrt::com_ptr true_condition; - - // Helper to get the taskbar HWND for the monitor under the cursor HWND GetTaskbarHwndForCursorMonitor(HMONITOR monitor) { POINT pt; @@ -124,7 +117,7 @@ extern "C" child = nullptr; if (elements->GetElement(i, child.put()) < 0) return false; - TasklistButton button; + TasklistButton button = {}; if (VARIANT var_rect; child->GetCurrentPropertyValue(UIA_BoundingRectanglePropertyId, &var_rect) >= 0) { if (var_rect.vt == (VT_R8 | VT_ARRAY)) diff --git a/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.h b/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.h index cf71ee838f..4d833ba327 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.h +++ b/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.h @@ -1,9 +1,4 @@ #pragma once -#include -#include -#include -#include -#include struct TasklistButton { @@ -14,3 +9,15 @@ struct TasklistButton int height; int keynum; }; + +extern "C" +{ + winrt::com_ptr automation; + winrt::com_ptr element; + winrt::com_ptr true_condition; + + // Helper to get the taskbar HWND for the monitor under the cursor + HWND GetTaskbarHwndForCursorMonitor(HMONITOR monitor); + __declspec(dllexport) bool update_buttons(std::vector& buttons); + __declspec(dllexport) TasklistButton* get_buttons(HMONITOR monitor, int* size); +} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.IndexYmlGenerator/ShortcutGuide.IndexYmlGenerator/IndexYmlGenerator.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.IndexYmlGenerator/ShortcutGuide.IndexYmlGenerator/IndexYmlGenerator.cs index caf9f344cc..185401729a 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.IndexYmlGenerator/ShortcutGuide.IndexYmlGenerator/IndexYmlGenerator.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.IndexYmlGenerator/ShortcutGuide.IndexYmlGenerator/IndexYmlGenerator.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.IO; +using ShortcutGuide.Helpers; using ShortcutGuide.Models; using YamlDotNet.Serialization; diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DisplayHelper.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DisplayHelper.cs deleted file mode 100644 index a41d0a9b1b..0000000000 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DisplayHelper.cs +++ /dev/null @@ -1,88 +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 System; -using System.Runtime.InteropServices; -using Windows.Foundation; -using WinUIEx; - -namespace ShortcutGuide -{ - public static partial class DisplayHelper - { - private enum MonitorFromWindowDwFlags : int - { - MONITOR_DEFAULTTONEAREST = 2, - } - - public static Rect GetWorkAreaForDisplayWithWindow(IntPtr hwnd) - { - foundMonitorIndex = -1; - monitorIndex = 0; - var monitor = MonitorFromWindow(hwnd, (int)MonitorFromWindowDwFlags.MONITOR_DEFAULTTONEAREST); - EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, MonitorEnumProc, new LPARAM(monitor)); - return MonitorInfo.GetDisplayMonitors()[foundMonitorIndex].RectWork; - } - - [StructLayout(LayoutKind.Sequential)] - private struct RECT - { - public int Left; - public int Top; - public int Right; - public int Bottom; - } - - private static int foundMonitorIndex = -1; - private static int monitorIndex; - - private static bool MonitorEnumProc(IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData) - { - IntPtr targetMonitor = dwData; - - if (hMonitor == targetMonitor) - { - foundMonitorIndex = monitorIndex; - return false; // Stop enumeration - } - - monitorIndex++; - return true; // Continue enumeration - } - - private delegate bool MonitorEnumDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData); - - [LibraryImport("User32.dll")] - private static partial IntPtr MonitorFromWindow(nint hwnd, int dwFlags); - - [LibraryImport("User32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - private static partial bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData); - - public struct LPARAM(IntPtr value) - { - public IntPtr Value = value; - - public static implicit operator IntPtr(LPARAM lParam) - { - return lParam.Value; - } - - public static implicit operator LPARAM(IntPtr value) - { - return new LPARAM(value); - } - - public static implicit operator LPARAM(int value) - { - return new LPARAM(new IntPtr(value)); - } - - public static implicit operator int(LPARAM lParam) - { - return lParam.Value.ToInt32(); - } - } - } -} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/DisplayHelper.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/DisplayHelper.cs new file mode 100644 index 0000000000..97facff029 --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/DisplayHelper.cs @@ -0,0 +1,44 @@ +// 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 Windows.Foundation; +using WinUIEx; + +namespace ShortcutGuide.Helpers +{ + public static partial class DisplayHelper + { + private enum MonitorFromWindowDwFlags : int + { + MONITOR_DEFAULTTONEAREST = 2, + } + + public static Rect GetWorkAreaForDisplayWithWindow(nint hwnd) + { + foundMonitorIndex = -1; + monitorIndex = 0; + var monitor = NativeMethods.MonitorFromWindow(hwnd, (int)MonitorFromWindowDwFlags.MONITOR_DEFAULTTONEAREST); + NativeMethods.EnumDisplayMonitors(nint.Zero, nint.Zero, MonitorEnumProc, new NativeMethods.LPARAM(monitor)); + return MonitorInfo.GetDisplayMonitors()[foundMonitorIndex].RectWork; + } + + private static int foundMonitorIndex = -1; + private static int monitorIndex; + + private static bool MonitorEnumProc(nint hMonitor, nint hdcMonitor, ref NativeMethods.RECT lprcMonitor, nint dwData) + { + nint targetMonitor = dwData; + + if (hMonitor == targetMonitor) + { + foundMonitorIndex = monitorIndex; + return false; + } + + monitorIndex++; + return true; + } + } +} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DpiHelper.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/DpiHelper.cs similarity index 97% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DpiHelper.cs rename to src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/DpiHelper.cs index 343998b68d..bfdde35051 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/DpiHelper.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/DpiHelper.cs @@ -2,7 +2,7 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace ShortcutGuide +namespace ShortcutGuide.Helpers { // This class is rewritten from C++ to C# from the measure tool project internal static partial class DpiHelper diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ManifestInterpreter.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/ManifestInterpreter.cs similarity index 84% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ManifestInterpreter.cs rename to src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/ManifestInterpreter.cs index 6dbc040056..eddcbc79fe 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ManifestInterpreter.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/ManifestInterpreter.cs @@ -13,7 +13,7 @@ using System.Text.RegularExpressions; using ShortcutGuide.Models; using YamlDotNet.Serialization; -namespace ShortcutGuide +namespace ShortcutGuide.Helpers { public class ManifestInterpreter { @@ -26,17 +26,11 @@ namespace ShortcutGuide IEnumerable files = Directory.EnumerateFiles(path, applicationName + ".*.yml") ?? throw new FileNotFoundException($"The file for the application '{applicationName}' was not found in '{path}'."); - if (files.Any(f => f.EndsWith($".{Language}.yml", StringComparison.InvariantCulture))) - { - return YamlToShortcutList(File.ReadAllText(Path.Combine(path, applicationName + $".{Language}.yml"))); - } - - if (files.Any(f => f.EndsWith(".en-US.yml", StringComparison.InvariantCulture))) - { - return YamlToShortcutList(File.ReadAllText(files.First(f => f.EndsWith(".en-US.yml", StringComparison.InvariantCulture)))); - } - - throw new FileNotFoundException($"The file for the application '{applicationName}' was not found in '{path}' with the language '{Language}' or 'en-US'."); + return files.Any(f => f.EndsWith($".{Language}.yml", StringComparison.InvariantCulture)) + ? YamlToShortcutList(File.ReadAllText(Path.Combine(path, applicationName + $".{Language}.yml"))) + : files.Any(f => f.EndsWith(".en-US.yml", StringComparison.InvariantCulture)) + ? YamlToShortcutList(File.ReadAllText(files.First(f => f.EndsWith(".en-US.yml", StringComparison.InvariantCulture)))) + : throw new FileNotFoundException($"The file for the application '{applicationName}' was not found in '{path}' with the language '{Language}' or 'en-US'."); } public static ShortcutFile YamlToShortcutList(string content) @@ -60,7 +54,7 @@ namespace ShortcutGuide public static string[] GetAllCurrentApplicationIds() { - IntPtr handle = NativeMethods.GetForegroundWindow(); + nint handle = NativeMethods.GetForegroundWindow(); List applicationIds = []; diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/PowerToysShortcutsPopulator.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs similarity index 99% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/PowerToysShortcutsPopulator.cs rename to src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs index b26ccf0034..b2b39a1dac 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/PowerToysShortcutsPopulator.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs @@ -7,6 +7,7 @@ using System.Globalization; using System.IO; using System.Text.RegularExpressions; using Microsoft.PowerToys.Settings.UI.Library; +using ShortcutGuide.Helpers; namespace ShortcutGuide { diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/TasklistPositions.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/TasklistPositions.cs new file mode 100644 index 0000000000..296933434e --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/TasklistPositions.cs @@ -0,0 +1,38 @@ +// 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.Runtime.InteropServices; +using TasklistButton = NativeMethods.TasklistButton; + +namespace ShortcutGuide.Helpers +{ + internal sealed partial class TasklistPositions + { + public static TasklistButton[] GetButtons() + { + var monitor = NativeMethods.MonitorFromWindow(MainWindow.WindowHwnd, 0); + nint ptr = NativeMethods.GetTasklistButtons(monitor, out int size); + if (ptr == nint.Zero) + { + return []; + } + + if (size <= 0) + { + return []; + } + + TasklistButton[] buttons = new TasklistButton[size]; + nint currentPtr = ptr; + for (int i = 0; i < size; i++) + { + buttons[i] = Marshal.PtrToStructure(currentPtr); + currentPtr += Marshal.SizeOf(); + } + + return buttons; + } + } +} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutEntry.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutEntry.cs index 4f14835143..3f46852107 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutEntry.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutEntry.cs @@ -2,17 +2,13 @@ // 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.CompilerServices; using System.Text.Json.Serialization; using System.Threading.Tasks; using Microsoft.PowerToys.Settings.UI.Library.Utilities; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Markup; -using ShortcutGuide; using Windows.UI.Text; using static ShortcutGuide.Models.ShortcutEntry; @@ -165,7 +161,7 @@ namespace ShortcutGuide.Models // Use monospaced font to ensure the text doesn't move FontFamily = new("Courier New"), - TextDecorations = Windows.UI.Text.TextDecorations.Underline, + TextDecorations = TextDecorations.Underline, }; shortcutStackPanel.Children.Add(animatedTextBlock); diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs index 466551d453..c263045bce 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs @@ -4,20 +4,21 @@ using System; using System.Runtime.InteropServices; -using System.Text; using Windows.Graphics; internal static partial class NativeMethods { - [LibraryImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - internal static partial bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); - - internal static readonly IntPtr HWND_TOPMOST = new System.IntPtr(-1); + internal static readonly IntPtr HWND_TOPMOST = new(-1); internal const uint SWP_NOSIZE = 0x0001; internal const uint SWP_NOMOVE = 0x0002; internal const uint SWP_NOACTIVATE = 0x0010; internal const uint SWP_SHOWWINDOW = 0x0040; + internal const int GWL_STYLE = -16; + internal const int WS_CAPTION = 0x00C00000; + + [LibraryImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); [LibraryImport("user32.dll", SetLastError = true)] internal static partial int GetWindowLongW(IntPtr hWnd, int nIndex); @@ -29,36 +30,71 @@ internal static partial class NativeMethods internal static partial IntPtr FindWindowA(in string lpClassName, in string? lpWindowName); [LibraryImport("user32.dll", StringMarshalling = StringMarshalling.Utf16)] - public static partial IntPtr FindWindowExA(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); + internal static partial IntPtr FindWindowExA(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [LibraryImport("User32.dll")] - internal static partial IntPtr MonitorFromWindow(int hwnd, int dwFlags); + internal static partial IntPtr MonitorFromWindow(IntPtr hwnd, int dwFlags); [LibraryImport("Shcore.dll")] - internal static partial long GetDpiForMonitor(int hmonitor, int dpiType, ref int dpiX, ref int dpiY); + internal static partial long GetDpiForMonitor(IntPtr hmonitor, int dpiType, ref int dpiX, ref int dpiY); [LibraryImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] - public static partial bool GetCursorPos(out POINT lpPoint); + internal static partial bool GetCursorPos(out POINT lpPoint); [LibraryImport("user32.dll")] - public static partial IntPtr GetForegroundWindow(); + internal static partial IntPtr GetForegroundWindow(); - [DllImport("user32.dll", SetLastError = true)] - public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId); + [LibraryImport("user32.dll", SetLastError = true)] + internal static partial uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId); - [DllImport("ole32.dll", SetLastError = true)] - public static extern uint CoCreateInstance( - in Guid rclsid, - IntPtr pUnkOuter, - uint dwClsContext, - in Guid riid, - out IntPtr ppv); + [LibraryImport("ShortcutGuide.CPPProject.dll", EntryPoint = "get_buttons")] + internal static partial IntPtr GetTasklistButtons(IntPtr monitor, out int size); - public struct POINT + [LibraryImport("User32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData); + + internal delegate bool MonitorEnumDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData); + + internal struct LPARAM(IntPtr value) { - public int X; - public int Y; + internal IntPtr Value = value; + + public static implicit operator IntPtr(LPARAM lParam) + { + return lParam.Value; + } + + public static implicit operator LPARAM(IntPtr value) + { + return new LPARAM(value); + } + + public static implicit operator LPARAM(int value) + { + return new LPARAM(new IntPtr(value)); + } + + public static implicit operator int(LPARAM lParam) + { + return lParam.Value.ToInt32(); + } + } + + [StructLayout(LayoutKind.Sequential)] + internal struct RECT + { + public int Left; + public int Top; + public int Right; + public int Bottom; + } + + internal struct POINT + { + internal int X; + internal int Y; public static implicit operator PointInt32(POINT point) { @@ -66,6 +102,20 @@ internal static partial class NativeMethods } } - internal const int GWL_STYLE = -16; - internal const int WS_CAPTION = 0x00C00000; + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct TasklistButton + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string Name; + + public int X; + + public int Y; + + public int Width; + + public int Height; + + public int Keynum; + } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs index 628887adf9..c381cedcdc 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs @@ -9,6 +9,7 @@ using System.Threading; using ManagedCommon; using Microsoft.UI.Dispatching; using Microsoft.Windows.AppLifecycle; +using ShortcutGuide.Helpers; namespace ShortcutGuide { diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.Designer.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.Designer.cs index 46507ec7b3..2fc8285ae7 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.Designer.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.Designer.cs @@ -60,6 +60,60 @@ namespace ShortcutGuide.Properties { } } + /// + /// Looks up a localized string similar to Error displaying the application's shortcuts. + /// + internal static string ErrorInAppParsing { + get { + return ResourceManager.GetString("ErrorInAppParsing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There has been an error displaying this category. + /// + internal static string ErrorInCategoryParsing { + get { + return ResourceManager.GetString("ErrorInCategoryParsing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No shortcuts pinned or recommended. + /// + internal static string NoShortcutsInOverview { + get { + return ResourceManager.GetString("NoShortcutsInOverview", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Overview. + /// + internal static string Overview { + get { + return ResourceManager.GetString("Overview", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pin. + /// + internal static string PinShortcut { + get { + return ResourceManager.GetString("PinShortcut", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No results found. + /// + internal static string SearchBlank { + get { + return ResourceManager.GetString("SearchBlank", resourceCulture); + } + } + /// /// Looks up a localized string similar to Shortcut Guide. /// @@ -68,5 +122,14 @@ namespace ShortcutGuide.Properties { return ResourceManager.GetString("Title", resourceCulture); } } + + /// + /// Looks up a localized string similar to Unpin. + /// + internal static string UnpinShortcut { + get { + return ResourceManager.GetString("UnpinShortcut", resourceCulture); + } + } } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.resx b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.resx index dcbe0da53c..a91a80368d 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.resx +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.resx @@ -117,7 +117,35 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Error displaying the application's shortcuts + Shortcuts refers to keyboard shortcuts; Application refers to a PC application + + + There has been an error displaying this category + + + No shortcuts pinned or recommended + Shortcuts refers to keyboard shortcuts + + + Overview + Category title + + + Pin + Refers to the action of pinning something on a pinboard + + + No results found + Results refers to search results + Shortcut Guide + Shortcut refers to a keyboard shortcut + + + Unpin + Refers to the action of unpinning something from a pinboard \ No newline at end of file diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs index a1561262a0..4c23428c73 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Globalization; using System.IO; using System.Text.Json; @@ -14,6 +13,7 @@ using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Input; +using ShortcutGuide.Helpers; using ShortcutGuide.Models; using ShortcutGuide.Properties; using Windows.Foundation; @@ -28,12 +28,12 @@ namespace ShortcutGuide /// public sealed partial class MainWindow : WindowEx { + private readonly string[] _currentApplicationIds; + public static nint WindowHwnd { get; set; } private AppWindow _appWindow; - private string[] _currentApplicationIds; - public MainWindow() { _currentApplicationIds = ManifestInterpreter.GetAllCurrentApplicationIds(); diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs index 7ad99dcc3f..2a6d486aed 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs @@ -3,21 +3,19 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.IO; -using System.Linq; using System.Runtime.CompilerServices; using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Library; -using Microsoft.UI; -using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Media.Animation; using Microsoft.UI.Xaml.Shapes; +using ShortcutGuide.Helpers; using ShortcutGuide.Models; +using ShortcutGuide.Properties; using Windows.Foundation; namespace ShortcutGuide @@ -25,7 +23,7 @@ namespace ShortcutGuide public sealed partial class ShortcutView : Page, INotifyPropertyChanged { private readonly DispatcherTimer _taskbarUpdateTimer = new() { Interval = TimeSpan.FromMilliseconds(500) }; - private bool _showTaskbarShortcuts = true; + private readonly bool _showTaskbarShortcuts; private ShortcutFile shortcutList = ManifestInterpreter.GetShortcutsOfApplication(ShortcutPageParameters.CurrentPageName); public ShortcutView() @@ -37,7 +35,11 @@ namespace ShortcutGuide try { - CategorySelector.Items.Add(new SelectorBarItem() { Text = "Overview", Name = i.ToString(CultureInfo.InvariantCulture) }); + CategorySelector.Items.Add(new SelectorBarItem() + { + Text = Resource.ResourceManager.GetString("Overview", CultureInfo.CurrentUICulture), + Name = i.ToString(CultureInfo.InvariantCulture), + }); i++; @@ -87,7 +89,7 @@ namespace ShortcutGuide { OverviewStackPanel.Visibility = Visibility.Collapsed; ErrorMessage.Visibility = Visibility.Visible; - ErrorMessage.Text = "Error displaying the applications shortcuts"; + ErrorMessage.Text = Resource.ResourceManager.GetString("ErrorInAppParsing", CultureInfo.CurrentUICulture); } } @@ -113,14 +115,14 @@ namespace ShortcutGuide { canvases[i].Visibility = Visibility.Visible; Rect workArea = DisplayHelper.GetWorkAreaForDisplayWithWindow(MainWindow.WindowHwnd); - DoubleAnimation animation = new DoubleAnimation + DoubleAnimation animation = new() { To = (buttons[i].X - workArea.Left) / DpiHelper.GetDPIScaleForWindow(MainWindow.WindowHwnd.ToInt32()), Duration = TimeSpan.FromMilliseconds(500), }; // Create the storyboard - Storyboard storyboard = new Storyboard(); + Storyboard storyboard = new(); storyboard.Children.Add(animation); // Set the target and property @@ -216,7 +218,7 @@ namespace ShortcutGuide { OverviewStackPanel.Visibility = Visibility.Collapsed; ErrorMessage.Visibility = Visibility.Visible; - ErrorMessage.Text = "No shortcuts pinned or recommended"; + ErrorMessage.Text = Resource.ResourceManager.GetString("NoShortcutsInOverview", CultureInfo.CurrentUICulture); } } @@ -275,7 +277,7 @@ namespace ShortcutGuide { ShortcutListElement.Visibility = Visibility.Collapsed; ErrorMessage.Visibility = Visibility.Visible; - ErrorMessage.Text = "No results found"; + ErrorMessage.Text = Resource.ResourceManager.GetString("SearchBlank", CultureInfo.CurrentUICulture); } } @@ -307,7 +309,7 @@ namespace ShortcutGuide catch (NullReferenceException) { ErrorMessage.Visibility = Visibility.Visible; - ErrorMessage.Text = "Error displaying category"; + ErrorMessage.Text = Resource.ResourceManager.GetString("ErrorInCategoryParsing", CultureInfo.CurrentUICulture); } FilterBy(_searchFilter); @@ -350,7 +352,7 @@ namespace ShortcutGuide bool isItemPinned = ShortcutPageParameters.PinnedShortcuts[ShortcutPageParameters.CurrentPageName].Contains(originalObject); - pinItem.Text = isItemPinned ? "Unpin" : "Pin"; + pinItem.Text = isItemPinned ? Resource.ResourceManager.GetString("UnpinShortcut", CultureInfo.CurrentUICulture) : Resource.ResourceManager.GetString("PinShortcut", CultureInfo.CurrentUICulture); pinItem.Icon = new SymbolIcon(isItemPinned ? Symbol.UnPin : Symbol.Pin); } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/TasklistPositions.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/TasklistPositions.cs deleted file mode 100644 index e924348802..0000000000 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/TasklistPositions.cs +++ /dev/null @@ -1,188 +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 System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using UIAutomationClient; - -namespace ShortcutGuide -{ - internal sealed partial class TasklistPositions - { - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - public struct TasklistButton - { - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] - public string Name; - - public int X; - - public int Y; - - public int Width; - - public int Height; - - public int Keynum; - } - - /* - private IUIAutomation? _automation; - private IUIAutomationElement? _element; - private IUIAutomationCondition? _trueCondition; - public void Update() - { - - // Get HWND of the tasklist - var tasklistHwnd = NativeMethods.FindWindowA("Shell_TrayWnd", null); - if (tasklistHwnd == IntPtr.Zero) - { - return; - } - - tasklistHwnd = NativeMethods.FindWindowExA(tasklistHwnd, IntPtr.Zero, "ReBarWindow32", string.Empty); - if (tasklistHwnd == IntPtr.Zero) - { - return; - } - - tasklistHwnd = NativeMethods.FindWindowExA(tasklistHwnd, IntPtr.Zero, "MSTaskSwWClass", string.Empty); - if (tasklistHwnd == IntPtr.Zero) - { - return; - } - - tasklistHwnd = NativeMethods.FindWindowExA(tasklistHwnd, IntPtr.Zero, "MSTaskListWClass", string.Empty); - if (tasklistHwnd == IntPtr.Zero) - { - return; - } - - if (_automation == null) - { - _automation = new CUIAutomation(); - _trueCondition = _automation.CreateTrueCondition(); - } - - _element = null; - _element = _automation.ElementFromHandle(tasklistHwnd); - } - - public bool UpdateButtons(List buttons) - { - if (_automation == null || _element == null) - { - return false; - } - - IUIAutomationElementArray elements = _element.FindAll(TreeScope.TreeScope_Children, _trueCondition); - if (elements == null) - { - return false; - } - - int count = elements.Length; - var foundButtons = new List(count); - - for (int i = 0; i < count; ++i) - { - var child = elements.GetElement(i); - var button = default(TasklistButton); - - object rectObj = child.GetCurrentPropertyValue(30001); - if (rectObj is double[] arr && arr.Length == 4) - { - button.X = (long)arr[0]; - button.Y = (long)arr[1]; - button.Width = (long)arr[2]; - button.Height = (long)arr[3]; - } - else if (rectObj is Windows.Foundation.Rect wrect) - { - button.X = (long)wrect.X; - button.Y = (long)wrect.Y; - button.Width = (long)wrect.Width; - button.Height = (long)wrect.Height; - } - else - { - System.Diagnostics.Debug.WriteLine($"rectObj type: {rectObj?.GetType()} value: {rectObj}"); - continue; // Don't return false, just skip - } - - object nameObj = child.GetCurrentPropertyValue(30011); - button.Name = nameObj as string ?? string.Empty; - - foundButtons.Add(button); - } - - // assign keynums - buttons.Clear(); - foreach (var button in foundButtons) - { - if (buttons.Count == 0) - { - var b = button; - b.KeyNumber = 1; - buttons.Add(b); - } - else - { - var last = buttons[^1]; - if (button.X < last.X || button.Y < last.Y) - { - break; - } - - if (button.Name == last.Name) - { - continue; - } - - var b = button; - b.KeyNumber = last.KeyNumber + 1; - buttons.Add(b); - if (b.KeyNumber == 10) - { - break; - } - } - } - - return true; - }*/ - - [DllImport("ShortcutGuide.CPPProject.dll", EntryPoint = "get_buttons")] - public static extern IntPtr GetTasklistButtons(nint monitor, out int size); - - [LibraryImport("User32.dll")] - private static partial IntPtr MonitorFromWindow(nint hwnd, int dwFlags); - - public static TasklistButton[] GetButtons() - { - var monitor = MonitorFromWindow(MainWindow.WindowHwnd, 0); - IntPtr ptr = GetTasklistButtons(monitor, out int size); - if (ptr == IntPtr.Zero) - { - return []; - } - - if (size <= 0) - { - return []; - } - - TasklistButton[] buttons = new TasklistButton[size]; - IntPtr currentPtr = ptr; - for (int i = 0; i < size; i++) - { - buttons[i] = Marshal.PtrToStructure(currentPtr); - currentPtr += Marshal.SizeOf(); - } - - return buttons; - } - } -} From afc27e873f1fc05d931c7467c40cad2276a72914 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Sun, 15 Jun 2025 23:20:26 +0200 Subject: [PATCH 57/99] Remove some hosts references and fix close button --- .../Assets/Hosts/AppList.scale-100.png | Bin 567 -> 0 bytes .../Assets/Hosts/AppList.scale-125.png | Bin 768 -> 0 bytes .../Assets/Hosts/AppList.scale-150.png | Bin 1001 -> 0 bytes .../Assets/Hosts/AppList.scale-200.png | Bin 1542 -> 0 bytes .../Assets/Hosts/AppList.scale-400.png | Bin 4283 -> 0 bytes .../ShortcutGuide.Ui/Assets/Hosts/Hosts.ico | Bin 178017 -> 0 bytes .../Assets/ShortcutGuide/ShortcutGuide.ico | Bin 0 -> 16958 bytes .../ShortcutGuide.Ui/Models/ShortcutEntry.cs | 20 ++++--- .../ShortcutGuide.Ui/Package.appxmanifest | 51 ------------------ .../ShortcutGuide.Ui/Program.cs | 18 ++++--- .../ShortcutGuide.Ui/ShortcutGuide.Ui.csproj | 14 ++--- .../ShortcutGuideXAML/App.xaml.cs | 5 ++ .../ShortcutGuideXAML/MainWindow.xaml.cs | 6 ++- .../ShortcutGuideXAML/ShortcutView.xaml.cs | 10 ++++ .../ShortcutGuide.Ui/app.manifest | 2 +- 15 files changed, 47 insertions(+), 79 deletions(-) delete mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-100.png delete mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-125.png delete mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-150.png delete mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-200.png delete mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-400.png delete mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/Hosts.ico create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/ShortcutGuide.ico delete mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Package.appxmanifest diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-100.png b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-100.png deleted file mode 100644 index adcd8d708a6c94e27261b5833fe2b4fec72f5d30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 567 zcmV-70?7S|P)T6ps7Uw|u7PB|fEVXhgs-n#hsi}$ZT%LvstE%eIB3^IuGfvn{GLuTFQc83DnR}l5?B1Oa zJmthp&4kRTj`k=i)hW-7ZC>-*UC)1a7pK+Ww9F*TKs>t%#*qVkzW?w`>Ww<7Aalx_ zz#@=m8(?Bll~5ZESYDlFFqq=dzQYdo_rgR>z&RiuMijlCSHQTsn;k9&gf$YEU`7I2i}qhd@UhF%@NDb%x&I z0j-H<%+60TvouL#q6x_S`aD>IOhz6N#gy&eyC=3_`?oHbQL6{-pSM}PZcQ@-VFW^g zLK;`xy5+>|xEnXF6Ux-`j8U&stJlJk2F9fg%oC37-#RW`z7R+MI%4P74mqq`ziBgu zgUbDXbR-2vBb>0kgGcH9T3ow%lPhn(Dtd?e)SGqp{?U%X;hrd(BM~A@0Q-lI#%~}0 zcw%J(qYNs{6h#Fc`Nm(7E7h~fS*k$93=~sCkle><9Rv2cd?N!^gFFBL002ovPDHLk FV1jzu2EhOT diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-125.png b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-125.png deleted file mode 100644 index 4ff1604ac8d710dc132d6bba7fa2260d45f58c7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 768 zcmV+b1ONPqP)bLVtfH3X`H)Fm!5y`eFlA6%{6AA253UnK-R?BSPy@8`You}DowH4J_ zp06=8vEcb5LsZwUj#cFdlu#&oC@f_H5N52~IAC>czgOM1kLo}lm)*Qqfxfo&tM0qP z<=Lg!cIh^U4h@0=(6eQNP#sv?AHRKl!c9BYQ8Zf2O)QWm>$a@1uUcX9>;!wR+Z(2$ zB>oqeBqWj|h=S72kjw$b0FW@t(hQ~-Pa%Uy+IXD4m6t)BhmY}DF?oc``aoc;bpw3>ydzBx*((Q;vA zCa{QTADO)~GypT&xpDs2^ImrM6*L=7s_Uw>AyHj7z^)ti#puCv?dEF+fQHfo2%sz1 zw#~8653y%VHcjU;wt#O%lQMXa!jHr=DDo^0000X1^@s6D=Y3@000B9Nkl`2Y3EbTw1$2!hfJXvh;I=0a+`YfzoEhM`wR`oo zVlN5^LTQlzAZQvJHm|$$@bKF6fGm*)GbY785-O>RR9cw`r~!rcoAHpdC!fE&4b+MN zCYF|<3X}k9KT3)g5@0YqeeCJdkQsn7rP@i*b-@G_RqV&VYy&0oDA|cGEa{c^_668wi?hdHe7?K0Fy=&}w6PWRZt1?4{*qwQ-$-#!8UnKz%@h z>Wl*?cHq;iNjjdz*@{V?K!#^v=HGHH_+v}bZg%Le`qF8(V8{WQQndX*+Km>r z9^6XxujUkiAb~}uQ9`2E?b9o|3}KhbW{czSl zPN7iGBb`oT{@WZ0qP(+$teeH^)C%@qJ|xSd^I*g;s?C+O4!#EXZbPr#lYIl@6HmUx&kZ();hKz5t(w@z$kXrGc4Rx8qKEz056huDC*hPl zaR>J!_dcNA2na(MaJUXsgEckPH9$e9*~aM8ZvrAzt*T(R**3V*bX6bfm=tl79Yn+= zqlOFP4F?^qDdn%_f%r21H%Jm1Fvd;pGlmVf;;m*P1&v-}jGN%hpmQ|%xq03XVP*mV XqGl$9@}BWF00000NkvXXu0mjfQmfq% diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-200.png b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/Hosts/AppList.scale-200.png deleted file mode 100644 index a585ff9ad6cd56a1565e5ba7ccbeceacb15c806a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1542 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 AK>z>% literal 0 HcmV?d00001 diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutEntry.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutEntry.cs index 3f46852107..66528c019d 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutEntry.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutEntry.cs @@ -62,13 +62,19 @@ namespace ShortcutGuide.Models async void AnimateTextBlock(TextBlock animatedTextBlock, string text, int delay = 500) { - int index = 0; - - while (true) + try + { + int index = 0; + + while (!ShortcutView.AnimationCancellationTokenSource.Token.IsCancellationRequested) + { + animatedTextBlock.Text = text[index].ToString(); + index = (index + 1) % text.Length; + await Task.Delay(delay); + } + } + catch { - animatedTextBlock.Text = text[index].ToString(); - index = (index + 1) % text.Length; - await Task.Delay(delay); } } @@ -254,7 +260,7 @@ namespace ShortcutGuide.Models async void AnimateStackPanels(StackPanel[] panels, int delay = 2000) { int index = 0; - while (true) + while (!ShortcutView.AnimationCancellationTokenSource.Token.IsCancellationRequested) { foreach (StackPanel panel in panels) { diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Package.appxmanifest b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Package.appxmanifest deleted file mode 100644 index 5d8b7d8069..0000000000 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Package.appxmanifest +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - ShortcutGuide.Ui - aaron - Assets\StoreLogo.png - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs index c381cedcdc..7670fc8145 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs @@ -8,6 +8,7 @@ using System.IO; using System.Threading; using ManagedCommon; using Microsoft.UI.Dispatching; +using Microsoft.UI.Xaml; using Microsoft.Windows.AppLifecycle; using ShortcutGuide.Helpers; @@ -25,6 +26,12 @@ namespace ShortcutGuide [STAThread] public static void Main() { + if (PowerToys.GPOWrapper.GPOWrapper.GetConfiguredShortcutGuideEnabledValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled) + { + Logger.LogWarning("Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator."); + return; + } + if (!Directory.Exists(ManifestInterpreter.GetPathOfIntepretations())) { Directory.CreateDirectory(ManifestInterpreter.GetPathOfIntepretations()); @@ -43,17 +50,11 @@ namespace ShortcutGuide Logger.InitializeLogger("\\ShortcutGuide\\Logs"); WinRT.ComWrappersSupport.InitializeComWrappers(); - if (PowerToys.GPOWrapper.GPOWrapper.GetConfiguredShortcutGuideEnabledValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled) - { - Logger.LogWarning("Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator."); - return; - } - var instanceKey = AppInstance.FindOrRegisterForKey("PowerToys_ShortcutGuide_Instance"); if (instanceKey.IsCurrent) { - Microsoft.UI.Xaml.Application.Start((p) => + Application.Start((p) => { var context = new DispatcherQueueSynchronizationContext(DispatcherQueue.GetForCurrentThread()); SynchronizationContext.SetSynchronizationContext(context); @@ -65,6 +66,9 @@ namespace ShortcutGuide Logger.LogWarning("Another instance of ShortcutGuide is running. Exiting ShortcutGuide"); } + // Something prevents the process from exiting, so we need to kill it manually. + Process.GetCurrentProcess().Kill(); + return; } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj index 911ac0502f..0fd7e74638 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj @@ -17,7 +17,7 @@ ..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps PowerToys.ShortcutGuide DISABLE_XAML_GENERATED_MAIN,TRACE - Assets/Hosts/Hosts.ico + Assets\ShortcutGuide\ShortcutGuide.ico PowerToys.ShortcutGuide.pri @@ -28,14 +28,10 @@ + - - - - - PreserveNewest @@ -46,7 +42,7 @@ - + @@ -72,10 +68,6 @@ - - - - PowerToys.GPOWrapper diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs index 8813aa5b35..84a79446eb 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs @@ -17,6 +17,11 @@ namespace ShortcutGuide { _window = new MainWindow(); _window.Activate(); + _window.Closed += (s, e) => + { + _window = null; + Current.Exit(); + }; } private Window? _window; diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs index 4c23428c73..fe7b930c26 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text.Json; +using System.Threading.Tasks; using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.UI; using Microsoft.UI.Windowing; @@ -79,7 +80,7 @@ namespace ShortcutGuide if (e.WindowActivationState == WindowActivationState.Deactivated) { #if !DEBUG - Environment.Exit(0); + Close(); #endif } @@ -153,7 +154,8 @@ namespace ShortcutGuide public void CloseButton_Clicked(object sender, RoutedEventArgs e) { - Environment.Exit(0); + ShortcutView.AnimationCancellationTokenSource.Cancel(); + Close(); } private void SearchBox_TextChanged(object sender, TextChangedEventArgs e) diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs index 2a6d486aed..ade3bb62b0 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs @@ -8,6 +8,7 @@ using System.Globalization; using System.IO; using System.Runtime.CompilerServices; using System.Text.Json; +using System.Threading; using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; @@ -24,11 +25,13 @@ namespace ShortcutGuide { private readonly DispatcherTimer _taskbarUpdateTimer = new() { Interval = TimeSpan.FromMilliseconds(500) }; private readonly bool _showTaskbarShortcuts; + public static readonly CancellationTokenSource AnimationCancellationTokenSource = new(); private ShortcutFile shortcutList = ManifestInterpreter.GetShortcutsOfApplication(ShortcutPageParameters.CurrentPageName); public ShortcutView() { InitializeComponent(); + AnimationCancellationTokenSource.TryReset(); DataContext = this; int i = -1; @@ -91,6 +94,13 @@ namespace ShortcutGuide ErrorMessage.Visibility = Visibility.Visible; ErrorMessage.Text = Resource.ResourceManager.GetString("ErrorInAppParsing", CultureInfo.CurrentUICulture); } + + Unloaded += (s, e) => + { + AnimationCancellationTokenSource.Cancel(); + _taskbarUpdateTimer.Tick -= UpdateTaskbarIndicators; + _taskbarUpdateTimer.Stop(); + }; } private void UpdateTaskbarIndicators(object? sender, object? e) diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/app.manifest b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/app.manifest index a5aa870b41..f3ee9d42c8 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/app.manifest +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/app.manifest @@ -1,7 +1,7 @@ - + From 48d8e333758fbddcc59765dbcb16b83c6ae40871 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Wed, 18 Jun 2025 21:05:34 +0200 Subject: [PATCH 58/99] Refactoring --- .../IndexYmlGenerator.cs | 2 +- .../Exceptions/InvalidYamlFileException.cs | 10 -- .../ShortcutGuide.Ui/Helpers/DisplayHelper.cs | 19 ++- .../ShortcutGuide.Ui/Helpers/DpiHelper.cs | 2 +- .../Helpers/ManifestInterpreter.cs | 34 ++--- .../Helpers/PowerToysShortcutsPopulator.cs | 5 +- .../Helpers/ResourceLoaderInstance.cs | 18 +++ .../Helpers/TasklistPositions.cs | 5 +- .../ShortcutGuide.Ui/Models/ShortcutEntry.cs | 123 ++++++++-------- .../ShortcutGuide.Ui/NativeMethods.cs | 10 +- .../ShortcutGuide.Ui/Program.cs | 8 +- .../Properties/Resource.Designer.cs | 135 ------------------ .../ShortcutGuide.Ui/ShortcutGuide.Ui.csproj | 13 -- .../ShortcutGuideXAML/App.xaml | 3 +- .../ShortcutGuideXAML/App.xaml.cs | 4 +- .../ShortcutGuideXAML/MainWindow.xaml | 1 - .../ShortcutGuideXAML/MainWindow.xaml.cs | 23 ++- .../ShortcutGuideXAML/ShortcutView.xaml | 10 +- .../ShortcutGuideXAML/ShortcutView.xaml.cs | 57 ++++---- .../en-us/Resources.resw} | 2 +- 20 files changed, 164 insertions(+), 320 deletions(-) delete mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Exceptions/InvalidYamlFileException.cs create mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/ResourceLoaderInstance.cs delete mode 100644 src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.Designer.cs rename src/modules/ShortcutGuideV2/ShortcutGuide.Ui/{Properties/Resource.resx => Strings/en-us/Resources.resw} (99%) diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.IndexYmlGenerator/ShortcutGuide.IndexYmlGenerator/IndexYmlGenerator.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.IndexYmlGenerator/ShortcutGuide.IndexYmlGenerator/IndexYmlGenerator.cs index 185401729a..d8a1179733 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.IndexYmlGenerator/ShortcutGuide.IndexYmlGenerator/IndexYmlGenerator.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.IndexYmlGenerator/ShortcutGuide.IndexYmlGenerator/IndexYmlGenerator.cs @@ -21,7 +21,7 @@ namespace ShortcutGuide.IndexYmlGenerator // Todo: Exception handling public static void CreateIndexYmlFile() { - string path = ManifestInterpreter.GetPathOfIntepretations(); + string path = ManifestInterpreter.GetPathOfInterpretations(); if (File.Exists(Path.Combine(path, "index.yml"))) { File.Delete(Path.Combine(path, "index.yml")); diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Exceptions/InvalidYamlFileException.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Exceptions/InvalidYamlFileException.cs deleted file mode 100644 index 01f75a5a87..0000000000 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Exceptions/InvalidYamlFileException.cs +++ /dev/null @@ -1,10 +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. - -namespace ShortcutGuide.Exceptions -{ - internal sealed class InvalidYamlFileException : System.Exception - { - } -} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/DisplayHelper.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/DisplayHelper.cs index 97facff029..cc968333cb 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/DisplayHelper.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/DisplayHelper.cs @@ -2,30 +2,29 @@ // 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 Windows.Foundation; using WinUIEx; namespace ShortcutGuide.Helpers { - public static partial class DisplayHelper + public static class DisplayHelper { - private enum MonitorFromWindowDwFlags : int + private enum MonitorFromWindowDwFlags { MONITOR_DEFAULTTONEAREST = 2, } public static Rect GetWorkAreaForDisplayWithWindow(nint hwnd) { - foundMonitorIndex = -1; - monitorIndex = 0; + _foundMonitorIndex = -1; + _monitorIndex = 0; var monitor = NativeMethods.MonitorFromWindow(hwnd, (int)MonitorFromWindowDwFlags.MONITOR_DEFAULTTONEAREST); NativeMethods.EnumDisplayMonitors(nint.Zero, nint.Zero, MonitorEnumProc, new NativeMethods.LPARAM(monitor)); - return MonitorInfo.GetDisplayMonitors()[foundMonitorIndex].RectWork; + return MonitorInfo.GetDisplayMonitors()[_foundMonitorIndex].RectWork; } - private static int foundMonitorIndex = -1; - private static int monitorIndex; + private static int _foundMonitorIndex = -1; + private static int _monitorIndex; private static bool MonitorEnumProc(nint hMonitor, nint hdcMonitor, ref NativeMethods.RECT lprcMonitor, nint dwData) { @@ -33,11 +32,11 @@ namespace ShortcutGuide.Helpers if (hMonitor == targetMonitor) { - foundMonitorIndex = monitorIndex; + _foundMonitorIndex = _monitorIndex; return false; } - monitorIndex++; + _monitorIndex++; return true; } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/DpiHelper.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/DpiHelper.cs index bfdde35051..c63f449af1 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/DpiHelper.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/DpiHelper.cs @@ -5,7 +5,7 @@ namespace ShortcutGuide.Helpers { // This class is rewritten from C++ to C# from the measure tool project - internal static partial class DpiHelper + internal static class DpiHelper { #pragma warning disable SA1310 // Field names should not contain underscore private const int DEFAULT_DPI = 96; diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/ManifestInterpreter.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/ManifestInterpreter.cs index eddcbc79fe..70497c6b07 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/ManifestInterpreter.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/ManifestInterpreter.cs @@ -22,14 +22,15 @@ namespace ShortcutGuide.Helpers public static ShortcutFile GetShortcutsOfApplication(string applicationName) { - string path = GetPathOfIntepretations(); + string path = GetPathOfInterpretations(); IEnumerable files = Directory.EnumerateFiles(path, applicationName + ".*.yml") ?? throw new FileNotFoundException($"The file for the application '{applicationName}' was not found in '{path}'."); - return files.Any(f => f.EndsWith($".{Language}.yml", StringComparison.InvariantCulture)) + IEnumerable filesEnumerable = files as string[] ?? files.ToArray(); + return filesEnumerable.Any(f => f.EndsWith($".{Language}.yml", StringComparison.InvariantCulture)) ? YamlToShortcutList(File.ReadAllText(Path.Combine(path, applicationName + $".{Language}.yml"))) - : files.Any(f => f.EndsWith(".en-US.yml", StringComparison.InvariantCulture)) - ? YamlToShortcutList(File.ReadAllText(files.First(f => f.EndsWith(".en-US.yml", StringComparison.InvariantCulture)))) + : filesEnumerable.Any(f => f.EndsWith(".en-US.yml", StringComparison.InvariantCulture)) + ? YamlToShortcutList(File.ReadAllText(filesEnumerable.First(f => f.EndsWith(".en-US.yml", StringComparison.InvariantCulture)))) : throw new FileNotFoundException($"The file for the application '{applicationName}' was not found in '{path}' with the language '{Language}' or 'en-US'."); } @@ -39,14 +40,14 @@ namespace ShortcutGuide.Helpers return deserializer.Deserialize(content); } - public static string GetPathOfIntepretations() + public static string GetPathOfInterpretations() { return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "WinGet", "KeyboardShortcuts"); } public static IndexFile GetIndexYamlFile() { - string path = GetPathOfIntepretations(); + string path = GetPathOfInterpretations(); string content = File.ReadAllText(Path.Combine(path, "index.yml")); Deserializer deserializer = new(); return deserializer.Deserialize(content); @@ -58,15 +59,7 @@ namespace ShortcutGuide.Helpers List applicationIds = []; - static bool IsMatch(string input, string filter) - { - input = input.ToLower(CultureInfo.InvariantCulture); - filter = filter.ToLower(CultureInfo.InvariantCulture); - string regexPattern = "^" + Regex.Escape(filter).Replace("\\*", ".*") + "$"; - return Regex.IsMatch(input, regexPattern); - } - - var processes = Process.GetProcesses(); + Process[] processes = Process.GetProcesses(); if (NativeMethods.GetWindowThreadProcessId(handle, out uint processId) > 0) { @@ -115,11 +108,14 @@ namespace ShortcutGuide.Helpers } return [.. applicationIds]; - } - public static ShortcutFile GetShortcutsOfDefaultShell() - { - return GetShortcutsOfApplication(GetIndexYamlFile().DefaultShellName); + static bool IsMatch(string input, string filter) + { + input = input.ToLower(CultureInfo.InvariantCulture); + filter = filter.ToLower(CultureInfo.InvariantCulture); + string regexPattern = "^" + Regex.Escape(filter).Replace("\\*", ".*") + "$"; + return Regex.IsMatch(input, regexPattern); + } } } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs index b2b39a1dac..af777f1b31 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs @@ -7,15 +7,14 @@ using System.Globalization; using System.IO; using System.Text.RegularExpressions; using Microsoft.PowerToys.Settings.UI.Library; -using ShortcutGuide.Helpers; -namespace ShortcutGuide +namespace ShortcutGuide.Helpers { internal sealed partial class PowerToysShortcutsPopulator { public static void Populate() { - string path = Path.Combine(ManifestInterpreter.GetPathOfIntepretations(), $"Microsoft.PowerToys.{ManifestInterpreter.Language}.yml"); + string path = Path.Combine(ManifestInterpreter.GetPathOfInterpretations(), $"Microsoft.PowerToys.{ManifestInterpreter.Language}.yml"); string content = File.ReadAllText(path); diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/ResourceLoaderInstance.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/ResourceLoaderInstance.cs new file mode 100644 index 0000000000..549bbb0b56 --- /dev/null +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/ResourceLoaderInstance.cs @@ -0,0 +1,18 @@ +// 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.Windows.ApplicationModel.Resources; + +namespace ShortcutGuide.Helpers +{ + internal static class ResourceLoaderInstance + { + internal static ResourceLoader ResourceLoader { get; private set; } + + static ResourceLoaderInstance() + { + ResourceLoader = new ResourceLoader("PowerToys.ShortcutGuide.pri"); + } + } +} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/TasklistPositions.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/TasklistPositions.cs index 296933434e..3056a0b28c 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/TasklistPositions.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/TasklistPositions.cs @@ -2,13 +2,12 @@ // 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.Runtime.InteropServices; -using TasklistButton = NativeMethods.TasklistButton; +using TasklistButton = ShortcutGuide.NativeMethods.TasklistButton; namespace ShortcutGuide.Helpers { - internal sealed partial class TasklistPositions + internal sealed class TasklistPositions { public static TasklistButton[] GetButtons() { diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutEntry.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutEntry.cs index 66528c019d..bd7ce34f3c 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutEntry.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutEntry.cs @@ -75,6 +75,7 @@ namespace ShortcutGuide.Models } catch { + // ignored } } @@ -86,7 +87,7 @@ namespace ShortcutGuide.Models shortcutStackPanel.Orientation = Orientation.Horizontal; // If any entry is blank, we skip the whole shortcut - if (!shortcutEntry.Ctrl && !shortcutEntry.Alt && !shortcutEntry.Shift && !shortcutEntry.Win && shortcutEntry.Keys.Length == 0) + if (shortcutEntry is { Ctrl: false, Alt: false, Shift: false, Win: false, Keys.Length: 0 }) { return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, shortcutStackPanel, shortcut); } @@ -103,21 +104,18 @@ namespace ShortcutGuide.Models shortcutStackPanel.Children.Add(shortcutIndexTextBlock); } - void AddNewTextToStackPanel(string text) - { - shortcutStackPanel.Children.Add(new TextBlock { Text = text, Margin = new Thickness(3), VerticalAlignment = VerticalAlignment.Center }); - } - if (shortcutEntry.Win) { PathIcon winIcon = (XamlReader.Load(@"") as PathIcon)!; - Viewbox winIconContainer = new(); - winIconContainer.Child = winIcon; - winIconContainer.HorizontalAlignment = HorizontalAlignment.Center; - winIconContainer.VerticalAlignment = VerticalAlignment.Center; - winIconContainer.Height = 24; - winIconContainer.Width = 24; - winIconContainer.Margin = new Thickness(3); + Viewbox winIconContainer = new() + { + Child = winIcon, + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + Height = 24, + Width = 24, + Margin = new Thickness(3), + }; shortcutStackPanel.Children.Add(winIconContainer); } @@ -136,7 +134,7 @@ namespace ShortcutGuide.Models AddNewTextToStackPanel("Shift"); } - foreach (object key in shortcutEntry.Keys) + foreach (string key in shortcutEntry.Keys) { switch (key) { @@ -208,18 +206,10 @@ namespace ShortcutGuide.Models shortcutStackPanel.Children.Add(arrowUDTextBlock); AnimateTextBlock(arrowUDTextBlock, "↑↓", 1000); break; - case string name when name.StartsWith('<') && name.EndsWith('>'): + case { } name when name.StartsWith('<') && name.EndsWith('>'): AddNewTextToStackPanel(name[1..^1]); break; - case int num: - if (num == 0) - { - break; - } - - AddNewTextToStackPanel(Helper.GetKeyName((uint)num)); - break; - case string num when int.TryParse(num, out int parsedNum): + case { } num when int.TryParse(num, out int parsedNum): if (parsedNum == 0) { break; @@ -228,55 +218,76 @@ namespace ShortcutGuide.Models AddNewTextToStackPanel(Helper.GetKeyName((uint)parsedNum)); break; default: - AddNewTextToStackPanel((string)key); + AddNewTextToStackPanel(key); break; } } + + continue; + + void AddNewTextToStackPanel(string text) + { + shortcutStackPanel.Children.Add(new TextBlock { Text = text, Margin = new Thickness(3), VerticalAlignment = VerticalAlignment.Center }); + } } StackPanel stackPanelToReturn = shortcutStackPanels[0]; - if (shortcutStackPanels.Count == 0) + switch (shortcutStackPanels.Count) { - return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, new StackPanel(), shortcut); - } - else if (shortcutStackPanels.Count > 1) - { - stackPanelToReturn = new StackPanel(); - - stackPanelToReturn.Orientation = Orientation.Vertical; - foreach (StackPanel panel in shortcutStackPanels) + case 0: + return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, new StackPanel(), shortcut); + case <= 1: + return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, stackPanelToReturn, shortcut); + default: { - panel.Visibility = Visibility.Collapsed; - stackPanelToReturn.Children.Add(panel); - } - - shortcutStackPanels[0].Visibility = Visibility.Visible; - for (int i = 1; i < shortcutStackPanels.Count; i++) - { - shortcutStackPanels[i].Visibility = Visibility.Collapsed; - } - - async void AnimateStackPanels(StackPanel[] panels, int delay = 2000) - { - int index = 0; - while (!ShortcutView.AnimationCancellationTokenSource.Token.IsCancellationRequested) { - foreach (StackPanel panel in panels) + stackPanelToReturn = new StackPanel + { + Orientation = Orientation.Vertical, + }; + + foreach (StackPanel panel in shortcutStackPanels) { panel.Visibility = Visibility.Collapsed; + stackPanelToReturn.Children.Add(panel); } - panels[index].Visibility = Visibility.Visible; - index = (index + 1) % panels.Length; - await Task.Delay(delay); + shortcutStackPanels[0].Visibility = Visibility.Visible; + for (int i = 1; i < shortcutStackPanels.Count; i++) + { + shortcutStackPanels[i].Visibility = Visibility.Collapsed; + } + + async void AnimateStackPanels(StackPanel[] panels, int delay = 2000) + { + try + { + int index = 0; + while (!ShortcutView.AnimationCancellationTokenSource.Token.IsCancellationRequested) + { + foreach (StackPanel panel in panels) + { + panel.Visibility = Visibility.Collapsed; + } + + panels[index].Visibility = Visibility.Visible; + index = (index + 1) % panels.Length; + await Task.Delay(delay); + } + } + catch + { + // ignored + } + } + + AnimateStackPanels([.. shortcutStackPanels]); } + + return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, stackPanelToReturn, shortcut); } - - AnimateStackPanels([.. shortcutStackPanels]); } - - return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, stackPanelToReturn, shortcut); } } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs index c263045bce..3ba85fc270 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs @@ -6,13 +6,10 @@ using System; using System.Runtime.InteropServices; using Windows.Graphics; +namespace ShortcutGuide; + internal static partial class NativeMethods { - internal static readonly IntPtr HWND_TOPMOST = new(-1); - internal const uint SWP_NOSIZE = 0x0001; - internal const uint SWP_NOMOVE = 0x0002; - internal const uint SWP_NOACTIVATE = 0x0010; - internal const uint SWP_SHOWWINDOW = 0x0040; internal const int GWL_STYLE = -16; internal const int WS_CAPTION = 0x00C00000; @@ -29,9 +26,6 @@ internal static partial class NativeMethods [LibraryImport("user32.dll", StringMarshalling = StringMarshalling.Utf16)] internal static partial IntPtr FindWindowA(in string lpClassName, in string? lpWindowName); - [LibraryImport("user32.dll", StringMarshalling = StringMarshalling.Utf16)] - internal static partial IntPtr FindWindowExA(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); - [LibraryImport("User32.dll")] internal static partial IntPtr MonitorFromWindow(IntPtr hwnd, int dwFlags); diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs index 7670fc8145..3010737113 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs @@ -32,16 +32,16 @@ namespace ShortcutGuide return; } - if (!Directory.Exists(ManifestInterpreter.GetPathOfIntepretations())) + if (!Directory.Exists(ManifestInterpreter.GetPathOfInterpretations())) { - Directory.CreateDirectory(ManifestInterpreter.GetPathOfIntepretations()); + Directory.CreateDirectory(ManifestInterpreter.GetPathOfInterpretations()); } // Todo: Only copy files after an update. // Todo: Handle error foreach (var file in InbuiltManifestFiles) { - File.Copy(Path.GetDirectoryName(Environment.ProcessPath) + "\\Assets\\ShortcutGuide\\" + file, ManifestInterpreter.GetPathOfIntepretations() + "\\" + file, true); + File.Copy(Path.GetDirectoryName(Environment.ProcessPath) + "\\Assets\\ShortcutGuide\\" + file, ManifestInterpreter.GetPathOfInterpretations() + "\\" + file, true); } Process.Start(Path.GetDirectoryName(Environment.ProcessPath) + "\\PowerToys.ShortcutGuide.IndexYmlGenerator.exe"); @@ -68,8 +68,6 @@ namespace ShortcutGuide // Something prevents the process from exiting, so we need to kill it manually. Process.GetCurrentProcess().Kill(); - - return; } } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.Designer.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.Designer.cs deleted file mode 100644 index 2fc8285ae7..0000000000 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.Designer.cs +++ /dev/null @@ -1,135 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace ShortcutGuide.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resource { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resource() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ShortcutGuide.Properties.Resource", typeof(Resource).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to Error displaying the application's shortcuts. - /// - internal static string ErrorInAppParsing { - get { - return ResourceManager.GetString("ErrorInAppParsing", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There has been an error displaying this category. - /// - internal static string ErrorInCategoryParsing { - get { - return ResourceManager.GetString("ErrorInCategoryParsing", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to No shortcuts pinned or recommended. - /// - internal static string NoShortcutsInOverview { - get { - return ResourceManager.GetString("NoShortcutsInOverview", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Overview. - /// - internal static string Overview { - get { - return ResourceManager.GetString("Overview", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Pin. - /// - internal static string PinShortcut { - get { - return ResourceManager.GetString("PinShortcut", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to No results found. - /// - internal static string SearchBlank { - get { - return ResourceManager.GetString("SearchBlank", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Shortcut Guide. - /// - internal static string Title { - get { - return ResourceManager.GetString("Title", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unpin. - /// - internal static string UnpinShortcut { - get { - return ResourceManager.GetString("UnpinShortcut", resourceCulture); - } - } - } -} diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj index 0fd7e74638..baaa25dd33 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj @@ -100,19 +100,6 @@ - - - True - True - Resource.resx - - - - - ResXFileCodeGenerator - Resource.Designer.cs - - MSBuild:Compile diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml index 96acc70087..ecf79cfe49 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml @@ -2,8 +2,7 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs index 84a79446eb..923d8da426 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs @@ -6,7 +6,7 @@ using Microsoft.UI.Xaml; namespace ShortcutGuide { - public partial class App : Application + public partial class App { public App() { @@ -17,7 +17,7 @@ namespace ShortcutGuide { _window = new MainWindow(); _window.Activate(); - _window.Closed += (s, e) => + _window.Closed += (_, _) => { _window = null; Current.Exit(); diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml index 4a6b398f56..a42615b474 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml @@ -4,7 +4,6 @@ x:Class="ShortcutGuide.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:local="using:ShortcutGuide" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs index fe7b930c26..cfe427260a 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs @@ -2,12 +2,10 @@ // 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.Globalization; using System.IO; using System.Text.Json; -using System.Threading.Tasks; using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.UI; using Microsoft.UI.Windowing; @@ -16,18 +14,17 @@ using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Input; using ShortcutGuide.Helpers; using ShortcutGuide.Models; -using ShortcutGuide.Properties; using Windows.Foundation; using Windows.Graphics; using WinUIEx; -using static NativeMethods; +using static ShortcutGuide.NativeMethods; namespace ShortcutGuide { /// /// An empty window that can be used on its own or navigated to within a Frame. /// - public sealed partial class MainWindow : WindowEx + public sealed partial class MainWindow { private readonly string[] _currentApplicationIds; @@ -41,7 +38,7 @@ namespace ShortcutGuide InitializeComponent(); - Title = Resource.ResourceManager.GetString("Title", CultureInfo.InvariantCulture)!; + Title = ResourceLoaderInstance.ResourceLoader.GetString("Title")!; var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this); WindowHwnd = hwnd; @@ -92,7 +89,7 @@ namespace ShortcutGuide _appWindow = AppWindow.GetFromWindowId(windowId); GetCursorPos(out POINT lpPoint); - _appWindow.Move(lpPoint with { Y = lpPoint.Y - ((int)Height / 2), X = lpPoint.X - ((int)Width / 2) }); + _appWindow.Move(new POINT { Y = lpPoint.Y - ((int)Height / 2), X = lpPoint.X - ((int)Width / 2) }); float dpiScale = DpiHelper.GetDPIScaleForWindow((int)hwnd); @@ -104,13 +101,15 @@ namespace ShortcutGuide _setPosition = true; AppWindow.Changed += (_, a) => { - if (a.DidPresenterChange) + if (!a.DidPresenterChange) { - Rect monitorRect = DisplayHelper.GetWorkAreaForDisplayWithWindow(hwnd); - float dpiScale = DpiHelper.GetDPIScaleForWindow((int)hwnd); - this.SetWindowSize(monitorRect.Width / dpiScale, monitorRect.Height / dpiScale / 2); - _appWindow.Move(new PointInt32((int)monitorRect.X, (int)(monitorRect.Y + (int)(monitorRect.Height / 2)))); + return; } + + Rect monitorRect = DisplayHelper.GetWorkAreaForDisplayWithWindow(hwnd); + float dpiScale = DpiHelper.GetDPIScaleForWindow((int)hwnd); + this.SetWindowSize(monitorRect.Width / dpiScale, monitorRect.Height / dpiScale / 2); + _appWindow.Move(new PointInt32((int)monitorRect.X, (int)(monitorRect.Y + (int)(monitorRect.Height / 2)))); }; } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml index 971809d29b..9b4d749e61 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml @@ -44,7 +44,7 @@ - + @@ -54,7 +54,7 @@ - + @@ -64,16 +64,16 @@ - + - + - + diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs index ade3bb62b0..6bb32c65ad 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs @@ -16,17 +16,16 @@ using Microsoft.UI.Xaml.Media.Animation; using Microsoft.UI.Xaml.Shapes; using ShortcutGuide.Helpers; using ShortcutGuide.Models; -using ShortcutGuide.Properties; using Windows.Foundation; namespace ShortcutGuide { - public sealed partial class ShortcutView : Page, INotifyPropertyChanged + public sealed partial class ShortcutView : INotifyPropertyChanged { private readonly DispatcherTimer _taskbarUpdateTimer = new() { Interval = TimeSpan.FromMilliseconds(500) }; private readonly bool _showTaskbarShortcuts; public static readonly CancellationTokenSource AnimationCancellationTokenSource = new(); - private ShortcutFile shortcutList = ManifestInterpreter.GetShortcutsOfApplication(ShortcutPageParameters.CurrentPageName); + private readonly ShortcutFile _shortcutList = ManifestInterpreter.GetShortcutsOfApplication(ShortcutPageParameters.CurrentPageName); public ShortcutView() { @@ -40,20 +39,20 @@ namespace ShortcutGuide { CategorySelector.Items.Add(new SelectorBarItem() { - Text = Resource.ResourceManager.GetString("Overview", CultureInfo.CurrentUICulture), + Text = ResourceLoaderInstance.ResourceLoader.GetString("Overview"), Name = i.ToString(CultureInfo.InvariantCulture), }); i++; - foreach (var category in shortcutList.Shortcuts) + foreach (var category in _shortcutList.Shortcuts) { switch (category.SectionName) { - case string name when name.StartsWith("", StringComparison.Ordinal): + case { } name when name.StartsWith("", StringComparison.Ordinal): _showTaskbarShortcuts = true; break; - case string name when name.StartsWith('<') && name.EndsWith('>'): + case { } name when name.StartsWith('<') && name.EndsWith('>'): break; default: CategorySelector.Items.Add(new SelectorBarItem() { Text = category.SectionName, Name = i.ToString(CultureInfo.InvariantCulture) }); @@ -66,7 +65,7 @@ namespace ShortcutGuide CategorySelector.SelectedItem = CategorySelector.Items[0]; CategorySelector.SelectionChanged += CategorySelector_SelectionChanged; - foreach (var shortcut in shortcutList.Shortcuts[0].Properties) + foreach (var shortcut in _shortcutList.Shortcuts[0].Properties) { ShortcutListElement.Items.Add((ShortcutTemplateDataObject)shortcut); } @@ -92,10 +91,10 @@ namespace ShortcutGuide { OverviewStackPanel.Visibility = Visibility.Collapsed; ErrorMessage.Visibility = Visibility.Visible; - ErrorMessage.Text = Resource.ResourceManager.GetString("ErrorInAppParsing", CultureInfo.CurrentUICulture); + ErrorMessage.Text = ResourceLoaderInstance.ResourceLoader.GetString("ErrorInAppParsing"); } - Unloaded += (s, e) => + Unloaded += (_, _) => { AnimationCancellationTokenSource.Cancel(); _taskbarUpdateTimer.Tick -= UpdateTaskbarIndicators; @@ -105,7 +104,7 @@ namespace ShortcutGuide private void UpdateTaskbarIndicators(object? sender, object? e) { - var buttons = TasklistPositions.GetButtons(); + NativeMethods.TasklistButton[] buttons = TasklistPositions.GetButtons(); Canvas[] canvases = [ TaskbarIndicator1, TaskbarIndicator2, @@ -171,7 +170,7 @@ namespace ShortcutGuide set { _contentHeight = value; - OnPropertyChanged(nameof(ContentHeight)); + OnPropertyChanged(); } } @@ -191,13 +190,8 @@ namespace ShortcutGuide PinnedListTitle.Visibility = Visibility.Visible; ShortcutListElement.Visibility = Visibility.Collapsed; - foreach (var list in shortcutList.Shortcuts) + foreach (var list in _shortcutList.Shortcuts) { - if (list.Properties == null) - { - continue; - } - foreach (var shortcut in list.Properties) { if (shortcut.Recommended) @@ -228,7 +222,7 @@ namespace ShortcutGuide { OverviewStackPanel.Visibility = Visibility.Collapsed; ErrorMessage.Visibility = Visibility.Visible; - ErrorMessage.Text = Resource.ResourceManager.GetString("NoShortcutsInOverview", CultureInfo.CurrentUICulture); + ErrorMessage.Text = ResourceLoaderInstance.ResourceLoader.GetString("NoShortcutsInOverview"); } } @@ -256,13 +250,8 @@ namespace ShortcutGuide OverviewStackPanel.Visibility = Visibility.Collapsed; - foreach (var list in shortcutList.Shortcuts) + foreach (var list in _shortcutList.Shortcuts) { - if (list.Properties == null) - { - continue; - } - foreach (var shortcut in list.Properties) { if (shortcut.Name.Contains(filter, StringComparison.InvariantCultureIgnoreCase)) @@ -274,7 +263,7 @@ namespace ShortcutGuide } else { - foreach (var shortcut in shortcutList.Shortcuts[int.Parse(CategorySelector.SelectedItem.Name, CultureInfo.InvariantCulture)].Properties) + foreach (var shortcut in _shortcutList.Shortcuts[int.Parse(CategorySelector.SelectedItem.Name, CultureInfo.InvariantCulture)].Properties) { if (shortcut.Name.Contains(filter, StringComparison.InvariantCultureIgnoreCase)) { @@ -283,12 +272,14 @@ namespace ShortcutGuide } } - if (ShortcutListElement.Items.Count == 0) + if (ShortcutListElement.Items.Count != 0) { - ShortcutListElement.Visibility = Visibility.Collapsed; - ErrorMessage.Visibility = Visibility.Visible; - ErrorMessage.Text = Resource.ResourceManager.GetString("SearchBlank", CultureInfo.CurrentUICulture); + return; } + + ShortcutListElement.Visibility = Visibility.Collapsed; + ErrorMessage.Visibility = Visibility.Visible; + ErrorMessage.Text = ResourceLoaderInstance.ResourceLoader.GetString("SearchBlank"); } public void CategorySelector_SelectionChanged(SelectorBar sender, SelectorBarSelectionChangedEventArgs e) @@ -311,7 +302,7 @@ namespace ShortcutGuide return; } - foreach (var shortcut in shortcutList.Shortcuts[int.Parse(sender.SelectedItem.Name, CultureInfo.InvariantCulture)].Properties) + foreach (var shortcut in _shortcutList.Shortcuts[int.Parse(sender.SelectedItem.Name, CultureInfo.InvariantCulture)].Properties) { ShortcutListElement.Items.Add((ShortcutTemplateDataObject)shortcut); } @@ -319,7 +310,7 @@ namespace ShortcutGuide catch (NullReferenceException) { ErrorMessage.Visibility = Visibility.Visible; - ErrorMessage.Text = Resource.ResourceManager.GetString("ErrorInCategoryParsing", CultureInfo.CurrentUICulture); + ErrorMessage.Text = ResourceLoaderInstance.ResourceLoader.GetString("ErrorInCategoryParsing"); } FilterBy(_searchFilter); @@ -362,7 +353,7 @@ namespace ShortcutGuide bool isItemPinned = ShortcutPageParameters.PinnedShortcuts[ShortcutPageParameters.CurrentPageName].Contains(originalObject); - pinItem.Text = isItemPinned ? Resource.ResourceManager.GetString("UnpinShortcut", CultureInfo.CurrentUICulture) : Resource.ResourceManager.GetString("PinShortcut", CultureInfo.CurrentUICulture); + pinItem.Text = isItemPinned ? ResourceLoaderInstance.ResourceLoader.GetString("UnpinShortcut") : ResourceLoaderInstance.ResourceLoader.GetString("PinShortcut"); pinItem.Icon = new SymbolIcon(isItemPinned ? Symbol.UnPin : Symbol.Pin); } } diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.resx b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Strings/en-us/Resources.resw similarity index 99% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.resx rename to src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Strings/en-us/Resources.resw index a91a80368d..de6af34d87 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Properties/Resource.resx +++ b/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Strings/en-us/Resources.resw @@ -1,4 +1,4 @@ - + - - + + WinExe @@ -9,7 +9,7 @@ enable false false - ..\..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps + ..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps PowerToys.ShortcutGuide.IndexYmlGenerator @@ -18,7 +18,7 @@ - + diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Notepad.en-US.yml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Notepad.en-US.yml similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Notepad.en-US.yml rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Notepad.en-US.yml diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Shell.en-US.yml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Shell.en-US.yml similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Shell.en-US.yml rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Shell.en-US.yml diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.WindowsExplorer.en-US.yml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.WindowsExplorer.en-US.yml similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.WindowsExplorer.en-US.yml rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.WindowsExplorer.en-US.yml diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/CopilotKey.png b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/CopilotKey.png similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/CopilotKey.png rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/CopilotKey.png diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/Microsoft.PowerToys.en-US.yml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/Microsoft.PowerToys.en-US.yml similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/Microsoft.PowerToys.en-US.yml rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/Microsoft.PowerToys.en-US.yml diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/OfficeKey.png b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/OfficeKey.png similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/OfficeKey.png rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/OfficeKey.png diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/ShortcutGuide.ico b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/ShortcutGuide.ico similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Assets/ShortcutGuide/ShortcutGuide.ico rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/ShortcutGuide.ico diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/DisplayHelper.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/DisplayHelper.cs similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/DisplayHelper.cs rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/DisplayHelper.cs diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/DpiHelper.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/DpiHelper.cs similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/DpiHelper.cs rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/DpiHelper.cs diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/ManifestInterpreter.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/ManifestInterpreter.cs similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/ManifestInterpreter.cs rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/ManifestInterpreter.cs diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/ResourceLoaderInstance.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/ResourceLoaderInstance.cs similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/ResourceLoaderInstance.cs rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/ResourceLoaderInstance.cs diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/TasklistPositions.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/TasklistPositions.cs similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Helpers/TasklistPositions.cs rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/TasklistPositions.cs diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/IndexFile.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/IndexFile.cs similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/IndexFile.cs rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/IndexFile.cs diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutCategory.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutCategory.cs similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutCategory.cs rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutCategory.cs diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutEntry.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutEntry.cs rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutFile.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutFile.cs similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutFile.cs rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutFile.cs diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/NativeMethods.cs similarity index 97% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/NativeMethods.cs index 3ba85fc270..3582708b3a 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/NativeMethods.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/NativeMethods.cs @@ -42,6 +42,9 @@ internal static partial class NativeMethods [LibraryImport("user32.dll", SetLastError = true)] internal static partial uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId); + [LibraryImport("user32.dll")] + internal static partial short GetAsyncKeyState(int vKey); + [LibraryImport("ShortcutGuide.CPPProject.dll", EntryPoint = "get_buttons")] internal static partial IntPtr GetTasklistButtons(IntPtr monitor, out int size); diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Program.cs similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Program.cs rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Program.cs diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/App.xaml.cs diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs similarity index 91% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs index cfe427260a..135977e425 100644 --- a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs @@ -16,6 +16,7 @@ using ShortcutGuide.Helpers; using ShortcutGuide.Models; using Windows.Foundation; using Windows.Graphics; +using Windows.System; using WinUIEx; using static ShortcutGuide.NativeMethods; @@ -27,6 +28,7 @@ namespace ShortcutGuide public sealed partial class MainWindow { private readonly string[] _currentApplicationIds; + /*private readonly bool _isInWindowsKeyMode;*/ public static nint WindowHwnd { get; set; } @@ -38,6 +40,21 @@ namespace ShortcutGuide InitializeComponent(); + // Todo: Reimplement holding the Windows key down to show the guide. + /* + _isInWindowsKeyMode = (GetAsyncKeyState(0x5B) & 0x8000) != 0 || (GetAsyncKeyState(0x5C) & 0x8000) != 0; + + if (_isInWindowsKeyMode) + { + Current.CoreWindow.KeyUp += (_, e) => + { + if (e.VirtualKey is (VirtualKey)0x5B or (VirtualKey)0x5C) + { + Close(); + } + }; + }*/ + Title = ResourceLoaderInstance.ResourceLoader.GetString("Title")!; var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this); diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutTemplateDataObject.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutTemplateDataObject.cs similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutTemplateDataObject.cs rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutTemplateDataObject.cs diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Strings/en-us/Resources.resw b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Strings/en-us/Resources.resw similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/Strings/en-us/Resources.resw rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/Strings/en-us/Resources.resw diff --git a/src/modules/ShortcutGuideV2/ShortcutGuide.Ui/app.manifest b/src/modules/ShortcutGuide/ShortcutGuide.Ui/app.manifest similarity index 100% rename from src/modules/ShortcutGuideV2/ShortcutGuide.Ui/app.manifest rename to src/modules/ShortcutGuide/ShortcutGuide.Ui/app.manifest diff --git a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/0.svg b/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/0.svg deleted file mode 100644 index b797f8b7ef..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/0.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/1.svg b/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/1.svg deleted file mode 100644 index 6e1e3d28f1..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/1.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/2.svg b/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/2.svg deleted file mode 100644 index 5183242c1b..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/2.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/3.svg b/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/3.svg deleted file mode 100644 index 63ad68f061..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/3.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/4.svg b/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/4.svg deleted file mode 100644 index 4f7e36f8bd..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/4.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/5.svg b/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/5.svg deleted file mode 100644 index 0fd52f6585..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/5.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/6.svg b/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/6.svg deleted file mode 100644 index 00303cdb32..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/6.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/7.svg b/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/7.svg deleted file mode 100644 index cce8aedbaa..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/7.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/8.svg b/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/8.svg deleted file mode 100644 index 57f4856b6b..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/8.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/9.svg b/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/9.svg deleted file mode 100644 index 2e0f33c493..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/9.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/no_active_window.svg b/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/no_active_window.svg deleted file mode 100644 index 69d390bd08..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/no_active_window.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/overlay.svg b/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/overlay.svg deleted file mode 100644 index fff83ab395..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/overlay.svg +++ /dev/null @@ -1,205 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/overlay_portrait.svg b/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/overlay_portrait.svg deleted file mode 100644 index 82c0314973..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/Assets/ShortcutGuide/overlay_portrait.svg +++ /dev/null @@ -1,208 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/PropertySheet.props b/src/modules/ShortcutGuide/ShortcutGuide/PropertySheet.props deleted file mode 100644 index b0c622690f..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/PropertySheet.props +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/Resources.resx b/src/modules/ShortcutGuide/ShortcutGuide/Resources.resx deleted file mode 100644 index 34942e7a52..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/Resources.resx +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Opacity of the Shortcut Guide's overlay background (%) - - - Choose Shortcut Guide overlay color - - - Light - - - Dark - - - System default app mode - - - Shows a help overlay with Windows shortcuts when the Windows key is pressed. - - - Shortcut Guide - - - No action - - - Restore - - - Snap right - - - Snap left - - - Snap upper right - - - Snap upper left - - - Snap lower right - - - Snap lower left - - - Minimize - - - Maximize - - \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/Shortcut-Guide.ico b/src/modules/ShortcutGuide/ShortcutGuide/Shortcut-Guide.ico deleted file mode 100644 index eb90c1450fc447114e49c173e5415ac40205c25d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16958 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 AK>z>% diff --git a/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.base.rc b/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.base.rc deleted file mode 100644 index 1f88309dd2..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.base.rc +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include "Generated Files/resource.h" -#include "../../../../common/version/version.h" - -#define APSTUDIO_READONLY_SYMBOLS -#include "winres.h" -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_ICON1 ICON "Shortcut-Guide.ico" - - ///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION FILE_VERSION - PRODUCTVERSION PRODUCT_VERSION - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT2_UNKNOWN -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "CompanyName", COMPANY_NAME - VALUE "FileDescription", FILE_DESCRIPTION - VALUE "FileVersion", FILE_VERSION_STRING - VALUE "InternalName", INTERNAL_NAME - VALUE "LegalCopyright", COPYRIGHT_NOTE - VALUE "OriginalFilename", ORIGINAL_FILENAME - VALUE "ProductName", PRODUCT_NAME - VALUE "ProductVersion", PRODUCT_VERSION_STRING - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj b/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj deleted file mode 100644 index 4bb709f180..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj +++ /dev/null @@ -1,187 +0,0 @@ - - - - - - - - true - true - true - true - 15.0 - {2edb3eb4-fa92-4bff-b2d8-566584837231} - Win32Proj - ShortcutGuide - - - - Application - v143 - v141 - v142 - Unicode - - - true - true - - - false - true - false - - - - - - - - - - - - - - - PowerToys.$(MSBuildProjectName) - - - ..\..\..\..\$(Platform)\$(Configuration)\ - - - - ;..\..\..\common\inc;..\..\..\common\Telemetry;..\..\..\;..\;%(AdditionalIncludeDirectories) - - - ole32.lib;Shell32.lib;OleAut32.lib;Dbghelp.lib;Dwmapi.lib;Dcomp.lib;Shlwapi.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Document - $(OutDir)\Assets\ShortcutGuide - - - Document - $(OutDir)\Assets\ShortcutGuide - - - Document - $(OutDir)\Assets\ShortcutGuide - - - Document - $(OutDir)\Assets\ShortcutGuide - - - Document - $(OutDir)\Assets\ShortcutGuide - - - Document - $(OutDir)\Assets\ShortcutGuide - - - Document - $(OutDir)\Assets\ShortcutGuide - - - Document - $(OutDir)\Assets\ShortcutGuide - - - Document - $(OutDir)\Assets\ShortcutGuide - - - Document - $(OutDir)\Assets\ShortcutGuide - - - Document - $(OutDir)\Assets\ShortcutGuide - - - Document - $(OutDir)\Assets\ShortcutGuide - - - Document - $(OutDir)\Assets\ShortcutGuide - - - - - {caba8dfb-823b-4bf2-93ac-3f31984150d9} - - - {d9b8fc84-322a-4f9f-bbb9-20915c47ddfd} - - - {6955446d-23f7-4023-9bb3-8657f904af99} - - - {8f021b46-362b-485c-bfba-ccf83e820cbd} - - - {98537082-0fdb-40de-abd8-0dc5a4269bab} - - - - - - - - - - - - - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj.filters b/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj.filters deleted file mode 100644 index af14da58f3..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj.filters +++ /dev/null @@ -1,201 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;svg;tiff;tif;png;wav;mfcribbon-ms - - - {cb917ac7-30da-494b-81f1-cbe4415e91f4} - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Resource Files - - - Generated Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - - Resource Files - - - - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - - - Resource Files - - - - - Generated Files - - - - - Resource Files - - - - - - \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuideConstants.h b/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuideConstants.h deleted file mode 100644 index 3d0e434abf..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuideConstants.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include - -namespace ShortcutGuideConstants -{ - // Name of the powertoy module. - inline const std::wstring ModuleKey = L"Shortcut Guide"; -} \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuideSettings.h b/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuideSettings.h deleted file mode 100644 index a39f2f2511..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuideSettings.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include - -struct ShortcutGuideSettings -{ - std::wstring hotkey = L"shift+win+/"; - int overlayOpacity = 90; - std::wstring theme = L"system"; - std::wstring disabledApps = L""; - bool shouldReactToPressedWinKey = false; - int windowsKeyPressTimeForGlobalWindowsShortcuts = 900; - int windowsKeyPressTimeForTaskbarIconShortcuts = 900; -}; diff --git a/src/modules/ShortcutGuide/ShortcutGuide/animation.cpp b/src/modules/ShortcutGuide/ShortcutGuide/animation.cpp deleted file mode 100644 index 4bc039a3e2..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/animation.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "pch.h" -#include "animation.h" - -Animation::Animation(double duration, double start, double stop) : - duration(duration), start_value(start), end_value(stop), start(std::chrono::high_resolution_clock::now()) {} - -void Animation::reset() -{ - start = std::chrono::high_resolution_clock::now(); -} -void Animation::reset(double animation_duration) -{ - duration = animation_duration; - reset(); -} -void Animation::reset(double animation_duration, double animation_start, double animation_stop) -{ - start_value = animation_start; - end_value = animation_stop; - reset(animation_duration); -} - -static double ease_out_expo(double t) -{ - return 1 - pow(2, -8 * t); -} - -double Animation::apply_animation_function(double t, AnimFunctions apply_function) -{ - switch (apply_function) - { - case EASE_OUT_EXPO: - return ease_out_expo(t); - case LINEAR: - default: - return t; - } -} - -double Animation::value(AnimFunctions apply_function) const -{ - auto anim_duration = std::chrono::high_resolution_clock::now() - start; - double t = std::chrono::duration(anim_duration).count() / duration; - if (t >= 1) - return end_value; - return start_value + (end_value - start_value) * apply_animation_function(t, apply_function); -} -bool Animation::done() const -{ - return std::chrono::high_resolution_clock::now() - start >= std::chrono::duration(duration); -} diff --git a/src/modules/ShortcutGuide/ShortcutGuide/animation.h b/src/modules/ShortcutGuide/ShortcutGuide/animation.h deleted file mode 100644 index 61ae59b661..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/animation.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include - -/* - Usage: - When creating animation constructor takes one parameter - how long - should the animation take in seconds. - - Call reset() when starting animation. - - When rendering, call value() to get value from 0 to 1 - depending on animation - progress. -*/ -class Animation -{ -public: - enum AnimFunctions - { - LINEAR = 0, - EASE_OUT_EXPO - }; - - Animation(double duration = 1, double start = 0, double stop = 1); - void reset(); - void reset(double animation_duration); - void reset(double animation_duration, double animation_start, double animation_stop); - double value(AnimFunctions apply_function) const; - bool done() const; - -private: - static double apply_animation_function(double t, AnimFunctions apply_function); - std::chrono::high_resolution_clock::time_point start; - double start_value, end_value, duration; -}; diff --git a/src/modules/ShortcutGuide/ShortcutGuide/d2d_svg.cpp b/src/modules/ShortcutGuide/ShortcutGuide/d2d_svg.cpp deleted file mode 100644 index 0f01aaf403..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/d2d_svg.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include "pch.h" -#include "d2d_svg.h" - -D2DSVG& D2DSVG::load(const std::wstring& filename, ID2D1DeviceContext5* d2d_dc) -{ - svg = nullptr; - winrt::com_ptr svg_stream; - auto h = SHCreateStreamOnFileEx(filename.c_str(), - STGM_READ, - FILE_ATTRIBUTE_NORMAL, - FALSE, - nullptr, - svg_stream.put()); - winrt::check_hresult(h); - - auto h1 = d2d_dc->CreateSvgDocument( - svg_stream.get(), - D2D1::SizeF(1, 1), - svg.put()); - - winrt::check_hresult(h1); - - winrt::com_ptr root; - svg->GetRoot(root.put()); - float tmp; - winrt::check_hresult(root->GetAttributeValue(L"width", &tmp)); - svg_width = static_cast(tmp); - winrt::check_hresult(root->GetAttributeValue(L"height", &tmp)); - svg_height = static_cast(tmp); - return *this; -} - -D2DSVG& D2DSVG::resize(int x, int y, int width, int height, float fill, float max_scale) -{ - // Center - transform = D2D1::Matrix3x2F::Identity(); - transform = transform * D2D1::Matrix3x2F::Translation((width - svg_width) / 2.0f, (height - svg_height) / 2.0f); - float h_scale = fill * height / svg_height; - float v_scale = fill * width / svg_width; - used_scale = std::min(h_scale, v_scale); - if (max_scale > 0) - { - used_scale = std::min(used_scale, max_scale); - } - transform = transform * D2D1::Matrix3x2F::Scale(used_scale, used_scale, D2D1::Point2F(width / 2.0f, height / 2.0f)); - transform = transform * D2D1::Matrix3x2F::Translation(static_cast(x), static_cast(y)); - return *this; -} - -D2DSVG& D2DSVG::recolor(uint32_t oldcolor, uint32_t newcolor) -{ - auto new_color = D2D1::ColorF(newcolor & 0xFFFFFF, 1); - auto old_color = D2D1::ColorF(oldcolor & 0xFFFFFF, 1); - std::function recurse = [&](ID2D1SvgElement* element) { - if (!element) - return; - if (element->IsAttributeSpecified(L"fill")) - { - D2D1_COLOR_F elem_fill; - winrt::com_ptr paint; - element->GetAttributeValue(L"fill", paint.put()); - paint->GetColor(&elem_fill); - if (elem_fill.r == old_color.r && elem_fill.g == old_color.g && elem_fill.b == old_color.b) - { - winrt::check_hresult(element->SetAttributeValue(L"fill", new_color)); - } - } - winrt::com_ptr sub; - element->GetFirstChild(sub.put()); - while (sub) - { - recurse(sub.get()); - winrt::com_ptr next; - element->GetNextChild(sub.get(), next.put()); - sub = next; - } - }; - winrt::com_ptr root; - svg->GetRoot(root.put()); - recurse(root.get()); - return *this; -} - -D2DSVG& D2DSVG::render(ID2D1DeviceContext5* d2d_dc) -{ - D2D1_MATRIX_3X2_F current; - d2d_dc->GetTransform(¤t); - d2d_dc->SetTransform(transform * current); - d2d_dc->DrawSvgDocument(svg.get()); - d2d_dc->SetTransform(current); - return *this; -} - -D2DSVG& D2DSVG::toggle_element(const wchar_t* id, bool visible) -{ - winrt::com_ptr element; - if (svg->FindElementById(id, element.put()) != S_OK) - return *this; - if (!element) - return *this; - element->SetAttributeValue(L"display", visible ? D2D1_SVG_DISPLAY::D2D1_SVG_DISPLAY_INLINE : D2D1_SVG_DISPLAY::D2D1_SVG_DISPLAY_NONE); - return *this; -} - -winrt::com_ptr D2DSVG::find_element(const std::wstring& id) -{ - winrt::com_ptr element; - winrt::check_hresult(svg->FindElementById(id.c_str(), element.put())); - return element; -} - -D2D1_RECT_F D2DSVG::rescale(D2D1_RECT_F rect) -{ - D2D1_RECT_F result; - auto src = reinterpret_cast(&rect); - auto dst = reinterpret_cast(&result); - dst[0] = src[0] * transform; - dst[1] = src[1] * transform; - return result; -} diff --git a/src/modules/ShortcutGuide/ShortcutGuide/d2d_svg.h b/src/modules/ShortcutGuide/ShortcutGuide/d2d_svg.h deleted file mode 100644 index 08869b2de1..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/d2d_svg.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include -#include -#include -#include - -class D2DSVG -{ -public: - D2DSVG& load(const std::wstring& filename, ID2D1DeviceContext5* d2d_dc); - D2DSVG& resize(int x, int y, int width, int height, float fill, float max_scale = -1.0f); - D2DSVG& render(ID2D1DeviceContext5* d2d_dc); - D2DSVG& recolor(uint32_t oldcolor, uint32_t newcolor); - float get_scale() const { return used_scale; } - int width() const { return svg_width; } - int height() const { return svg_height; } - D2DSVG& toggle_element(const wchar_t* id, bool visible); - winrt::com_ptr find_element(const std::wstring& id); - D2D1_RECT_F rescale(D2D1_RECT_F rect); - -protected: - float used_scale = 1.0f; - winrt::com_ptr svg; - int svg_width = -1, svg_height = -1; - D2D1::Matrix3x2F transform; -}; diff --git a/src/modules/ShortcutGuide/ShortcutGuide/d2d_text.cpp b/src/modules/ShortcutGuide/ShortcutGuide/d2d_text.cpp deleted file mode 100644 index 7f25c4e32c..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/d2d_text.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "pch.h" -#include "d2d_text.h" - -D2DText::D2DText(float text_size, float scale) -{ - winrt::check_hresult(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(factory), reinterpret_cast(factory.put_void()))); - resize(text_size, scale); - winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER)); - winrt::check_hresult(format->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER)); -} - -D2DText& D2DText::resize(float text_size, float scale) -{ - format = nullptr; - winrt::check_hresult(factory->CreateTextFormat(L"Segoe UI", - nullptr, - DWRITE_FONT_WEIGHT_NORMAL, - DWRITE_FONT_STYLE_NORMAL, - DWRITE_FONT_STRETCH_NORMAL, - text_size * scale, - L"en-us", - format.put())); - winrt::check_hresult(format->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER)); - return *this; -} - -D2DText& D2DText::set_alignment_left() -{ - winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING)); - return *this; -} - -D2DText& D2DText::set_alignment_center() -{ - winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER)); - return *this; -} - -D2DText& D2DText::set_alignment_right() -{ - winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_TRAILING)); - return *this; -} - -void D2DText::write(ID2D1DeviceContext5* d2d_dc, D2D1_COLOR_F color, D2D1_RECT_F rect, std::wstring text) -{ - winrt::com_ptr brush; - d2d_dc->CreateSolidColorBrush(color, brush.put()); - d2d_dc->DrawText(text.c_str(), - static_cast(text.length()), - format.get(), - rect, - brush.get()); -} diff --git a/src/modules/ShortcutGuide/ShortcutGuide/d2d_text.h b/src/modules/ShortcutGuide/ShortcutGuide/d2d_text.h deleted file mode 100644 index 513dc120e5..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/d2d_text.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include -#include - -class D2DText -{ -public: - D2DText(float text_size = 15.0f, float scale = 1.0f); - D2DText& resize(float text_size, float scale); - D2DText& set_alignment_left(); - D2DText& set_alignment_center(); - D2DText& set_alignment_right(); - void write(ID2D1DeviceContext5* d2d_dc, D2D1_COLOR_F color, D2D1_RECT_F rect, std::wstring text); - -private: - winrt::com_ptr factory; - winrt::com_ptr format; -}; diff --git a/src/modules/ShortcutGuide/ShortcutGuide/d2d_window.cpp b/src/modules/ShortcutGuide/ShortcutGuide/d2d_window.cpp deleted file mode 100644 index f4bf7e9cf6..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/d2d_window.cpp +++ /dev/null @@ -1,211 +0,0 @@ -#include "pch.h" -#include "d2d_window.h" - -#include - -D2DWindow::D2DWindow() -{ - static const WCHAR* class_name = L"PToyD2DPopup"; - WNDCLASS wc = {}; - wc.hCursor = LoadCursor(nullptr, IDC_ARROW); - wc.hInstance = reinterpret_cast(&__ImageBase); - wc.lpszClassName = class_name; - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = d2d_window_proc; - RegisterClass(&wc); - hwnd = CreateWindowExW(WS_EX_TOOLWINDOW | WS_EX_TOPMOST | WS_EX_NOREDIRECTIONBITMAP | WS_EX_LAYERED, - wc.lpszClassName, - L"PToyD2DPopup", - WS_POPUP | WS_VISIBLE, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - nullptr, - nullptr, - wc.hInstance, - this); - WINRT_VERIFY(hwnd); -} - -void D2DWindow::show(UINT x, UINT y, UINT width, UINT height) -{ - if (!initialized) - { - base_init(); - } - base_resize(width, height); - render_empty(); - hidden = false; - on_show(); - SetWindowPos(hwnd, HWND_TOPMOST, x, y, width, height, 0); - ShowWindow(hwnd, SW_SHOWNORMAL); - SetForegroundWindow(hwnd); - UpdateWindow(hwnd); -} - -void D2DWindow::hide() -{ - hidden = true; - ShowWindow(hwnd, SW_HIDE); - on_hide(); -} - -void D2DWindow::initialize() -{ - base_init(); -} - -void D2DWindow::base_init() -{ - std::unique_lock lock(mutex); - // D2D1Factory is independent from the device, no need to recreate it if we need to recreate the device. - if (!d2d_factory) - { -#ifdef _DEBUG - D2D1_FACTORY_OPTIONS options = { D2D1_DEBUG_LEVEL_INFORMATION }; -#else - D2D1_FACTORY_OPTIONS options = {}; -#endif - winrt::check_hresult(D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, - __uuidof(d2d_factory), - &options, - d2d_factory.put_void())); - } - // For all other stuff - assign nullptr first to release the object, to reset the com_ptr. - d2d_dc = nullptr; - d2d_device = nullptr; - dxgi_factory = nullptr; - dxgi_device = nullptr; - d3d_device = nullptr; - winrt::check_hresult(D3D11CreateDevice(nullptr, - D3D_DRIVER_TYPE_HARDWARE, - nullptr, - D3D11_CREATE_DEVICE_BGRA_SUPPORT, - nullptr, - 0, - D3D11_SDK_VERSION, - d3d_device.put(), - nullptr, - nullptr)); - winrt::check_hresult(d3d_device->QueryInterface(__uuidof(dxgi_device), dxgi_device.put_void())); - winrt::check_hresult(CreateDXGIFactory2(0, __uuidof(dxgi_factory), dxgi_factory.put_void())); - winrt::check_hresult(d2d_factory->CreateDevice(dxgi_device.get(), d2d_device.put())); - winrt::check_hresult(d2d_device->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, d2d_dc.put())); - init(); - initialized = true; -} - -void D2DWindow::base_resize(UINT width, UINT height) -{ - std::unique_lock lock(mutex); - if (!initialized) - { - return; - } - window_width = width; - window_height = height; - if (window_width == 0 || window_height == 0) - { - return; - } - DXGI_SWAP_CHAIN_DESC1 sc_description = {}; - sc_description.Format = DXGI_FORMAT_B8G8R8A8_UNORM; - sc_description.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - sc_description.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; - sc_description.BufferCount = 2; - sc_description.SampleDesc.Count = 1; - sc_description.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED; - sc_description.Width = window_width; - sc_description.Height = window_height; - dxgi_swap_chain = nullptr; - winrt::check_hresult(dxgi_factory->CreateSwapChainForComposition(dxgi_device.get(), - &sc_description, - nullptr, - dxgi_swap_chain.put())); - composition_device = nullptr; - winrt::check_hresult(DCompositionCreateDevice(dxgi_device.get(), - __uuidof(composition_device), - composition_device.put_void())); - - composition_target = nullptr; - winrt::check_hresult(composition_device->CreateTargetForHwnd(hwnd, true, composition_target.put())); - - composition_visual = nullptr; - winrt::check_hresult(composition_device->CreateVisual(composition_visual.put())); - winrt::check_hresult(composition_visual->SetContent(dxgi_swap_chain.get())); - winrt::check_hresult(composition_target->SetRoot(composition_visual.get())); - - dxgi_surface = nullptr; - winrt::check_hresult(dxgi_swap_chain->GetBuffer(0, __uuidof(dxgi_surface), dxgi_surface.put_void())); - D2D1_BITMAP_PROPERTIES1 properties = {}; - properties.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; - properties.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM; - properties.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW; - - d2d_bitmap = nullptr; - winrt::check_hresult(d2d_dc->CreateBitmapFromDxgiSurface(dxgi_surface.get(), - properties, - d2d_bitmap.put())); - d2d_dc->SetTarget(d2d_bitmap.get()); - resize(); -} - -void D2DWindow::base_render() -{ - std::unique_lock lock(mutex); - if (!initialized || !d2d_dc || !d2d_bitmap) - return; - d2d_dc->BeginDraw(); - render(d2d_dc.get()); - winrt::check_hresult(d2d_dc->EndDraw()); - winrt::check_hresult(dxgi_swap_chain->Present(1, 0)); - winrt::check_hresult(composition_device->Commit()); -} - -void D2DWindow::render_empty() -{ - std::unique_lock lock(mutex); - if (!initialized || !d2d_dc || !d2d_bitmap) - return; - d2d_dc->BeginDraw(); - d2d_dc->Clear(); - winrt::check_hresult(d2d_dc->EndDraw()); - winrt::check_hresult(dxgi_swap_chain->Present(1, 0)); - winrt::check_hresult(composition_device->Commit()); -} - -D2DWindow::~D2DWindow() -{ - ShowWindow(hwnd, SW_HIDE); - DestroyWindow(hwnd); -} - -D2DWindow* D2DWindow::this_from_hwnd(HWND window) -{ - return reinterpret_cast(GetWindowLongPtr(window, GWLP_USERDATA)); -} - -LRESULT __stdcall D2DWindow::d2d_window_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) -{ - auto self = this_from_hwnd(window); - switch (message) - { - case WM_NCCREATE: - { - auto create_struct = reinterpret_cast(lparam); - SetWindowLongPtr(window, GWLP_USERDATA, reinterpret_cast(create_struct->lpCreateParams)); - return TRUE; - } - case WM_MOVE: - case WM_SIZE: - self->base_resize(static_cast(lparam) & 0xFFFF, static_cast(lparam) >> 16); - [[fallthrough]]; - case WM_PAINT: - self->base_render(); - return 0; - - default: - return DefWindowProc(window, message, wparam, lparam); - } -} diff --git a/src/modules/ShortcutGuide/ShortcutGuide/d2d_window.h b/src/modules/ShortcutGuide/ShortcutGuide/d2d_window.h deleted file mode 100644 index b062962d28..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/d2d_window.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "d2d_svg.h" - -#include -#include - -class D2DWindow -{ -public: - D2DWindow(); - void show(UINT x, UINT y, UINT width, UINT height); - void hide(); - void initialize(); - virtual ~D2DWindow(); - -protected: - // Implement this: - - // Initialization - called when D2D device needs to be created. - // When called all D2DWindow members will be initialized, including d2d_dc - virtual void init() = 0; - // resize - when called, window_width and window_height will have current window size - virtual void resize() = 0; - // render - called on WM_PAINT, BeginPaint/EndPaint is handled by D2DWindow - virtual void render(ID2D1DeviceContext5* d2d_dc) = 0; - // on_show, on_hide - called when the window is about to be shown or about to be hidden - virtual void on_show() = 0; - virtual void on_hide() = 0; - - static LRESULT __stdcall d2d_window_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam); - static D2DWindow* this_from_hwnd(HWND window); - - void base_init(); - void base_resize(UINT width, UINT height); - void base_render(); - void render_empty(); - - std::recursive_mutex mutex; - bool hidden = true; - bool initialized = false; - HWND hwnd; - UINT window_width{}; - UINT window_height{}; - winrt::com_ptr d3d_device; - winrt::com_ptr dxgi_device; - winrt::com_ptr dxgi_factory; - winrt::com_ptr dxgi_swap_chain; - winrt::com_ptr composition_device; - winrt::com_ptr composition_target; - winrt::com_ptr composition_visual; - winrt::com_ptr dxgi_surface; - winrt::com_ptr d2d_bitmap; - winrt::com_ptr d2d_factory; - winrt::com_ptr d2d_device; - winrt::com_ptr d2d_dc; -}; diff --git a/src/modules/ShortcutGuide/ShortcutGuide/main.cpp b/src/modules/ShortcutGuide/ShortcutGuide/main.cpp deleted file mode 100644 index 713446403b..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/main.cpp +++ /dev/null @@ -1,144 +0,0 @@ -#include "pch.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "shortcut_guide.h" -#include "target_state.h" -#include "ShortcutGuideConstants.h" -#include "trace.h" - -const std::wstring instanceMutexName = L"Local\\PowerToys_ShortcutGuide_InstanceMutex"; - -// set current path to the executable path -bool SetCurrentPath() -{ - TCHAR buffer[MAX_PATH] = { 0 }; - if (!GetModuleFileName(NULL, buffer, MAX_PATH)) - { - Logger::error(L"Failed to get module path. {}", get_last_error_or_default(GetLastError())); - return false; - } - - if (!PathRemoveFileSpec(buffer)) - { - Logger::error(L"Failed to remove file from module path. {}", get_last_error_or_default(GetLastError())); - return false; - } - - std::error_code err; - std::filesystem::current_path(buffer, err); - if (err.value()) - { - Logger::error("Failed to set current path. {}", err.message()); - return false; - } - - return true; -} - -int WINAPI wWinMain(_In_ HINSTANCE /*hInstance*/, _In_opt_ HINSTANCE /*hPrevInstance*/, _In_ PWSTR lpCmdLine, _In_ int /*nCmdShow*/) -{ - winrt::init_apartment(); - LoggerHelpers::init_logger(ShortcutGuideConstants::ModuleKey, L"ShortcutGuide", LogSettings::shortcutGuideLoggerName); - - Shared::Trace::ETWTrace trace; - trace.UpdateState(true); - - if (powertoys_gpo::getConfiguredShortcutGuideEnabledValue() == powertoys_gpo::gpo_rule_configured_disabled) - { - Logger::warn(L"Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator."); - return 0; - } - - InitUnhandledExceptionHandler(); - Logger::trace("Starting Shortcut Guide"); - - if (!SetCurrentPath()) - { - return false; - } - - Trace::RegisterProvider(); - if (std::wstring(lpCmdLine).find(L' ') != std::wstring::npos) - { - Logger::trace("Sending settings telemetry"); - auto settings = OverlayWindow::GetSettings(); - Trace::SendSettings(settings); - Trace::UnregisterProvider(); - return 0; - } - - auto mutex = CreateMutex(nullptr, true, instanceMutexName.c_str()); - if (mutex == nullptr) - { - Logger::error(L"Failed to create mutex. {}", get_last_error_or_default(GetLastError())); - } - - if (GetLastError() == ERROR_ALREADY_EXISTS) - { - Logger::warn(L"Shortcut Guide instance is already running"); - Trace::UnregisterProvider(); - return 0; - } - - std::wstring pid = std::wstring(lpCmdLine); - if (!pid.empty()) - { - auto mainThreadId = GetCurrentThreadId(); - ProcessWaiter::OnProcessTerminate(pid, [mainThreadId](int err) { - if (err != ERROR_SUCCESS) - { - Logger::error(L"Failed to wait for parent process exit. {}", get_last_error_or_default(err)); - } - else - { - Logger::trace(L"PowerToys runner exited."); - } - - Logger::trace(L"Exiting Shortcut Guide"); - PostThreadMessage(mainThreadId, WM_QUIT, 0, 0); - }); - } - - auto hwnd = GetForegroundWindow(); - auto window = OverlayWindow(hwnd); - EventWaiter exitEventWaiter; - if (window.IsDisabled()) - { - Logger::trace("SG is disabled for the current foreground app. Exiting SG"); - Trace::UnregisterProvider(); - return 0; - } - else - { - auto mainThreadId = GetCurrentThreadId(); - exitEventWaiter = EventWaiter(CommonSharedConstants::SHORTCUT_GUIDE_EXIT_EVENT, [mainThreadId, &window](int err) { - if (err != ERROR_SUCCESS) - { - Logger::error(L"Failed to wait for {} event. {}", CommonSharedConstants::SHORTCUT_GUIDE_EXIT_EVENT, get_last_error_or_default(err)); - } - else - { - Logger::trace(L"{} event was signaled", CommonSharedConstants::SHORTCUT_GUIDE_EXIT_EVENT); - } - - window.CloseWindow(HideWindowType::THE_SHORTCUT_PRESSED, mainThreadId); - }); - } - - window.ShowWindow(); - run_message_loop(); - - trace.Flush(); - Trace::UnregisterProvider(); - return 0; -} diff --git a/src/modules/ShortcutGuide/ShortcutGuide/native_event_waiter.cpp b/src/modules/ShortcutGuide/ShortcutGuide/native_event_waiter.cpp deleted file mode 100644 index b038ea4ffd..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/native_event_waiter.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "pch.h" -#include "native_event_waiter.h" - -void NativeEventWaiter::run() -{ - while (!aborting) - { - auto result = WaitForSingleObject(event_handle, timeout); - if (!aborting && result == WAIT_OBJECT_0) - { - action(); - } - } -} - -NativeEventWaiter::NativeEventWaiter(const std::wstring& event_name, std::function action) -{ - event_handle = CreateEventW(NULL, FALSE, FALSE, event_name.c_str()); - this->action = action; - running_thread = std::thread([&]() { run(); }); -} - -NativeEventWaiter::~NativeEventWaiter() -{ - aborting = true; - SetEvent(event_handle); - running_thread.join(); - CloseHandle(event_handle); -} diff --git a/src/modules/ShortcutGuide/ShortcutGuide/native_event_waiter.h b/src/modules/ShortcutGuide/ShortcutGuide/native_event_waiter.h deleted file mode 100644 index d7dcaa603e..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/native_event_waiter.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "pch.h" -#include "common/interop/shared_constants.h" - -class NativeEventWaiter -{ - static const int timeout = 1000; - - HANDLE event_handle = nullptr; - std::function action = nullptr; - std::atomic aborting = false; - - void run(); - std::thread running_thread; - -public: - NativeEventWaiter(const std::wstring& event_name, std::function action); - ~NativeEventWaiter(); -}; diff --git a/src/modules/ShortcutGuide/ShortcutGuide/overlay_window.h b/src/modules/ShortcutGuide/ShortcutGuide/overlay_window.h deleted file mode 100644 index 00f05db565..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/overlay_window.h +++ /dev/null @@ -1,114 +0,0 @@ -#pragma once -#include "animation.h" -#include "d2d_svg.h" -#include "d2d_window.h" -#include "d2d_text.h" - -#include -#include -#include "tasklist_positions.h" - -struct ScaleResult -{ - double scale; - RECT rect; -}; - -class D2DOverlaySVG : public D2DSVG -{ -public: - D2DOverlaySVG& load(const std::wstring& filename, ID2D1DeviceContext5* d2d_dc); - D2DOverlaySVG& resize(int x, int y, int width, int height, float fill, float max_scale = -1.0f); - D2DOverlaySVG& find_thumbnail(const std::wstring& id); - D2DOverlaySVG& find_window_group(const std::wstring& id); - ScaleResult get_thumbnail_rect_and_scale(int x_offset, int y_offset, int window_cx, int window_cy, float fill); - D2DOverlaySVG& toggle_window_group(bool active); - winrt::com_ptr find_element(const std::wstring& id); - D2D1_RECT_F get_maximize_label() const; - D2D1_RECT_F get_minimize_label() const; - D2D1_RECT_F get_snap_left() const; - D2D1_RECT_F get_snap_right() const; - -private: - D2D1_POINT_2F thumbnail_top_left = {}; - D2D1_POINT_2F thumbnail_bottom_right = {}; - RECT thumbnail_scaled_rect = {}; - winrt::com_ptr window_group; -}; - -struct AnimateKeys -{ - Animation animation; - D2D1_COLOR_F original; - winrt::com_ptr button; - int vk_code; -}; - -class D2DOverlayWindow : public D2DWindow -{ -public: - D2DOverlayWindow(); - void show(HWND window, bool snappable); - ~D2DOverlayWindow(); - void apply_overlay_opacity(float opacity); - void apply_press_time_for_global_windows_shortcuts(int press_time); - void apply_press_time_for_taskbar_icon_shortcuts(int press_time); - void set_theme(const std::wstring& theme); - void quick_hide(); - - HWND get_window_handle(); - void SetWindowCloseType(std::wstring wCloseType) - { - windowCloseType = wCloseType; - } - -private: - std::wstring windowCloseType; - bool show_thumbnail(const RECT& rect, double alpha); - void hide_thumbnail(); - virtual void init() override; - virtual void resize() override; - virtual void render(ID2D1DeviceContext5* d2dd2d_device_context_dc) override; - virtual void on_show() override; - virtual void on_hide() override; - float get_overlay_opacity(); - - bool running = true; - std::vector key_animations; - std::vector monitors; - Box total_screen; - int monitor_dx = 0, monitor_dy = 0; - D2DText text; - WindowsColors colors; - Animation background_animation; - Animation global_windows_shortcuts_animation; - Animation taskbar_icon_shortcuts_animation; - bool global_windows_shortcuts_shown = false; - bool taskbar_icon_shortcuts_shown = false; - RECT window_rect = {}; - Tasklist tasklist; - std::vector tasklist_buttons; - std::thread tasklist_thread; - bool tasklist_update = false; - std::mutex tasklist_cv_mutex; - std::condition_variable tasklist_cv; - - HTHUMBNAIL thumbnail = nullptr; - HWND active_window = nullptr; - bool active_window_snappable = false; - D2DOverlaySVG landscape, portrait; - D2DOverlaySVG* use_overlay = nullptr; - D2DSVG no_active; - std::vector arrows; - std::chrono::steady_clock::time_point shown_start_time; - float overlay_opacity = 0.9f; - enum - { - Light, - Dark, - System - } theme_setting = System; - bool light_mode = true; - UINT milliseconds_press_time_for_global_windows_shortcuts = 900; - UINT milliseconds_press_time_for_taskbar_icon_shortcuts = 900; -}; diff --git a/src/modules/ShortcutGuide/ShortcutGuide/packages.config b/src/modules/ShortcutGuide/ShortcutGuide/packages.config deleted file mode 100644 index 09bfc449e2..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/pch.cpp b/src/modules/ShortcutGuide/ShortcutGuide/pch.cpp deleted file mode 100644 index 1d9f38c57d..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/pch.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "pch.h" diff --git a/src/modules/ShortcutGuide/ShortcutGuide/pch.h b/src/modules/ShortcutGuide/ShortcutGuide/pch.h deleted file mode 100644 index 0dfbbb9ec9..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/pch.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once -#define NOMINMAX -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide/resource.base.h b/src/modules/ShortcutGuide/ShortcutGuide/resource.base.h deleted file mode 100644 index 75f509067c..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/resource.base.h +++ /dev/null @@ -1,13 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by ShortcutGuide.rc - -////////////////////////////// -// Non-localizable - -#define FILE_DESCRIPTION "PowerToys ShortcutGuide" -#define INTERNAL_NAME "ShortcutGuide" -#define ORIGINAL_FILENAME "PowerToys.ShortcutGuide.exe" - -// Non-localizable -////////////////////////////// diff --git a/src/modules/ShortcutGuide/ShortcutGuide/shortcut_guide.cpp b/src/modules/ShortcutGuide/ShortcutGuide/shortcut_guide.cpp deleted file mode 100644 index 719f713e79..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/shortcut_guide.cpp +++ /dev/null @@ -1,505 +0,0 @@ -#include "pch.h" -#include "shortcut_guide.h" -#include "target_state.h" -#include "trace.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// TODO: refactor singleton -OverlayWindow* overlay_window_instance = nullptr; - -namespace -{ - // Window properties relevant to ShortcutGuide - struct ShortcutGuideWindowInfo - { - HWND hwnd = nullptr; // Handle to the top-level foreground window or nullptr if there is no such window - bool snappable = false; // True, if the window can react to Windows Snap keys - bool disabled = false; - }; - - ShortcutGuideWindowInfo GetShortcutGuideWindowInfo(HWND active_window) - { - ShortcutGuideWindowInfo result; - active_window = GetAncestor(active_window, GA_ROOT); - if (!IsWindowVisible(active_window)) - { - return result; - } - - auto style = GetWindowLong(active_window, GWL_STYLE); - auto exStyle = GetWindowLong(active_window, GWL_EXSTYLE); - if ((style & WS_CHILD) == WS_CHILD || - (style & WS_DISABLED) == WS_DISABLED || - (exStyle & WS_EX_TOOLWINDOW) == WS_EX_TOOLWINDOW || - (exStyle & WS_EX_NOACTIVATE) == WS_EX_NOACTIVATE) - { - return result; - } - std::array class_name; - GetClassNameA(active_window, class_name.data(), static_cast(class_name.size())); - if (is_system_window(active_window, class_name.data())) - { - return result; - } - static HWND cortana_hwnd = nullptr; - if (cortana_hwnd == nullptr) - { - if (strcmp(class_name.data(), "Windows.UI.Core.CoreWindow") == 0 && - get_process_path(active_window).ends_with(L"SearchUI.exe")) - { - cortana_hwnd = active_window; - return result; - } - } - else if (cortana_hwnd == active_window) - { - return result; - } - result.hwnd = active_window; - // In reality, Windows Snap works if even one of those styles is set - // for a window, it is just limited. If there is no WS_MAXIMIZEBOX using - // WinKey + Up just won't maximize the window. Similarly, without - // WS_MINIMIZEBOX the window will not get minimized. A "Save As..." dialog - // is a example of such window - it can be snapped to both sides and to - // all screen corners, but will not get maximized nor minimized. - // For now, since ShortcutGuide can only disable entire "Windows Controls" - // group, we require that the window supports all the options. - result.snappable = ((style & WS_MAXIMIZEBOX) == WS_MAXIMIZEBOX) && - ((style & WS_MINIMIZEBOX) == WS_MINIMIZEBOX) && - ((style & WS_THICKFRAME) == WS_THICKFRAME); - return result; - } - - const LPARAM eventActivateWindow = 1; - - bool wasWinPressed = false; - bool isWinPressed() - { - return (GetAsyncKeyState(VK_LWIN) & 0x8000) || (GetAsyncKeyState(VK_RWIN) & 0x8000); - } - - // all modifiers without win key - std::vector modifierKeys = { VK_SHIFT, VK_LSHIFT, VK_RSHIFT, VK_CONTROL, VK_LCONTROL, VK_RCONTROL, VK_MENU, VK_LMENU, VK_RMENU }; - - // returns false if there are other modifiers pressed or win key isn' pressed - bool onlyWinPressed() - { - if (!isWinPressed()) - { - return false; - } - - for (auto key : modifierKeys) - { - if (GetAsyncKeyState(key) & 0x8000) - { - return false; - } - } - - return true; - } - - constexpr bool isWin(int key) - { - return key == VK_LWIN || key == VK_RWIN; - } - - constexpr bool isKeyDown(LowlevelKeyboardEvent event) - { - return event.wParam == WM_KEYDOWN || event.wParam == WM_SYSKEYDOWN; - } - - LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) - { - LowlevelKeyboardEvent event; - if (nCode == HC_ACTION) - { - event.lParam = reinterpret_cast(lParam); - event.wParam = wParam; - - if (event.lParam->vkCode == VK_ESCAPE) - { - Logger::trace(L"ESC key was pressed"); - overlay_window_instance->CloseWindow(HideWindowType::ESC_PRESSED); - } - - if (wasWinPressed && !isKeyDown(event) && isWin(event.lParam->vkCode)) - { - Logger::trace(L"Win key was released"); - overlay_window_instance->CloseWindow(HideWindowType::WIN_RELEASED); - } - - if (isKeyDown(event) && isWin(event.lParam->vkCode)) - { - wasWinPressed = true; - } - - if (onlyWinPressed() && isKeyDown(event) && !isWin(event.lParam->vkCode)) - { - Logger::trace(L"Shortcut with win key was pressed"); - overlay_window_instance->CloseWindow(HideWindowType::WIN_SHORTCUT_PRESSED); - } - } - - return CallNextHookEx(NULL, nCode, wParam, lParam); - } - - LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) - { - if (nCode >= 0) - { - switch (wParam) - { - case WM_LBUTTONUP: - case WM_RBUTTONUP: - case WM_MBUTTONUP: - case WM_XBUTTONUP: - // Don't close with mouse click if activation is windows key and the key is pressed - if (!overlay_window_instance->win_key_activation() || !isWinPressed()) - { - overlay_window_instance->CloseWindow(HideWindowType::MOUSE_BUTTONUP); - } - break; - default: - break; - } - } - - return CallNextHookEx(0, nCode, wParam, lParam); - } - - std::wstring ToWstring(HideWindowType type) - { - switch (type) - { - case HideWindowType::ESC_PRESSED: - return L"ESC_PRESSED"; - case HideWindowType::WIN_RELEASED: - return L"WIN_RELEASED"; - case HideWindowType::WIN_SHORTCUT_PRESSED: - return L"WIN_SHORTCUT_PRESSED"; - case HideWindowType::THE_SHORTCUT_PRESSED: - return L"THE_SHORTCUT_PRESSED"; - case HideWindowType::MOUSE_BUTTONUP: - return L"MOUSE_BUTTONUP"; - } - - return L""; - } -} - -OverlayWindow::OverlayWindow(HWND activeWindow) -{ - overlay_window_instance = this; - this->activeWindow = activeWindow; - app_name = GET_RESOURCE_STRING(IDS_SHORTCUT_GUIDE); - - Logger::info("Overlay Window is creating"); - init_settings(); - keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), NULL); - if (!keyboardHook) - { - Logger::warn(L"Failed to create low level keyboard hook. {}", get_last_error_or_default(GetLastError())); - } - - mouseHook = SetWindowsHookEx(WH_MOUSE_LL, LowLevelMouseProc, GetModuleHandle(NULL), NULL); - if (!mouseHook) - { - Logger::warn(L"Failed to create low level mouse hook. {}", get_last_error_or_default(GetLastError())); - } -} - -void OverlayWindow::ShowWindow() -{ - winkey_popup = std::make_unique(); - winkey_popup->apply_overlay_opacity(overlayOpacity.value / 100.0f); - winkey_popup->set_theme(theme.value); - - // The press time only takes effect when the shortcut guide is activated by pressing the win key. - if (shouldReactToPressedWinKey.value) - { - winkey_popup->apply_press_time_for_global_windows_shortcuts(windowsKeyPressTimeForGlobalWindowsShortcuts.value); - winkey_popup->apply_press_time_for_taskbar_icon_shortcuts(windowsKeyPressTimeForTaskbarIconShortcuts.value); - } - else - { - winkey_popup->apply_press_time_for_global_windows_shortcuts(0); - winkey_popup->apply_press_time_for_taskbar_icon_shortcuts(0); - } - - target_state = std::make_unique(); - try - { - winkey_popup->initialize(); - } - catch (...) - { - Logger::critical("Winkey popup failed to initialize"); - return; - } - - target_state->toggle_force_shown(); -} - -void OverlayWindow::CloseWindow(HideWindowType type, int mainThreadId) -{ - if (mainThreadId == 0) - { - mainThreadId = GetCurrentThreadId(); - } - - if (this->winkey_popup) - { - if (shouldReactToPressedWinKey.value) - { - // Send a dummy key to prevent Start Menu from activating - INPUT dummyEvent[1] = {}; - dummyEvent[0].type = INPUT_KEYBOARD; - dummyEvent[0].ki.wVk = 0xFF; - dummyEvent[0].ki.dwFlags = KEYEVENTF_KEYUP; - SendInput(1, dummyEvent, sizeof(INPUT)); - } - this->winkey_popup->SetWindowCloseType(ToWstring(type)); - Logger::trace(L"Terminating process"); - PostThreadMessage(mainThreadId, WM_QUIT, 0, 0); - } -} - -bool OverlayWindow::IsDisabled() -{ - WCHAR exePath[MAX_PATH] = L""; - overlay_window_instance->get_exe_path(activeWindow, exePath); - if (wcslen(exePath) > 0) - { - return is_disabled_app(exePath); - } - - return false; -} - -OverlayWindow::~OverlayWindow() -{ - if (event_waiter) - { - event_waiter.reset(); - } - - if (winkey_popup) - { - winkey_popup->hide(); - } - - if (target_state) - { - target_state->exit(); - target_state.reset(); - } - - if (winkey_popup) - { - winkey_popup.reset(); - } - - if (keyboardHook) - { - UnhookWindowsHookEx(keyboardHook); - } -} - -void OverlayWindow::on_held() -{ - auto windowInfo = GetShortcutGuideWindowInfo(activeWindow); - if (windowInfo.disabled) - { - target_state->was_hidden(); - return; - } - winkey_popup->show(windowInfo.hwnd, windowInfo.snappable); -} - -void OverlayWindow::quick_hide() -{ - winkey_popup->quick_hide(); -} - -void OverlayWindow::was_hidden() -{ - target_state->was_hidden(); -} - -bool OverlayWindow::overlay_visible() const -{ - return target_state->active(); -} - -bool OverlayWindow::win_key_activation() const -{ - return shouldReactToPressedWinKey.value; -} - -void OverlayWindow::init_settings() -{ - auto settings = GetSettings(); - overlayOpacity.value = settings.overlayOpacity; - theme.value = settings.theme; - disabledApps.value = settings.disabledApps; - shouldReactToPressedWinKey.value = settings.shouldReactToPressedWinKey; - windowsKeyPressTimeForGlobalWindowsShortcuts.value = settings.windowsKeyPressTimeForGlobalWindowsShortcuts; - windowsKeyPressTimeForTaskbarIconShortcuts.value = settings.windowsKeyPressTimeForTaskbarIconShortcuts; - update_disabled_apps(); -} - -bool OverlayWindow::is_disabled_app(wchar_t* exePath) -{ - if (exePath == nullptr) - { - return false; - } - - auto exePathUpper = std::wstring(exePath); - CharUpperBuffW(exePathUpper.data(), static_cast(exePathUpper.length())); - for (const auto& row : disabled_apps_array) - { - const auto pos = exePathUpper.rfind(row); - const auto last_slash = exePathUpper.rfind('\\'); - // Check that row occurs in disabled_apps_array, and its last occurrence contains in itself the first character after the last backslash. - if (pos != std::wstring::npos && pos <= last_slash + 1 && pos + row.length() > last_slash) - { - return true; - } - } - return false; -} - -void OverlayWindow::update_disabled_apps() -{ - disabled_apps_array.clear(); - auto disabledUppercase = disabledApps.value; - CharUpperBuffW(disabledUppercase.data(), static_cast(disabledUppercase.length())); - std::wstring_view view(disabledUppercase); - view = trim(view); - while (!view.empty()) - { - auto pos = (std::min)(view.find_first_of(L"\r\n"), view.length()); - disabled_apps_array.emplace_back(view.substr(0, pos)); - view.remove_prefix(pos); - view = trim(view); - } -} - -void OverlayWindow::get_exe_path(HWND window, wchar_t* path) -{ - if (disabled_apps_array.empty()) - { - return; - } - - DWORD pid = 0; - GetWindowThreadProcessId(window, &pid); - if (pid != 0) - { - HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); - if (processHandle && GetProcessImageFileName(processHandle, path, MAX_PATH) > 0) - { - CloseHandle(processHandle); - } - } -} - -ShortcutGuideSettings OverlayWindow::GetSettings() noexcept -{ - ShortcutGuideSettings settings; - json::JsonObject properties; - try - { - PowerToysSettings::PowerToyValues settingsValues = - PowerToysSettings::PowerToyValues::load_from_settings_file(app_key); - - auto settingsObject = settingsValues.get_raw_json(); - if (!settingsObject.GetView().Size()) - { - return settings; - } - - properties = settingsObject.GetNamedObject(L"properties"); - } - catch (...) - { - Logger::warn("Failed to read settings. Use default settings"); - return settings; - } - - try - { - settings.hotkey = PowerToysSettings::HotkeyObject::from_json(properties.GetNamedObject(OpenShortcut::name)).to_string(); - } - catch (...) - { - } - - try - { - settings.overlayOpacity = static_cast(properties.GetNamedObject(OverlayOpacity::name).GetNamedNumber(L"value")); - } - catch (...) - { - } - - try - { - settings.shouldReactToPressedWinKey = properties.GetNamedObject(ShouldReactToPressedWinKey::name).GetNamedBoolean(L"value"); - } - catch (...) - { - } - - try - { - settings.windowsKeyPressTimeForGlobalWindowsShortcuts = static_cast(properties.GetNamedObject(WindowsKeyPressTimeForGlobalWindowsShortcuts::name).GetNamedNumber(L"value")); - } - catch (...) - { - } - - try - { - settings.windowsKeyPressTimeForTaskbarIconShortcuts = static_cast(properties.GetNamedObject(WindowsKeyPressTimeForTaskbarIconShortcuts::name).GetNamedNumber(L"value")); - } - catch (...) - { - } - - try - { - settings.theme = (std::wstring)properties.GetNamedObject(Theme::name).GetNamedString(L"value"); - } - catch (...) - { - } - - try - { - settings.disabledApps = (std::wstring)properties.GetNamedObject(DisabledApps::name).GetNamedString(L"value"); - } - catch (...) - { - } - - return settings; -} diff --git a/src/modules/ShortcutGuide/ShortcutGuide/shortcut_guide.h b/src/modules/ShortcutGuide/ShortcutGuide/shortcut_guide.h deleted file mode 100644 index 57f9bf3267..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/shortcut_guide.h +++ /dev/null @@ -1,106 +0,0 @@ -#pragma once -#include "../interface/powertoy_module_interface.h" -//#include -#include "overlay_window.h" -#include "native_event_waiter.h" -#include "ShortcutGuideSettings.h" -#include "ShortcutGuideConstants.h" - -#include "Generated Files/resource.h" - -// We support only one instance of the overlay -extern class OverlayWindow* overlay_window_instance; - -class TargetState; - -enum class HideWindowType -{ - ESC_PRESSED, - WIN_RELEASED, - WIN_SHORTCUT_PRESSED, - THE_SHORTCUT_PRESSED, - MOUSE_BUTTONUP -}; - -class OverlayWindow -{ -public: - OverlayWindow(HWND activeWindow); - void ShowWindow(); - void CloseWindow(HideWindowType type, int mainThreadId = 0); - bool IsDisabled(); - - void on_held(); - void quick_hide(); - void was_hidden(); - - bool overlay_visible() const; - bool win_key_activation() const; - - bool is_disabled_app(wchar_t* exePath); - - void get_exe_path(HWND window, wchar_t* exePath); - ~OverlayWindow(); - static ShortcutGuideSettings GetSettings() noexcept; -private: - std::wstring app_name; - //contains the non localized key of the powertoy - static inline std::wstring app_key = ShortcutGuideConstants::ModuleKey; - std::unique_ptr target_state; - std::unique_ptr winkey_popup; - std::unique_ptr event_waiter; - std::vector disabled_apps_array; - void init_settings(); - void update_disabled_apps(); - HWND activeWindow; - HHOOK keyboardHook; - HHOOK mouseHook; - - struct OverlayOpacity - { - static inline PCWSTR name = L"overlay_opacity"; - int value; - int resourceId = IDS_SETTING_DESCRIPTION_OVERLAY_OPACITY; - } overlayOpacity{}; - - struct Theme - { - static inline PCWSTR name = L"theme"; - std::wstring value; - int resourceId = IDS_SETTING_DESCRIPTION_THEME; - std::vector> keys_and_texts = { - { L"system", IDS_SETTING_DESCRIPTION_THEME_SYSTEM }, - { L"light", IDS_SETTING_DESCRIPTION_THEME_LIGHT }, - { L"dark", IDS_SETTING_DESCRIPTION_THEME_DARK } - }; - } theme; - - struct DisabledApps - { - static inline PCWSTR name = L"disabled_apps"; - std::wstring value; - } disabledApps; - - struct ShouldReactToPressedWinKey - { - static inline PCWSTR name = L"use_legacy_press_win_key_behavior"; - bool value; - } shouldReactToPressedWinKey; - - struct WindowsKeyPressTimeForGlobalWindowsShortcuts - { - static inline PCWSTR name = L"press_time"; - int value; - } windowsKeyPressTimeForGlobalWindowsShortcuts; - - struct WindowsKeyPressTimeForTaskbarIconShortcuts - { - static inline PCWSTR name = L"press_time_for_taskbar_icon_shortcuts"; - int value; - } windowsKeyPressTimeForTaskbarIconShortcuts; - - struct OpenShortcut - { - static inline PCWSTR name = L"open_shortcutguide"; - } openShortcut; -}; diff --git a/src/modules/ShortcutGuide/ShortcutGuide/start_visible.cpp b/src/modules/ShortcutGuide/ShortcutGuide/start_visible.cpp deleted file mode 100644 index 17efa76b7d..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/start_visible.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "pch.h" -#include "start_visible.h" - -bool is_start_visible() -{ - static const auto app_visibility = []() { - winrt::com_ptr result; - CoCreateInstance(CLSID_AppVisibility, - nullptr, - CLSCTX_INPROC_SERVER, - __uuidof(result), - result.put_void()); - return result; - }(); - - if (!app_visibility) - { - return false; - } - - BOOL visible; - auto result = app_visibility->IsLauncherVisible(&visible); - return SUCCEEDED(result) && visible; -} diff --git a/src/modules/ShortcutGuide/ShortcutGuide/start_visible.h b/src/modules/ShortcutGuide/ShortcutGuide/start_visible.h deleted file mode 100644 index a1431086a2..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/start_visible.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -bool is_start_visible(); diff --git a/src/modules/ShortcutGuide/ShortcutGuide/target_state.cpp b/src/modules/ShortcutGuide/ShortcutGuide/target_state.cpp deleted file mode 100644 index 98fd9bb722..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/target_state.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "pch.h" -#include "target_state.h" -#include "start_visible.h" -#include -#include - -constexpr unsigned VK_S = 0x53; - -void TargetState::was_hidden() -{ - std::unique_lock lock(mutex); - // Ignore callbacks from the D2DOverlayWindow - if (state == ForceShown) - { - return; - } - state = Hidden; - lock.unlock(); - cv.notify_one(); -} - -void TargetState::exit() -{ - std::unique_lock lock(mutex); - state = Exiting; - lock.unlock(); - cv.notify_one(); -} - -void TargetState::toggle_force_shown() -{ - std::unique_lock lock(mutex); - if (state != ForceShown) - { - state = ForceShown; - overlay_window_instance->on_held(); - } - else - { - state = Hidden; - } -} - -bool TargetState::active() const -{ - return state == ForceShown || state == Shown; -} diff --git a/src/modules/ShortcutGuide/ShortcutGuide/target_state.h b/src/modules/ShortcutGuide/ShortcutGuide/target_state.h deleted file mode 100644 index c1f51e3f60..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/target_state.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#include -#include -#include "shortcut_guide.h" - -struct KeyEvent -{ - bool key_down; - unsigned vk_code; -}; - -class TargetState -{ -public: - TargetState() = default; - void was_hidden(); - void exit(); - - void toggle_force_shown(); - bool active() const; - -private: - std::recursive_mutex mutex; - std::condition_variable_any cv; - enum State - { - Hidden, - Shown, - ForceShown, - Exiting - }; - std::atomic state = Hidden; -}; diff --git a/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.cpp b/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.cpp deleted file mode 100644 index 0368eecb6c..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.cpp +++ /dev/null @@ -1,186 +0,0 @@ -#include "pch.h" -#include "tasklist_positions.h" - -// Tried my hardest adapting this to C#, but FindWindowW didn't work properly in C#. ~Noraa Junker - -extern "C" -{ - HWND GetTaskbarHwndForCursorMonitor(HMONITOR monitor) - { - POINT pt; - if (!GetCursorPos(&pt)) - return nullptr; - - // Find the primary taskbar - HWND primaryTaskbar = FindWindowW(L"Shell_TrayWnd", nullptr); - if (primaryTaskbar) - { - MONITORINFO mi = { sizeof(mi) }; - if (GetWindowRect(primaryTaskbar, &mi.rcMonitor)) - { - HMONITOR primaryMonitor = MonitorFromRect(&mi.rcMonitor, MONITOR_DEFAULTTONEAREST); - if (primaryMonitor == monitor) - return primaryTaskbar; - } - } - - // Find the secondary taskbar(s) - HWND secondaryTaskbar = nullptr; - while ((secondaryTaskbar = FindWindowExW(nullptr, secondaryTaskbar, L"Shell_SecondaryTrayWnd", nullptr)) != nullptr) - { - MONITORINFO mi = { sizeof(mi) }; - RECT rc; - if (GetWindowRect(secondaryTaskbar, &rc)) - { - HMONITOR monitor = MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST); - if (monitor == monitor) - return secondaryTaskbar; - } - } - - return nullptr; - } - - __declspec(dllexport) void update(HMONITOR monitor) - { - // Get HWND of the tasklist for the monitor under the cursor - auto taskbar_hwnd = GetTaskbarHwndForCursorMonitor(monitor); - if (!taskbar_hwnd) - return; - - wchar_t class_name[64] = {}; - GetClassNameW(taskbar_hwnd, class_name, 64); - - HWND tasklist_hwnd = nullptr; - - if (wcscmp(class_name, L"Shell_TrayWnd") == 0) - { - // Primary taskbar structure - tasklist_hwnd = FindWindowExW(taskbar_hwnd, 0, L"ReBarWindow32", nullptr); - if (!tasklist_hwnd) - return; - tasklist_hwnd = FindWindowExW(tasklist_hwnd, 0, L"MSTaskSwWClass", nullptr); - if (!tasklist_hwnd) - return; - tasklist_hwnd = FindWindowExW(tasklist_hwnd, 0, L"MSTaskListWClass", nullptr); - if (!tasklist_hwnd) - return; - } - else if (wcscmp(class_name, L"Shell_SecondaryTrayWnd") == 0) - { - // Secondary taskbar structure - HWND workerw = FindWindowExW(taskbar_hwnd, 0, L"WorkerW", nullptr); - if (!workerw) - return; - tasklist_hwnd = FindWindowExW(workerw, 0, L"MSTaskListWClass", nullptr); - if (!tasklist_hwnd) - return; - } - else - { - // Unknown taskbar type - return; - } - - if (!automation) - { - winrt::check_hresult(CoCreateInstance(CLSID_CUIAutomation, - nullptr, - CLSCTX_INPROC_SERVER, - IID_IUIAutomation, - automation.put_void())); - winrt::check_hresult(automation->CreateTrueCondition(true_condition.put())); - } - element = nullptr; - winrt::check_hresult(automation->ElementFromHandle(tasklist_hwnd, element.put())); - } - - __declspec(dllexport) bool update_buttons(std::vector& buttons) - { - if (!automation || !element) - { - return false; - } - winrt::com_ptr elements; - if (element->FindAll(TreeScope_Children, true_condition.get(), elements.put()) < 0) - return false; - if (!elements) - return false; - int count; - if (elements->get_Length(&count) < 0) - return false; - winrt::com_ptr child; - std::vector found_buttons; - found_buttons.reserve(count); - for (int i = 0; i < count; ++i) - { - child = nullptr; - if (elements->GetElement(i, child.put()) < 0) - return false; - TasklistButton button = {}; - if (VARIANT var_rect; child->GetCurrentPropertyValue(UIA_BoundingRectanglePropertyId, &var_rect) >= 0) - { - if (var_rect.vt == (VT_R8 | VT_ARRAY)) - { - LONG pos; - double value; - pos = 0; - SafeArrayGetElement(var_rect.parray, &pos, &value); - button.x = static_cast(value); - pos = 1; - SafeArrayGetElement(var_rect.parray, &pos, &value); - button.y = static_cast(value); - pos = 2; - SafeArrayGetElement(var_rect.parray, &pos, &value); - button.width = static_cast(value); - pos = 3; - SafeArrayGetElement(var_rect.parray, &pos, &value); - button.height = static_cast(value); - } - VariantClear(&var_rect); - } - else - { - return false; - } - if (BSTR automation_id; child->get_CurrentAutomationId(&automation_id) >= 0) - { - wcsncpy_s(button.name, automation_id, _countof(button.name)); - SysFreeString(automation_id); - } - found_buttons.push_back(button); - } - // assign keynums - buttons.clear(); - for (auto& button : found_buttons) - { - if (buttons.empty()) - { - button.keynum = 1; - buttons.push_back(std::move(button)); - } - else - { - if (button.x < buttons.back().x || button.y < buttons.back().y) // skip 2nd row - break; - if (wcsncmp(button.name, buttons.back().name, _countof(button.name)) == 0) - continue; // skip buttons from the same app - button.keynum = buttons.back().keynum + 1; - buttons.push_back(std::move(button)); - if (buttons.back().keynum == 10) - break; // no more than 10 buttons - } - } - return true; - } - - __declspec(dllexport) TasklistButton* get_buttons(HMONITOR monitor, int* size) - { - update(monitor); - static std::vector buttons; - update_buttons(buttons); - *size = static_cast(buttons.size()); - return buttons.data(); - } -} - diff --git a/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.h b/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.h deleted file mode 100644 index 4d833ba327..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/tasklist_positions.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -struct TasklistButton -{ - wchar_t name[256]; - int x; - int y; - int width; - int height; - int keynum; -}; - -extern "C" -{ - winrt::com_ptr automation; - winrt::com_ptr element; - winrt::com_ptr true_condition; - - // Helper to get the taskbar HWND for the monitor under the cursor - HWND GetTaskbarHwndForCursorMonitor(HMONITOR monitor); - __declspec(dllexport) bool update_buttons(std::vector& buttons); - __declspec(dllexport) TasklistButton* get_buttons(HMONITOR monitor, int* size); -} diff --git a/src/modules/ShortcutGuide/ShortcutGuide/trace.cpp b/src/modules/ShortcutGuide/ShortcutGuide/trace.cpp deleted file mode 100644 index f2a414d6ac..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/trace.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "pch.h" -#include "trace.h" - -#include - -TRACELOGGING_DEFINE_PROVIDER( - g_hProvider, - "Microsoft.PowerToys", - // {38e8889b-9731-53f5-e901-e8a7c1753074} - (0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74), - TraceLoggingOptionProjectTelemetry()); - -void Trace::SendGuideSession(const __int64 duration_ms, const wchar_t* close_type) noexcept -{ - TraceLoggingWriteWrapper( - g_hProvider, - "ShortcutGuide_GuideSession", - TraceLoggingInt64(duration_ms, "DurationInMs"), - TraceLoggingWideString(close_type, "CloseType"), - ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), - TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), - TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); -} - -void Trace::SendSettings(ShortcutGuideSettings settings) noexcept -{ - TraceLoggingWriteWrapper( - g_hProvider, - "ShortcutGuide_Settings", - TraceLoggingWideString(settings.hotkey.c_str(), "Hotkey"), - TraceLoggingInt32(settings.overlayOpacity, "OverlayOpacity"), - TraceLoggingWideString(settings.theme.c_str(), "Theme"), - TraceLoggingWideString(settings.disabledApps.c_str(), "DisabledApps"), - TraceLoggingBoolean(settings.shouldReactToPressedWinKey, "ShouldReactToPressedWinKey"), - TraceLoggingInt32(settings.windowsKeyPressTimeForGlobalWindowsShortcuts, "WindowsKeyPressTimeForGlobalWindowsShortcuts"), - TraceLoggingInt32(settings.windowsKeyPressTimeForTaskbarIconShortcuts, "WindowsKeyPressTimeForTaskbarIconShortcuts"), - ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), - TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), - TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); -} diff --git a/src/modules/ShortcutGuide/ShortcutGuide/trace.h b/src/modules/ShortcutGuide/ShortcutGuide/trace.h deleted file mode 100644 index a3446a8570..0000000000 --- a/src/modules/ShortcutGuide/ShortcutGuide/trace.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once -#include "ShortcutGuideSettings.h" - -#include - -class Trace : public telemetry::TraceBase -{ -public: - static void SendGuideSession(const __int64 duration_ms, const wchar_t* close_type) noexcept; - static void SendSettings(ShortcutGuideSettings settings) noexcept; -}; diff --git a/src/modules/ShortcutGuide/ShortcutGuideModuleInterface/dllmain.cpp b/src/modules/ShortcutGuide/ShortcutGuideModuleInterface/dllmain.cpp index 6b85947048..0b011bf6c5 100644 --- a/src/modules/ShortcutGuide/ShortcutGuideModuleInterface/dllmain.cpp +++ b/src/modules/ShortcutGuide/ShortcutGuideModuleInterface/dllmain.cpp @@ -131,10 +131,6 @@ public: virtual std::optional GetHotkeyEx() override { Logger::trace("GetHotkeyEx()"); - if (m_shouldReactToPressedWinKey) - { - return std::nullopt; - } return m_hotkey; } @@ -170,16 +166,6 @@ public: } } - virtual bool keep_track_of_pressed_win_key() override - { - return m_shouldReactToPressedWinKey; - } - - virtual UINT milliseconds_win_key_must_be_pressed() override - { - return std::min(m_millisecondsWinKeyPressTimeForGlobalWindowsShortcuts, m_millisecondsWinKeyPressTimeForTaskbarIconShortcuts); - } - private: std::wstring app_name; //contains the non localized key of the powertoy @@ -193,7 +179,6 @@ private: // If the module should be activated through the legacy pressing windows key behavior. const UINT DEFAULT_MILLISECONDS_WIN_KEY_PRESS_TIME_FOR_GLOBAL_WINDOWS_SHORTCUTS = 900; const UINT DEFAULT_MILLISECONDS_WIN_KEY_PRESS_TIME_FOR_TASKBAR_ICON_SHORTCUTS = 900; - bool m_shouldReactToPressedWinKey = false; UINT m_millisecondsWinKeyPressTimeForGlobalWindowsShortcuts = DEFAULT_MILLISECONDS_WIN_KEY_PRESS_TIME_FOR_GLOBAL_WINDOWS_SHORTCUTS; UINT m_millisecondsWinKeyPressTimeForTaskbarIconShortcuts = DEFAULT_MILLISECONDS_WIN_KEY_PRESS_TIME_FOR_TASKBAR_ICON_SHORTCUTS; @@ -290,8 +275,6 @@ private: void ParseSettings(PowerToysSettings::PowerToyValues& settings) { m_shouldReactToPressedWinKey = false; - m_millisecondsWinKeyPressTimeForGlobalWindowsShortcuts = DEFAULT_MILLISECONDS_WIN_KEY_PRESS_TIME_FOR_GLOBAL_WINDOWS_SHORTCUTS; - m_millisecondsWinKeyPressTimeForTaskbarIconShortcuts = DEFAULT_MILLISECONDS_WIN_KEY_PRESS_TIME_FOR_TASKBAR_ICON_SHORTCUTS; auto settingsObject = settings.get_raw_json(); if (settingsObject.GetView().Size()) @@ -328,36 +311,6 @@ private: { Logger::warn("Failed to initialize Shortcut Guide start shortcut"); } - try - { - // Parse Legacy windows key press behavior settings - auto jsonUseLegacyWinKeyBehaviorObject = settingsObject.GetNamedObject(L"properties").GetNamedObject(L"use_legacy_press_win_key_behavior"); - m_shouldReactToPressedWinKey = jsonUseLegacyWinKeyBehaviorObject.GetNamedBoolean(L"value"); - auto jsonPressTimeForGlobalWindowsShortcutsObject = settingsObject.GetNamedObject(L"properties").GetNamedObject(L"press_time"); - auto jsonPressTimeForTaskbarIconShortcutsObject = settingsObject.GetNamedObject(L"properties").GetNamedObject(L"press_time_for_taskbar_icon_shortcuts"); - int value = static_cast(jsonPressTimeForGlobalWindowsShortcutsObject.GetNamedNumber(L"value")); - if (value >= 0) - { - m_millisecondsWinKeyPressTimeForGlobalWindowsShortcuts = value; - } - else - { - throw std::runtime_error("Invalid Press Time Windows Shortcuts value"); - } - value = static_cast(jsonPressTimeForTaskbarIconShortcutsObject.GetNamedNumber(L"value")); - if (value >= 0) - { - m_millisecondsWinKeyPressTimeForTaskbarIconShortcuts = value; - } - else - { - throw std::runtime_error("Invalid Press Time Taskbar Shortcuts value"); - } - } - catch (...) - { - Logger::warn("Failed to get legacy win key behavior settings"); - } } else { From 411f4df2c031c4ce7b9d34a51b1a1c2f117efee1 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Sun, 27 Jul 2025 16:59:25 +0200 Subject: [PATCH 60/99] Remove legacy shortcut behaviour --- 2 | 79 ++++++++++++++++++ .../Helpers/PowerToysShortcutsPopulator.cs | 4 +- .../ShortcutGuideXAML/MainWindow.xaml.cs | 2 - .../ShortcutGuideModuleInterface/dllmain.cpp | 2 - .../ShortcutGuideProperties.cs | 16 ---- .../ShortcutGuideSettings.cs | 2 +- .../OOBE/Views/OobeShortcutGuide.xaml.cs | 11 +-- .../SettingsXAML/Views/ShortcutGuidePage.xaml | 52 +----------- .../ViewModels/DashboardViewModel.cs | 4 +- .../ViewModels/Flyout/LauncherViewModel.cs | 4 +- .../ViewModels/ShortcutGuideViewModel.cs | 80 ------------------- 11 files changed, 86 insertions(+), 170 deletions(-) create mode 100644 2 diff --git a/2 b/2 new file mode 100644 index 0000000000..1a484908d9 --- /dev/null +++ b/2 @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs index af777f1b31..4d61dc239d 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs @@ -40,9 +40,7 @@ namespace ShortcutGuide.Helpers content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut, "Screen Ruler", content); { ShortcutGuideProperties settingsProperties = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties; - content = settingsProperties.UseLegacyPressWinKeyBehavior.Value - ? HotkeySettingsToYaml(new HotkeySettings(true, false, false, false, 0), "Shortcut Guide", content) - : HotkeySettingsToYaml(settingsProperties.DefaultOpenShortcutGuide, "Shortcut Guide", content); + content = HotkeySettingsToYaml(settingsProperties.DefaultOpenShortcutGuide, "Shortcut Guide", content); } content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut, "Text Extractor", content); diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs index 135977e425..7d2a50187b 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Library; @@ -16,7 +15,6 @@ using ShortcutGuide.Helpers; using ShortcutGuide.Models; using Windows.Foundation; using Windows.Graphics; -using Windows.System; using WinUIEx; using static ShortcutGuide.NativeMethods; diff --git a/src/modules/ShortcutGuide/ShortcutGuideModuleInterface/dllmain.cpp b/src/modules/ShortcutGuide/ShortcutGuideModuleInterface/dllmain.cpp index 0b011bf6c5..6b322ae6ad 100644 --- a/src/modules/ShortcutGuide/ShortcutGuideModuleInterface/dllmain.cpp +++ b/src/modules/ShortcutGuide/ShortcutGuideModuleInterface/dllmain.cpp @@ -274,8 +274,6 @@ private: void ParseSettings(PowerToysSettings::PowerToyValues& settings) { - m_shouldReactToPressedWinKey = false; - auto settingsObject = settings.get_raw_json(); if (settingsObject.GetView().Size()) { diff --git a/src/settings-ui/Settings.UI.Library/ShortcutGuideProperties.cs b/src/settings-ui/Settings.UI.Library/ShortcutGuideProperties.cs index d34a2f748a..4cf498073d 100644 --- a/src/settings-ui/Settings.UI.Library/ShortcutGuideProperties.cs +++ b/src/settings-ui/Settings.UI.Library/ShortcutGuideProperties.cs @@ -15,10 +15,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library public ShortcutGuideProperties() { - OverlayOpacity = new IntProperty(90); - UseLegacyPressWinKeyBehavior = new BoolProperty(false); - PressTimeForGlobalWindowsShortcuts = new IntProperty(900); - PressTimeForTaskbarIconShortcuts = new IntProperty(900); Theme = new StringProperty("system"); DisabledApps = new StringProperty(); OpenShortcutGuide = DefaultOpenShortcutGuide; @@ -27,18 +23,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library [JsonPropertyName("open_shortcutguide")] public HotkeySettings OpenShortcutGuide { get; set; } - [JsonPropertyName("overlay_opacity")] - public IntProperty OverlayOpacity { get; set; } - - [JsonPropertyName("use_legacy_press_win_key_behavior")] - public BoolProperty UseLegacyPressWinKeyBehavior { get; set; } - - [JsonPropertyName("press_time")] - public IntProperty PressTimeForGlobalWindowsShortcuts { get; set; } - - [JsonPropertyName("press_time_for_taskbar_icon_shortcuts")] - public IntProperty PressTimeForTaskbarIconShortcuts { get; set; } - [JsonPropertyName("theme")] public StringProperty Theme { get; set; } diff --git a/src/settings-ui/Settings.UI.Library/ShortcutGuideSettings.cs b/src/settings-ui/Settings.UI.Library/ShortcutGuideSettings.cs index c39e757fe3..2be444f0ff 100644 --- a/src/settings-ui/Settings.UI.Library/ShortcutGuideSettings.cs +++ b/src/settings-ui/Settings.UI.Library/ShortcutGuideSettings.cs @@ -19,7 +19,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library { Name = ModuleName; Properties = new ShortcutGuideProperties(); - Version = "1.0"; + Version = "2.0"; } public string GetModuleName() diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShortcutGuide.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShortcutGuide.xaml.cs index 5702ddcb9f..b6a92080aa 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShortcutGuide.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShortcutGuide.xaml.cs @@ -32,7 +32,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views private void Start_ShortcutGuide_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) { - var executablePath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "..", @"PowerToys.ShortcutGuide.exe"); + var executablePath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "..", @"WinUI3Apps//PowerToys.ShortcutGuide.exe"); var id = System.Environment.ProcessId.ToString(CultureInfo.InvariantCulture); var p = Process.Start(executablePath, id); if (p != null) @@ -58,14 +58,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views ViewModel.LogOpeningModuleEvent(); var settingsProperties = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties; - if ((bool)settingsProperties.UseLegacyPressWinKeyBehavior.Value) - { - HotkeyControl.Keys = new List { 92 }; - } - else - { - HotkeyControl.Keys = settingsProperties.OpenShortcutGuide.GetKeysList(); - } + HotkeyControl.Keys = settingsProperties.OpenShortcutGuide.GetKeysList(); } protected override void OnNavigatedFrom(NavigationEventArgs e) diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/ShortcutGuidePage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/ShortcutGuidePage.xaml index 1189e48700..d5433b655f 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/ShortcutGuidePage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/ShortcutGuidePage.xaml @@ -30,53 +30,11 @@ - - - - - - - + HeaderIcon="{ui:FontIcon Glyph=}"> - - - - - - - - - - @@ -90,14 +48,6 @@ - - - - diff --git a/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs index 8dd97c85fa..8885e2686a 100644 --- a/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs @@ -424,9 +424,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels { ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(new SettingsUtils()); - var shortcut = moduleSettingsRepository.SettingsConfig.Properties.UseLegacyPressWinKeyBehavior.Value - ? new List { 92 } // Right Windows key code - : moduleSettingsRepository.SettingsConfig.Properties.OpenShortcutGuide.GetKeysList(); + var shortcut = moduleSettingsRepository.SettingsConfig.Properties.OpenShortcutGuide.GetKeysList(); var list = new List { diff --git a/src/settings-ui/Settings.UI/ViewModels/Flyout/LauncherViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/Flyout/LauncherViewModel.cs index a1db1e2dd0..faa8e0cce3 100644 --- a/src/settings-ui/Settings.UI/ViewModels/Flyout/LauncherViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/Flyout/LauncherViewModel.cs @@ -112,9 +112,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private string GetShortcutGuideToolTip() { var shortcutGuideSettings = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig; - return shortcutGuideSettings.Properties.UseLegacyPressWinKeyBehavior.Value - ? "Win" - : shortcutGuideSettings.Properties.OpenShortcutGuide.ToString(); + return shortcutGuideSettings.Properties.OpenShortcutGuide.ToString(); } internal void StartBugReport() diff --git a/src/settings-ui/Settings.UI/ViewModels/ShortcutGuideViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/ShortcutGuideViewModel.cs index 6ae2dd0746..527d5877e7 100644 --- a/src/settings-ui/Settings.UI/ViewModels/ShortcutGuideViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/ShortcutGuideViewModel.cs @@ -50,10 +50,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels InitializeEnabledValue(); - _useLegacyPressWinKeyBehavior = Settings.Properties.UseLegacyPressWinKeyBehavior.Value; - _pressTimeForGlobalWindowsShortcuts = Settings.Properties.PressTimeForGlobalWindowsShortcuts.Value; - _pressTimeForTaskbarIconShortcuts = Settings.Properties.PressTimeForTaskbarIconShortcuts.Value; - _opacity = Settings.Properties.OverlayOpacity.Value; _disabledApps = Settings.Properties.DisabledApps.Value; switch (Settings.Properties.Theme.Value) @@ -83,10 +79,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private bool _enabledStateIsGPOConfigured; private bool _isEnabled; private int _themeIndex; - private bool _useLegacyPressWinKeyBehavior; - private int _pressTimeForGlobalWindowsShortcuts; - private int _pressTimeForTaskbarIconShortcuts; - private int _opacity; public bool IsEnabled { @@ -163,78 +155,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels } } - public int OverlayOpacity - { - get - { - return _opacity; - } - - set - { - if (_opacity != value) - { - _opacity = value; - Settings.Properties.OverlayOpacity.Value = value; - NotifyPropertyChanged(); - } - } - } - - public bool UseLegacyPressWinKeyBehavior - { - get - { - return _useLegacyPressWinKeyBehavior; - } - - set - { - if (_useLegacyPressWinKeyBehavior != value) - { - _useLegacyPressWinKeyBehavior = value; - Settings.Properties.UseLegacyPressWinKeyBehavior.Value = value; - NotifyPropertyChanged(); - } - } - } - - public int PressTime - { - get - { - return _pressTimeForGlobalWindowsShortcuts; - } - - set - { - if (_pressTimeForGlobalWindowsShortcuts != value) - { - _pressTimeForGlobalWindowsShortcuts = value; - Settings.Properties.PressTimeForGlobalWindowsShortcuts.Value = value; - NotifyPropertyChanged(); - } - } - } - - public int DelayTime - { - get - { - return _pressTimeForTaskbarIconShortcuts; - } - - set - { - if (_pressTimeForTaskbarIconShortcuts != value) - { - _pressTimeForTaskbarIconShortcuts = value; - Settings.Properties.PressTimeForTaskbarIconShortcuts.Value = value; - NotifyPropertyChanged(); - } - } - } - public string DisabledApps { get From eff58e1df5b4a868beaf52028b2661744d046e5f Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Sun, 27 Jul 2025 17:42:41 +0200 Subject: [PATCH 61/99] Fix closing by shortcut add closing by ESC and fix missing files from CPPProject --- .../ShortcutGuide.CPPProject.vcxproj | 12 +- .../ShortcutGuide.CPPProject.vcxproj.filters | 8 +- .../ShortcutGuide.CPPProject/pch.cpp | 1 + .../ShortcutGuide.CPPProject/pch.h | 29 +++ .../tasklist_positions.cpp | 185 ++++++++++++++++++ .../tasklist_positions.h | 23 +++ .../ShortcutGuideXAML/MainWindow.xaml.cs | 9 + .../ShortcutGuideModuleInterface/dllmain.cpp | 42 ++-- 8 files changed, 272 insertions(+), 37 deletions(-) create mode 100644 src/modules/ShortcutGuide/ShortcutGuide.CPPProject/pch.cpp create mode 100644 src/modules/ShortcutGuide/ShortcutGuide.CPPProject/pch.h create mode 100644 src/modules/ShortcutGuide/ShortcutGuide.CPPProject/tasklist_positions.cpp create mode 100644 src/modules/ShortcutGuide/ShortcutGuide.CPPProject/tasklist_positions.h diff --git a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj index dcfe871e5b..9e585bc34b 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj +++ b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj @@ -126,23 +126,23 @@ - + Create Create Create Create - - - - - + {d9b8fc84-322a-4f9f-bbb9-20915c47ddfd} + + + + diff --git a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj.filters b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj.filters index da95b2b982..bf13bf1b4e 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj.filters +++ b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj.filters @@ -15,18 +15,18 @@ - + Source Files - + Source Files - + Header Files - + Header Files diff --git a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/pch.cpp b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/pch.cpp new file mode 100644 index 0000000000..1d9f38c57d --- /dev/null +++ b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/pch.h b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/pch.h new file mode 100644 index 0000000000..677423795e --- /dev/null +++ b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/pch.h @@ -0,0 +1,29 @@ +#pragma once +#define NOMINMAX +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/tasklist_positions.cpp b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/tasklist_positions.cpp new file mode 100644 index 0000000000..872c9fc045 --- /dev/null +++ b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/tasklist_positions.cpp @@ -0,0 +1,185 @@ +#include "pch.h" +#include "tasklist_positions.h" + +// Tried my hardest adapting this to C#, but FindWindowW didn't work properly in C#. ~Noraa Junker + +extern "C" +{ + HWND GetTaskbarHwndForCursorMonitor(HMONITOR monitor) + { + POINT pt; + if (!GetCursorPos(&pt)) + return nullptr; + + // Find the primary taskbar + HWND primaryTaskbar = FindWindowW(L"Shell_TrayWnd", nullptr); + if (primaryTaskbar) + { + MONITORINFO mi = { sizeof(mi) }; + if (GetWindowRect(primaryTaskbar, &mi.rcMonitor)) + { + HMONITOR primaryMonitor = MonitorFromRect(&mi.rcMonitor, MONITOR_DEFAULTTONEAREST); + if (primaryMonitor == monitor) + return primaryTaskbar; + } + } + + // Find the secondary taskbar(s) + HWND secondaryTaskbar = nullptr; + while ((secondaryTaskbar = FindWindowExW(nullptr, secondaryTaskbar, L"Shell_SecondaryTrayWnd", nullptr)) != nullptr) + { + MONITORINFO mi = { sizeof(mi) }; + RECT rc; + if (GetWindowRect(secondaryTaskbar, &rc)) + { + HMONITOR monitor = MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST); + if (monitor == monitor) + return secondaryTaskbar; + } + } + + return nullptr; + } + + __declspec(dllexport) void update(HMONITOR monitor) + { + // Get HWND of the tasklist for the monitor under the cursor + auto taskbar_hwnd = GetTaskbarHwndForCursorMonitor(monitor); + if (!taskbar_hwnd) + return; + + wchar_t class_name[64] = {}; + GetClassNameW(taskbar_hwnd, class_name, 64); + + HWND tasklist_hwnd = nullptr; + + if (wcscmp(class_name, L"Shell_TrayWnd") == 0) + { + // Primary taskbar structure + tasklist_hwnd = FindWindowExW(taskbar_hwnd, 0, L"ReBarWindow32", nullptr); + if (!tasklist_hwnd) + return; + tasklist_hwnd = FindWindowExW(tasklist_hwnd, 0, L"MSTaskSwWClass", nullptr); + if (!tasklist_hwnd) + return; + tasklist_hwnd = FindWindowExW(tasklist_hwnd, 0, L"MSTaskListWClass", nullptr); + if (!tasklist_hwnd) + return; + } + else if (wcscmp(class_name, L"Shell_SecondaryTrayWnd") == 0) + { + // Secondary taskbar structure + HWND workerw = FindWindowExW(taskbar_hwnd, 0, L"WorkerW", nullptr); + if (!workerw) + return; + tasklist_hwnd = FindWindowExW(workerw, 0, L"MSTaskListWClass", nullptr); + if (!tasklist_hwnd) + return; + } + else + { + // Unknown taskbar type + return; + } + + if (!automation) + { + winrt::check_hresult(CoCreateInstance(CLSID_CUIAutomation, + nullptr, + CLSCTX_INPROC_SERVER, + IID_IUIAutomation, + automation.put_void())); + winrt::check_hresult(automation->CreateTrueCondition(true_condition.put())); + } + element = nullptr; + winrt::check_hresult(automation->ElementFromHandle(tasklist_hwnd, element.put())); + } + + __declspec(dllexport) bool update_buttons(std::vector& buttons) + { + if (!automation || !element) + { + return false; + } + winrt::com_ptr elements; + if (element->FindAll(TreeScope_Children, true_condition.get(), elements.put()) < 0) + return false; + if (!elements) + return false; + int count; + if (elements->get_Length(&count) < 0) + return false; + winrt::com_ptr child; + std::vector found_buttons; + found_buttons.reserve(count); + for (int i = 0; i < count; ++i) + { + child = nullptr; + if (elements->GetElement(i, child.put()) < 0) + return false; + TasklistButton button = {}; + if (VARIANT var_rect; child->GetCurrentPropertyValue(UIA_BoundingRectanglePropertyId, &var_rect) >= 0) + { + if (var_rect.vt == (VT_R8 | VT_ARRAY)) + { + LONG pos; + double value; + pos = 0; + SafeArrayGetElement(var_rect.parray, &pos, &value); + button.x = static_cast(value); + pos = 1; + SafeArrayGetElement(var_rect.parray, &pos, &value); + button.y = static_cast(value); + pos = 2; + SafeArrayGetElement(var_rect.parray, &pos, &value); + button.width = static_cast(value); + pos = 3; + SafeArrayGetElement(var_rect.parray, &pos, &value); + button.height = static_cast(value); + } + VariantClear(&var_rect); + } + else + { + return false; + } + if (BSTR automation_id; child->get_CurrentAutomationId(&automation_id) >= 0) + { + wcsncpy_s(button.name, automation_id, _countof(button.name)); + SysFreeString(automation_id); + } + found_buttons.push_back(button); + } + // assign keynums + buttons.clear(); + for (auto& button : found_buttons) + { + if (buttons.empty()) + { + button.keynum = 1; + buttons.push_back(std::move(button)); + } + else + { + if (button.x < buttons.back().x || button.y < buttons.back().y) // skip 2nd row + break; + if (wcsncmp(button.name, buttons.back().name, _countof(button.name)) == 0) + continue; // skip buttons from the same app + button.keynum = buttons.back().keynum + 1; + buttons.push_back(std::move(button)); + if (buttons.back().keynum == 10) + break; // no more than 10 buttons + } + } + return true; + } + + __declspec(dllexport) TasklistButton* get_buttons(HMONITOR monitor, int* size) + { + update(monitor); + static std::vector buttons; + update_buttons(buttons); + *size = static_cast(buttons.size()); + return buttons.data(); + } +} \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/tasklist_positions.h b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/tasklist_positions.h new file mode 100644 index 0000000000..4d833ba327 --- /dev/null +++ b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/tasklist_positions.h @@ -0,0 +1,23 @@ +#pragma once + +struct TasklistButton +{ + wchar_t name[256]; + int x; + int y; + int width; + int height; + int keynum; +}; + +extern "C" +{ + winrt::com_ptr automation; + winrt::com_ptr element; + winrt::com_ptr true_condition; + + // Helper to get the taskbar HWND for the monitor under the cursor + HWND GetTaskbarHwndForCursorMonitor(HMONITOR monitor); + __declspec(dllexport) bool update_buttons(std::vector& buttons); + __declspec(dllexport) TasklistButton* get_buttons(HMONITOR monitor, int* size); +} diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs index 7d2a50187b..3f55218493 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs @@ -15,6 +15,7 @@ using ShortcutGuide.Helpers; using ShortcutGuide.Models; using Windows.Foundation; using Windows.Graphics; +using Windows.System; using WinUIEx; using static ShortcutGuide.NativeMethods; @@ -85,6 +86,14 @@ namespace ShortcutGuide string pinnedPath = settingsUtils.GetSettingsFilePath(ShortcutGuideSettings.ModuleName, "Pinned.json"); ShortcutPageParameters.PinnedShortcuts = JsonSerializer.Deserialize>>(File.ReadAllText(pinnedPath))!; } + + Content.KeyUp += (_, e) => + { + if (e.Key == VirtualKey.Escape) + { + Close(); + } + }; } private void Window_Activated(object sender, WindowActivatedEventArgs e) diff --git a/src/modules/ShortcutGuide/ShortcutGuideModuleInterface/dllmain.cpp b/src/modules/ShortcutGuide/ShortcutGuideModuleInterface/dllmain.cpp index 6b322ae6ad..433a9be4b1 100644 --- a/src/modules/ShortcutGuide/ShortcutGuideModuleInterface/dllmain.cpp +++ b/src/modules/ShortcutGuide/ShortcutGuideModuleInterface/dllmain.cpp @@ -104,7 +104,10 @@ public: if (_enabled) { _enabled = false; - TerminateProcess(); + if (IsProcessActive()) + { + TerminateProcess(m_hProcess, 0); + } } else { @@ -144,7 +147,7 @@ public: if (IsProcessActive()) { - TerminateProcess(); + TerminateProcess(m_hProcess, 0); return; } @@ -224,33 +227,18 @@ private: return true; } - void TerminateProcess() - { - if (m_hProcess) - { - if (WaitForSingleObject(m_hProcess, 0) != WAIT_OBJECT_0) - { - if (exitEvent && SetEvent(exitEvent)) - { - Logger::trace(L"Signaled {}", CommonSharedConstants::SHORTCUT_GUIDE_EXIT_EVENT); - } - else - { - Logger::warn(L"Failed to signal {}", CommonSharedConstants::SHORTCUT_GUIDE_EXIT_EVENT); - } - } - else - { - CloseHandle(m_hProcess); - m_hProcess = nullptr; - Logger::trace("SG process was already terminated"); - } - } - } - bool IsProcessActive() { - return m_hProcess && WaitForSingleObject(m_hProcess, 0) != WAIT_OBJECT_0; + if (!m_hProcess) + { + return false; + } + auto result = WaitForSingleObject(m_hProcess, 0); + if (result == WAIT_FAILED) + { + Logger::error("Failed to wait for SG process."); + } + return result == WAIT_TIMEOUT; } void InitSettings() From bff3874b5fa3f073e2613ef46dbeef7db2eb29eb Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Sun, 27 Jul 2025 18:48:32 +0200 Subject: [PATCH 62/99] Only display powertoys shortcuts if the modules are enabled --- .../Helpers/PowerToysShortcutsPopulator.cs | 115 +++++++++++++++--- 1 file changed, 96 insertions(+), 19 deletions(-) diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs index 4d61dc239d..6f06d9a95c 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs @@ -23,28 +23,105 @@ namespace ShortcutGuide.Helpers content = PoulateRegex().Replace(content, populateStartString + Environment.NewLine); - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.AdvancedPasteUIShortcut, "Advanced Paste", content, "Open Advanced Paste window"); - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.PasteAsPlainTextShortcut, "Advanced Paste", content, "Paste as plain text directly"); - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.PasteAsMarkdownShortcut, "Advanced Paste", content, "Paste as markdown directly"); - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.PasteAsJsonShortcut, "Advanced Paste", content, "Paste as JSON directly"); - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.Hotkey, "Always On Top", content, "Pin a window"); - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut, "Color Picker", content, "Pick a color"); - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ThumbnailHotkey, "Crop And Lock", content, "Thumbnail"); - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ReparentHotkey, "Crop And Lock", content, "Reparent"); - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.FancyzonesEditorHotkey, "FancyZones", content, "Open editor"); - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut, "Mouse Highlight", content, "Highlight clicks"); - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut, "Mouse Jump", content, "Quickly move the mouse pointer"); - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut, "Mouse Pointer Crosshairs", content, "Show crosshairs"); - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut, "Peek", content); - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.OpenPowerLauncher, "PowerToys Run", content); - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut, "Screen Ruler", content); + ISettingsUtils settingsUtils = new SettingsUtils(); + EnabledModules enabledModules = SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Enabled; + if (enabledModules.AdvancedPaste) { - ShortcutGuideProperties settingsProperties = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties; - content = HotkeySettingsToYaml(settingsProperties.DefaultOpenShortcutGuide, "Shortcut Guide", content); + AdvancedPasteProperties advancedPasteProperties = SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties; + content = HotkeySettingsToYaml(advancedPasteProperties.AdvancedPasteUIShortcut, "Advanced Paste", content, "Open Advanced Paste window"); + content = HotkeySettingsToYaml(advancedPasteProperties.PasteAsPlainTextShortcut, "Advanced Paste", content, "Paste as plain text directly"); + content = HotkeySettingsToYaml(advancedPasteProperties.PasteAsMarkdownShortcut, "Advanced Paste", content, "Paste as markdown directly"); + content = HotkeySettingsToYaml(advancedPasteProperties.PasteAsJsonShortcut, "Advanced Paste", content, "Paste as JSON directly"); + if (advancedPasteProperties.AdditionalActions.ImageToText.IsShown) + { + content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.ImageToText.Shortcut, "Advanced Paste", content, "Paste image to text"); + } + + if (advancedPasteProperties.AdditionalActions.PasteAsFile.IsShown) + { + content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsTxtFile.Shortcut, "Advanced Paste", content, "Paste as .txt file"); + content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsPngFile.Shortcut, "Advanced Paste", content, "Paste as .png file"); + content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsHtmlFile.Shortcut, "Advanced Paste", content, "Paste as .html file"); + } + + if (advancedPasteProperties.AdditionalActions.Transcode.IsShown) + { + content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.Transcode.TranscodeToMp3.Shortcut, "Advanced Paste", content, "Transcode to .mp3"); + content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.Transcode.TranscodeToMp4.Shortcut, "Advanced Paste", content, "Transcode to .mp4"); + } } - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut, "Text Extractor", content); - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.Hotkey, "Workspaces", content); + if (enabledModules.AlwaysOnTop) + { + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.Hotkey, "Always On Top", content, "Pin a window"); + } + + if (enabledModules.ColorPicker) + { + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, "Color Picker", content, "Pick a color"); + } + + if (enabledModules.CmdPal) + { + content = HotkeySettingsToYaml(new CmdPalProperties().Hotkey, "Command Palette", content, "Open Command Palette"); + } + + if (enabledModules.CropAndLock) + { + CropAndLockProperties cropAndLockProperties = SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties; + content = HotkeySettingsToYaml(cropAndLockProperties.ThumbnailHotkey, "Crop And Lock", content, "Thumbnail"); + content = HotkeySettingsToYaml(cropAndLockProperties.ReparentHotkey, "Crop And Lock", content, "Reparent"); + } + + if (enabledModules.FancyZones) + { + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.FancyzonesEditorHotkey, "FancyZones", content, "Open editor"); + } + + if (enabledModules.MouseHighlighter) + { + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, "Mouse Highlight", content, "Highlight clicks"); + } + + if (enabledModules.MouseJump) + { + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, "Mouse Jump", content, "Quickly move the mouse pointer"); + } + + if (enabledModules.MousePointerCrosshairs) + { + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, "Mouse Pointer Crosshairs", content, "Show crosshairs"); + } + + if (enabledModules.Peek) + { + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, "Peek", content); + } + + if (enabledModules.PowerLauncher) + { + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.OpenPowerLauncher, "PowerToys Run", content); + } + + if (enabledModules.MeasureTool) + { + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, "Screen Ruler", content); + } + + if (enabledModules.ShortcutGuide) + { + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.DefaultOpenShortcutGuide, "Shortcut Guide", content); + } + + if (enabledModules.PowerOcr) + { + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, "Text Extractor", content); + } + + if (enabledModules.Workspaces) + { + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.Hotkey, "Workspaces", content); + } content += populateEndString; From 639b29eb8c76433c2f820a3f55dc5f1f7ee685fd Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Sun, 27 Jul 2025 19:39:43 +0200 Subject: [PATCH 63/99] Fix pinning and unpinning shortcuts --- .../ShortcutGuide.Ui/Models/ShortcutEntry.cs | 124 ++++++++++++------ .../ShortcutGuideXAML/ShortcutView.xaml.cs | 3 +- 2 files changed, 88 insertions(+), 39 deletions(-) diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs index bd7ce34f3c..a4b1bb819f 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; +using System.Linq; using System.Text.Json.Serialization; using System.Threading.Tasks; using Microsoft.PowerToys.Settings.UI.Library.Utilities; @@ -16,6 +17,29 @@ namespace ShortcutGuide.Models { public class ShortcutEntry(string name, string? description, bool recommended, ShortcutDescription[] shortcutDescriptions) { + public override bool Equals(object? obj) + { + return obj is ShortcutEntry other && Name == other.Name && + Description == other.Description && + Shortcut.Length == other.Shortcut.Length && + Shortcut.SequenceEqual(other.Shortcut); + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + + public static bool operator ==(ShortcutEntry? left, ShortcutEntry? right) + { + return (left is null && right is null) || (left is not null && right is not null && left.Equals(right)); + } + + public static bool operator !=(ShortcutEntry? left, ShortcutEntry? right) + { + return !(left == right); + } + public ShortcutEntry() : this(string.Empty, string.Empty, false, []) { @@ -54,6 +78,30 @@ namespace ShortcutGuide.Models [JsonPropertyName(nameof(Keys))] public string[] Keys { get; set; } = keys; + + public override bool Equals(object? obj) + { + return obj is ShortcutDescription other && Ctrl == other.Ctrl && + Shift == other.Shift && + Alt == other.Alt && + Win == other.Win && + Keys.SequenceEqual(other.Keys); + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + + public static bool operator ==(ShortcutDescription? left, ShortcutDescription? right) + { + return (left is null && right is null) || (left is not null && right is not null && left.Equals(right)); + } + + public static bool operator !=(ShortcutDescription? left, ShortcutDescription? right) + { + return !(left == right); + } } public static implicit operator ShortcutTemplateDataObject(ShortcutEntry shortcut) @@ -240,53 +288,53 @@ namespace ShortcutGuide.Models case <= 1: return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, stackPanelToReturn, shortcut); default: - { { - stackPanelToReturn = new StackPanel { - Orientation = Orientation.Vertical, - }; - - foreach (StackPanel panel in shortcutStackPanels) - { - panel.Visibility = Visibility.Collapsed; - stackPanelToReturn.Children.Add(panel); - } - - shortcutStackPanels[0].Visibility = Visibility.Visible; - for (int i = 1; i < shortcutStackPanels.Count; i++) - { - shortcutStackPanels[i].Visibility = Visibility.Collapsed; - } - - async void AnimateStackPanels(StackPanel[] panels, int delay = 2000) - { - try + stackPanelToReturn = new StackPanel { - int index = 0; - while (!ShortcutView.AnimationCancellationTokenSource.Token.IsCancellationRequested) - { - foreach (StackPanel panel in panels) - { - panel.Visibility = Visibility.Collapsed; - } + Orientation = Orientation.Vertical, + }; - panels[index].Visibility = Visibility.Visible; - index = (index + 1) % panels.Length; - await Task.Delay(delay); + foreach (StackPanel panel in shortcutStackPanels) + { + panel.Visibility = Visibility.Collapsed; + stackPanelToReturn.Children.Add(panel); + } + + shortcutStackPanels[0].Visibility = Visibility.Visible; + for (int i = 1; i < shortcutStackPanels.Count; i++) + { + shortcutStackPanels[i].Visibility = Visibility.Collapsed; + } + + async void AnimateStackPanels(StackPanel[] panels, int delay = 2000) + { + try + { + int index = 0; + while (!ShortcutView.AnimationCancellationTokenSource.Token.IsCancellationRequested) + { + foreach (StackPanel panel in panels) + { + panel.Visibility = Visibility.Collapsed; + } + + panels[index].Visibility = Visibility.Visible; + index = (index + 1) % panels.Length; + await Task.Delay(delay); + } + } + catch + { + // ignored } } - catch - { - // ignored - } + + AnimateStackPanels([.. shortcutStackPanels]); } - AnimateStackPanels([.. shortcutStackPanels]); + return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, stackPanelToReturn, shortcut); } - - return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, stackPanelToReturn, shortcut); - } } } } diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs index 6bb32c65ad..fc3e7e425f 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs @@ -6,6 +6,7 @@ using System; using System.ComponentModel; using System.Globalization; using System.IO; +using System.Linq; using System.Runtime.CompilerServices; using System.Text.Json; using System.Threading; @@ -351,7 +352,7 @@ namespace ShortcutGuide ShortcutEntry originalObject = dataObject.OriginalShortcutObject; - bool isItemPinned = ShortcutPageParameters.PinnedShortcuts[ShortcutPageParameters.CurrentPageName].Contains(originalObject); + bool isItemPinned = ShortcutPageParameters.PinnedShortcuts[ShortcutPageParameters.CurrentPageName].Any(x => x.Equals(originalObject)); pinItem.Text = isItemPinned ? ResourceLoaderInstance.ResourceLoader.GetString("UnpinShortcut") : ResourceLoaderInstance.ResourceLoader.GetString("PinShortcut"); pinItem.Icon = new SymbolIcon(isItemPinned ? Symbol.UnPin : Symbol.Pin); From 26f76105d4808fe8a1e454aedd690b274adf45d0 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Sun, 27 Jul 2025 19:42:18 +0200 Subject: [PATCH 64/99] Delete weird file --- 2 | 79 --------------------------------------------------------------- 1 file changed, 79 deletions(-) delete mode 100644 2 diff --git a/2 b/2 deleted file mode 100644 index 1a484908d9..0000000000 --- a/2 +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 509ad636fe05aa738484a972a0758f4c5d0ac9f9 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Sun, 27 Jul 2025 19:48:55 +0200 Subject: [PATCH 65/99] Fix spelling --- .github/actions/spell-check/expect.txt | 3 +++ .../Assets/ShortcutGuide/+WindowsNT.Shell.en-US.yml | 2 +- .../ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs | 4 ++-- .../ShortcutGuide.Ui/Models/ShortcutPageParameters.cs | 4 ++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index bc5ba04289..c5a58b670d 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -1145,6 +1145,7 @@ OUTOFCONTEXT Outptr outputtype outsettings +outsourced OVERLAPPEDWINDOW Oversampling OVERWRITEPROMPT @@ -1280,6 +1281,7 @@ projectname PROPERTYKEY Propset PROPVARIANT +Prt PRTL prvpane psapi @@ -1918,6 +1920,7 @@ WNDCLASSW WNDPROC wnode wom +workerw WORKSPACESEDITOR WORKSPACESLAUNCHER WORKSPACESSNAPSHOTTOOL diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Shell.en-US.yml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Shell.en-US.yml index 0e3913b0c5..4b7536a8ef 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Shell.en-US.yml +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Shell.en-US.yml @@ -346,7 +346,7 @@ Shortcuts: Alt: false Keys: - "/" - - Name: Open Gamebar + - Name: Open Game Bar Shortcut: - Win: true Ctrl: false diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs index 6f06d9a95c..16edb0ad96 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs @@ -21,7 +21,7 @@ namespace ShortcutGuide.Helpers const string populateStartString = "# "; const string populateEndString = "# "; - content = PoulateRegex().Replace(content, populateStartString + Environment.NewLine); + content = PopulateRegex().Replace(content, populateStartString + Environment.NewLine); ISettingsUtils settingsUtils = new SettingsUtils(); EnabledModules enabledModules = SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Enabled; @@ -152,6 +152,6 @@ namespace ShortcutGuide.Helpers } [GeneratedRegex(@"# [\s\S\n\r]*# ")] - private static partial Regex PoulateRegex(); + private static partial Regex PopulateRegex(); } } diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs index 99b4cd8a1e..f2faba001a 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs @@ -9,7 +9,7 @@ namespace ShortcutGuide.Models { internal struct ShortcutPageParameters { - public static SeachFilterObservable SearchFilter = new(); + public static SearchFilterObservable SearchFilter = new(); public static Dictionary> PinnedShortcuts = []; @@ -17,7 +17,7 @@ namespace ShortcutGuide.Models public static FrameHeightObservable FrameHeight = new(); - internal sealed class SeachFilterObservable + internal sealed class SearchFilterObservable { public event EventHandler? FilterChanged; From 0d5c85a00d33495bf84d7a10b923f10ef868f2f0 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Sun, 27 Jul 2025 20:09:54 +0200 Subject: [PATCH 66/99] Add taskbar launch shortcuts and make powertoys shortcuts empty by default --- .../Microsoft.PowerToys.en-US.yml | 158 +----------------- .../ShortcutGuide.Ui/Models/ShortcutEntry.cs | 3 + .../ShortcutGuideXAML/ShortcutView.xaml | 12 ++ .../ShortcutGuideXAML/ShortcutView.xaml.cs | 21 +++ 4 files changed, 37 insertions(+), 157 deletions(-) diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/Microsoft.PowerToys.en-US.yml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/Microsoft.PowerToys.en-US.yml index 3d4f539ce7..c768b4bb5e 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/Microsoft.PowerToys.en-US.yml +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/Microsoft.PowerToys.en-US.yml @@ -1,4 +1,4 @@ -PackageName: Microsoft.PowerToys +PackageName: Microsoft.PowerToys Name: PowerToys BackgroundProcess: True WindowFilter: "powertoys.exe" @@ -6,160 +6,4 @@ Shortcuts: - SectionName: General Properties: # - - Name: Advanced Paste - Shortcut: - - Win: True - Ctrl: False - Alt: False - Shift: True - Keys: - - 86 - Description: Open Advanced Paste window - - Name: Advanced Paste - Shortcut: - - Win: True - Ctrl: True - Alt: True - Shift: False - Keys: - - 86 - Description: Paste as plain text directly - - Name: Advanced Paste - Shortcut: - - Win: False - Ctrl: False - Alt: False - Shift: False - Keys: - - 0 - Description: Paste as markdown directly - - Name: Advanced Paste - Shortcut: - - Win: False - Ctrl: False - Alt: False - Shift: False - Keys: - - 0 - Description: Paste as JSON directly - - Name: Always On Top - Shortcut: - - Win: True - Ctrl: True - Alt: False - Shift: False - Keys: - - 84 - Description: Pin a window - - Name: Color Picker - Shortcut: - - Win: True - Ctrl: False - Alt: False - Shift: True - Keys: - - 67 - Description: Pick a color - - Name: Crop And Lock - Shortcut: - - Win: True - Ctrl: True - Alt: False - Shift: True - Keys: - - 84 - Description: Thumbnail - - Name: Crop And Lock - Shortcut: - - Win: True - Ctrl: True - Alt: False - Shift: True - Keys: - - 82 - Description: Reparent - - Name: FancyZones - Shortcut: - - Win: True - Ctrl: False - Alt: False - Shift: True - Keys: - - 192 - Description: Open editor - - Name: Mouse Highlight - Shortcut: - - Win: True - Ctrl: False - Alt: False - Shift: True - Keys: - - 72 - Description: Highlight clicks - - Name: Mouse Jump - Shortcut: - - Win: True - Ctrl: False - Alt: False - Shift: True - Keys: - - 68 - Description: Quickly move the mouse pointer - - Name: Mouse Pointer Crosshairs - Shortcut: - - Win: True - Ctrl: False - Alt: True - Shift: False - Keys: - - 80 - Description: Show crosshairs - - Name: Peek - Shortcut: - - Win: False - Ctrl: True - Alt: False - Shift: False - Keys: - - 32 - - Name: PowerToys Run - Shortcut: - - Win: False - Ctrl: False - Alt: True - Shift: False - Keys: - - 32 - - Name: Screen Ruler - Shortcut: - - Win: True - Ctrl: True - Alt: False - Shift: True - Keys: - - 77 - - Name: Shortcut Guide - Shortcut: - - Win: True - Ctrl: False - Alt: False - Shift: True - Keys: - - 191 - - Name: Text Extractor - Shortcut: - - Win: True - Ctrl: False - Alt: False - Shift: True - Keys: - - 84 - - Name: Workspaces - Shortcut: - - Win: True - Ctrl: True - Alt: False - Shift: False - Keys: - - 192 # \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs index a4b1bb819f..39b72caa75 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs @@ -204,6 +204,9 @@ namespace ShortcutGuide.Models case "": AddNewTextToStackPanel("↓"); break; + case "": + AddNewTextToStackPanel("..."); + break; case "": TextBlock animatedTextBlock = new() { diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml index 9b4d749e61..d0c998a11e 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml @@ -69,6 +69,18 @@ + + + + + + + + + + + + diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs index fc3e7e425f..28c7616ae9 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml.cs @@ -225,6 +225,23 @@ namespace ShortcutGuide ErrorMessage.Visibility = Visibility.Visible; ErrorMessage.Text = ResourceLoaderInstance.ResourceLoader.GetString("NoShortcutsInOverview"); } + + if (_showTaskbarShortcuts) + { + TaskbarLaunchShortcutsListElement.Visibility = Visibility.Visible; + TaskbarLaunchShortcutsListElement.Items.Clear(); + TaskbarLaunchShortcutsTitle.Visibility = Visibility.Visible; + foreach (var item in _shortcutList.Shortcuts.First(x => x.SectionName.StartsWith("", StringComparison.InvariantCulture)).Properties) + { + TaskbarLaunchShortcutsListElement.Items.Add((ShortcutTemplateDataObject)item); + } + } + else + { + TaskbarLaunchShortcutsListElement.Visibility = Visibility.Collapsed; + TaskbarLaunchShortcutsTitle.Visibility = Visibility.Collapsed; + TaskbarLaunchShortcutsDescription.Visibility = Visibility.Collapsed; + } } private string _searchFilter = string.Empty; @@ -288,10 +305,14 @@ namespace ShortcutGuide ShortcutListElement.Items.Clear(); RecommendedListElement.Items.Clear(); PinnedListElement.Items.Clear(); + TaskbarLaunchShortcutsListElement.Items.Clear(); ErrorMessage.Visibility = Visibility.Collapsed; RecommendedListElement.Visibility = Visibility.Collapsed; PinnedListElement.Visibility = Visibility.Collapsed; OverviewStackPanel.Visibility = Visibility.Collapsed; + TaskbarLaunchShortcutsListElement.Visibility = Visibility.Collapsed; + TaskbarLaunchShortcutsTitle.Visibility = Visibility.Collapsed; + TaskbarLaunchShortcutsDescription.Visibility = Visibility.Collapsed; ShortcutListElement.Visibility = Visibility.Visible; try From 16c4a56ca19c4ef55071da6c916541615ea8a053 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Sun, 27 Jul 2025 20:29:36 +0200 Subject: [PATCH 67/99] Make settings button work and add settings placeholder --- .../ShortcutGuide/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj | 1 + .../ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml | 4 ++-- .../ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs | 6 ++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj index baaa25dd33..6eb84f06e6 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj @@ -95,6 +95,7 @@ + diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml index a42615b474..68fcdb8618 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml @@ -20,12 +20,12 @@ - + - + + + This app may display content provided by third-party sources. Microsoft does not endorse or assume responsibility for the accuracy, reliability, or legality of such content. + The content related to Windows is always based on the latest release build of Windows. + + + - - - + diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs index 3be294a49f..176e971ac7 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs @@ -196,5 +196,10 @@ namespace ShortcutGuide { SettingsDeepLink.OpenSettings(SettingsDeepLink.SettingsWindow.ShortcutGuide, true); } + + private void InformationButton_Click(object sender, RoutedEventArgs e) + { + InformationTip.IsOpen = !InformationTip.IsOpen; + } } } From 68b7b4183f6f36d5114ddd271b9f0f357425e967 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Sun, 27 Jul 2025 21:11:16 +0200 Subject: [PATCH 70/99] Make UI better --- .../ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml | 8 ++++---- .../ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml index 2d83a9a527..e668d580cf 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml @@ -21,7 +21,7 @@ - @@ -30,15 +30,15 @@ The content related to Windows is always based on the latest release build of Windows. - + - - diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml index d0c998a11e..b5bfaea3c5 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml @@ -27,8 +27,8 @@ - - + + From b1d52336222d4decf58b5888c72c699c0b4dd738 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Sun, 27 Jul 2025 21:12:12 +0200 Subject: [PATCH 71/99] Fix spelling --- .../ShortcutGuide.Ui/Strings/en-us/Resources.resw | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Strings/en-us/Resources.resw b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Strings/en-us/Resources.resw index de6af34d87..a59ee3319a 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Strings/en-us/Resources.resw +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Strings/en-us/Resources.resw @@ -134,7 +134,7 @@ Pin - Refers to the action of pinning something on a pinboard + Refers to the action of pinning something on a pin board No results found @@ -146,6 +146,6 @@ Unpin - Refers to the action of unpinning something from a pinboard + Refers to the action of unpinning something from a pin board \ No newline at end of file From f8cc513f9c23bf03966e98138a4349c9fd2ebbc7 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Sun, 27 Jul 2025 22:06:15 +0200 Subject: [PATCH 72/99] Localization --- .../Helpers/PowerToysShortcutsPopulator.cs | 51 ++++++++++--------- .../Helpers/ResourceLoaderInstance.cs | 3 ++ .../ShortcutGuideXAML/MainWindow.xaml | 14 ++--- .../ShortcutGuideXAML/ShortcutView.xaml | 8 +-- .../Strings/en-us/Resources.resw | 37 ++++++++++++++ 5 files changed, 77 insertions(+), 36 deletions(-) diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs index 16edb0ad96..64c1a0860e 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs @@ -7,6 +7,7 @@ using System.Globalization; using System.IO; using System.Text.RegularExpressions; using Microsoft.PowerToys.Settings.UI.Library; +using static ShortcutGuide.Helpers.ResourceLoaderInstance; namespace ShortcutGuide.Helpers { @@ -28,99 +29,99 @@ namespace ShortcutGuide.Helpers if (enabledModules.AdvancedPaste) { AdvancedPasteProperties advancedPasteProperties = SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties; - content = HotkeySettingsToYaml(advancedPasteProperties.AdvancedPasteUIShortcut, "Advanced Paste", content, "Open Advanced Paste window"); - content = HotkeySettingsToYaml(advancedPasteProperties.PasteAsPlainTextShortcut, "Advanced Paste", content, "Paste as plain text directly"); - content = HotkeySettingsToYaml(advancedPasteProperties.PasteAsMarkdownShortcut, "Advanced Paste", content, "Paste as markdown directly"); - content = HotkeySettingsToYaml(advancedPasteProperties.PasteAsJsonShortcut, "Advanced Paste", content, "Paste as JSON directly"); + content = HotkeySettingsToYaml(advancedPasteProperties.AdvancedPasteUIShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("AdvancedPasteUI_Shortcut/Header")); + content = HotkeySettingsToYaml(advancedPasteProperties.PasteAsPlainTextShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("PasteAsPlainText_Shortcut/Header")); + content = HotkeySettingsToYaml(advancedPasteProperties.PasteAsMarkdownShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("PasteAsMarkdown_Shortcut/Header")); + content = HotkeySettingsToYaml(advancedPasteProperties.PasteAsJsonShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("PasteAsJson_Shortcut/Header")); if (advancedPasteProperties.AdditionalActions.ImageToText.IsShown) { - content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.ImageToText.Shortcut, "Advanced Paste", content, "Paste image to text"); + content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.ImageToText.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("ImageToText/Header")); } if (advancedPasteProperties.AdditionalActions.PasteAsFile.IsShown) { - content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsTxtFile.Shortcut, "Advanced Paste", content, "Paste as .txt file"); - content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsPngFile.Shortcut, "Advanced Paste", content, "Paste as .png file"); - content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsHtmlFile.Shortcut, "Advanced Paste", content, "Paste as .html file"); + content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsTxtFile.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("PasteAsTxtFile/Header")); + content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsPngFile.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("PasteAsPngFile/Header")); + content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsHtmlFile.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("PasteAsHtmlFile/Header")); } if (advancedPasteProperties.AdditionalActions.Transcode.IsShown) { - content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.Transcode.TranscodeToMp3.Shortcut, "Advanced Paste", content, "Transcode to .mp3"); - content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.Transcode.TranscodeToMp4.Shortcut, "Advanced Paste", content, "Transcode to .mp4"); + content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.Transcode.TranscodeToMp3.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("TranscodeToMp3/Header")); + content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.Transcode.TranscodeToMp4.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("TranscodeToMp4/Header")); } } if (enabledModules.AlwaysOnTop) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.Hotkey, "Always On Top", content, "Pin a window"); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.Hotkey, SettingsResourceLoader.GetString("AlwaysOnTop/ModuleTitle"), content, SettingsResourceLoader.GetString("AlwaysOnTop_ShortDescription")); } if (enabledModules.ColorPicker) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, "Color Picker", content, "Pick a color"); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("ColorPicker/ModuleTitle"), content, SettingsResourceLoader.GetString("ColorPicker_ShortDescription")); } if (enabledModules.CmdPal) { - content = HotkeySettingsToYaml(new CmdPalProperties().Hotkey, "Command Palette", content, "Open Command Palette"); + content = HotkeySettingsToYaml(new CmdPalProperties().Hotkey, SettingsResourceLoader.GetString("CmdPal/ModuleTitle"), content); } if (enabledModules.CropAndLock) { CropAndLockProperties cropAndLockProperties = SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties; - content = HotkeySettingsToYaml(cropAndLockProperties.ThumbnailHotkey, "Crop And Lock", content, "Thumbnail"); - content = HotkeySettingsToYaml(cropAndLockProperties.ReparentHotkey, "Crop And Lock", content, "Reparent"); + content = HotkeySettingsToYaml(cropAndLockProperties.ThumbnailHotkey, SettingsResourceLoader.GetString("CropAndLock/ModuleTitle"), content, SettingsResourceLoader.GetString("CropAndLock_Thumbnail")); + content = HotkeySettingsToYaml(cropAndLockProperties.ReparentHotkey, SettingsResourceLoader.GetString("CropAndLock/ModuleTitle"), content, SettingsResourceLoader.GetString("CropAndLock_Reparent")); } if (enabledModules.FancyZones) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.FancyzonesEditorHotkey, "FancyZones", content, "Open editor"); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.FancyzonesEditorHotkey, SettingsResourceLoader.GetString("FancyZones/ModuleTitle"), content, SettingsResourceLoader.GetString("FancyZones_OpenEditor")); } if (enabledModules.MouseHighlighter) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, "Mouse Highlight", content, "Highlight clicks"); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MouseUtils_MouseHighlighter/Header"), content, SettingsResourceLoader.GetString("MouseHighlighter_ShortDescription")); } if (enabledModules.MouseJump) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, "Mouse Jump", content, "Quickly move the mouse pointer"); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MouseUtils_MouseJump/Header"), content, SettingsResourceLoader.GetString("MouseJump_ShortDescription")); } if (enabledModules.MousePointerCrosshairs) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, "Mouse Pointer Crosshairs", content, "Show crosshairs"); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MouseUtils_MousePointerCrosshairs/Header"), content, SettingsResourceLoader.GetString("MouseCrosshairs_ShortDescription")); } if (enabledModules.Peek) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, "Peek", content); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("Peek/ModuleTitle"), content); } if (enabledModules.PowerLauncher) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.OpenPowerLauncher, "PowerToys Run", content); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.OpenPowerLauncher, SettingsResourceLoader.GetString("PowerLauncher/ModuleTitle"), content); } if (enabledModules.MeasureTool) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, "Screen Ruler", content); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MeasureTool/ModuleTitle"), content, SettingsResourceLoader.GetString("ScreenRuler_ShortDescription")); } if (enabledModules.ShortcutGuide) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.DefaultOpenShortcutGuide, "Shortcut Guide", content); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.DefaultOpenShortcutGuide, SettingsResourceLoader.GetString("ShortcutGuide/ModuleTitle"), content, SettingsResourceLoader.GetString("ShortcutGuide_ShortDescription")); } if (enabledModules.PowerOcr) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, "Text Extractor", content); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("TextExtractor/ModuleTitle"), content, SettingsResourceLoader.GetString("PowerOcr_ShortDescription")); } if (enabledModules.Workspaces) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.Hotkey, "Workspaces", content); + content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.Hotkey, SettingsResourceLoader.GetString("Workspaces/ModuleTitle"), content, SettingsResourceLoader.GetString("Workspaces_ShortDescription")); } content += populateEndString; diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/ResourceLoaderInstance.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/ResourceLoaderInstance.cs index 549bbb0b56..3441f76ef3 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/ResourceLoaderInstance.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/ResourceLoaderInstance.cs @@ -10,9 +10,12 @@ namespace ShortcutGuide.Helpers { internal static ResourceLoader ResourceLoader { get; private set; } + internal static ResourceLoader SettingsResourceLoader { get; private set; } + static ResourceLoaderInstance() { ResourceLoader = new ResourceLoader("PowerToys.ShortcutGuide.pri"); + SettingsResourceLoader = new ResourceLoader("PowerToys.Settings.pri"); } } } diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml index e668d580cf..98eb459133 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml @@ -21,24 +21,24 @@ - - + - This app may display content provided by third-party sources. Microsoft does not endorse or assume responsibility for the accuracy, reliability, or legality of such content. - The content related to Windows is always based on the latest release build of Windows. + + - + - - diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml index b5bfaea3c5..f2425e0ea7 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml @@ -50,7 +50,7 @@ - + @@ -60,7 +60,7 @@ - + @@ -70,8 +70,8 @@ - - + + diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Strings/en-us/Resources.resw b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Strings/en-us/Resources.resw index a59ee3319a..970a75ac91 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Strings/en-us/Resources.resw +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Strings/en-us/Resources.resw @@ -117,6 +117,9 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Close + Error displaying the application's shortcuts Shortcuts refers to keyboard shortcuts; Application refers to a PC application @@ -124,6 +127,18 @@ There has been an error displaying this category + + Open additional information + + + Additional information + + + This app may display content provided by third-party sources. Microsoft does not endorse or assume responsibility for the accuracy, reliability, or legality of such content. + + + The content related to Windows is always based on the latest release build of Windows. + No shortcuts pinned or recommended Shortcuts refers to keyboard shortcuts @@ -132,14 +147,36 @@ Overview Category title + + Pinned Shortcuts + Shortcuts refers to keyboard shortcuts + Pin Refers to the action of pinning something on a pin board + + Recommended Shortcuts + Shortcuts refers to keyboard shortcuts + No results found Results refers to search results + + Search shortcuts + + + Open settings + + + Use these keys together with a number displayed below + keys refers to keyboard keys + + + Taskbar Launch Shortcuts + Shortcuts refers to keyboard shortcuts + Shortcut Guide Shortcut refers to a keyboard shortcut From 2e6f80f94461f0e7afbca55da4292fb302bb7040 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Sun, 27 Jul 2025 22:45:14 +0200 Subject: [PATCH 73/99] Respect theme selection --- .../ShortcutGuideXAML/MainWindow.xaml | 73 ++++++++++--------- .../ShortcutGuideXAML/MainWindow.xaml.cs | 21 ++++++ 2 files changed, 58 insertions(+), 36 deletions(-) diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml index 98eb459133..d39c3389a1 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml @@ -7,40 +7,41 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs index 176e971ac7..285b82e1f1 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs @@ -5,7 +5,9 @@ using System.Collections.Generic; using System.IO; using System.Text.Json; +using System.Windows.Media; using Common.UI; +using ManagedCommon; using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.UI; using Microsoft.UI.Windowing; @@ -95,6 +97,25 @@ namespace ShortcutGuide Close(); } }; + + switch (SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.Theme.Value) + { + case "dark": + ((FrameworkElement)Content).RequestedTheme = ElementTheme.Dark; + MainPage.RequestedTheme = ElementTheme.Dark; + MainPage.Background = new Microsoft.UI.Xaml.Media.SolidColorBrush(Windows.UI.Color.FromArgb(255, 0, 0, 0)); + break; + case "light": + ((FrameworkElement)Content).RequestedTheme = ElementTheme.Light; + MainPage.RequestedTheme = ElementTheme.Light; + MainPage.Background = new Microsoft.UI.Xaml.Media.SolidColorBrush(Windows.UI.Color.FromArgb(255, 255, 255, 255)); + break; + case "system": + // Ignore, as the theme will be set by the system. + break; + default: + throw new InvalidDataException("Invalid theme value in settings."); + } } private void Window_Activated(object sender, WindowActivatedEventArgs e) From 3458d01d4c0e147e076a0c57017d6a070fb18126 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Sun, 27 Jul 2025 23:48:49 +0200 Subject: [PATCH 74/99] Respect excluded apps --- .../ShortcutGuide.CPPProject.vcxproj | 6 +++ .../ShortcutGuide.CPPProject.vcxproj.filters | 6 +++ .../ShortcutGuide.CPPProject/excluded_app.cpp | 39 +++++++++++++++++++ .../ShortcutGuide.CPPProject/excluded_app.h | 7 ++++ .../ShortcutGuide.CPPProject/pch.h | 3 ++ .../ShortcutGuide.Ui/NativeMethods.cs | 4 ++ .../ShortcutGuide/ShortcutGuide.Ui/Program.cs | 5 +++ 7 files changed, 70 insertions(+) create mode 100644 src/modules/ShortcutGuide/ShortcutGuide.CPPProject/excluded_app.cpp create mode 100644 src/modules/ShortcutGuide/ShortcutGuide.CPPProject/excluded_app.h diff --git a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj index 9e585bc34b..e7a222f0ae 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj +++ b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj @@ -105,6 +105,7 @@ true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true + ..\..\..\common\utils; Console @@ -126,6 +127,7 @@ + Create Create @@ -138,8 +140,12 @@ {d9b8fc84-322a-4f9f-bbb9-20915c47ddfd} + + {6955446d-23f7-4023-9bb3-8657f904af99} + + diff --git a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj.filters b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj.filters index bf13bf1b4e..1d265b5370 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj.filters +++ b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj.filters @@ -21,6 +21,9 @@ Source Files + + Source Files + @@ -29,5 +32,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/excluded_app.cpp b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/excluded_app.cpp new file mode 100644 index 0000000000..0f7fe4a336 --- /dev/null +++ b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/excluded_app.cpp @@ -0,0 +1,39 @@ +#include "pch.h" +#include "excluded_app.h" +#include + +extern "C" +{ + __declspec(dllexport) bool IsCurrentWindowExcludedFromShortcutGuide() + { + PowerToysSettings::PowerToyValues settings = PowerToysSettings::PowerToyValues::load_from_settings_file(L"Shortcut Guide"); + auto settingsObject = settings.get_raw_json(); + std::wstring apps = settingsObject.GetNamedObject(L"properties").GetNamedObject(L"disabled_apps").GetNamedString(L"value").c_str(); + auto excludedUppercase = apps; + CharUpperBuffW(excludedUppercase.data(), static_cast(excludedUppercase.length())); + std::wstring_view view(excludedUppercase); + view = left_trim(trim(view)); + + while (!view.empty()) + { + auto pos = (std::min)(view.find_first_of(L"\r\n"), view.length()); + m_excludedApps.emplace_back(view.substr(0, pos)); + view.remove_prefix(pos); + view = left_trim(trim(view)); + } + + if (m_excludedApps.empty()) + { + return false; + } + + if (HWND foregroundApp{ GetForegroundWindow() }) + { + auto processPath = get_process_path(foregroundApp); + CharUpperBuffW(processPath.data(), static_cast(processPath.length())); + + return check_excluded_app(foregroundApp, processPath, m_excludedApps); + } + return false; + } +} diff --git a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/excluded_app.h b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/excluded_app.h new file mode 100644 index 0000000000..652449a138 --- /dev/null +++ b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/excluded_app.h @@ -0,0 +1,7 @@ +#pragma once + +extern "C" +{ + std::vector m_excludedApps; + __declspec(dllexport) bool IsCurrentWindowExcludedFromShortcutGuide(); +} diff --git a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/pch.h b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/pch.h index 677423795e..1c0d2b748b 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/pch.h +++ b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/pch.h @@ -27,3 +27,6 @@ #include #include #include +#include +#include +#include <../SettingsAPI/settings_objects.h> diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/NativeMethods.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/NativeMethods.cs index 3582708b3a..987912c464 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/NativeMethods.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/NativeMethods.cs @@ -48,6 +48,10 @@ internal static partial class NativeMethods [LibraryImport("ShortcutGuide.CPPProject.dll", EntryPoint = "get_buttons")] internal static partial IntPtr GetTasklistButtons(IntPtr monitor, out int size); + [LibraryImport("ShortcutGuide.CPPProject.dll", EntryPoint = "IsCurrentWindowExcludedFromShortcutGuide")] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool IsCurrentWindowExcludedFromShortcutGuide(); + [LibraryImport("User32.dll")] [return: MarshalAs(UnmanagedType.Bool)] internal static partial bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData); diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Program.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Program.cs index 3010737113..f36e6b202c 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Program.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Program.cs @@ -37,6 +37,11 @@ namespace ShortcutGuide Directory.CreateDirectory(ManifestInterpreter.GetPathOfInterpretations()); } + if (NativeMethods.IsCurrentWindowExcludedFromShortcutGuide()) + { + return; + } + // Todo: Only copy files after an update. // Todo: Handle error foreach (var file in InbuiltManifestFiles) From 84ab12027b828ca51732a81fd46f1ee550205d2c Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Mon, 28 Jul 2025 02:02:55 +0200 Subject: [PATCH 75/99] Add welcome screen and update settings and OOBE --- .../ShortcutGuide.Ui/ShortcutGuide.Ui.csproj | 6 +++ .../ShortcutGuideXAML/MainWindow.xaml | 1 + .../ShortcutGuideXAML/MainWindow.xaml.cs | 46 +++++++++++++++++- .../ShortcutGuideXAML/OOBEView.xaml | 43 ++++++++++++++++ .../ShortcutGuideXAML/OOBEView.xaml.cs | 16 ++++++ .../Strings/en-us/Resources.resw | 33 +++++++++++++ .../ShortcutGuideProperties.cs | 4 ++ .../Settings/Modules/OOBE/ShortcutGuide.png | Bin 263160 -> 130540 bytes .../Assets/Settings/Modules/ShortcutGuide.png | Bin 90990 -> 130540 bytes .../OOBE/Views/OobeShellPage.xaml | 6 ++- .../SettingsXAML/Views/ShellPage.xaml | 6 ++- .../Settings.UI/Strings/en-us/Resources.resw | 12 ++--- .../ViewModels/DashboardViewModel.cs | 1 + 13 files changed, 164 insertions(+), 10 deletions(-) create mode 100644 src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/OOBEView.xaml create mode 100644 src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/OOBEView.xaml.cs diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj index 6eb84f06e6..290ff52c77 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj @@ -32,6 +32,7 @@ + PreserveNewest @@ -101,6 +102,11 @@ + + + MSBuild:Compile + + MSBuild:Compile diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml index d39c3389a1..66323b6f4c 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml @@ -28,6 +28,7 @@ + diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs index 285b82e1f1..ca33d546e6 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs @@ -16,6 +16,7 @@ using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Input; using ShortcutGuide.Helpers; using ShortcutGuide.Models; +using ShortcutGuide.ShortcutGuideXAML; using Windows.Foundation; using Windows.Graphics; using Windows.System; @@ -31,6 +32,7 @@ namespace ShortcutGuide { private readonly string[] _currentApplicationIds; /*private readonly bool _isInWindowsKeyMode;*/ + private readonly bool _firstRun; public static nint WindowHwnd { get; set; } @@ -98,7 +100,10 @@ namespace ShortcutGuide } }; - switch (SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.Theme.Value) + ShortcutGuideSettings shortcutGuideSettings = SettingsRepository.GetInstance(settingsUtils).SettingsConfig; + ShortcutGuideProperties shortcutGuideProperties = shortcutGuideSettings.Properties; + + switch (shortcutGuideProperties.Theme.Value) { case "dark": ((FrameworkElement)Content).RequestedTheme = ElementTheme.Dark; @@ -116,6 +121,12 @@ namespace ShortcutGuide default: throw new InvalidDataException("Invalid theme value in settings."); } + + _firstRun = shortcutGuideProperties.FirstRun.Value; + shortcutGuideProperties.FirstRun = new BoolProperty(false); +#pragma warning disable CA1869 // Cache and reuse 'JsonSerializerOptions' instances + settingsUtils.SaveSettings(JsonSerializer.Serialize(shortcutGuideSettings, new JsonSerializerOptions { WriteIndented = true }), "Shortcut Guide"); +#pragma warning restore CA1869 // Cache and reuse 'JsonSerializerOptions' instances } private void Window_Activated(object sender, WindowActivatedEventArgs e) @@ -179,13 +190,26 @@ namespace ShortcutGuide } } + if (_firstRun) + { + CreateAndOpenWelcomePage(); + } + WindowSelector.SelectedItem = WindowSelector.Items[0]; } } public void WindowSelectionChanged(object sender, SelectorBarSelectionChangedEventArgs e) { - ShortcutPageParameters.CurrentPageName = ((SelectorBar)sender).SelectedItem.Name; + string newPageName = ((SelectorBar)sender).SelectedItem.Name; + + if (newPageName == "") + { + ContentFrame.Navigate(typeof(OOBEView)); + return; + } + + ShortcutPageParameters.CurrentPageName = newPageName; ContentFrame.Loaded += (_, _) => ShortcutPageParameters.FrameHeight.OnFrameHeightChanged(ContentFrame.ActualHeight); @@ -222,5 +246,23 @@ namespace ShortcutGuide { InformationTip.IsOpen = !InformationTip.IsOpen; } + + private void HyperlinkButton_Click(object sender, RoutedEventArgs e) + { + if (WindowSelector.Items[0].Name == "") + { + WindowSelector.SelectedItem = WindowSelector.Items[0]; + } + else + { + CreateAndOpenWelcomePage(); + } + } + + private void CreateAndOpenWelcomePage() + { + WindowSelector.Items.Insert(0, new SelectorBarItem { Name = "", Text = ResourceLoaderInstance.ResourceLoader.GetString("Welcome"), Icon = new FontIcon { Glyph = "\uE789" } }); + WindowSelector.SelectedItem = WindowSelector.Items[0]; + } } } diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/OOBEView.xaml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/OOBEView.xaml new file mode 100644 index 0000000000..b93aacedad --- /dev/null +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/OOBEView.xaml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/OOBEView.xaml.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/OOBEView.xaml.cs new file mode 100644 index 0000000000..b57bc967e5 --- /dev/null +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/OOBEView.xaml.cs @@ -0,0 +1,16 @@ +// 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.Controls; + +namespace ShortcutGuide.ShortcutGuideXAML +{ + public sealed partial class OOBEView : Page + { + public OOBEView() + { + InitializeComponent(); + } + } +} diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Strings/en-us/Resources.resw b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Strings/en-us/Resources.resw index 970a75ac91..ef33f956af 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Strings/en-us/Resources.resw +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Strings/en-us/Resources.resw @@ -143,6 +143,12 @@ No shortcuts pinned or recommended Shortcuts refers to keyboard shortcuts + + Send your feedback of the new experience + + + Welcome to the new Shortcut Guide V2 + Overview Category title @@ -169,6 +175,9 @@ Open settings + + Show welcome screen + Use these keys together with a number displayed below keys refers to keyboard keys @@ -185,4 +194,28 @@ Unpin Refers to the action of unpinning something from a pin board + + The new Shortcut Guide V2 now includes shortcuts from other applications (when they are running), the ability to pin your favorite shortcuts (by right-clicking on them) and a search function. +Currently the following apps are available built in: + + + More apps are to be added soon! + +Click on a section in the header to see this apps shortcuts. + + + Microsoft Windows + + + Microsoft PowerToys + + + Windows Explorer + + + Windows Notepad + + + This page will only be displayed at the first run. To access it again click the "i" icon in the header and then on "Show welcome screen". + \ No newline at end of file diff --git a/src/settings-ui/Settings.UI.Library/ShortcutGuideProperties.cs b/src/settings-ui/Settings.UI.Library/ShortcutGuideProperties.cs index 4cf498073d..1895b47a9a 100644 --- a/src/settings-ui/Settings.UI.Library/ShortcutGuideProperties.cs +++ b/src/settings-ui/Settings.UI.Library/ShortcutGuideProperties.cs @@ -18,6 +18,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library Theme = new StringProperty("system"); DisabledApps = new StringProperty(); OpenShortcutGuide = DefaultOpenShortcutGuide; + FirstRun = new BoolProperty(true); } [JsonPropertyName("open_shortcutguide")] @@ -28,5 +29,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library [JsonPropertyName("disabled_apps")] public StringProperty DisabledApps { get; set; } + + [JsonPropertyName("first_run")] + public BoolProperty FirstRun { get; set; } } } diff --git a/src/settings-ui/Settings.UI/Assets/Settings/Modules/OOBE/ShortcutGuide.png b/src/settings-ui/Settings.UI/Assets/Settings/Modules/OOBE/ShortcutGuide.png index ccef1f4c312e31b6b0bf12bf5a4152c33bed9d2a..7e639fdb90291c8eb78f29e7fae3f7db8f0663ec 100644 GIT binary patch literal 130540 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 literal 263160 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 Nv4$m1qtgwyhM!oBV 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

4}% zXFxj(il-W$#?{C0tMpzSpf0jrjd?UMVmzT;lh{-`c!jK$=owup_fR2RUhMM(E4&!l z_(9}4#=7BY7Q2ZBGePLNDP>#Fk(HzkfZ<7nI{-aE!oL*^aiN{CO6}?MjpZp|U)h`s z8c{dbrF%?Z(gJmzpxwGvY)|z+s44(^0u{XW_d9$2>~<(wTHvs?wMyaQbQ9Ep*^B`3 zkGY3-+j4c26N;c9D)BaANvtVBl?%M|+_Od-Q6_4(ic(kZAr+Su3#R!4BMH+5sk|H* zj2x^Cs?%Tr8Mxdq9{bMCSj4Bj?txHxhrp72N3|AupeITO*J0qAAuI7N9Uy=mWhi)%itN6s4)^*eGneOsjS89V*^Gc4hH?n;W`x zIrp*paTgL|i+ad`j}Dq9td!QA{5O#v~Xr? zpb`{<)GyG$(UTljbjuOPUm3;x(VGa(v^@i{y~^u@K{q&kjp2@BrjHXWZ^A#6Wv0P-;HOZrLm*EZ@W8Ar+|t$Cnwk|kLw1S+Io_6G z{S!B?0Y8Dbr3SYGR?Ltb&=2usEj(Ste9s_XQ{9fAR<`zD_`*y^Il8bHMjy=(Bf!|2 zZz(@EHoSd)d}GVuY?>(M#k%*9u$1I*eNDF4P^>WSQQUd<=vUGv#t8DO68@@$_ z^gwV})%9?IK%ke~otk9*%_0I-Q+e61q%X-ozR;?f5W{$+`vQywf2y7ULs zjTlAT4aDvfEaI1^3cX-Qz3Kb1hOroMh=zOfh{6zBzdY{2(s$SgYGgb#N7;$0`z|2r&MA-yh15FAABaR@pwWy)9PAS3f+8xkNxv1- z>Qg6YmT%2`p;h$C_;Qw@`4a(sx}R!vNhE1bqJUxhVF zya=}t$9bke(Ju7!ebQy=Y&?QDIh!pqZ77Lkgb_LpF3~a)%{x{o)~^;KIKUXMcCg`? z2lN`fH1OyqU;@^wr07njBy`X~b%ZK1KKA_rt(2lumnxKwW9`H5frUww0G+G}dx;ko zmRZOTs*XIN(Hcmxa85q2i4zZguOdm+mf zD3u{#s-Ti?Rg~1(tP@8;O`D36T*nGpA`J+cDs6GG(90Uu;4|=O`B#wg1&u$H$@l^5 zcic;3)B!^n7wII-gE=4AY^VOp7 zNuSF=50XXuT#z`Xx#sFd4(4Z#D3uPzed*F5~Q)js4%8eW05nB_l|HjFiI@kNe*+2{R0xMTBm` zB-sJMBNGW}7ql!Q!Eyxp+7a#W*Alq|H*g2eVNh_6YF;E!3K0uIu-#UbHpSpfrGX4j zMNX-_M_aU)MK}dnxfozew3;ANV*v&P!iakV>#}>CX?XAJ1GQ?1|!O z27C7iRMl_4|NirT|Nfb;Q#bti`w)Zw@jJ58Z}QZ?{`J3q{MUbfNx<`u|NKK*z^P}# zepCh5!EYF4>Hy!FWg(%?Dz@=R;EhesxkPLe(O=k}xH|_!N`2uQRuvidCHy#*>Dy(| z8me8S?UcX6^6@2Cj*NVPrW^G9f{n$@f=fssG zrDAKV(|_)UB#b>V1l9Y;$OLK2F*iEMK;x7+NvWXcx+H^lT$`98*>zvAOeC4I#+kHZ zC9muI)b@YQ8@APU(_YIQTj4M=hqq0)har;8(kF$Aa~ya#JXMk*i?3)Y&lRfL%@RoV zJ&ii?rC`y-g(OmH?cQ-ItEC7dXRR5Coxy2By@~mWQ%v^-B|Z0FRM$2^1KPPPho{vAGuZ)QS$RceEsl$zVI4 zfIYCJ&MIZf4SS32cPbcW!`By8$aDf--_N&`Dy{b0>HPd0SofBl(d^lW>L5oi@ZJ6N zu06f4e~;uG&in3C`iW_M>=_M2Kmi@HSdB2GICT(78nl^}MXaheA;2nUbK0L^Rs#nO z$%b_{{r$=&AydO<81N(^)5B8n>lNi98zQv=6xT8-FQbkrGInhR-=}b|r_8c~Rsua< z3Bhv0!_+JH(hQNng^t$j-IJs9Petw`EX2sID75^`dRSnTUL2s!Y?%_kDycMw(~-`5XRDy~tX%4={% zIDSA=ajW0zDn6|0peC5(N$%ER#=xZ~Bbxja*_^O6*I*qlX(@h#*R)J>bXFv* z5HK*T3qQrj&bg+-(Q^c88VXw?hJgVBMV#lR&{hnV`40_Ey0%2wn_yY{z|t>Xea0D) z^P-B+Ab`Ot)!K6Bn9zcCX|;7+|8YifA<-UlTF6ZD$oFZ2?D+cmnfO=#aV1~w?&$Cu z7ipJp7cf*X&c5^QwHQ=d*krZ!hDluuRI%2Ij28tIDW$l@GR4$;jgb zuvPaVSfZ>FWxDS=iHH^F$nzyP`1LusvG`Swv`EGQj2-b2v0oQ`7M>+&J@honO6O{z8}^cJ~>@i6T%wn$d$q}#!+?5k=w9{N|0Zv z;zvt1&1Vqh&8GzrtwIy=b2KfLyJfTH&3&*}D7Bc^?m`!eJ$6r_zl7ct{!U()PmL(MZn8mrMjU&G%(nCA!srV(zGZ6ingfJ5+gaKR6G*D8|F7 z2K$1C6MS~$Pyi@{oq>)f*2!#-L9{+6=q)h=Ib-ilGGf@zWr^Md6k%%QkZ-P4^Wgk@ z%x^T%!n8BRn1>Gs^>cYTv+Pt_wt1k(X!}l>?9c`#DgM7FcBCA}X^Ev(?4TQB`2GI> zj6k%EKs`6PhJ8^*pU8)vlYp_4^jje zX5QkRZRm*`1UYSlzARp>J3z0${`%`UX1&uW_>;vneH*$-xCqti1%Y~Y(#g1FshcR# zE-7t66}OF#E5!n`l+pGyNQV=peu6d< z{9ld}Pm0i{&Y&=%Iaq}wID_TL{}gX_UD_Vb!<^$v6lL{h^Mr~kwc-+h2t_7V$QQvK zG+>~JMCfowT9LM}J;vtZ9b($ySmiuPqRQ_vSM?ON`@GF9vYh-vs=)t9IND`6yRtCQ zD*O_54d0>C9TE(kJ;%L>nuFf)Vu17{(wnc&m(Hz|%%d>UZ>0AwH%ZRTu$C3+=-D~N z7G3i;Pl#LrCHadnKrAya3lpJQmE{a?H?ws9{GVR~ljTm04SR$v(~lwP@1Em;J204P zcu*Ej8w_QT*f-V#INiZQEI$d*Ern?FCAtiVYAH2G8Q zYSqwagaZ##*ix26cZBxY$M5c$bFJZpvyS!Y_wRYx0MvGk<7@AnHgncrK|#-M=)w6X#z}pT z(?!29^c4G0Y!@9mIhmr1zAIooP9;{+bFyS}o%ZwoN=2^amOlZyE067-K4nt7@Q*c7 zvj>0V4o-H(fAq7l723UqQki|6CyO8H>SGQlXY2>Fm8MR}60Gh`L8;gDPJlal|sKR%fF`t{ZlQ?k?h*h=JO53SwB zd+|qla#>d5k+0Csf=)1(|=|Aqm5j>`dheZ1eTJJU*Jo9sLdyZDV71K9G>`pUxGY zt%$!M0OTvPIZRo>$|DUb<49F0(2w`bW2b_k&4c{rNHK>EL_hG(D2$J4T+{#OtM2W8(C8^@~ z48d{S(A1p4;3ftOMb%iyDp?ySH|!9`(0^@$rlfxQXj9x5ExJe()RPJtV}IM$M;Eqw zd2H)=1iR@RzQBH)MYkWe$BD(6apv^dqZ6v1sk0v5o?rD`*|&=3daP+sSXZFJICsR8 zsih6UHgG!oC%onCtOQWWm9WEN@#HW3IesCRW-GnM$RIw9clbAAPIG&FB_1s;FCJ#j zTd0FcQ)|obmGVw#bw+< zUW_Z-B1rT4_3Ky8XUfI=$tLDC2*xVH5YP3MOe)k0ZhEJTw45zP@(Hck42e3EL|jF6 zGn?mp7Nr+W=qm~=*ajsYh`S{BU_ZI*m|9+359J1eyAU;xE96e!;|j4C-dKY82N}Io zb~2d$5FPe@OVb6ms#GL)0N*rvR!=zOWq6qGfXJ9J1v0Cnc`auR4(HZ#mI&-zQ6KMN z65-{L)wr~N3lk@oQN@W$9PdLuO&cGLXzhWF!@*kAMl#Z`_vWVL%CTt+NX3&dxwvQX zTv63=bkM2J8yVPY@t6SupW~NVuQZDoe)`H#*&R4%PXXMStY*6OLcNwM>yOoh#Jv(LL))8xBOx_4Tv79K!P)%!aJ z`@|anrAW(RW=lzsMschuF{CK{E_%{R{@CYm7eCXDyeL+DM!ygj z!*q`?%3bodJ`bh*se+8XuRs6%Gwp1*)=Pv3+O&fovvau}dym|HH*vx$HI!nzjR(W6mSqjk;vOyaX2smN*|pkM15Y)0c*N4*de3t@+Zeg-(2yo*(5Fr z1KqR2CpjH1RjPcpAQJ8OR;hZb>|5M2H^-~Sy;N^MG|>1QM~4zZ1lqh%t2e+=9J zM8?O`zb~LKPCgMl{5F0hjUO(0L=#1Ia6ds3r^TCEH9_+xqU*04c6W4cC_NH>CKd?9c{nMU zR&Bf+eWIz2^VTsK9-?Cae&O!1r(zK6EfeXIiveL0ZnpPQ;EkzO8Uym#yr#8cH^KAz zv@^b|=Q8DiU@wJ}Qq*xFPXz%1je($fF|OWvvp~O`^Obib&@}z%`or}>+P!SXAPy!r zI+QH<>u~DwqQzeoY4-G_yk1z1Bnmcah~F}_ocTNFgJY#f`d5-Ukn0Jdje!=yCSAgz z3=&mB0tRi`XXCj2#bQyVO-xjfDwN0@JBV)#N7+0{YrTdKQ3U+7(Ks&SwrkSSw-#>9 zwpciq#jb931&`J!e{ok}36BNO-G9DNXF17J%1USb=AJ!6eBjRj~U|!>;Sdcvq5l5(h_z z+Fgnvwc}c^Qw9e~Kwt1ix#F8fI1A^T{2bW*ajxI77ku!$WekdGt)$7TP!o;Y0u*ccx(DUb6mmwA$-^umi7HQ3 ziFZNX+As5w3=~kd*eHWKOyUdNFMv)DOB-U@vWnsZ8IaqMt8-YgF~Lx%uxk3TtVlkq zZ;R=wR{_^0YYcUXi0@N3ne}peX@2q*@qVNgcz_i~=SsyKA<2!*#adXX?>zU(O3Lhv)1k|wbxow&b-Tt%%Ulor&&(;C~TdL`Up{t zvSM~JWOq;KX9i*tE~=*hcU>YKAebU7ox+LZm@@Y9D6~3Jo_N%0W}IjKO`!z6^py_c zo3BLcCpdjybk4BryD2p5I1GHxIWQaVvM>Z7Jx{#KP#Q4IXs_o$Hr`Ay%k`o6k~5Hv z7vw>^3|TYYgG?lZbu6+J0#k}y>E};2JCZW|m!4i+0JUSV9+Yx%o=gEDzsSFDW(+=5 zG+ja@&@o^c>m%MLR*l7vP8!IU9;@)Mk`NZ*0Ajs754Ynd;<5f;6^5sbcfYZHD=*B+ z0IRe3gwY0N=ZEVDdnM5We2Xc+;&m>(CzT)L{-wc_m?}112{$_gCAS##O{__fUUOL- z83eAyg%o!#q2E}uEdtxA4Y9uBGvllDdRIzcOjR5$q{ZvS*v#pLV;H7!QtlnfWNW6a z(Vi&&)5)e>iVFcx0IND!_2uc}>`Xvds1N6paKVKI_N~jqa@_LcKV(3$4#oUpoq*Ax zy|fpxYL)RyG`GHZe-qk1k(~@+g!rQ&E1Qh?aR;feUZ%-Z0Nm;3Uov3=`-}GRc-Y7Y z4mz1R7EbT<3V#HPAPD+hrwy-XcSyPnxN?5F5D9-0p1~Jm(5+KTv;jXR>`bm z>9ojd0KUhTTIO6N&*Zc~VDhh5dw#ushM2j?Hu!I@wLT!NabC z{}3_n0-(QI`kA5~s;?7WA1}SDFVPHiN)MEp$E%|t9DjTEC*w=Zk%h1auQEjN5}>`K zJ4=EH&Vgn&3!tRSWkT@4TiHrG(`c_)h`Mt7XFqbDS|E)jJJgMdBh9U&jHQmZfg- zT<}YMIo*aT2=}Mr8QuVK3`T{zS*d)%^z1ZGz^&!;aXoNxAaj;1PvoT)pV$He+t;#N z^n)Eety3DNK~UbB(WQf3fmlT$5je1&#&>l&U#!-ki(B?(eX?mX#P$4`%_pI zkvw}eP%t|x0X9mNJXbjB>+?Ltus=_3xKmZG{cLOYA=+jnK0Vd&p3YsP` zNKa5m+ry}JgR#T68r}6crBZ+S%&E8`#S}Z)Y=Td#zU?QS;liCmKE*Yl;XU8{y)xdU zJ(Ei8FwZ$lzV{?I7kFioYPbS6q-1jZ9tai5q|94fCEb*?E2hTSZ6Mp5yx9YHb&Nub zi(%b91NU&QJj2&MWlB#?NA@c~utNK(>v5&nYDqsKW0vRE94yPy2xvUcNdU>b6pdhx;n)v8cQ)9wcPRwHtVs(I8cthdf1s0AjF&Q zgv8!|{xQdR?73>W*8u1o>$zm3M3vF@aV5-|%h76|3$nQ5C2x}@EDh|f;XxO|u_F;A zC;Uz>0l4di7IR&1<1Ru9{k2a+%3SS>EegC6MntK?UCU~Ofd!kZ#;{J@qjruAB)Sq2 zqGQv<`+&Tsnvq{O26HbZmPWHIY?dP~jD8APtJZd~Z=5pLijJ-4OW(qr^F^7KT<7+1 zp+vyA6xcP#xHI-WE^B@5O1mxzqw+urv6j69=ckP62l^e?tStoC1-7*z6tWP0IL;to zRErEV`LPQB`LMa*w*hfoo#2Fe#1+sFWL1O{B#|5oc-A#ZVx9vu313}Qo+)zyYQ6Pk z#iw|`;uB?-#AU3)G-A>o`NtC6C7&q~5zow!mN!*>Y0O*uzwCgFx4AW-fu7EA+uI=a z@F1BW^h9a*nO9^ln{lkl#I>61pgHET*j+RI+U8rlFiYw=jG5&@%-bAow)gDsITF#v z^~Y#`j`sfidz)=bk1u{ z1Zt6grXz)IpiM6ie>9N{k0IosWy2#3P@w}6=~RFBO~!@?z{9B|%d|037PxG(ik5VU z4#dVlxSN@K{X9pmd59~fw#TP>fMN&fr07&L%j>g@Xi-WOk2I#cmYMA(iUt4xY^G+1 zlnjUovd@gxN4OQYQv9&Yi))F`>vM^l)BDae^m#islLwW`ntKkoLOL`p2~H$&n-QyV z&RHx8^0B#GrzL`w+0?9A3D@osI@YY`N_MlmYzH8dP(7hy^*tUdy~^v&WLa~lv{scx zggU<3BRR2z5?0oZ9Jo2If=&)5=vcOl`{;_CHpCUGACMpdk}}y2Wn$S^mi(s0W_FMm*)f7Oz)WE!CzK=4^&=w< z!r4H)zaMCz5>jmxL0&DU_4rHhHX@5GWcoDo{dY_W=wj^hSsJJ%_v@V+AAk-mUCG_5 z)h56_g_dPT(d#~RHedXdq;+nFUxfF}8COI%s6GA+F^|T;A_yS(-17YTK#_Xb@^s`6 zb3V|qp8cEvkVs$05wIl@Oa2(9mMlyE zOFF6hDWw80%pESzKw}h#tUrbk-fpe{EtMw;x(jZr%iX2qv!%%sg#~?K>1bvqKzq(* z&}bQVS9+M+<=Qs7nMVX`lZM5K9doi+b6vaE{Jy`wzCsgGmaF1XT}Kj^@I36zgQ!0NgsPmjzS z$6yvXy!G#AFEJ`U-{_xwDdSir=DUC9W3!leD234n8X*V-M=&=P=}dV@heP3{bvMX0 zr6yaZroKW^?{RF#xeuV^OhiMSpK22t;UYP!AIsB{!%~CWhF*Sbo{-)@zqK4>J)r&y zw$zz@F5po*CI|Bs!DV(^#cBI|4|SWlZ_o<0GA#+p6@F?UJFY5Xo8d zdVB;`TeML~w~Sb}4QQq3*Q=+;s%(wb=sBoS=a{c#jl{OwK9s8Vr=5&0%VF1>oR;4J zj2Ue4X`t=c5|a*`tE?k!8d>IUw;)vtvs$Zb(&hvY#M*6fgIFkIUu@}j#g?osC4>KUC1 zpygDi6{amiANMz30jPKzk+wV=x!U#H`${`to;@)^tL%JWrqTK7DQ ztutB(T*=fHo<_>^qePC0i09$`kaEYqJQqC|p&)K@lP;NhIex>Q_N*Jqrpt235@TUTE^o<7x3VbYbwNae3_f{9Q&RQi z(td8lPbg~$L!J`%w15BWpJM_s>meH3M2L8LUdke9H@FJSZe^Gf>D|i(t%2YbZkfMi z9+Xnxb@i{Ws$?fLoiq5GkFg$rdkBGlZ;U+g^VHrm?zF*~+DKN68$K$P=fu@cPgqbS5m^=D1S zIuQjx67M5%QAS3@%7>*Qr?0K`nIIBDKHD?N&6(1*sFJ5dl2Tan=-nfyk-I%@&0B9~ zCeRl=fm0>0(&wx037xJk6m*ro@_d19*Znk+7q1#>{uuR7DTk?y*D#^X6Y zHvP%FFq8)r4HWJO9iH9)_gNAR`3rH8+^x5_zRVZiSFEjKI+QpXnJlOSbW%xJN4@L% z`@~88J>w!(K_#2ZZ-|i3^-qIrpmBMg5D6*Yw9%g0!b*x+uGB03@3`jW<6l;Ip@2@z z)6iLRq6L|NhOE~a)746#D9&j_SM5SXY+DfwJG}56Zi`x-Q>8aKZC``3%o+C0I;D57I|{egFA7V>@j0E6Gum2{YOg z-#v`eH%JdWGF%AEKNr`zFIm4t2=lx9I>uJtUexI_-mA@_W}p#lnbYhCk`ZJI`N5;i z!eX^b>k(1UQ~PpPL9Lbp7;RV2E0wMyt#HCq4HLzK1CZ+MrC5z}tWDR$6s8RsU+k`5&c8-z{AU!l3G9v%}eu&e=R*Y;TvT;LI5X_^9z&;dWOb=a6%m zzV*sSxZZ1I`#_=@TcVFR-6~cfdW#}#t-n8)0UdaINQY3hD276SwEdXKXYJnEiY;ep zNpgd0?T}atBiUdb^A6)>8XjI!S!JuJURbricUO(|1s+>gW# zt>*JAW}H_(e&MCiDG8T7bc~p2;U|2BJM_bUOfAGmWW{Y zbV5LJp0}R0xX$?Al|7j5;8Oec<8{8S)?P2th-tQcw_(1Yanur+OMm|9)w6QZN-ZTb z(^c0Gi(0&0zbk1NcW&lH!Z|w`1I-vvA+c`u-a~LhQcYf$|E#vHS7L4rOHsq9Fsu$IoQJP#__=nm;hs;Y8LA&AIIaDe9@HOI zer+ZWU&=`^e_t)vb7cCLqtW^WrX&QdH!wz*^tXGluB1Lx42{Iz6f}ia!t_)?979h_ z6F0njccFgkS7z>(>wz7asJt{K&B(eA`yx_Bk+u|VnhrvatK}eLECYcA1Is_y+TdOsP{ObEkH&X3u)W(u znQ>1<3A}?UqICQBfBxBZ4+8J2mRe)k19M>)8aYPz>{w|>4LeVpGlvQ87!jtkRL>H% z#9P^4DeiiUeeSQ~uUAc9Mc%YWzFc{yftRDiF47g-e*av24vj7 zUe&|NcK3apf*Xr?owfCrN^>OeNqstMb@}6M=8WGy=(%t0`@5Ni|Cg#WQF9!}k+4Zn za(C4pFFW`B&~ub6Qr^V>L;7mxp6)ECY?DAB5D1WXzJER9RxTJInwj7h;?^4;u|HbS zqcx|w@(-ASP{ZU01|Fy>Q0tatP6|~0)GAeCu?Xw2W^6lYS;5y_#}Akn=fM44gJ31> znD^xBd1Q_3OC8iBeQa~Sd&#nHAy;)^Sr6`^$84*XGv2y;-7*u~+8=~N?M|^lvT!{{ zcjP(R=RJ>Yl)6jS9cU0X;OtbLB%x!rGuXo)X{9!|?;Kb2rs%+A&HjTElbtb8HlueumuQd?d#YH0&>pLMa;x-l_t+ zOP-(14ex>7?)4VDJT7X=Ng59ZB{l;j5jD5pB_gtR<}TMzhr81`tNIUa|9hKk?rknQb;ptMlY8N^Fo=STazUT-Aq z##l=|$RT~}E?-ZS4cDv>&OF9(eJ>VSEsq&uH^x*lgTLOdDir?lw?Dn#scU&|k8O`H z0Metq{_~&csZRLiIRYZ?;0^?0A;`o|n=h5(&n=Is?gZSE`QP96{rQ~l6kqHam}1}i z7zjssC*Qw+%iFF%G}^!Z{TjW!-^bXW-@ot2kqtmuc7xPcY!aJ{F&rV@Mkf|!t?iVU6+FcdiXhr9BInhYhB$TGdbc$B#sN-+sxr0IO#|l=l&IkgN61H#(l5 z_0BSW|Aklzo*x@@>mrMcPYag;J2_r{Mul+A)=K<`avdiC`gmqRfkp=A=&_D>O8ncP z_FP#hjxAp+vy^N4OD-oykm*sopb*f+X+T2>(VaS=EdY5OgLCs< z$Dvk>GNc9$6>Z(OKozJw@3}H0xu2DvNW?9ok%9hs)40>rPO1+$k!^I4xGO?J*-}Ij zc9%e01*!4aYR+^}y8jWImr!e(QsnlUXxX=cXpk66=X~_wwlj_PlMQTD{;fiq_qkuo znSIT*)OqLmbWBrRtL;GsBLdtG8!JZh>beWkQqN!K@$Rsqa;B|(RLOUU$OT14?FTR0 znigY-d}<3{F^Sn{0@PQZ^s_cHbLu?#Mp$ht@_A*$ESVauM=|0Jpg0d zS-HGgFM-Z4^su75&gds5Z?paH|9)q2@!GeJb~Qf>nA!{@Ne@TgLT$`=Zk3U2;(gAf znd%vkm2>jmz2~tc@h2T7aSXhlAI@u%8oh@Ss@sS?HqO?&kAXsxJG|a~>~amVz%e#S zP#22>4-N#g?Is|S`AB^qU(f^h_c#HrJ3Z^`mXs!YuOkswN%(RpHRZueb?p@CF{p= zps#^RX(iDq(zotqxO|v{e3{++KEZ@tz$OdXBL?TMm3pPiLlC%i z`8?M~g5<~Rq5PWorj<2Z+E@os3ozP^iNE~mciZ!eW8RY3BX_xdm#N;cc_Ez%K*?d4 zZQBR;+{cp%`m|7$vv2zX1_QlNC?!puskF|QU zO7#*Jx*t^$%PB-$2MIA6-v)l1h=iLuO#AN>_!&L6oT69@2nxJW%TV%~nk3B7pNODO zW)~uc4pt?EwzK?L`TB9q$6SS>qp`PMw*iEklC-k+s5v~DHUHCI7vmQp=&%CyHH}dD zNFN@9SlmjN&D^^Lxm1i=x;kSIgF?SoZ8Ok*ZIFR2f?`qjR`z?<8a7ZOs;>7%ja)m{ zWvwT7!Phgp7{ki9)-O?#(B3yCc|{<@vG1cJ%D4M|$rP#;mE9}mkfjd2r*7n@ksWHm z!8f-!_K1?sd;*DI`?$WWyASpG+|^Mh%h8*&8P8|(7&Zm#yH5sb*zx$K$Z! zXq{)9^OA~k%dpWL9Z!LPybG}vNg?);+2YpY%Ov$`#ud@2fXetn&ok^_!Owwh=>pGV zUW;tcL13~vCyW%CN4ct;Ca6oZng)2_Hn!F`IFZhsJxVD}F?*4Ty|jESnP8_zZ2wBNlB2l% z+0fZ^+ipGK<%7V~ff9+oV$9bMlNmfK#eWa0bikwqiUNxRlPB+gd`dqZ9QQ$!bJC0G znQ}kXm$-K#ls%QiV#SfH#Pw~k`dt=bh!#O+4=J6JL>dUJ zrbj@_6L%syT_m(xY^AR2;BN(@NLm-#EggMPz}&j~P}CTY@2g71TkR~&ES*I?(p;AZ z90Fepk?AJ$Pbgz~;S8wlwp16@m=y z)DFR2>RK>et9MH7R22I)XMV3qix{T`riXC!Q98GZ1InjF7-qpW&-nXa|LEv;VtU(8 z2!(%Eh@SI3j~^|z*nV}_g15rc*2iWCNAR3Ei7A18uWj|t#BFAXviWk4?#{lnPbsE3 z&8>Id*g@p!XNiQ}A7KcXCSgIGmpuUwz2EJ(AAcrl69ds(eVfrzt$DpI{oIig3+ zY{yx=c6zoTGyC@>Xjh4q!WeO_v_NP>-A6XhDTlrHv4EVItS;MgwKSp3208j_pZrV+ zTlW;# zqHPbryw}6X;)@o0I1+nm^`fo{)agatMriS=Mpsj&ip*5>jd(+0)t4BDguHK~+6Q85 z=$G>8B}@+lV!nOV7@jj#mQ24-yWaO|3DTU^cv%VqJayo*HrI)egG1=oC#s>@heH@T z9&bb8mDU3Sc{7I6?6@2)lcW}hjozJW6K}>}|MWY*&SYe^@hM_>W;u|o4NS)IYJGeS zlg#5k5X0q#`uQBuN5wU+YwLFpWf4b4mB$rT9do*USAwMSChLUh;<9JYDCWr)b>B&_ zjA#h~yqdInQ9w04bs9A$Uqzh9AzjK3b@PDLfxUpqan!%YqWtlaW#-yqdN%gR0)aY_Ydtp?qM(diM&06runG?0yPJJr|o zNRbrZJ1u$h53hnQbSU9~tGT?0;O3A?HhtNQdi1z#H(QhVatNXMUUa>kh&z;y}>?rSE`PauD+pn3NIqPJD zqQvStdEekdaj~3y+G_j2&>nq`KW+L|Ez)(2eZLnhevG&l7k#)v#@x>5P+Gzo)JVFA z(4$SDN;4)a#Ji?6jed+f@&dfZ95JAu&I(v{+>cvNod3;>&~@(f{bIGm=A`rmB@o}c zV3AhP82Po~s#1csHQqu+=r<-kUFOd{s+*6_+C|_NbSN z-N&m5`dffm*hwip-CZd56o*zPx82~^AcO&I^?dxTDn+*ud}U#%XSSg) z3?2oY0y_ibqY^S5?W+dc~o1ckCz7%)narXV0(QUq?Z*A;J+#GMKcKLE|_@kK* zVXr*0RiG4JoyUJD2B%7v5zhxQ;*6(xoCa?sVbY{BtviQ7v#$o0DY+C!+)HcbQIcd` zY)E~?*hvKFxGDFtLPtb?d&JyzG@(EE_EI+Cb*uXf5LL36a8g(aIEw4|N1|E+bSgD}D=z4FdN2Lx*M91vwEgk4+%3eQS zDOBE{*1LAr#BXcO3b_1aEp;T`4dl!=)-AGh8VMlDc{;JM>}Hk^W$#jr0zIR!gLwAn z2a(HJ_fkR_6I=I3x-)B4`8r}@z;M-OCeg7)d5zi?1rLHID?K#?$0iu544a=4W*|}9 zve7G+rA@VU`sI!%i4a(JLRpR0Id4Y>nljGUqT$}Ab`fd!mQ7J%kEj4wmnth$m9dW)sdh=)?%?qG68Wgc zS-r8$PG_R0?ZO%x54AtQO6smldkwIcgaYRu;yEDqp*sh6c34bV_8Mx5EHyQvi5Lu8 zNw`sJA*xc3W<(zC zF__BW?D-8@?i~a?T{jFy9*?fUWV5tf=e9p3a~(pk?h)U)A3$|$IU(L;{JlG0_^OJc zoRmOwV{-=Cui4kME40+d^;T*UL6<#T2S({)Z~4h6@%eno8h)!rxwh^|MoLpiL$um< zX{BSe>09wGK@oRzF{t*LXM!tQMcE~>R}ojVG#?<_*~anymlvR>k=I+-3trgZ&Go1$ z$gwh{S_2%FWJ;Vsr|;oy*-HL{nA0jOk4`BM=e>KpZO^=*$4h~pW^}b+#X1v9zxn>r zdVQv2-=x4_a)8ST+8rZ6Z+tqoO zm8kew`?NVk!+Y)!J=NZJR&gBwi61?NRfZ8z62M0?&snZnXw$(d-MB(of=ca6y9{AI zfzI2mo;81EFGlF+^exx&z0CTls*TS5Z<-+H$jCvqboRJx3s+fe*S($RvKW4Dks*+4 z=F^J-#d;(mZC!frw^H2D5O&R~huJ&5d2ThX5>M;vh=$WqIco>q=WZZKaJ`Mqu^1Jh z`?kwSO=im!wQ#7Y1S48@ekzo0kr+*3t5l1ch8|^oj(#u<-)iML@7*>1W~x4hUK4$U z?G5O&XT+A}lsGC#^CexW<6K+%xDH|gu4=bbQGD-~NkZ;mKpj^SEU{9DRTd(22lR@R z2L!-Z&w)rj;Gas6#=DJkYEUnoH|QI9@+R{7sYQ*96_CUOchM8%yB>Q}DwUcU~}U}Wh7(qX=@l{iXO$>_lcl_H&KxG{y;xJQ#Up=qm?X^VQLVDQI7bmmwS zf)&DJ!95YP{R`FVy&L*GbmAz)v7A0c@S)05HmS}`9bEk0aCgO;d=@aXl#3_3Zr`>z zgrY)aG?vxFGOCh3bn%y7FCmG?W62W{y23Yvq*rg+A z@KJ5?)~2)cC_tavj!Mah+I_I0O3XYAZ=l|&#ZXVy^zsJX5p!@)>~s_4xgoH z)Z_~CSKChD(^h0{1%cl4@O=`AJT3(cw{;TAGu6x#g;5x0CM32@zi){`aOIT!0dHN5GyOTl_jW`Jjy<0>z7@Tu74gtq)R$xmKqbfK{Sv!ErBghXYcHQnr zgk2gvHbT&gZ{Hw0YuH!#RwJ?}GPw7>=B7ZW?!R;KNbRguCrt!uUAlB)mQbUz3=%b+ zyG*^ualj~*7dry|S&z;0>xsyGQWAyx){jhM@qBKR3I}0bs(JNtnEpn}QcaDY&wZi* z9yDDAR{B5K!_Rn8%CNTPB=}bRFl&H%%2RjES1&Rvmcc8jaW~QG>1w(VpsNicHd6iE zZPE%Wy@VZ#Y|4Htl9eY0!_3QvF2xk~RFkX|Yx)V_pH}fF$noNCA;g?>3;d zY?u9lTnjyCvBxAt=E(dOh@k`0_;@f`?(dS{eW2(yE<}e+Dce|(@b-kiKDdKS(iL%* zp^xad!5Qcqf%91m3tLGusuI%Ue5de=PgJN5FYlhw;&kuILwV=_m30;hax+^FPP@oG z`E%(lmzjBAcA1lD7ug%>E6=4|{3ksPZda9#j*j$65*Y2IZ(n}e>TA@)+qDscbzA}? zK1j8jv}5++jMW#ZcVkp-xOn|S`}RX0!{1Y@hg%kr6@?cC2VThK?xrKmj;m$iJ$?4N z#Ukk1Ye>cI%b4=>c5}_x6#1hWbo9#58BCm7HgPxZ)6#+6@Tl{E1|}`pV!h~#?VI1s z=elFgNhX_}%xKjm^j7Xvbij+(B)s*|`UQUl!AuVACHdE_wFFuKbEtAgOby&P%|-31h!PaK}j+hW`MTH z__#%SmOih2GE;#f^+NzTv|VcMGwwqbVt;H&dIIs6d5&%Zlo8K}h4K*Ep1{<+oH93z#_U6s_8O6hax!fi>f zVufuK@R_uhMsL2jx5gwTno6VB-i7tteJ9W`d1JcnfJ9 z6N5@Wt?!Q+-7B=i^1AY_$pkYYs$ABEH4u?@_-cRpUDFWFbJhbAPj%=;9kGQMoe-gzbT;27i4G#>Yc>FzDIu0d~c& zh)B-d3W}oA`{Y`R$+KEZa9-k{$sj{hvA>uV`9L)ULK;nz3YM<0lmyPLVtO%5# zv*8r(2X$QXE1u@FZ9XSn{PjApNCL=?KJ49?Fp&W14696I+?*JnFHQ)+=^PkI9<2jM zAfJdIe<~|;rLI)z8!)!C+}yp3G5be;GHf?KR;-#7HWxIw^-s_a5is3H3sb}de=)$s zSQ%)MI1ejMLvvy&HhEG8+r!H@?YO%TgIox{Q{B=`7;KSPMQhUt{lq6WF>B4(>~^PO zgg^Vk-(;l0@WfxU%P0@f4;VRWMwIx(anW-($&$?_YfmvnHO$wmq&i1Sxr}M~5024% zN8}y!28SM#{A7B4SF0b7J0?_nEn5dTCg~aMuoOGq z9X50TEEmLh?(0}TVOjj_jb+C9)yIhY9%K5?fBV<-yxzY2uttw&XKeCfVoP;m6=PJ2 znf<1-RQoI{@8lx2LzbOzTM(9NlcO7ikKZ^4Au-ob^=V)^rC$USm zZ};+RBpth9Fu?o0y`ttio8uQ%`Opy5P3Qqy9CB!nK(9EO!=<-beb3WN_XsK9 zx3%M2O#2qnXfN#}>#z-svS2r0GK7Y?M@-&^FR6x>)6e6DpSxgh z_jT~}>kKKG1^KxpM);*yw7oIj1pa zJ!;O;d$9!^8mrEzw9w8@QxLS{murG+eBxT1;G}JuR9n0)F`KNtT{P|K1uya1#WwK) zX|05U@51HN5STSU|J$n!!W&P>XI!nCjh*rkM2b5EtzIyM_FUtSm} ziR$ZJ(_uOH!2ncbq&~!Qju}0cW&RG5t9alhE@`8^$FR<4E!`r<2T0iTxt-;5it9;82oxaVw@_a;B$Rx(`ZonOCh}A6Ns2|f?*mY z9UvHA?KRErIUDaRE~ES|tjRcUg(}ML?E_icyJiehm*zNeipR8yKp?+X#I?DT4n-Tp zdyQIMfAJT8;;@C%+PeseyrWL=!YdTZX#D8RGQN0@hT@h2fkqPQ4@>N{>mj#|DYyw* z7?5bF-Aw(t7#ItU@`e5h-a!QvFS-s7v+o*NT<75d0#7!%C&5phoAn2Xq3%O$fcW76vAU7Av8^%x^QQ~tzfO#h&4OKb_n~Qp6rD3~SJ5mL{&-{I=uwF5#ar5Kv!VV~kQxFU3gq#uh)U2%;TbW_w>^ zUKFtKN4}z7!@;h*8}AWkdlz~UMqfl+EZS|fS)|^o`Y+`zq|lB-wlMoXg>-2DU6zkm z(xlu=3HmultrriO<8yTSkX@ZRH2Z4LE!2SE8qC*<+sd%?01;g!d;7;at*0YHUSp~dT0%8`&7E5Ah}_-*T@ zr;8bqwQ+PQNzRkqxN;7-8U&L{rr(UAeV}(y8~~y*&enS_C77}G zS#DS+A%fPW%dGR6g29oN39*cptager^nelEFNcDuSZPf zyAJCwOv^h}RBx+UgD-v_!?qX_z{Ke%5i?aj1T??HK0I%jclRt|^=*M7(nQ4b)!Q8( zj^%zcA#xt|_4fHE+R?N}NWPepc1+889SeDR_4o>^J{re$tx+4|zvv2jcsb8rM}2*w z476lcet+4jE2g3-bT=&(vEvUAEB0n%8j7d9TM;%`EjosCsYh-7B-;ep3RT1=H;HIl(u6;!f$CQF^)7~8zVZI8r!E&3)nIv$(!C)Xg=V<$zyj;iVf}FB) zg*=)lIp(NQ7s2{?4>Jp*-eY2d$)3)~HpFMfjQKgoFwLWB7_8M%sN)~B1ZW{FX}DA8 z%JZ!qumAqf|Jr}}tUd+~zH@T&F^G3r!xru0KB=|w`JqpQ--g?xL`I|DwygKOC+Zic zi;EHe4|V9h80QHa!07!wDVTH_hp-|hS_+6>iF3|lk9|zWo=NfGy{&h1kX{b9k=*V4kzpB$DApb%ad)S^UBvS$-C}oy`*eq38}9%RpGt` z++27S>o*ov$GRXaa`eXd5owpiCXxk_N(q1Rhrg3bzHFqI_x-YL#C_UjJ;fviSaOVt z%_f>%>XlC+8Gb~cMRN?vh&d5af_Ui?4yH4WZWmMX`T0e9;$FdOFt0`x6BU6uEP4%D zCwVTQr|YbuHpT4TgNB_>2MLL;xk6{R(1j_E|P1<_`oML^Ou&){3p0@29z zB?Jpl+gf+49=ExG$hCK!ThF~9%W})^ib?23$Nrdady#{QV`*&Px?RNjf@tgqzg}?y zPPIi6-GUi3k-t0Iq z7(?~gDS0swbsesu-q4LV!qyJem}GOv_4rkP^rJ6Bl!f+Op{<;KQ_;d>G({4h)+?M> z&dD=USJ@SK*|ir-Zr&9%saGDo>oIPWyCXDFd!#Io(OT2Fi>zfGHAx%<1JElwh&)wtlh$8yQOn!~cev_{mC1M+Hf&FL)7^a@=m!wy;*FW{O%e|)3E;DA{dI) z5RyWGMP{j7;#nZCpEI6Vc{D=XF#aO+Wt87uF0ZyG&W@ikX=u zh~(qAFwf$)i2$Jr1dDNooeb7!h88@&xVNtcf;P1*T{z_|lME?|UB_MC8hh&~4=plS z4viGis6XkPPzY)_7m8EGopZS@K9Dsqf|XRzomYJ|AF5_p%}Y_jxY>`DV=$55*e_xX z>efqP_O3{!yq_fKq%uZx6l*cMTnbVFLtppX*L>}r?!7ea!fq(XT(nnNjS1g~Q32u^ z{4d$*c>p&I^NU7CskO0L*4t-aRh^|(-ozM`GZA9|Z(Y?iB#rV0H!J_;%jfS8YxVF1 z@|Kh6RP8}IS-cXc!U&!zCG|E*=|pWrY~6+#j5k}zlhY_Hro>=YPSI5bX|=ANywxuA z@)%kZGv#g3!epz0XlspgGG=IScN)Ym)6_Ar^LX6Bv{&|RtbCT|-nww&b9Z2HUNM%n zb%SJAS_U<=!T?2F<<^?2Dtx63c;N&;f>oIS@tNU}PEi5TpX~ypT{;YUDVd=t7#U{o z5ja>~Gy@I`rh^SHp#0bLV))0u|Le;ik(sqEhFo^$PJ$cZhB;;kH7Zj$BfLzQ^Q2`qPrgO9y6I`zf9BGS^*I|cAp>VO|4|D-~ zqHO&49?P4^5mgzSFxkP(7S5zZgM-O!+YKkkr|AmIE7|lUEiTjT_1h7g4gcT&{eRCr z=aMm`MYTMA{-m6T*S62GWU;mNE^H!W2pU&nmH7uI}B;e#N zS{aAuYJ0t3kH9!ET_G^j7|kd4nk*QnP_*}C-4ME}CKOUmPFuP{bidBm+BD>cK42xI zGSdgM@bg=W42xTKYc-=GFqAH45@rw1Yr2k$@Zweh*OZ^V*7H>PvubopU6AIZ7(D04 zD4F+EF^L0-8hYc^hWFof>Tv$$V&L2RySXZX6bf*_=NvSP&kwl960=-f*YNfJ{{3&> zKEH9O_Hm)1O$pq+jBCgeUWOlj)%RCL%T8J{6W768hIdP&Y(tycT1uukyfQG(9DO)d z7YoxkefN@dm!bfm^$`9QL*iPif_}FEp{D1E+9A-!&vUu-q!gK3Cen#Xp#S^&HAxUr zJllPuM|r(k*jzS(=3?GU4qIrwlc&i5xt%1uHc{|Ib&ZeLH!Z)sM{CRb@L09WPj!M~ zr0f+=HKxvq5wVrZL)#HD%k$(~m5V>UE_!3hM(^-Q;ZOePcfk60A(gCl?k16w{mail zai?R}wt3ol^2hY%68@ir%r6LV)j zR!b@V*3Vq>WdXr-n|6PS)If}Oho&X<@I%r!>5{&UemU{w6csYDj%6Z@_&NH^j5IM9 zgwlse_hTbO(}FunsUNS_>f7h1wIf^ucOlQE+cJY0ts$7!lm@(LgNOSe z64%6)PkR)0z>|wq1=9v7T9MH*N4afQ|1T!)3UV5F9JNgkDeK@d4Dc(!T;I{^TU2>P zE<((9?2#{xWwDzboq|D7a#*Z}X8g&_Qn@U}^aAJ73(dqGGet`s7sC|YDjgHPJSUEB zPN`*mM*tfBUJgmR#aY+%`JV(F#)unP45+k6G)5qO+K20k+GgABV50ek|qHI z6%4&mrgg*-lY1IsAEWig?;@l?Q9|Q{TR3OB1Zx<}7s}2rm%14yI)_ES+jr9a&zEf4 ziR@(9Xs1tB@iUq0-OIxO!$E?3m!kjmK@i1AyFu-3!e2 zp=b3C?JbE3UawlXtdz9~`(TB~oV@`WOPfKnR)F8Nej;Tzx`Z5bd?WBf&SM3s(42*H zmOJ>}ThihgPIq2>QhD3GoV2*ZYCWtP2iI)I7wq_03;Bo1t>nvhrti^}9T03+!eFjj zVT76_r;et?Y2(ZI029NZ&O zUC1YL&ogzC&DJ+tW1f7U2qGF(!WFL=PTxg@BRF=BPp1cZ;pL<=crPhObrD5Tb+_iHR2U$Vq$RbKflrA;BBo3 + Tag="ShortcutGuide"> + + + + + Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/ShortcutGuide.png}"> + + + + Product name: Navigation view item name for PowerRename - Shortcut Guide + Shortcut Guide V2 Product name: Navigation view item name for Shortcut Guide @@ -1082,7 +1082,7 @@ Inactive color - Shows a help overlay with Windows shortcuts. + Shows a help overlay with shortcuts for your apps and Windows. Press duration before showing global Windows shortcuts (ms) @@ -1092,7 +1092,7 @@ Activation method - Use a shortcut or press the Windows key for some time to activate + Use a shortcut to activate Shortcut Guide Custom shortcut @@ -1350,7 +1350,7 @@ do not loc - Shortcut Guide + Shortcut Guide V2 Shortcut Guide @@ -2029,7 +2029,7 @@ Made with 💗 by Microsoft and the PowerToys community. Screen Ruler is a quick and easy way to measure pixels on your screen. - Shortcut Guide presents the user with a listing of available shortcuts for the current state of the desktop. + The new Shortcut Guide displays keyboard shortcuts for your apps and for the Windows environment. A collection of utilities to enhance your mouse. @@ -2221,7 +2221,7 @@ From there, simply click on one of the supported files in the File Explorer and Do not localize this string - Shortcut Guide + Shortcut Guide V2 Do not localize this string diff --git a/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs index 8885e2686a..e66b3c07fe 100644 --- a/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs @@ -72,6 +72,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels var newItem = new DashboardListItem() { Tag = moduleType, + IsNew = moduleType == ModuleType.ShortcutGuide, Label = resourceLoader.GetString(ModuleHelper.GetModuleLabelResourceName(moduleType)), IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && ModuleHelper.GetIsModuleEnabled(generalSettingsConfig, moduleType)), IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled, From 145247c4fb27b30ebd0c283c95552ca8232130bf Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Mon, 28 Jul 2025 02:07:14 +0200 Subject: [PATCH 76/99] Add attribution in settings --- .../Settings.UI/SettingsXAML/Views/ShortcutGuidePage.xaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/ShortcutGuidePage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/ShortcutGuidePage.xaml index d5433b655f..d9d4a51cc9 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/ShortcutGuidePage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/ShortcutGuidePage.xaml @@ -76,5 +76,8 @@ + + + \ No newline at end of file From 97cba618da63747b9af383be82a60ba7614c5c80 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Mon, 28 Jul 2025 14:08:42 +0200 Subject: [PATCH 77/99] Add explorer shortcuts, fix animation stopping and add an error when index.yml generation fails --- .../ShortcutGuide/+WindowsNT.Shell.en-US.yml | 20 +- .../+WindowsNT.WindowsExplorer.en-US.yml | 265 +++++++++++++++++- .../ShortcutGuide/ShortcutGuide.Ui/Program.cs | 12 +- .../ShortcutGuideXAML/MainWindow.xaml.cs | 2 - 4 files changed, 278 insertions(+), 21 deletions(-) diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Shell.en-US.yml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Shell.en-US.yml index 4b7536a8ef..e845324580 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Shell.en-US.yml +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.Shell.en-US.yml @@ -12,21 +12,6 @@ Shortcuts: Alt: true Keys: - F4 - - Name: Test shortcut - Shortcut: - - Win: false - Ctrl: true - Shift: false - Alt: false - Keys: - - K - - Win: false - Ctrl: true - Shift: false - Alt: false - Keys: - - C - - Name: Open shutdown box Description: When no windows are open Shortcut: @@ -203,7 +188,6 @@ Shortcuts: Alt: false Keys: - F4 - Recommended: true - Name: Switch desktop Shortcut: - Win: true @@ -212,6 +196,7 @@ Shortcuts: Alt: false Keys: - "" + Recommended: true - SectionName: "Windows key" Properties: - Name: Open start menu @@ -222,7 +207,6 @@ Shortcuts: Alt: false Keys: - "" - Recommended: true - Name: Open Action Center Shortcut: - Win: true @@ -314,6 +298,7 @@ Shortcuts: Alt: false Keys: - "Down" + Recommended: true - Name: Open file Explorer Shortcut: - Win: true @@ -338,6 +323,7 @@ Shortcuts: Alt: false Keys: - "F" + Recommended: true - Name: Start IME reconversion Shortcut: - Win: true diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.WindowsExplorer.en-US.yml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.WindowsExplorer.en-US.yml index 19ae44f559..e27cbfc675 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.WindowsExplorer.en-US.yml +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Assets/ShortcutGuide/+WindowsNT.WindowsExplorer.en-US.yml @@ -1,3 +1,266 @@ PackageName: +WindowsNT.WindowsExplorer WindowFilter: "explorer.exe" -Shortcuts: \ No newline at end of file +Name: Windows Explorer +Shortcuts: + - SectionName: General + Properties: + - Name: Open File Explorer + Shortcut: + - Win: true + Ctrl: false + Shift: false + Alt: false + Keys: + - "E" + Recommended: true + - Name: Select the address bar + Shortcut: + - Win: false + Ctrl: false + Shift: false + Alt: true + Keys: + - "D" + - Name: Select the address bar + Shortcut: + - Win: false + Ctrl: true + Shift: false + Alt: false + Keys: + - "L" + - Name: Select the address bar + Shortcut: + - Win: false + Ctrl: false + Shift: false + Alt: false + Keys: + - "F4" + - Name: Select the search box + Shortcut: + - Win: false + Ctrl: true + Shift: false + Alt: false + Keys: + - "E" + - Name: Select the search box + Shortcut: + - Win: false + Ctrl: false + Shift: false + Alt: false + Keys: + - "F3" + - Name: Select the search box + Shortcut: + - Win: false + Ctrl: true + Shift: false + Alt: false + Keys: + - "F" + - Name: Refresh the window + Shortcut: + - Win: false + Ctrl: false + Shift: false + Alt: false + Keys: + - "F5" + - Name: Cycle through elements in the active window + Shortcut: + - Win: false + Ctrl: false + Shift: false + Alt: false + Keys: + - "F6" + - Name: Maximize or restore the active window + Shortcut: + - Win: false + Ctrl: false + Shift: false + Alt: false + Keys: + - "F11" + - SectionName: Navigation + Properties: + - Name: Navigate to the previous folder + Shortcut: + - Win: false + Ctrl: false + Shift: false + Alt: true + Keys: + - "" + - Name: Navigate to the previous folder + Shortcut: + - Win: false + Ctrl: false + Shift: false + Alt: false + Keys: + - "" + - Name: Navigate to the next folder + Shortcut: + - Win: false + Ctrl: false + Shift: false + Alt: true + Keys: + - "" + - Name: Move up a level in the folder path + Shortcut: + - Win: false + Ctrl: false + Shift: false + Alt: true + Keys: + - "" + - SectionName: "Window management" + Properties: + - Name: Open a new window + Shortcut: + - Win: false + Ctrl: true + Shift: false + Alt: false + Keys: + - "N" + - Name: Open a new tab + Shortcut: + - Win: false + Ctrl: true + Shift: false + Alt: false + Keys: + - "T" + Recommended: true + - Name: Close the current active tab + Shortcut: + - Win: false + Ctrl: true + Shift: false + Alt: false + Keys: + - "W" + - Name: Move to the next tab + Shortcut: + - Win: false + Ctrl: true + Shift: false + Alt: false + Keys: + - "Tab" + - Name: Move to the previous tab + Shortcut: + - Win: false + Ctrl: true + Shift: true + Alt: false + Keys: + - "Tab" + - Name: Move to that tab number + Shortcut: + - Win: false + Ctrl: true + Shift: false + Alt: false + Keys: + - "Number (1-9)" + - Name: Show/Hide the preview pane + Shortcut: + - Win: false + Ctrl: false + Shift: false + Alt: true + Keys: + - "P" + - Name: Show/Hide the details pane + Shortcut: + - Win: false + Ctrl: false + Shift: true + Alt: true + Keys: + - "P" + - Name: Resize all columns to fit text + Shortcut: + - Win: false + Ctrl: true + Shift: false + Alt: false + Keys: + - "+" + - Name: Expand all folders + Description: In the navigation pane + Shortcut: + - Win: false + Ctrl: true + Shift: true + Alt: false + Keys: + - "E" + - SectionName: "File management" + Properties: + - Name: Display properties for the selected item + Shortcut: + - Win: false + Ctrl: false + Shift: false + Alt: true + Keys: + - "Enter" + - Name: Delete the selected item + Shortcut: + - Win: false + Ctrl: false + Shift: false + Alt: false + Keys: + - "" + - Name: Delete the selected item + Shortcut: + - Win: false + Ctrl: true + Shift: false + Alt: false + Keys: + - "D" + - Name: Delete the selected item permanently + Description: "This removes the item without sending it to the Recycle Bin" + Shortcut: + - Win: false + Ctrl: true + Shift: false + Alt: false + Keys: + - "D" + - Name: Create a new folder + Shortcut: + - Win: false + Ctrl: true + Shift: true + Alt: false + Keys: + - "N" + Recommended: true + - Name: Rename the selected item + Shortcut: + - Win: false + Ctrl: false + Shift: false + Alt: false + Keys: + - "F2" + - Name: Select multiple items + Shortcut: + - Win: false + Ctrl: true + Shift: false + Alt: false + Keys: + - "" + \ No newline at end of file diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Program.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Program.cs index f36e6b202c..e2602e1f19 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Program.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Program.cs @@ -6,11 +6,13 @@ using System; using System.Diagnostics; using System.IO; using System.Threading; +using System.Windows; using ManagedCommon; using Microsoft.UI.Dispatching; using Microsoft.UI.Xaml; using Microsoft.Windows.AppLifecycle; using ShortcutGuide.Helpers; +using Application = Microsoft.UI.Xaml.Application; namespace ShortcutGuide { @@ -49,7 +51,15 @@ namespace ShortcutGuide File.Copy(Path.GetDirectoryName(Environment.ProcessPath) + "\\Assets\\ShortcutGuide\\" + file, ManifestInterpreter.GetPathOfInterpretations() + "\\" + file, true); } - Process.Start(Path.GetDirectoryName(Environment.ProcessPath) + "\\PowerToys.ShortcutGuide.IndexYmlGenerator.exe"); + Process indexGeneration = Process.Start(Path.GetDirectoryName(Environment.ProcessPath) + "\\PowerToys.ShortcutGuide.IndexYmlGenerator.exe"); + indexGeneration.WaitForExit(); + if (indexGeneration.ExitCode != 0) + { + Logger.LogError("Index generation failed with exit code: " + indexGeneration.ExitCode); + MessageBox.Show($"Shortcut Guide encountered an error while generating the index file. There is likely a corrupt shortcuts file in \"{ManifestInterpreter.GetPathOfInterpretations()}\". Try deleting this directory.", "Error displaying shortcuts", MessageBoxButton.OK, MessageBoxImage.Error); + return; + } + PowerToysShortcutsPopulator.Populate(); Logger.InitializeLogger("\\ShortcutGuide\\Logs"); diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs index ca33d546e6..cf23526b7c 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml.cs @@ -5,9 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Text.Json; -using System.Windows.Media; using Common.UI; -using ManagedCommon; using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.UI; using Microsoft.UI.Windowing; From 84d4cbb16d622637f5e32333552d02411d4c1c28 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Mon, 28 Jul 2025 16:12:36 +0200 Subject: [PATCH 78/99] Refactoring, commenting and fixing some little lefrover bugs --- .../IndexYmlGenerator.cs | 2 +- .../ShortcutGuide.Ui/Helpers/DisplayHelper.cs | 19 +- .../ShortcutGuide.Ui/Helpers/DpiHelper.cs | 4 +- .../Helpers/ManifestInterpreter.cs | 45 ++- .../Helpers/PowerToysShortcutsPopulator.cs | 82 +++-- .../Helpers/ResourceLoaderInstance.cs | 6 + .../Helpers/TasklistPositions.cs | 9 +- .../ShortcutGuide.Ui/Models/ShortcutEntry.cs | 338 ++++++++++-------- .../Models/ShortcutPageParameters.cs | 15 + .../ShortcutGuide.Ui/NativeMethods.cs | 5 + .../ShortcutGuide/ShortcutGuide.Ui/Program.cs | 9 +- .../ShortcutGuideXAML/MainWindow.xaml | 2 +- .../ShortcutGuideXAML/MainWindow.xaml.cs | 32 +- 13 files changed, 337 insertions(+), 231 deletions(-) diff --git a/src/modules/ShortcutGuide/ShortcutGuide.IndexYmlGenerator/IndexYmlGenerator.cs b/src/modules/ShortcutGuide/ShortcutGuide.IndexYmlGenerator/IndexYmlGenerator.cs index d8a1179733..1997bc1023 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.IndexYmlGenerator/IndexYmlGenerator.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.IndexYmlGenerator/IndexYmlGenerator.cs @@ -21,7 +21,7 @@ namespace ShortcutGuide.IndexYmlGenerator // Todo: Exception handling public static void CreateIndexYmlFile() { - string path = ManifestInterpreter.GetPathOfInterpretations(); + string path = ManifestInterpreter.PathOfManifestFiles; if (File.Exists(Path.Combine(path, "index.yml"))) { File.Delete(Path.Combine(path, "index.yml")); diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/DisplayHelper.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/DisplayHelper.cs index cc968333cb..e638ff1c7e 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/DisplayHelper.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/DisplayHelper.cs @@ -9,21 +9,28 @@ namespace ShortcutGuide.Helpers { public static class DisplayHelper { - private enum MonitorFromWindowDwFlags - { - MONITOR_DEFAULTTONEAREST = 2, - } - + ///

+ /// Returns the display work area for the monitor that contains the specified window. + /// + /// The window handle + /// A element containing the display area public static Rect GetWorkAreaForDisplayWithWindow(nint hwnd) { _foundMonitorIndex = -1; _monitorIndex = 0; - var monitor = NativeMethods.MonitorFromWindow(hwnd, (int)MonitorFromWindowDwFlags.MONITOR_DEFAULTTONEAREST); + var monitor = NativeMethods.MonitorFromWindow(hwnd, (int)NativeMethods.MonitorFromWindowDwFlags.MONITOR_DEFAULTTONEAREST); NativeMethods.EnumDisplayMonitors(nint.Zero, nint.Zero, MonitorEnumProc, new NativeMethods.LPARAM(monitor)); return MonitorInfo.GetDisplayMonitors()[_foundMonitorIndex].RectWork; } + /// + /// The index of the monitor that contains the specified window. -1 indicates that no monitor was found (yet). + /// private static int _foundMonitorIndex = -1; + + /// + /// The index of the monitor in the enumeration. This is used to find the correct monitor in the list of monitors. + /// private static int _monitorIndex; private static bool MonitorEnumProc(nint hMonitor, nint hdcMonitor, ref NativeMethods.RECT lprcMonitor, nint dwData) diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/DpiHelper.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/DpiHelper.cs index c63f449af1..78f5fa8b12 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/DpiHelper.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/DpiHelper.cs @@ -20,13 +20,13 @@ namespace ShortcutGuide.Helpers return (float)dpi / DEFAULT_DPI; } - public static long GetScreenDPIForWindow(int hwnd, ref int dpi) + private static long GetScreenDPIForWindow(int hwnd, ref int dpi) { var targetMonitor = NativeMethods.MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); return GetScreenDPIForMonitor(targetMonitor.ToInt32(), ref dpi); } - public static long GetScreenDPIForMonitor(int targetMonitor, ref int dpi) + private static long GetScreenDPIForMonitor(int targetMonitor, ref int dpi) { if (targetMonitor != 0) { diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/ManifestInterpreter.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/ManifestInterpreter.cs index 70497c6b07..e45ccb58d1 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/ManifestInterpreter.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/ManifestInterpreter.cs @@ -15,18 +15,34 @@ using YamlDotNet.Serialization; namespace ShortcutGuide.Helpers { + /// + /// Helps to interpret the manifest files for the Shortcut Guide. + /// public class ManifestInterpreter { // Todo: Get language from settings or environment variable, default to "en-US" + + /// + /// Gets the language used for the manifest files. + /// public static string Language => "en-US"; + /// + /// Returns the shortcuts for a specific application. + /// + /// + /// The method should only be called if the application is known to have a shortcuts file. + /// + /// The manifest id. + /// The deserialized shortcuts file. + /// The requested file was not found. public static ShortcutFile GetShortcutsOfApplication(string applicationName) { - string path = GetPathOfInterpretations(); + string path = PathOfManifestFiles; IEnumerable files = Directory.EnumerateFiles(path, applicationName + ".*.yml") ?? throw new FileNotFoundException($"The file for the application '{applicationName}' was not found in '{path}'."); - IEnumerable filesEnumerable = files as string[] ?? files.ToArray(); + IEnumerable filesEnumerable = files as string[] ?? [.. files]; return filesEnumerable.Any(f => f.EndsWith($".{Language}.yml", StringComparison.InvariantCulture)) ? YamlToShortcutList(File.ReadAllText(Path.Combine(path, applicationName + $".{Language}.yml"))) : filesEnumerable.Any(f => f.EndsWith(".en-US.yml", StringComparison.InvariantCulture)) @@ -34,25 +50,38 @@ namespace ShortcutGuide.Helpers : throw new FileNotFoundException($"The file for the application '{applicationName}' was not found in '{path}' with the language '{Language}' or 'en-US'."); } - public static ShortcutFile YamlToShortcutList(string content) + /// + /// Deserializes the content of a YAML file to a . + /// + /// The content of the YAML file. + /// A deserialized object. + private static ShortcutFile YamlToShortcutList(string content) { Deserializer deserializer = new(); return deserializer.Deserialize(content); } - public static string GetPathOfInterpretations() - { - return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "WinGet", "KeyboardShortcuts"); - } + /// + /// Gets the path to the directory where the manifest files are stored. + /// + public static string PathOfManifestFiles => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "WinGet", "KeyboardShortcuts"); + /// + /// Retrieves the index YAML file that contains the list of all applications and their shortcuts. + /// + /// A deserialized object. public static IndexFile GetIndexYamlFile() { - string path = GetPathOfInterpretations(); + string path = PathOfManifestFiles; string content = File.ReadAllText(Path.Combine(path, "index.yml")); Deserializer deserializer = new(); return deserializer.Deserialize(content); } + /// + /// Retrieves all application IDs that should be displayed, based on the foreground window and background processes. + /// + /// An array of all application IDs. public static string[] GetAllCurrentApplicationIds() { nint handle = NativeMethods.GetForegroundWindow(); diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs index 64c1a0860e..b96bcfa8b9 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/PowerToysShortcutsPopulator.cs @@ -5,132 +5,147 @@ using System; using System.Globalization; using System.IO; +using System.Text; using System.Text.RegularExpressions; using Microsoft.PowerToys.Settings.UI.Library; using static ShortcutGuide.Helpers.ResourceLoaderInstance; namespace ShortcutGuide.Helpers { + /// + /// Populates the PowerToys shortcuts in the manifest files. + /// internal sealed partial class PowerToysShortcutsPopulator { + /// + /// Populates the PowerToys shortcuts in the manifest files. + /// public static void Populate() { - string path = Path.Combine(ManifestInterpreter.GetPathOfInterpretations(), $"Microsoft.PowerToys.{ManifestInterpreter.Language}.yml"); + string path = Path.Combine(ManifestInterpreter.PathOfManifestFiles, $"Microsoft.PowerToys.{ManifestInterpreter.Language}.yml"); - string content = File.ReadAllText(path); + StringBuilder content = new(File.ReadAllText(path)); const string populateStartString = "# "; const string populateEndString = "# "; - content = PopulateRegex().Replace(content, populateStartString + Environment.NewLine); + content = new(PopulateRegex().Replace(content.ToString(), populateStartString + Environment.NewLine)); ISettingsUtils settingsUtils = new SettingsUtils(); EnabledModules enabledModules = SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Enabled; if (enabledModules.AdvancedPaste) { AdvancedPasteProperties advancedPasteProperties = SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties; - content = HotkeySettingsToYaml(advancedPasteProperties.AdvancedPasteUIShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("AdvancedPasteUI_Shortcut/Header")); - content = HotkeySettingsToYaml(advancedPasteProperties.PasteAsPlainTextShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("PasteAsPlainText_Shortcut/Header")); - content = HotkeySettingsToYaml(advancedPasteProperties.PasteAsMarkdownShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("PasteAsMarkdown_Shortcut/Header")); - content = HotkeySettingsToYaml(advancedPasteProperties.PasteAsJsonShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("PasteAsJson_Shortcut/Header")); + content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdvancedPasteUIShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("AdvancedPasteUI_Shortcut/Header"))); + content.Append(HotkeySettingsToYaml(advancedPasteProperties.PasteAsPlainTextShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("PasteAsPlainText_Shortcut/Header"))); + content.Append(HotkeySettingsToYaml(advancedPasteProperties.PasteAsMarkdownShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("PasteAsMarkdown_Shortcut/Header"))); + content.Append(HotkeySettingsToYaml(advancedPasteProperties.PasteAsJsonShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("PasteAsJson_Shortcut/Header"))); if (advancedPasteProperties.AdditionalActions.ImageToText.IsShown) { - content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.ImageToText.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("ImageToText/Header")); + content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.ImageToText.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("ImageToText/Header"))); } if (advancedPasteProperties.AdditionalActions.PasteAsFile.IsShown) { - content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsTxtFile.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("PasteAsTxtFile/Header")); - content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsPngFile.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("PasteAsPngFile/Header")); - content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsHtmlFile.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("PasteAsHtmlFile/Header")); + content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsTxtFile.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("PasteAsTxtFile/Header"))); + content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsPngFile.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("PasteAsPngFile/Header"))); + content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsHtmlFile.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("PasteAsHtmlFile/Header"))); } if (advancedPasteProperties.AdditionalActions.Transcode.IsShown) { - content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.Transcode.TranscodeToMp3.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("TranscodeToMp3/Header")); - content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.Transcode.TranscodeToMp4.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("TranscodeToMp4/Header")); + content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.Transcode.TranscodeToMp3.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("TranscodeToMp3/Header"))); + content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.Transcode.TranscodeToMp4.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("TranscodeToMp4/Header"))); } } if (enabledModules.AlwaysOnTop) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.Hotkey, SettingsResourceLoader.GetString("AlwaysOnTop/ModuleTitle"), content, SettingsResourceLoader.GetString("AlwaysOnTop_ShortDescription")); + content.Append(HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.Hotkey, SettingsResourceLoader.GetString("AlwaysOnTop/ModuleTitle"), SettingsResourceLoader.GetString("AlwaysOnTop_ShortDescription"))); } if (enabledModules.ColorPicker) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("ColorPicker/ModuleTitle"), content, SettingsResourceLoader.GetString("ColorPicker_ShortDescription")); + content.Append(HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("ColorPicker/ModuleTitle"), SettingsResourceLoader.GetString("ColorPicker_ShortDescription"))); } if (enabledModules.CmdPal) { - content = HotkeySettingsToYaml(new CmdPalProperties().Hotkey, SettingsResourceLoader.GetString("CmdPal/ModuleTitle"), content); + content.Append(HotkeySettingsToYaml(new CmdPalProperties().Hotkey, SettingsResourceLoader.GetString("CmdPal/ModuleTitle"))); } if (enabledModules.CropAndLock) { CropAndLockProperties cropAndLockProperties = SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties; - content = HotkeySettingsToYaml(cropAndLockProperties.ThumbnailHotkey, SettingsResourceLoader.GetString("CropAndLock/ModuleTitle"), content, SettingsResourceLoader.GetString("CropAndLock_Thumbnail")); - content = HotkeySettingsToYaml(cropAndLockProperties.ReparentHotkey, SettingsResourceLoader.GetString("CropAndLock/ModuleTitle"), content, SettingsResourceLoader.GetString("CropAndLock_Reparent")); + content.Append(HotkeySettingsToYaml(cropAndLockProperties.ThumbnailHotkey, SettingsResourceLoader.GetString("CropAndLock/ModuleTitle"), SettingsResourceLoader.GetString("CropAndLock_Thumbnail"))); + content.Append(HotkeySettingsToYaml(cropAndLockProperties.ReparentHotkey, SettingsResourceLoader.GetString("CropAndLock/ModuleTitle"), SettingsResourceLoader.GetString("CropAndLock_Reparent"))); } if (enabledModules.FancyZones) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.FancyzonesEditorHotkey, SettingsResourceLoader.GetString("FancyZones/ModuleTitle"), content, SettingsResourceLoader.GetString("FancyZones_OpenEditor")); + content.Append(HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.FancyzonesEditorHotkey, SettingsResourceLoader.GetString("FancyZones/ModuleTitle"), SettingsResourceLoader.GetString("FancyZones_OpenEditor"))); } if (enabledModules.MouseHighlighter) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MouseUtils_MouseHighlighter/Header"), content, SettingsResourceLoader.GetString("MouseHighlighter_ShortDescription")); + content.Append(HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MouseUtils_MouseHighlighter/Header"), SettingsResourceLoader.GetString("MouseHighlighter_ShortDescription"))); } if (enabledModules.MouseJump) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MouseUtils_MouseJump/Header"), content, SettingsResourceLoader.GetString("MouseJump_ShortDescription")); + content.Append(HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MouseUtils_MouseJump/Header"), SettingsResourceLoader.GetString("MouseJump_ShortDescription"))); } if (enabledModules.MousePointerCrosshairs) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MouseUtils_MousePointerCrosshairs/Header"), content, SettingsResourceLoader.GetString("MouseCrosshairs_ShortDescription")); + content.Append(HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MouseUtils_MousePointerCrosshairs/Header"), SettingsResourceLoader.GetString("MouseCrosshairs_ShortDescription"))); } if (enabledModules.Peek) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("Peek/ModuleTitle"), content); + content.Append(HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("Peek/ModuleTitle"))); } if (enabledModules.PowerLauncher) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.OpenPowerLauncher, SettingsResourceLoader.GetString("PowerLauncher/ModuleTitle"), content); + content.Append(HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.OpenPowerLauncher, SettingsResourceLoader.GetString("PowerLauncher/ModuleTitle"))); } if (enabledModules.MeasureTool) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MeasureTool/ModuleTitle"), content, SettingsResourceLoader.GetString("ScreenRuler_ShortDescription")); + content.Append(HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MeasureTool/ModuleTitle"), SettingsResourceLoader.GetString("ScreenRuler_ShortDescription"))); } if (enabledModules.ShortcutGuide) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.DefaultOpenShortcutGuide, SettingsResourceLoader.GetString("ShortcutGuide/ModuleTitle"), content, SettingsResourceLoader.GetString("ShortcutGuide_ShortDescription")); + content.Append(HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.DefaultOpenShortcutGuide, SettingsResourceLoader.GetString("ShortcutGuide/ModuleTitle"), SettingsResourceLoader.GetString("ShortcutGuide_ShortDescription"))); } if (enabledModules.PowerOcr) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("TextExtractor/ModuleTitle"), content, SettingsResourceLoader.GetString("PowerOcr_ShortDescription")); + content.Append(HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("TextExtractor/ModuleTitle"), SettingsResourceLoader.GetString("PowerOcr_ShortDescription"))); } if (enabledModules.Workspaces) { - content = HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.Hotkey, SettingsResourceLoader.GetString("Workspaces/ModuleTitle"), content, SettingsResourceLoader.GetString("Workspaces_ShortDescription")); + content.Append(HotkeySettingsToYaml(SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Properties.Hotkey, SettingsResourceLoader.GetString("Workspaces/ModuleTitle"), SettingsResourceLoader.GetString("Workspaces_ShortDescription"))); } - content += populateEndString; + content.Append(populateEndString); - File.WriteAllText(path, content); + File.WriteAllText(path, content.ToString()); } - public static string HotkeySettingsToYaml(HotkeySettings hotkeySettings, string moduleName, string content, string? description = null) + /// + /// Converts the hotkey settings to a YAML format string for the manifest file. + /// + /// Object containing a hotkey from the settings. + /// The name of the PowerToys module. + /// Description of the action. + /// Yaml code for the manifest file. + private static string HotkeySettingsToYaml(HotkeySettings hotkeySettings, string moduleName, string? description = null) { + string content = string.Empty; content += " - Name: " + moduleName + Environment.NewLine; content += " Shortcut: " + Environment.NewLine; content += " - Win: " + hotkeySettings.Win.ToString() + Environment.NewLine; @@ -147,9 +162,10 @@ namespace ShortcutGuide.Helpers return content; } - public static string HotkeySettingsToYaml(KeyboardKeysProperty keyboardKeys, string moduleName, string content, string? description = null) + /// + private static string HotkeySettingsToYaml(KeyboardKeysProperty hotkeySettings, string moduleName, string? description = null) { - return HotkeySettingsToYaml(keyboardKeys.Value, moduleName, content, description); + return HotkeySettingsToYaml(hotkeySettings.Value, moduleName, description); } [GeneratedRegex(@"# [\s\S\n\r]*# ")] diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/ResourceLoaderInstance.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/ResourceLoaderInstance.cs index 3441f76ef3..f4e18161e9 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/ResourceLoaderInstance.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/ResourceLoaderInstance.cs @@ -8,8 +8,14 @@ namespace ShortcutGuide.Helpers { internal static class ResourceLoaderInstance { + /// + /// Gets the resource loader for the Shortcut Guide module. + /// internal static ResourceLoader ResourceLoader { get; private set; } + /// + /// Gets the resource loader for the Settings module. + /// internal static ResourceLoader SettingsResourceLoader { get; private set; } static ResourceLoaderInstance() diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/TasklistPositions.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/TasklistPositions.cs index 3056a0b28c..efbf444841 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/TasklistPositions.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Helpers/TasklistPositions.cs @@ -7,8 +7,15 @@ using TasklistButton = ShortcutGuide.NativeMethods.TasklistButton; namespace ShortcutGuide.Helpers { - internal sealed class TasklistPositions + /// + /// Provides methods to retrieve the positions of taskbar buttons on the current monitor. + /// + internal static class TasklistPositions { + /// + /// Retrieves the taskbar buttons for the current monitor. + /// + /// An array of the taskbar buttons. public static TasklistButton[] GetButtons() { var monitor = NativeMethods.MonitorFromWindow(MainWindow.WindowHwnd, 0); diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs index 39b72caa75..7f268338e5 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs @@ -2,9 +2,11 @@ // 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.Text.Json.Serialization; +using System.Threading; using System.Threading.Tasks; using Microsoft.PowerToys.Settings.UI.Library.Utilities; using Microsoft.UI.Xaml; @@ -108,31 +110,11 @@ namespace ShortcutGuide.Models { List shortcutStackPanels = []; - async void AnimateTextBlock(TextBlock animatedTextBlock, string text, int delay = 500) - { - try - { - int index = 0; - - while (!ShortcutView.AnimationCancellationTokenSource.Token.IsCancellationRequested) - { - animatedTextBlock.Text = text[index].ToString(); - index = (index + 1) % text.Length; - await Task.Delay(delay); - } - } - catch - { - // ignored - } - } - for (int i = 0; i < shortcut.Shortcut.Length; i++) { ShortcutDescription shortcutEntry = shortcut.Shortcut[i]; - StackPanel shortcutStackPanel = new(); + StackPanel shortcutStackPanel = new() { Orientation = Orientation.Horizontal }; shortcutStackPanels.Add(shortcutStackPanel); - shortcutStackPanel.Orientation = Orientation.Horizontal; // If any entry is blank, we skip the whole shortcut if (shortcutEntry is { Ctrl: false, Alt: false, Shift: false, Win: false, Keys.Length: 0 }) @@ -184,94 +166,7 @@ namespace ShortcutGuide.Models foreach (string key in shortcutEntry.Keys) { - switch (key) - { - case "": - shortcutStackPanel.Children.Add(new BitmapIcon() { UriSource = new("ms-appx:///Assets/ShortcutGuide/CopilotKey.png") }); - break; - case "": - shortcutStackPanel.Children.Add(new BitmapIcon() { UriSource = new("ms-appx:///Assets/ShortcutGuide/OfficeKey.png"), Height = 20, Width = 20 }); - break; - case "": - AddNewTextToStackPanel("←"); - break; - case "": - AddNewTextToStackPanel("→"); - break; - case "": - AddNewTextToStackPanel("↑"); - break; - case "": - AddNewTextToStackPanel("↓"); - break; - case "": - AddNewTextToStackPanel("..."); - break; - case "": - TextBlock animatedTextBlock = new() - { - Text = "A", - Margin = new Thickness(3), - VerticalAlignment = VerticalAlignment.Center, - - // Use monospaced font to ensure the text doesn't move - FontFamily = new("Courier New"), - TextDecorations = TextDecorations.Underline, - }; - - shortcutStackPanel.Children.Add(animatedTextBlock); - - AnimateTextBlock(animatedTextBlock, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); - break; - case "": - TextBlock arrowTextBlock = new() - { - Text = "→", - Margin = new Thickness(3), - VerticalAlignment = VerticalAlignment.Center, - }; - - shortcutStackPanel.Children.Add(arrowTextBlock); - - AnimateTextBlock(arrowTextBlock, "→↓←↑", 1000); - break; - case "": - TextBlock arrowLRTextBlock = new() - { - Text = "→", - Margin = new Thickness(3), - FontFamily = new("Courier New"), - VerticalAlignment = VerticalAlignment.Center, - }; - shortcutStackPanel.Children.Add(arrowLRTextBlock); - AnimateTextBlock(arrowLRTextBlock, "→←", 1000); - break; - case "": - TextBlock arrowUDTextBlock = new() - { - Text = "↑", - Margin = new Thickness(3), - FontFamily = new("Courier New"), - VerticalAlignment = VerticalAlignment.Center, - }; - shortcutStackPanel.Children.Add(arrowUDTextBlock); - AnimateTextBlock(arrowUDTextBlock, "↑↓", 1000); - break; - case { } name when name.StartsWith('<') && name.EndsWith('>'): - AddNewTextToStackPanel(name[1..^1]); - break; - case { } num when int.TryParse(num, out int parsedNum): - if (parsedNum == 0) - { - break; - } - - AddNewTextToStackPanel(Helper.GetKeyName((uint)parsedNum)); - break; - default: - AddNewTextToStackPanel(key); - break; - } + AddKeyToStackPanel(key, shortcutStackPanel); } continue; @@ -291,53 +186,190 @@ namespace ShortcutGuide.Models case <= 1: return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, stackPanelToReturn, shortcut); default: + stackPanelToReturn = new StackPanel { - { - stackPanelToReturn = new StackPanel - { - Orientation = Orientation.Vertical, - }; + Orientation = Orientation.Vertical, + }; - foreach (StackPanel panel in shortcutStackPanels) - { - panel.Visibility = Visibility.Collapsed; - stackPanelToReturn.Children.Add(panel); - } - - shortcutStackPanels[0].Visibility = Visibility.Visible; - for (int i = 1; i < shortcutStackPanels.Count; i++) - { - shortcutStackPanels[i].Visibility = Visibility.Collapsed; - } - - async void AnimateStackPanels(StackPanel[] panels, int delay = 2000) - { - try - { - int index = 0; - while (!ShortcutView.AnimationCancellationTokenSource.Token.IsCancellationRequested) - { - foreach (StackPanel panel in panels) - { - panel.Visibility = Visibility.Collapsed; - } - - panels[index].Visibility = Visibility.Visible; - index = (index + 1) % panels.Length; - await Task.Delay(delay); - } - } - catch - { - // ignored - } - } - - AnimateStackPanels([.. shortcutStackPanels]); - } - - return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, stackPanelToReturn, shortcut); + foreach (StackPanel panel in shortcutStackPanels) + { + panel.Visibility = Visibility.Collapsed; + stackPanelToReturn.Children.Add(panel); } + + shortcutStackPanels[0].Visibility = Visibility.Visible; + for (int i = 1; i < shortcutStackPanels.Count; i++) + { + shortcutStackPanels[i].Visibility = Visibility.Collapsed; + } + + AnimateStackPanels([.. shortcutStackPanels]); + + return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, stackPanelToReturn, shortcut); + } + } + + /// + /// Transforms a key string into a visual representation in the stack panel. + /// + /// The string reprensentation of the key. + /// The stackpanel to add the key to. + private static void AddKeyToStackPanel(string key, StackPanel shortcutStackPanel) + { + switch (key) + { + case "": + shortcutStackPanel.Children.Add(new BitmapIcon() { UriSource = new("ms-appx:///Assets/ShortcutGuide/CopilotKey.png") }); + break; + case "": + shortcutStackPanel.Children.Add(new BitmapIcon() { UriSource = new("ms-appx:///Assets/ShortcutGuide/OfficeKey.png"), Height = 20, Width = 20 }); + break; + case "": + AddNewTextToStackPanel("←"); + break; + case "": + AddNewTextToStackPanel("→"); + break; + case "": + AddNewTextToStackPanel("↑"); + break; + case "": + AddNewTextToStackPanel("↓"); + break; + case "": + AddNewTextToStackPanel("..."); + break; + case "": + TextBlock animatedTextBlock = new() + { + Text = "A", + Margin = new Thickness(3), + VerticalAlignment = VerticalAlignment.Center, + + // Use monospaced font to ensure the text doesn't move + FontFamily = new("Courier New"), + TextDecorations = TextDecorations.Underline, + }; + + shortcutStackPanel.Children.Add(animatedTextBlock); + + AnimateTextBlock(animatedTextBlock, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + break; + case "": + TextBlock arrowTextBlock = new() + { + Text = "→", + Margin = new Thickness(3), + VerticalAlignment = VerticalAlignment.Center, + }; + + shortcutStackPanel.Children.Add(arrowTextBlock); + + AnimateTextBlock(arrowTextBlock, "→↓←↑", 1000); + break; + case "": + TextBlock arrowLRTextBlock = new() + { + Text = "→", + Margin = new Thickness(3), + FontFamily = new("Courier New"), + VerticalAlignment = VerticalAlignment.Center, + }; + shortcutStackPanel.Children.Add(arrowLRTextBlock); + AnimateTextBlock(arrowLRTextBlock, "→←", 1000); + break; + case "": + TextBlock arrowUDTextBlock = new() + { + Text = "↑", + Margin = new Thickness(3), + FontFamily = new("Courier New"), + VerticalAlignment = VerticalAlignment.Center, + }; + shortcutStackPanel.Children.Add(arrowUDTextBlock); + AnimateTextBlock(arrowUDTextBlock, "↑↓", 1000); + break; + case { } name when name.StartsWith('<') && name.EndsWith('>'): + AddNewTextToStackPanel(name[1..^1]); + break; + case { } num when int.TryParse(num, out int parsedNum): + if (parsedNum == 0) + { + break; + } + + AddNewTextToStackPanel(Helper.GetKeyName((uint)parsedNum)); + break; + default: + AddNewTextToStackPanel(key); + break; + } + + void AddNewTextToStackPanel(string text) + { + shortcutStackPanel.Children.Add(new TextBlock { Text = text, Margin = new Thickness(3), VerticalAlignment = VerticalAlignment.Center }); + } + } + + /// + /// Animates the text of a TextBlock by cycling through the characters of a given string. + /// + /// + /// This function runs asynchronously and will not block the UI thread. Exceptions that occur during the animation will be caught and ignored to prevent crashes. + /// + /// The textblock to animate. + /// The characters to cycle through. + /// The delay to the next animation frame. + private static async void AnimateTextBlock(TextBlock animatedTextBlock, string text, int delay = 500) + { + try + { + int index = 0; + CancellationToken cancellationToken = ShortcutView.AnimationCancellationTokenSource.Token; + + while (!cancellationToken.IsCancellationRequested) + { + animatedTextBlock.Text = text[index].ToString(); + index = (index + 1) % text.Length; + await Task.Delay(delay); + } + } + catch + { + // ignored + } + } + + /// + /// Animates the visibility of the stack panels one after another. + /// + /// + /// This function runs asynchronously and will not block the UI thread. Exceptions that occur during the animation will be caught and ignored to prevent crashes. + /// + /// The panels to animate. + /// The delay to the next animation frame. + private static async void AnimateStackPanels(StackPanel[] panels, int delay = 2000) + { + try + { + int index = 0; + CancellationToken cancellationToken = ShortcutView.AnimationCancellationTokenSource.Token; + + while (!cancellationToken.IsCancellationRequested) + { + foreach (StackPanel panel in panels) + { + panel.Visibility = Visibility.Collapsed; + } + + panels[index].Visibility = Visibility.Visible; + index = (index + 1) % panels.Length; + await Task.Delay(delay); + } + } + catch + { + // ignored } } } diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs index f2faba001a..d88c4cda91 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutPageParameters.cs @@ -7,14 +7,29 @@ using System.Collections.Generic; namespace ShortcutGuide.Models { + /// + /// Represents the parameters for the shortcut page in the Shortcut Guide module. + /// internal struct ShortcutPageParameters { + /// + /// Gets or sets the content of the search box. + /// public static SearchFilterObservable SearchFilter = new(); + /// + /// Gets or sets the pinned shortcuts for the Shortcut Guide. + /// public static Dictionary> PinnedShortcuts = []; + /// + /// Gets or sets the name of the current page being displayed in the Shortcut Guide. + /// public static string CurrentPageName = string.Empty; + /// + /// The height of the frame that displays the shortcuts. + /// public static FrameHeightObservable FrameHeight = new(); internal sealed class SearchFilterObservable diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/NativeMethods.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/NativeMethods.cs index 987912c464..e1d830dcc9 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/NativeMethods.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/NativeMethods.cs @@ -119,4 +119,9 @@ internal static partial class NativeMethods public int Keynum; } + + public enum MonitorFromWindowDwFlags + { + MONITOR_DEFAULTTONEAREST = 2, + } } diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Program.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Program.cs index e2602e1f19..a8e4f61b0f 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Program.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Program.cs @@ -9,7 +9,6 @@ using System.Threading; using System.Windows; using ManagedCommon; using Microsoft.UI.Dispatching; -using Microsoft.UI.Xaml; using Microsoft.Windows.AppLifecycle; using ShortcutGuide.Helpers; using Application = Microsoft.UI.Xaml.Application; @@ -34,9 +33,9 @@ namespace ShortcutGuide return; } - if (!Directory.Exists(ManifestInterpreter.GetPathOfInterpretations())) + if (!Directory.Exists(ManifestInterpreter.PathOfManifestFiles)) { - Directory.CreateDirectory(ManifestInterpreter.GetPathOfInterpretations()); + Directory.CreateDirectory(ManifestInterpreter.PathOfManifestFiles); } if (NativeMethods.IsCurrentWindowExcludedFromShortcutGuide()) @@ -48,7 +47,7 @@ namespace ShortcutGuide // Todo: Handle error foreach (var file in InbuiltManifestFiles) { - File.Copy(Path.GetDirectoryName(Environment.ProcessPath) + "\\Assets\\ShortcutGuide\\" + file, ManifestInterpreter.GetPathOfInterpretations() + "\\" + file, true); + File.Copy(Path.GetDirectoryName(Environment.ProcessPath) + "\\Assets\\ShortcutGuide\\" + file, ManifestInterpreter.PathOfManifestFiles + "\\" + file, true); } Process indexGeneration = Process.Start(Path.GetDirectoryName(Environment.ProcessPath) + "\\PowerToys.ShortcutGuide.IndexYmlGenerator.exe"); @@ -56,7 +55,7 @@ namespace ShortcutGuide if (indexGeneration.ExitCode != 0) { Logger.LogError("Index generation failed with exit code: " + indexGeneration.ExitCode); - MessageBox.Show($"Shortcut Guide encountered an error while generating the index file. There is likely a corrupt shortcuts file in \"{ManifestInterpreter.GetPathOfInterpretations()}\". Try deleting this directory.", "Error displaying shortcuts", MessageBoxButton.OK, MessageBoxImage.Error); + MessageBox.Show($"Shortcut Guide encountered an error while generating the index file. There is likely a corrupt shortcuts file in \"{ManifestInterpreter.PathOfManifestFiles}\". Try deleting this directory.", "Error displaying shortcuts", MessageBoxButton.OK, MessageBoxImage.Error); return; } diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml index 66323b6f4c..b527eba93f 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml @@ -33,7 +33,7 @@ - + - + - - - + + + - + - + - - - +

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 literal 90990 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

diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/OOBEView.xaml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/OOBEView.xaml index b93aacedad..ec1959df73 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/OOBEView.xaml +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/OOBEView.xaml @@ -1,43 +1,47 @@ - + - - + + - - + + - - + + - - + + - - + + - - - + + + diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml index f2425e0ea7..f68b3a464d 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/ShortcutView.xaml @@ -1,37 +1,61 @@ - + + mc:Ignorable="d"> - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + @@ -40,97 +64,284 @@ - - - + + + - + - - + + - + - - + + - + - - - + + + - + - + - + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml index b503fce5ef..0a570fac21 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml @@ -165,7 +165,7 @@ helpers:NavHelper.NavigateTo="views:ShortcutGuidePage" Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/ShortcutGuide.png}"> - + - + From b553addcdda33af42640ff8ed9de37057490c34b Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Tue, 29 Jul 2025 18:51:21 +0200 Subject: [PATCH 82/99] Fix arm64 configuration --- PowerToys.sln | 8 -- .../ShortcutGuide.CPPProject.vcxproj | 114 +++++++++--------- 2 files changed, 60 insertions(+), 62 deletions(-) diff --git a/PowerToys.sln b/PowerToys.sln index 3f3c245ef4..a41fd9758f 100644 --- a/PowerToys.sln +++ b/PowerToys.sln @@ -2838,14 +2838,6 @@ Global {E816D7B0-4688-4ECB-97CC-3D8E798F3829}.Release|ARM64.Build.0 = Release|ARM64 {E816D7B0-4688-4ECB-97CC-3D8E798F3829}.Release|x64.ActiveCfg = Release|x64 {E816D7B0-4688-4ECB-97CC-3D8E798F3829}.Release|x64.Build.0 = Release|x64 - {00D8659C-2068-40B6-8B86-759CD6284BBB}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {00D8659C-2068-40B6-8B86-759CD6284BBB}.Debug|ARM64.Build.0 = Debug|ARM64 - {00D8659C-2068-40B6-8B86-759CD6284BBB}.Debug|x64.ActiveCfg = Debug|x64 - {00D8659C-2068-40B6-8B86-759CD6284BBB}.Debug|x64.Build.0 = Debug|x64 - {00D8659C-2068-40B6-8B86-759CD6284BBB}.Release|ARM64.ActiveCfg = Release|ARM64 - {00D8659C-2068-40B6-8B86-759CD6284BBB}.Release|ARM64.Build.0 = Release|ARM64 - {00D8659C-2068-40B6-8B86-759CD6284BBB}.Release|x64.ActiveCfg = Release|x64 - {00D8659C-2068-40B6-8B86-759CD6284BBB}.Release|x64.Build.0 = Release|x64 {C992FD2C-83B8-4941-9FC1-09730068D8EC}.Debug|ARM64.ActiveCfg = Debug|ARM64 {C992FD2C-83B8-4941-9FC1-09730068D8EC}.Debug|ARM64.Build.0 = Debug|ARM64 {C992FD2C-83B8-4941-9FC1-09730068D8EC}.Debug|x64.ActiveCfg = Debug|x64 diff --git a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj index e7a222f0ae..612b81decb 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj +++ b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj @@ -1,23 +1,39 @@ - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - + + + 15.0 + Win32Proj + {2d604c07-51fc-46bb-9eb7-75aecc7f5e81} + ShortcutGuide.CPPProject + ShortcutGuide.CPPProject + 10.0.26100.0 + + + + DynamicLibrary + true + v143 + Unicode + Spectre + + + DynamicLibrary + false + v143 + true + Unicode + Spectre + + + + + + + + + + 17.0 Win32Proj @@ -25,7 +41,6 @@ ShortcutGuideCPPProject 10.0.22621.0 - Application true @@ -52,11 +67,6 @@ true Unicode - - - - - @@ -70,42 +80,16 @@ - + ..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps\ - - - Level3 - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - Level3 - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - Level3 true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ..\..\..\common\utils; + ..\..\..\common\utils;..\..\..;%(AdditionalIncludeDirectories) Console @@ -120,18 +104,29 @@ true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true + ..\..\..\common\utils;..\..\..;%(AdditionalIncludeDirectories) Console true + + + ..\..\..\common\utils;..\..\..;%(AdditionalIncludeDirectories) + + + + + ..\..\..\common\utils;..\..\..;%(AdditionalIncludeDirectories) + + - Create + Create Create - Create + Create Create @@ -149,7 +144,18 @@ + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file From 387b7e97957afabd3240e357b953bdb6a4ef5d87 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Wed, 30 Jul 2025 16:50:20 +0200 Subject: [PATCH 83/99] So something was not right. Hopefully this fixes it. --- src/modules/ShortcutGuide/ShortcutGuide.CPPProject/pch.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/pch.h b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/pch.h index 1c0d2b748b..9e16b80256 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/pch.h +++ b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/pch.h @@ -27,6 +27,6 @@ #include #include #include -#include -#include +#include +#include #include <../SettingsAPI/settings_objects.h> From 3b7df37ac26622cf78484679fe59467e83d265cb Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Wed, 30 Jul 2025 17:21:37 +0200 Subject: [PATCH 84/99] That is a kinda embarrasing error --- .../ShortcutGuide.CPPProject/tasklist_positions.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/tasklist_positions.cpp b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/tasklist_positions.cpp index d26fb82724..23cfd37e3b 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/tasklist_positions.cpp +++ b/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/tasklist_positions.cpp @@ -32,8 +32,8 @@ extern "C" RECT rc; if (GetWindowRect(secondaryTaskbar, &rc)) { - HMONITOR monitor = MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST); - if (monitor == monitor) + HMONITOR taskbarMonitor = MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST); + if (monitor == taskbarMonitor) return secondaryTaskbar; } } From ac789a7fbe694b919abd6da718f497279e5fa6fc Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Wed, 30 Jul 2025 17:31:31 +0200 Subject: [PATCH 85/99] Remove failing test --- .../ViewModelTests/ShortcutGuide.cs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/ShortcutGuide.cs b/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/ShortcutGuide.cs index 3613d0cfa3..6d4cc893f5 100644 --- a/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/ShortcutGuide.cs +++ b/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/ShortcutGuide.cs @@ -47,7 +47,6 @@ namespace ViewModelTests // Verify that the old settings persisted Assert.AreEqual(originalGeneralSettings.Enabled.ShortcutGuide, viewModel.IsEnabled); - Assert.AreEqual(originalSettings.Properties.OverlayOpacity.Value, viewModel.OverlayOpacity); // Verify that the stub file was used var expectedCallCount = 2; // once via the view model, and once by the test (GetSettings) @@ -104,21 +103,5 @@ namespace ViewModelTests Func isDark = s => JsonSerializer.Deserialize(s).Properties.Theme.Value == "dark"; settingsUtilsMock.Verify(x => x.SaveSettings(It.Is(y => isDark(y)), It.IsAny(), It.IsAny()), Times.Once); } - - [TestMethod] - public void OverlayOpacityShouldSeOverlayOpacityToOneHundredWhenSuccessful() - { - // Arrange - var settingsUtilsMock = new Mock(); - ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(settingsUtilsMock.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockShortcutGuideSettingsUtils.Object), msg => { return 0; }, ShortCutGuideTestFolderName); - Assert.AreEqual(90, viewModel.OverlayOpacity); - - // Act - viewModel.OverlayOpacity = 100; - - // Assert - Func equal100 = s => JsonSerializer.Deserialize(s).Properties.OverlayOpacity.Value == 100; - settingsUtilsMock.Verify(x => x.SaveSettings(It.Is(y => equal100(y)), It.IsAny(), It.IsAny()), Times.Once); - } } } From cd844e38898695e4ab9a7dd2598de05a655d0f60 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Wed, 30 Jul 2025 18:17:26 +0200 Subject: [PATCH 86/99] Forgot notice.md and CPPProject has some trouble buildinng release x64 --- NOTICE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NOTICE.md b/NOTICE.md index d75fe99522..626db2b11b 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -1581,3 +1581,4 @@ SOFTWARE. - WinUIEx 2.2.0 - WPF-UI 3.0.5 - WyHash 1.0.5 +- YamlDotNet 16.3.0 From dc0877ebe525b6fc246b35a19b439ac6aa4bfce0 Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Fri, 1 Aug 2025 17:06:54 +0200 Subject: [PATCH 87/99] Make some adjustants to how the windows key is displayed --- .../ShortcutGuide.Ui/Models/ShortcutEntry.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs index 9b20d165f6..a205adc8e4 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs @@ -140,11 +140,9 @@ namespace ShortcutGuide.Models Viewbox winIconContainer = new() { Child = winIcon, - HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center, - Height = 24, - Width = 24, - Margin = new Thickness(3), + Height = 20, + Width = 20, + Margin = new Thickness(3, -1, 3, 2), }; shortcutStackPanel.Children.Add(winIconContainer); } From bb16ae170901ceb42dea7b1b230eff8859f44d4d Mon Sep 17 00:00:00 2001 From: Aaron Junker Date: Fri, 1 Aug 2025 17:51:32 +0200 Subject: [PATCH 88/99] Adress some PR comments and fix some bugs --- .../ShortcutGuide.Ui/Models/ShortcutEntry.cs | 12 +++++++---- .../ShortcutGuide/ShortcutGuide.Ui/Program.cs | 5 +---- .../ShortcutGuideXAML/MainWindow.xaml | 2 +- .../ShortcutGuideXAML/ShortcutView.xaml | 20 +++++++++---------- .../Strings/en-us/Resources.resw | 3 +++ 5 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs index a205adc8e4..911bb535b2 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Models/ShortcutEntry.cs @@ -14,6 +14,7 @@ using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Markup; using Windows.UI.Text; using static ShortcutGuide.Models.ShortcutEntry; +using Orientation = Microsoft.UI.Xaml.Controls.Orientation; namespace ShortcutGuide.Models { @@ -214,6 +215,8 @@ namespace ShortcutGuide.Models /// The StackPanel to add the key to. private static void AddKeyToStackPanel(string key, StackPanel shortcutStackPanel) { + Microsoft.UI.Xaml.Media.FontFamily monospaceFont = new("Courier New"); + switch (key) { case "": @@ -241,11 +244,11 @@ namespace ShortcutGuide.Models TextBlock animatedTextBlock = new() { Text = "A", - Margin = new Thickness(3), + Margin = new Thickness(3, 3, 3, 1), VerticalAlignment = VerticalAlignment.Center, // Use monospaced font to ensure the text doesn't move - FontFamily = new("Courier New"), + FontFamily = monospaceFont, TextDecorations = TextDecorations.Underline, }; @@ -258,6 +261,7 @@ namespace ShortcutGuide.Models { Text = "→", Margin = new Thickness(3), + FontFamily = monospaceFont, VerticalAlignment = VerticalAlignment.Center, }; @@ -270,7 +274,7 @@ namespace ShortcutGuide.Models { Text = "→", Margin = new Thickness(3), - FontFamily = new("Courier New"), + FontFamily = monospaceFont, VerticalAlignment = VerticalAlignment.Center, }; shortcutStackPanel.Children.Add(arrowLRTextBlock); @@ -281,7 +285,7 @@ namespace ShortcutGuide.Models { Text = "↑", Margin = new Thickness(3), - FontFamily = new("Courier New"), + FontFamily = monospaceFont, VerticalAlignment = VerticalAlignment.Center, }; shortcutStackPanel.Children.Add(arrowUDTextBlock); diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Program.cs b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Program.cs index a8e4f61b0f..61a61883b9 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/Program.cs +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/Program.cs @@ -33,10 +33,7 @@ namespace ShortcutGuide return; } - if (!Directory.Exists(ManifestInterpreter.PathOfManifestFiles)) - { - Directory.CreateDirectory(ManifestInterpreter.PathOfManifestFiles); - } + Directory.CreateDirectory(ManifestInterpreter.PathOfManifestFiles); if (NativeMethods.IsCurrentWindowExcludedFromShortcutGuide()) { diff --git a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml index 7b4f953ea0..01bbfd2ea7 100644 --- a/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml +++ b/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuideXAML/MainWindow.xaml @@ -79,7 +79,7 @@ Margin="0,0,6,0" HorizontalContentAlignment="Center" Click="SettingsButton_Clicked"> - +